feat(presence): added caching and last gateway event!
This commit is contained in:
		
							parent
							
								
									484c6e3c7b
								
							
						
					
					
						commit
						fb110946e0
					
				
					 9 changed files with 124 additions and 25 deletions
				
			
		|  | @ -22,6 +22,8 @@ export const guildCreate: GatewayEventHandler = async ( | ||||||
| 
 | 
 | ||||||
|   await guild.roles.fromPayload(d.roles) |   await guild.roles.fromPayload(d.roles) | ||||||
| 
 | 
 | ||||||
|  |   if (d.presences !== undefined) await guild.presences.fromPayload(d.presences) | ||||||
|  | 
 | ||||||
|   if (d.voice_states !== undefined) |   if (d.voice_states !== undefined) | ||||||
|     await guild.voiceStates.fromPayload(d.voice_states) |     await guild.voiceStates.fromPayload(d.voice_states) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ export const guildDelte: GatewayEventHandler = async ( | ||||||
|     await guild.members.flush() |     await guild.members.flush() | ||||||
|     await guild.channels.flush() |     await guild.channels.flush() | ||||||
|     await guild.roles.flush() |     await guild.roles.flush() | ||||||
|  |     await guild.presences.flush() | ||||||
|     await gateway.client.guilds.delete(d.id) |     await gateway.client.guilds.delete(d.id) | ||||||
| 
 | 
 | ||||||
|     gateway.client.emit('guildDelete', guild) |     gateway.client.emit('guildDelete', guild) | ||||||
|  |  | ||||||
|  | @ -14,7 +14,13 @@ export const guildMembersChunk: GatewayEventHandler = async ( | ||||||
|     await guild.members.set(member.user.id, member) |     await guild.members.set(member.user.id, member) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // TODO: Cache Presences
 |   if (d.chunk_index === 0) await guild.presences.flush() | ||||||
|  | 
 | ||||||
|  |   if (d.presences !== undefined) { | ||||||
|  |     for (const pres of d.presences) { | ||||||
|  |       await guild.presences.set(pres.user.id, pres) | ||||||
|  |     } | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   gateway.client.emit('guildMembersChunk', guild, { |   gateway.client.emit('guildMembersChunk', guild, { | ||||||
|     members: d.members.map((m) => m.user.id), |     members: d.members.map((m) => m.user.id), | ||||||
|  |  | ||||||
|  | @ -49,6 +49,7 @@ import { inviteCreate } from './inviteCreate.ts' | ||||||
| import { inviteDelete } from './inviteDelete.ts' | import { inviteDelete } from './inviteDelete.ts' | ||||||
| import { MessageReaction } from '../../structures/messageReaction.ts' | import { MessageReaction } from '../../structures/messageReaction.ts' | ||||||
| import { Invite } from '../../structures/invite.ts' | import { Invite } from '../../structures/invite.ts' | ||||||
|  | import { Presence } from '../../structures/presence.ts' | ||||||
| 
 | 
 | ||||||
| export const gatewayHandlers: { | export const gatewayHandlers: { | ||||||
|   [eventCode in GatewayEvents]: GatewayEventHandler | undefined |   [eventCode in GatewayEvents]: GatewayEventHandler | undefined | ||||||
|  | @ -150,5 +151,6 @@ export interface ClientEvents extends EventTypes { | ||||||
|   voiceStateAdd: (state: VoiceState) => void |   voiceStateAdd: (state: VoiceState) => void | ||||||
|   voiceStateRemove: (state: VoiceState) => void |   voiceStateRemove: (state: VoiceState) => void | ||||||
|   voiceStateUpdate: (state: VoiceState, after: VoiceState) => void |   voiceStateUpdate: (state: VoiceState, after: VoiceState) => void | ||||||
|  |   presenceUpdate: (presence: Presence) => void | ||||||
|   webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void |   webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,16 @@ | ||||||
|  | import { PresenceUpdatePayload } from '../../types/gateway.ts' | ||||||
| import { Gateway, GatewayEventHandler } from '../index.ts' | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
| 
 | 
 | ||||||
| export const presenceUpdate: GatewayEventHandler = async ( | export const presenceUpdate: GatewayEventHandler = async ( | ||||||
|   gateway: Gateway, |   gateway: Gateway, | ||||||
|   d: any |   d: PresenceUpdatePayload | ||||||
| ) => {} | ) => { | ||||||
|  |   const guild = await gateway.client.guilds.get(d.guild_id) | ||||||
|  |   if (guild === undefined) return | ||||||
|  | 
 | ||||||
|  |   await guild.presences.set(d.user.id, d) | ||||||
|  |   const presence = await guild.presences.get(d.user.id) | ||||||
|  |   if (presence === undefined) return | ||||||
|  | 
 | ||||||
|  |   gateway.client.emit('presenceUpdate', presence) | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										39
									
								
								src/managers/presences.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/managers/presences.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | ||||||
|  | import { Client } from '../models/client.ts' | ||||||
|  | import { Guild } from '../structures/guild.ts' | ||||||
|  | import { Presence } from '../structures/presence.ts' | ||||||
|  | import { User } from '../structures/user.ts' | ||||||
|  | import { PresenceUpdatePayload } from '../types/gateway.ts' | ||||||
|  | import { BaseManager } from './base.ts' | ||||||
|  | 
 | ||||||
|  | export class GuildPresencesManager extends BaseManager< | ||||||
|  |   PresenceUpdatePayload, | ||||||
|  |   Presence | ||||||
|  | > { | ||||||
|  |   guild: Guild | ||||||
|  | 
 | ||||||
|  |   constructor(client: Client, guild: Guild) { | ||||||
|  |     super(client, `presences:${guild.id}`, Presence) | ||||||
|  |     this.guild = guild | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async get(id: string): Promise<Presence | undefined> { | ||||||
|  |     const raw = await this._get(id) | ||||||
|  |     if (raw === undefined) return | ||||||
|  |     let user = await this.client.users.get(raw.user.id) | ||||||
|  |     if (user === undefined) user = new User(this.client, raw.user) | ||||||
|  |     const guild = await this.client.guilds.get(raw.guild_id) | ||||||
|  |     if (guild === undefined) return | ||||||
|  |     const presence = new Presence(this.client, raw, user, guild) | ||||||
|  |     return presence | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async fromPayload( | ||||||
|  |     data: PresenceUpdatePayload[] | ||||||
|  |   ): Promise<GuildPresencesManager> { | ||||||
|  |     await this.flush() | ||||||
|  |     for (const pres of data) { | ||||||
|  |       await this.set(pres.user.id, pres) | ||||||
|  |     } | ||||||
|  |     return this | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -7,7 +7,6 @@ import { | ||||||
|   IntegrationAccountPayload, |   IntegrationAccountPayload, | ||||||
|   IntegrationExpireBehavior, |   IntegrationExpireBehavior, | ||||||
| } from '../types/guild.ts' | } from '../types/guild.ts' | ||||||
| import { PresenceUpdatePayload } from '../types/gateway.ts' |  | ||||||
| import { Base } from './base.ts' | import { Base } from './base.ts' | ||||||
| import { RolesManager } from '../managers/roles.ts' | import { RolesManager } from '../managers/roles.ts' | ||||||
| import { InviteManager } from '../managers/invites.ts' | import { InviteManager } from '../managers/invites.ts' | ||||||
|  | @ -21,6 +20,7 @@ import { Application } from './application.ts' | ||||||
| import { GUILD_BAN, GUILD_BANS, GUILD_INTEGRATIONS } from '../types/endpoint.ts' | import { GUILD_BAN, GUILD_BANS, GUILD_INTEGRATIONS } from '../types/endpoint.ts' | ||||||
| import { GuildVoiceStatesManager } from '../managers/guildVoiceStates.ts' | import { GuildVoiceStatesManager } from '../managers/guildVoiceStates.ts' | ||||||
| import { RequestMembersOptions } from '../gateway/index.ts' | import { RequestMembersOptions } from '../gateway/index.ts' | ||||||
|  | import { GuildPresencesManager } from '../managers/presences.ts' | ||||||
| 
 | 
 | ||||||
| export class GuildBan extends Base { | export class GuildBan extends Base { | ||||||
|   guild: Guild |   guild: Guild | ||||||
|  | @ -147,7 +147,7 @@ export class Guild extends Base { | ||||||
|   voiceStates: GuildVoiceStatesManager |   voiceStates: GuildVoiceStatesManager | ||||||
|   members: MembersManager |   members: MembersManager | ||||||
|   channels: GuildChannelsManager |   channels: GuildChannelsManager | ||||||
|   presences?: PresenceUpdatePayload[] |   presences: GuildPresencesManager | ||||||
|   maxPresences?: number |   maxPresences?: number | ||||||
|   maxMembers?: number |   maxMembers?: number | ||||||
|   vanityURLCode?: string |   vanityURLCode?: string | ||||||
|  | @ -169,6 +169,7 @@ export class Guild extends Base { | ||||||
|     this.unavailable = data.unavailable |     this.unavailable = data.unavailable | ||||||
|     this.members = new MembersManager(this.client, this) |     this.members = new MembersManager(this.client, this) | ||||||
|     this.voiceStates = new GuildVoiceStatesManager(client, this) |     this.voiceStates = new GuildVoiceStatesManager(client, this) | ||||||
|  |     this.presences = new GuildPresencesManager(client, this) | ||||||
|     this.channels = new GuildChannelsManager( |     this.channels = new GuildChannelsManager( | ||||||
|       this.client, |       this.client, | ||||||
|       this.client.channels, |       this.client.channels, | ||||||
|  | @ -203,7 +204,6 @@ export class Guild extends Base { | ||||||
|       this.joinedAt = data.joined_at |       this.joinedAt = data.joined_at | ||||||
|       this.large = data.large |       this.large = data.large | ||||||
|       this.memberCount = data.member_count |       this.memberCount = data.member_count | ||||||
|       this.presences = data.presences |  | ||||||
|       this.maxPresences = data.max_presences |       this.maxPresences = data.max_presences | ||||||
|       this.maxMembers = data.max_members |       this.maxMembers = data.max_members | ||||||
|       this.vanityURLCode = data.vanity_url_code |       this.vanityURLCode = data.vanity_url_code | ||||||
|  | @ -252,7 +252,6 @@ export class Guild extends Base { | ||||||
|       this.joinedAt = data.joined_at ?? this.joinedAt |       this.joinedAt = data.joined_at ?? this.joinedAt | ||||||
|       this.large = data.large ?? this.large |       this.large = data.large ?? this.large | ||||||
|       this.memberCount = data.member_count ?? this.memberCount |       this.memberCount = data.member_count ?? this.memberCount | ||||||
|       this.presences = data.presences ?? this.presences |  | ||||||
|       this.maxPresences = data.max_presences ?? this.maxPresences |       this.maxPresences = data.max_presences ?? this.maxPresences | ||||||
|       this.maxMembers = data.max_members ?? this.maxMembers |       this.maxMembers = data.max_members ?? this.maxMembers | ||||||
|       this.vanityURLCode = data.vanity_url_code ?? this.vanityURLCode |       this.vanityURLCode = data.vanity_url_code ?? this.vanityURLCode | ||||||
|  |  | ||||||
|  | @ -1,5 +1,15 @@ | ||||||
| import { ActivityGame, ClientActivity, StatusType } from '../types/presence.ts' | import { | ||||||
| import { StatusUpdatePayload } from '../types/gateway.ts' |   ActivityGame, | ||||||
|  |   ActivityPayload, | ||||||
|  |   ClientActivity, | ||||||
|  |   ClientStatus, | ||||||
|  |   StatusType, | ||||||
|  | } from '../types/presence.ts' | ||||||
|  | import { PresenceUpdatePayload, StatusUpdatePayload } from '../types/gateway.ts' | ||||||
|  | import { Base } from './base.ts' | ||||||
|  | import { Guild } from './guild.ts' | ||||||
|  | import { User } from './user.ts' | ||||||
|  | import { Client } from '../models/client.ts' | ||||||
| 
 | 
 | ||||||
| enum ActivityTypes { | enum ActivityTypes { | ||||||
|   PLAYING = 0, |   PLAYING = 0, | ||||||
|  | @ -7,7 +17,37 @@ enum ActivityTypes { | ||||||
|   LISTENING = 2, |   LISTENING = 2, | ||||||
|   WATCHING = 3, |   WATCHING = 3, | ||||||
|   CUSTOM_STATUS = 4, |   CUSTOM_STATUS = 4, | ||||||
|   COMPETING = 5 |   COMPETING = 5, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class Presence extends Base { | ||||||
|  |   user: User | ||||||
|  |   guild: Guild | ||||||
|  |   status: StatusType | ||||||
|  |   // TODO: Maybe a new structure for this?
 | ||||||
|  |   activities: ActivityPayload[] | ||||||
|  |   clientStatus: ClientStatus | ||||||
|  | 
 | ||||||
|  |   constructor( | ||||||
|  |     client: Client, | ||||||
|  |     data: PresenceUpdatePayload, | ||||||
|  |     user: User, | ||||||
|  |     guild: Guild | ||||||
|  |   ) { | ||||||
|  |     super(client, data) | ||||||
|  |     this.user = user | ||||||
|  |     this.guild = guild | ||||||
|  |     this.status = data.status | ||||||
|  |     this.activities = data.activities | ||||||
|  |     this.clientStatus = data.client_status | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   fromPayload(data: PresenceUpdatePayload): Presence { | ||||||
|  |     this.status = data.status | ||||||
|  |     this.activities = data.activities | ||||||
|  |     this.clientStatus = data.client_status | ||||||
|  |     return this | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export class ClientPresence { | export class ClientPresence { | ||||||
|  | @ -16,7 +56,7 @@ export class ClientPresence { | ||||||
|   since?: number | null |   since?: number | null | ||||||
|   afk?: boolean |   afk?: boolean | ||||||
| 
 | 
 | ||||||
|   constructor (data?: ClientActivity | StatusUpdatePayload | ActivityGame) { |   constructor(data?: ClientActivity | StatusUpdatePayload | ActivityGame) { | ||||||
|     if (data !== undefined) { |     if (data !== undefined) { | ||||||
|       if ((data as ClientActivity).activity !== undefined) { |       if ((data as ClientActivity).activity !== undefined) { | ||||||
|         Object.assign(this, data) |         Object.assign(this, data) | ||||||
|  | @ -31,7 +71,7 @@ export class ClientPresence { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   parse (payload: StatusUpdatePayload): ClientPresence { |   parse(payload: StatusUpdatePayload): ClientPresence { | ||||||
|     this.afk = payload.afk |     this.afk = payload.afk | ||||||
|     this.activity = payload.activities ?? undefined |     this.activity = payload.activities ?? undefined | ||||||
|     this.since = payload.since |     this.since = payload.since | ||||||
|  | @ -39,20 +79,20 @@ export class ClientPresence { | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static parse (payload: StatusUpdatePayload): ClientPresence { |   static parse(payload: StatusUpdatePayload): ClientPresence { | ||||||
|     return new ClientPresence().parse(payload) |     return new ClientPresence().parse(payload) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   create (): StatusUpdatePayload { |   create(): StatusUpdatePayload { | ||||||
|     return { |     return { | ||||||
|       afk: this.afk === undefined ? false : this.afk, |       afk: this.afk === undefined ? false : this.afk, | ||||||
|       activities: this.createActivity(), |       activities: this.createActivity(), | ||||||
|       since: this.since === undefined ? null : this.since, |       since: this.since === undefined ? null : this.since, | ||||||
|       status: this.status === undefined ? 'online' : this.status |       status: this.status === undefined ? 'online' : this.status, | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   createActivity (): ActivityGame[] | null { |   createActivity(): ActivityGame[] | null { | ||||||
|     // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
 |     // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
 | ||||||
|     const activity = |     const activity = | ||||||
|       this.activity === undefined |       this.activity === undefined | ||||||
|  | @ -62,7 +102,7 @@ export class ClientPresence { | ||||||
|         : [this.activity] |         : [this.activity] | ||||||
|     if (activity === null) return activity |     if (activity === null) return activity | ||||||
|     else { |     else { | ||||||
|       activity.map(e => { |       activity.map((e) => { | ||||||
|         if (typeof e.type === 'string') e.type = ActivityTypes[e.type] |         if (typeof e.type === 'string') e.type = ActivityTypes[e.type] | ||||||
|         return e |         return e | ||||||
|       }) |       }) | ||||||
|  | @ -70,37 +110,37 @@ export class ClientPresence { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setStatus (status: StatusType): ClientPresence { |   setStatus(status: StatusType): ClientPresence { | ||||||
|     this.status = status |     this.status = status | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setActivity (activity: ActivityGame): ClientPresence { |   setActivity(activity: ActivityGame): ClientPresence { | ||||||
|     this.activity = activity |     this.activity = activity | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setActivities (activities: ActivityGame[]): ClientPresence { |   setActivities(activities: ActivityGame[]): ClientPresence { | ||||||
|     this.activity = activities |     this.activity = activities | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setAFK (afk: boolean): ClientPresence { |   setAFK(afk: boolean): ClientPresence { | ||||||
|     this.afk = afk |     this.afk = afk | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   removeAFK (): ClientPresence { |   removeAFK(): ClientPresence { | ||||||
|     this.afk = false |     this.afk = false | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   toggleAFK (): ClientPresence { |   toggleAFK(): ClientPresence { | ||||||
|     this.afk = this.afk === undefined ? true : !this.afk |     this.afk = this.afk === undefined ? true : !this.afk | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   setSince (since?: number): ClientPresence { |   setSince(since?: number): ClientPresence { | ||||||
|     this.since = since |     this.since = since | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -56,7 +56,7 @@ export enum ActivityFlags { | ||||||
|   SPECTATE = 1 << 2, |   SPECTATE = 1 << 2, | ||||||
|   JOIN_REQUEST = 1 << 3, |   JOIN_REQUEST = 1 << 3, | ||||||
|   SYNC = 1 << 4, |   SYNC = 1 << 4, | ||||||
|   PLAY = 1 << 5 |   PLAY = 1 << 5, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export type ActivityType = | export type ActivityType = | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue