Skip to content

Commit

Permalink
refactor: base class, shallow clone, symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
ckohen committed Aug 29, 2022
1 parent 480df0f commit 0e58825
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 29 deletions.
26 changes: 26 additions & 0 deletions packages/structures/src/Structure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { data as kData } from './utils/symbols';

export abstract class Structure<DataType, Omitted extends keyof DataType | '' = ''> {
protected [kData]: Readonly<Omit<DataType, Omitted>>;

protected constructor(data: Readonly<Omit<DataType, Omitted>>) {
// Do not shallow clone data here as subclasses should do it (also allows them to set the constructor to public)
this[kData] = data;
}

/**
* Update this structure with new data
* @param data - A payload with updated data for this structure
* @returns New structure with patched data
*/
public patch(data: Readonly<Partial<DataType>>): this {
// @ts-expect-error TS cannot identify the type of this.constructor properly because subclasses
return new this.constructor({ ...this.toJSON(), ...data }) as this;
}

public toJSON(): DataType {
// This will be DataType provided nothing is omitted, when omits occur, subclass needs to overwrite this.
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return { ...this[kData] } as DataType;
}
}
28 changes: 16 additions & 12 deletions packages/structures/src/users/Connection.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,80 @@
import type { APIConnection } from 'discord-api-types/v10';
import { Structure } from '../Structure';
import { data as kData } from '../utils/symbols';

/**
* Represents a user's connection on Discord.
*/
export class Connection {
export class Connection extends Structure<APIConnection> {
public constructor(
/**
* The raw data received from the API for the connection
*/
protected raw: APIConnection,
) {}
data: APIConnection,
) {
super({ ...data });
}

/**
* The id of the connection account
*/
public get id() {
return this.raw.id;
return this[kData].id;
}

/**
* The username of the connection account
*/
public get name() {
return this.raw.name;
return this[kData].name;
}

/**
* The type of service this connection is for
*/
public get type() {
return this.raw.type;
return this[kData].type;
}

/**
* Whether the connection is revoked
*/
public get revoked() {
return this.raw.revoked ?? false;
return this[kData].revoked ?? false;
}

/**
* Any integrations associated with this connection
*/
public get integrations() {
return this.raw.integrations ?? null;
return this[kData].integrations ?? null;
}

/**
* Whether the connection is verified
*/
public get verified() {
return this.raw.verified;
return this[kData].verified;
}

/**
* Whether friend sync is enabled for this connection
*/
public get friendSync() {
return this.raw.friend_sync;
return this[kData].friend_sync;
}

/**
* Whether activities related to this connection are shown in the users presence
*/
public get showActivity() {
return this.raw.show_activity;
return this[kData].show_activity;
}

/**
* The visibilty state for this connection
*/
public get visibility() {
return this.raw.visibility;
return this[kData].visibility;
}
}
39 changes: 22 additions & 17 deletions packages/structures/src/users/User.ts
Original file line number Diff line number Diff line change
@@ -1,120 +1,125 @@
import { DiscordSnowflake } from '@sapphire/snowflake';
import type { APIUser, Snowflake } from 'discord-api-types/v10';
import { Structure } from '../Structure';

import { data as kData } from '../utils/symbols';

/**
* Represents any user on Discord.
*/
export class User {
export class User extends Structure<APIUser> {
public constructor(
/**
* The raw data received from the API for the user
*/
protected raw: APIUser,
) {}
data: APIUser,
) {
super({ ...data });
}

/**
* The user's id
*/
public get id(): Snowflake {
return this.raw.id;
return this[kData].id;
}

/**
* The username of the user
*/
public get username() {
return this.raw.username;
return this[kData].username;
}

/**
* The user's 4 digit tag, in combination with the username can uniquely identify the user
*/
public get discriminator() {
return this.raw.discriminator;
return this[kData].discriminator;
}

/**
* The user avatar's hash
*/
public get avatar() {
return this.raw.avatar;
return this[kData].avatar;
}

/**
* Whether the user is a bot
*/
public get bot() {
return this.raw.bot ?? false;
return this[kData].bot ?? false;
}

/**
* Whether the user is an Official Discord System user
*/
public get system() {
return this.raw.system ?? false;
return this[kData].system ?? false;
}

/**
* Whether the user has mfa enabled
* <info>This property is only set when the user was fetched with an OAuth2 token and the `identify` scope</info>
*/
public get mfaEnabled() {
return this.raw.mfa_enabled;
return this[kData].mfa_enabled;
}

/**
* The user's banner hash
* <info>This property is only set when the user was manually fetched</info>
*/
public get banner() {
return this.raw.banner;
return this[kData].banner;
}

/**
* The base 10 accent color of the user's banner
* <info>This property is only set when the user was manually fetched</info>
*/
public get accentColor() {
return this.raw.accent_color;
return this[kData].accent_color;
}

/**
* The user's primary discord language
* <info>This property is only set when the user was fetched with an Oauth2 token and the `identify` scope</info>
*/
public get locale() {
return this.raw.locale;
return this[kData].locale;
}

/**
* Whether the email on the user's account has been verified
* <info>This property is only set when the user was fetched with an OAuth2 token and the `email` scope</info>
*/
public get verified() {
return this.raw.verified;
return this[kData].verified;
}

/**
* The user's email
* <info>This property is only set when the user was fetched with an OAuth2 token and the `email` scope</info>
*/
public get email() {
return this.raw.email;
return this[kData].email;
}

/**
* The type of nitro subscription on the user's account
* <info>This property is only set when the user was fetched with an OAuth2 token and the `identify` scope</info>
*/
public get premiumType() {
return this.raw.premium_type;
return this[kData].premium_type;
}

/**
* The flags for the user
*/
public get flags() {
return this.raw.public_flags;
return this[kData].public_flags;
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/structures/src/utils/symbols.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const data = Symbol('structure:data');

0 comments on commit 0e58825

Please sign in to comment.