diff --git a/mod.ts b/mod.ts index a94898b..9606984 100644 --- a/mod.ts +++ b/mod.ts @@ -2,6 +2,7 @@ export { GatewayIntents } from './src/types/gateway.ts' export { default as EventEmitter } from 'https://deno.land/std@0.74.0/node/events.ts' export { Base } from './src/structures/base.ts' export { Gateway } from './src/gateway/index.ts' +export type { ClientEvents } from './src/gateway/handlers/index.ts' export * from './src/models/client.ts' export { RESTManager } from './src/models/rest.ts' export * from './src/models/cacheAdapter.ts' @@ -80,3 +81,41 @@ export type { StatusType } from './src/types/presence.ts' export { ChannelTypes } from './src/types/channel.ts' +export type { ApplicationPayload } from './src/types/application.ts' +export type { ImageFormats, ImageSize } from './src/types/cdn.ts' +export type { + ChannelMention, + ChannelPayload, + FollowedChannel, + GuildNewsChannelPayload, + GuildChannelCategoryPayload, + GuildChannelPayload, + GuildTextChannelPayload, + GuildVoiceChannelPayload, + GroupDMChannelPayload +} from './src/types/channel.ts' +export type { EmojiPayload } from './src/types/emoji.ts' +export type { + GuildBanPayload, + GuildFeatures, + GuildIntegrationPayload, + GuildPayload +} from './src/types/guild.ts' +export type { InvitePayload, PartialInvitePayload } from './src/types/invite.ts' +export { PermissionFlags } from './src/types/permissionFlags.ts' +export type { + ActivityAssets, + ActivityEmoji, + ActivityFlags, + ActivityParty, + ActivityPayload, + ActivitySecrets, + ActivityTimestamps, + ActivityType +} from './src/types/presence.ts' +export type { RolePayload } from './src/types/role.ts' +export type { TemplatePayload } from './src/types/template.ts' +export type { UserPayload } from './src/types/user.ts' +export { UserFlags } from './src/types/userFlags.ts' +export type { VoiceStatePayload } from './src/types/voice.ts' +export type { WebhookPayload } from './src/types/webhook.ts' diff --git a/src/gateway/handlers/index.ts b/src/gateway/handlers/index.ts index 8934068..85e1d75 100644 --- a/src/gateway/handlers/index.ts +++ b/src/gateway/handlers/index.ts @@ -27,7 +27,7 @@ import { webhooksUpdate } from './webhooksUpdate.ts' import { messageDeleteBulk } from './messageDeleteBulk.ts' import { userUpdate } from './userUpdate.ts' import { typingStart } from './typingStart.ts' -import { GuildTextChannel } from '../../structures/textChannel.ts' +import { GuildTextChannel, TextChannel } from '../../structures/textChannel.ts' import { Guild } from '../../structures/guild.ts' import { User } from '../../structures/user.ts' import { Emoji } from '../../structures/emoji.ts' @@ -107,56 +107,223 @@ export interface VoiceServerUpdateData { } export interface ClientEvents extends EventTypes { + /** When Client has successfully connected to Discord */ ready: () => void + /** When a successful reconnect has been made */ reconnect: () => void + /** When a successful session resume has been done */ resumed: () => void + /** + * When a new Channel is created + * @param channel New Channel object + */ channelCreate: (channel: EveryChannelTypes) => void + /** + * When a Channel was deleted + * @param channel Channel object which was deleted + */ channelDelete: (channel: EveryChannelTypes) => void + /** + * Channel's Pinned Messages were updated + * @param before Channel object before update + * @param after Channel object after update + */ channelPinsUpdate: ( before: EveryTextChannelTypes, after: EveryTextChannelTypes ) => void + /** + * A Channel was updated + * @param before Channel object before update + * @param after Channel object after update + */ channelUpdate: (before: EveryChannelTypes, after: EveryChannelTypes) => void + /** + * A User was banned from a Guild + * @param guild The Guild from which User was banned + * @param user The User who was banned + */ guildBanAdd: (guild: Guild, user: User) => void + /** + * A ban from a User in Guild was elevated + * @param guild Guild from which ban was removed + * @param user User of which ban was elevated + */ guildBanRemove: (guild: Guild, user: User) => void + /** + * Client has joined a new Guild. + * @param guild The new Guild object + */ guildCreate: (guild: Guild) => void + /** + * A Guild in which Client was either deleted, or bot was kicked + * @param guild The Guild object + */ guildDelete: (guild: Guild) => void + /** + * A new Emoji was added to Guild + * @param guild Guild in which Emoji was added + * @param emoji The Emoji which was added + */ guildEmojiAdd: (guild: Guild, emoji: Emoji) => void + /** + * An Emoji was deleted from Guild + * @param guild Guild from which Emoji was deleted + * @param emoji Emoji which was deleted + */ guildEmojiDelete: (guild: Guild, emoji: Emoji) => void + /** + * An Emoji in a Guild was updated + * @param guild Guild in which Emoji was updated + * @param before Emoji object before update + * @param after Emoji object after update + */ guildEmojiUpdate: (guild: Guild, before: Emoji, after: Emoji) => void + /** + * Guild's Integrations were updated + * @param guild The Guild object + */ guildIntegrationsUpdate: (guild: Guild) => void + /** + * A new Member has joined a Guild + * @param member The Member object + */ guildMemberAdd: (member: Member) => void + /** + * A Guild Member has either left or was kicked from Guild + * @param member The Member object + */ guildMemberRemove: (member: Member) => void + /** + * A Guild Member was updated. Nickname changed, role assigned, etc. + * @param before Member object before update + * @param after Meber object after update + */ guildMemberUpdate: (before: Member, after: Member) => void + /** + * A new Role was created in Guild + * @param role The new Role object + */ guildRoleCreate: (role: Role) => void + /** + * A Role was deleted from the Guild + * @param role The Role object + */ guildRoleDelete: (role: Role) => void + /** + * A Role was updated in a Guild + * @param before Role object before update + * @param after Role object after updated + */ guildRoleUpdate: (before: Role, after: Role) => void + /** + * A Guild has been updated. For example name, icon, etc. + * @param before Guild object before update + * @param after Guild object after update + */ guildUpdate: (before: Guild, after: Guild) => void + /** + * A new Message was created (sent) + * @param message The new Message object + */ messageCreate: (message: Message) => void + /** + * A Message was deleted. + * @param message The Message object + */ messageDelete: (message: Message) => void + /** + * Messages were bulk deleted in a Guild Text Channel + * @param channel Channel in which Messages were deleted + * @param messages Collection of Messages deleted + * @param uncached Set of Messages deleted's IDs which were not cached + */ messageDeleteBulk: ( channel: GuildTextChannel, messages: Collection, uncached: Set ) => void + /** + * A Message was updated. For example content, embed, etc. + * @param before Message object before update + * @param after Message object after update + */ messageUpdate: (before: Message, after: Message) => void + /** + * Reaction was added to a Message + * @param reaction Reaction object + * @param user User who added the reaction + */ messageReactionAdd: (reaction: MessageReaction, user: User) => void + /** + * Reaction was removed fro a Message + * @param reaction Reaction object + * @param user User to who removed the reaction + */ messageReactionRemove: (reaction: MessageReaction, user: User) => void + /** + * All reactions were removed from a Message + * @param message Message from which reactions were removed + */ messageReactionRemoveAll: (message: Message) => void + /** + * All reactions of a single Emoji were removed + * @param message The Message object + * @param emoji The Emoji object + */ messageReactionRemoveEmoji: (message: Message, emoji: Emoji) => void + /** + * A User has started typing in a Text Channel + */ typingStart: ( user: User, - channel: EveryChannelTypes, + channel: TextChannel, at: Date, guildData?: TypingStartGuildData ) => void + /** + * A new Invite was created + * @param invite New Invite object + */ inviteCreate: (invite: Invite) => void + /** + * An Invite was deleted + * @param invite Invite object + */ inviteDelete: (invite: Invite) => void + /** + * A User was updated. For example username, avatar, etc. + * @param before The User object before update + * @param after The User object after update + */ userUpdate: (before: User, after: User) => void + /** + * Client has received credentials for establishing connection to Voice Server + */ voiceServerUpdate: (data: VoiceServerUpdateData) => void + /** + * A User has joined a Voice Channel + */ voiceStateAdd: (state: VoiceState) => void + /** + * A User has left a Voice Channel + */ voiceStateRemove: (state: VoiceState) => void + /** + * Voice State of a User has been updated + * @param before Voice State object before update + * @param after Voice State object after update + */ voiceStateUpdate: (state: VoiceState, after: VoiceState) => void + /** + * A User's presence has been updated + * @param presence New Presence + */ presenceUpdate: (presence: Presence) => void + /** + * Webhooks of a Channel in a Guild has been updated + * @param guild Guild in which Webhooks were updated + * @param channel Channel of which Webhooks were updated + */ webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void } diff --git a/src/gateway/index.ts b/src/gateway/index.ts index 6311ee9..4f8dacb 100644 --- a/src/gateway/index.ts +++ b/src/gateway/index.ts @@ -252,9 +252,9 @@ class Gateway { const payload: IdentityPayload = { token: this.token, properties: { - $os: Deno.build.os, - $browser: 'harmony', - $device: 'harmony' + $os: this.client.clientProperties.os ?? Deno.build.os, + $browser: this.client.clientProperties.browser ?? 'harmony', + $device: this.client.clientProperties.device ?? 'harmony' }, compress: true, shard: [0, 1], // TODO: Make sharding possible diff --git a/src/models/client.ts b/src/models/client.ts index 13646eb..9e6705b 100644 --- a/src/models/client.ts +++ b/src/models/client.ts @@ -13,6 +13,13 @@ import { ActivityGame, ClientActivity } from '../types/presence.ts' import { ClientEvents } from '../gateway/handlers/index.ts' import { Extension } from './extensions.ts' +/** OS related properties sent with Gateway Identify */ +export interface ClientProperties { + os?: 'darwin' | 'windows' | 'linux' | 'custom_os' | string + browser?: 'harmony' | string + device?: 'harmony' | string +} + /** Some Client Options to modify behaviour */ export interface ClientOptions { /** Token of the Bot/User */ @@ -33,6 +40,8 @@ export interface ClientOptions { reactionCacheLifetime?: number /** Whether to fetch Uncached Message of Reaction or not? */ fetchUncachedReactions?: boolean + /** Client Properties */ + clientProperties?: ClientProperties } /** @@ -61,6 +70,8 @@ export class Client extends EventEmitter { reactionCacheLifetime: number = 3600000 /** Whether to fetch Uncached Message of Reaction or not? */ fetchUncachedReactions: boolean = false + /** Client Properties */ + clientProperties: ClientProperties users: UsersManager = new UsersManager(this) guilds: GuildManager = new GuildManager(this) @@ -113,6 +124,15 @@ export class Client extends EventEmitter { }) this._decoratedEvents = undefined } + + this.clientProperties = + options.clientProperties === undefined + ? { + os: Deno.build.os, + browser: 'harmony', + device: 'harmony' + } + : options.clientProperties } /** diff --git a/src/structures/presence.ts b/src/structures/presence.ts index 0fdac0d..85593fb 100644 --- a/src/structures/presence.ts +++ b/src/structures/presence.ts @@ -50,17 +50,23 @@ export class Presence extends Base { } } +interface StatusPayload extends StatusUpdatePayload { + client_status?: ClientStatus +} + export class ClientPresence { status: StatusType = 'online' activity?: ActivityGame | ActivityGame[] since?: number | null afk?: boolean + clientStatus?: ClientStatus - constructor(data?: ClientActivity | StatusUpdatePayload | ActivityGame) { + constructor(data?: ClientActivity | StatusPayload | ActivityGame) { if (data !== undefined) { if ((data as ClientActivity).activity !== undefined) { Object.assign(this, data) - } else if ((data as StatusUpdatePayload).activities !== undefined) { + } else if ((data as StatusPayload).activities !== undefined) { + this.parse(data as StatusPayload) } else if ((data as ActivityGame).name !== undefined) { if (this.activity === undefined) { this.activity = data as ActivityGame @@ -71,11 +77,12 @@ export class ClientPresence { } } - parse(payload: StatusUpdatePayload): ClientPresence { + parse(payload: StatusPayload): ClientPresence { this.afk = payload.afk this.activity = payload.activities ?? undefined this.since = payload.since this.status = payload.status + // this.clientStatus = payload.client_status return this } @@ -83,12 +90,14 @@ export class ClientPresence { return new ClientPresence().parse(payload) } - create(): StatusUpdatePayload { + create(): StatusPayload { + console.log(this) return { afk: this.afk === undefined ? false : this.afk, activities: this.createActivity(), since: this.since === undefined ? null : this.since, status: this.status === undefined ? 'online' : this.status + // client_status: this.clientStatus } } @@ -144,4 +153,13 @@ export class ClientPresence { this.since = since return this } + + // setClientStatus( + // client: 'desktop' | 'web' | 'mobile', + // status: StatusType + // ): ClientPresence { + // if (this.clientStatus === undefined) this.clientStatus = {} + // this.clientStatus[client] = status + // return this + // } } diff --git a/src/test/index.ts b/src/test/index.ts index 2da0845..3ae10f5 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -2,7 +2,6 @@ import { Client, Intents, Message, - ClientPresence, Member, Role, GuildChannel, @@ -15,10 +14,9 @@ import { import { TOKEN } from './config.ts' const client = new Client({ - presence: new ClientPresence({ - name: 'Pokémon Sword', - type: 'COMPETING' - }) + clientProperties: { + browser: 'Discord iOS' + } // bot: false, // cache: new RedisCacheAdapter({ // hostname: '127.0.0.1', diff --git a/src/types/gateway.ts b/src/types/gateway.ts index 9d9bc29..5a1dd3e 100644 --- a/src/types/gateway.ts +++ b/src/types/gateway.ts @@ -120,11 +120,11 @@ export interface IdentityPayload { } export interface IdentityConnection { - $os: 'darwin' | 'windows' | 'linux' | 'custom os' - $browser: 'harmony' | 'Firefox' - $device: 'harmony' | '' - $referrer?: '' - $referring_domain?: '' + $os: 'darwin' | 'windows' | 'linux' | 'custom os' | string + $browser: 'harmony' | 'Firefox' | string + $device: 'harmony' | string + $referrer?: '' | string + $referring_domain?: '' | string } export interface Resume {