feat(presence): added caching and last gateway event!

This commit is contained in:
DjDeveloperr 2020-12-02 16:38:10 +05:30
parent 484c6e3c7b
commit fb110946e0
9 changed files with 124 additions and 25 deletions

View File

@ -22,6 +22,8 @@ export const guildCreate: GatewayEventHandler = async (
await guild.roles.fromPayload(d.roles)
if (d.presences !== undefined) await guild.presences.fromPayload(d.presences)
if (d.voice_states !== undefined)
await guild.voiceStates.fromPayload(d.voice_states)

View File

@ -14,6 +14,7 @@ export const guildDelte: GatewayEventHandler = async (
await guild.members.flush()
await guild.channels.flush()
await guild.roles.flush()
await guild.presences.flush()
await gateway.client.guilds.delete(d.id)
gateway.client.emit('guildDelete', guild)

View File

@ -14,7 +14,13 @@ export const guildMembersChunk: GatewayEventHandler = async (
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, {
members: d.members.map((m) => m.user.id),

View File

@ -49,6 +49,7 @@ import { inviteCreate } from './inviteCreate.ts'
import { inviteDelete } from './inviteDelete.ts'
import { MessageReaction } from '../../structures/messageReaction.ts'
import { Invite } from '../../structures/invite.ts'
import { Presence } from '../../structures/presence.ts'
export const gatewayHandlers: {
[eventCode in GatewayEvents]: GatewayEventHandler | undefined
@ -150,5 +151,6 @@ export interface ClientEvents extends EventTypes {
voiceStateAdd: (state: VoiceState) => void
voiceStateRemove: (state: VoiceState) => void
voiceStateUpdate: (state: VoiceState, after: VoiceState) => void
presenceUpdate: (presence: Presence) => void
webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void
}

View File

@ -1,6 +1,16 @@
import { PresenceUpdatePayload } from '../../types/gateway.ts'
import { Gateway, GatewayEventHandler } from '../index.ts'
export const presenceUpdate: GatewayEventHandler = async (
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
View 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
}
}

View File

@ -7,7 +7,6 @@ import {
IntegrationAccountPayload,
IntegrationExpireBehavior,
} from '../types/guild.ts'
import { PresenceUpdatePayload } from '../types/gateway.ts'
import { Base } from './base.ts'
import { RolesManager } from '../managers/roles.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 { GuildVoiceStatesManager } from '../managers/guildVoiceStates.ts'
import { RequestMembersOptions } from '../gateway/index.ts'
import { GuildPresencesManager } from '../managers/presences.ts'
export class GuildBan extends Base {
guild: Guild
@ -147,7 +147,7 @@ export class Guild extends Base {
voiceStates: GuildVoiceStatesManager
members: MembersManager
channels: GuildChannelsManager
presences?: PresenceUpdatePayload[]
presences: GuildPresencesManager
maxPresences?: number
maxMembers?: number
vanityURLCode?: string
@ -169,6 +169,7 @@ export class Guild extends Base {
this.unavailable = data.unavailable
this.members = new MembersManager(this.client, this)
this.voiceStates = new GuildVoiceStatesManager(client, this)
this.presences = new GuildPresencesManager(client, this)
this.channels = new GuildChannelsManager(
this.client,
this.client.channels,
@ -203,7 +204,6 @@ export class Guild extends Base {
this.joinedAt = data.joined_at
this.large = data.large
this.memberCount = data.member_count
this.presences = data.presences
this.maxPresences = data.max_presences
this.maxMembers = data.max_members
this.vanityURLCode = data.vanity_url_code
@ -252,7 +252,6 @@ export class Guild extends Base {
this.joinedAt = data.joined_at ?? this.joinedAt
this.large = data.large ?? this.large
this.memberCount = data.member_count ?? this.memberCount
this.presences = data.presences ?? this.presences
this.maxPresences = data.max_presences ?? this.maxPresences
this.maxMembers = data.max_members ?? this.maxMembers
this.vanityURLCode = data.vanity_url_code ?? this.vanityURLCode

View File

@ -1,5 +1,15 @@
import { ActivityGame, ClientActivity, StatusType } from '../types/presence.ts'
import { StatusUpdatePayload } from '../types/gateway.ts'
import {
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 {
PLAYING = 0,
@ -7,7 +17,37 @@ enum ActivityTypes {
LISTENING = 2,
WATCHING = 3,
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 {
@ -16,7 +56,7 @@ export class ClientPresence {
since?: number | null
afk?: boolean
constructor (data?: ClientActivity | StatusUpdatePayload | ActivityGame) {
constructor(data?: ClientActivity | StatusUpdatePayload | ActivityGame) {
if (data !== undefined) {
if ((data as ClientActivity).activity !== undefined) {
Object.assign(this, data)
@ -31,7 +71,7 @@ export class ClientPresence {
}
}
parse (payload: StatusUpdatePayload): ClientPresence {
parse(payload: StatusUpdatePayload): ClientPresence {
this.afk = payload.afk
this.activity = payload.activities ?? undefined
this.since = payload.since
@ -39,20 +79,20 @@ export class ClientPresence {
return this
}
static parse (payload: StatusUpdatePayload): ClientPresence {
static parse(payload: StatusUpdatePayload): ClientPresence {
return new ClientPresence().parse(payload)
}
create (): StatusUpdatePayload {
create(): StatusUpdatePayload {
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
status: this.status === undefined ? 'online' : this.status,
}
}
createActivity (): ActivityGame[] | null {
createActivity(): ActivityGame[] | null {
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
const activity =
this.activity === undefined
@ -62,7 +102,7 @@ export class ClientPresence {
: [this.activity]
if (activity === null) return activity
else {
activity.map(e => {
activity.map((e) => {
if (typeof e.type === 'string') e.type = ActivityTypes[e.type]
return e
})
@ -70,37 +110,37 @@ export class ClientPresence {
}
}
setStatus (status: StatusType): ClientPresence {
setStatus(status: StatusType): ClientPresence {
this.status = status
return this
}
setActivity (activity: ActivityGame): ClientPresence {
setActivity(activity: ActivityGame): ClientPresence {
this.activity = activity
return this
}
setActivities (activities: ActivityGame[]): ClientPresence {
setActivities(activities: ActivityGame[]): ClientPresence {
this.activity = activities
return this
}
setAFK (afk: boolean): ClientPresence {
setAFK(afk: boolean): ClientPresence {
this.afk = afk
return this
}
removeAFK (): ClientPresence {
removeAFK(): ClientPresence {
this.afk = false
return this
}
toggleAFK (): ClientPresence {
toggleAFK(): ClientPresence {
this.afk = this.afk === undefined ? true : !this.afk
return this
}
setSince (since?: number): ClientPresence {
setSince(since?: number): ClientPresence {
this.since = since
return this
}

View File

@ -56,7 +56,7 @@ export enum ActivityFlags {
SPECTATE = 1 << 2,
JOIN_REQUEST = 1 << 3,
SYNC = 1 << 4,
PLAY = 1 << 5
PLAY = 1 << 5,
}
export type ActivityType =