feat(reactions): implemented structures and events
This commit is contained in:
parent
a7336c19e3
commit
c7ef17a6d2
13 changed files with 431 additions and 153 deletions
|
@ -39,6 +39,12 @@ import { Collection } from '../../utils/collection.ts'
|
|||
import { voiceServerUpdate } from './voiceServerUpdate.ts'
|
||||
import { voiceStateUpdate } from './voiceStateUpdate.ts'
|
||||
import { VoiceState } from '../../structures/voiceState.ts'
|
||||
import { messageReactionAdd } from './messageReactionAdd.ts'
|
||||
import { messageReactionRemove } from './messageReactionRemove.ts'
|
||||
import { messageReactionRemoveAll } from './messageReactionRemoveAll.ts'
|
||||
import { messageReactionRemoveEmoji } from './messageReactionRemoveEmoji.ts'
|
||||
import { guildMembersChunk } from './guildMembersChunk.ts'
|
||||
import { presenceUpdate } from './presenceUpdate.ts'
|
||||
|
||||
export const gatewayHandlers: {
|
||||
[eventCode in GatewayEvents]: GatewayEventHandler | undefined
|
||||
|
@ -60,7 +66,7 @@ export const gatewayHandlers: {
|
|||
GUILD_MEMBER_ADD: guildMemberAdd,
|
||||
GUILD_MEMBER_REMOVE: guildMemberRemove,
|
||||
GUILD_MEMBER_UPDATE: guildMemberUpdate,
|
||||
GUILD_MEMBERS_CHUNK: undefined,
|
||||
GUILD_MEMBERS_CHUNK: guildMembersChunk,
|
||||
GUILD_ROLE_CREATE: guildRoleCreate,
|
||||
GUILD_ROLE_UPDATE: guildRoleUpdate,
|
||||
GUILD_ROLE_DELETE: guildRoleDelete,
|
||||
|
@ -70,11 +76,11 @@ export const gatewayHandlers: {
|
|||
MESSAGE_UPDATE: messageUpdate,
|
||||
MESSAGE_DELETE: messageDelete,
|
||||
MESSAGE_DELETE_BULK: messageDeleteBulk,
|
||||
MESSAGE_REACTION_ADD: undefined,
|
||||
MESSAGE_REACTION_REMOVE: undefined,
|
||||
MESSAGE_REACTION_REMOVE_ALL: undefined,
|
||||
MESSAGE_REACTION_REMOVE_EMOJI: undefined,
|
||||
PRESENCE_UPDATE: undefined,
|
||||
MESSAGE_REACTION_ADD: messageReactionAdd,
|
||||
MESSAGE_REACTION_REMOVE: messageReactionRemove,
|
||||
MESSAGE_REACTION_REMOVE_ALL: messageReactionRemoveAll,
|
||||
MESSAGE_REACTION_REMOVE_EMOJI: messageReactionRemoveEmoji,
|
||||
PRESENCE_UPDATE: presenceUpdate,
|
||||
TYPING_START: typingStart,
|
||||
USER_UPDATE: userUpdate,
|
||||
VOICE_STATE_UPDATE: voiceStateUpdate,
|
||||
|
|
51
src/gateway/handlers/messageReactionAdd.ts
Normal file
51
src/gateway/handlers/messageReactionAdd.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { Gateway, GatewayEventHandler } from '../index.ts'
|
||||
import { MessageReactionAddPayload } from '../../types/gateway.ts'
|
||||
import { TextChannel } from '../../structures/textChannel.ts'
|
||||
import { MessageReaction } from '../../structures/messageReaction.ts'
|
||||
import { UserPayload } from '../../types/user.ts'
|
||||
|
||||
export const messageReactionAdd: GatewayEventHandler = async (
|
||||
gateway: Gateway,
|
||||
d: MessageReactionAddPayload
|
||||
) => {
|
||||
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
|
||||
if (channel === undefined)
|
||||
channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id)
|
||||
if (channel === undefined) return
|
||||
|
||||
let message = await channel.messages.get(d.message_id)
|
||||
if (message === undefined) {
|
||||
if (gateway.client.fetchUncachedReactions === true) {
|
||||
message = await channel.messages.fetch(d.message_id)
|
||||
if (message === undefined) return
|
||||
} else return
|
||||
}
|
||||
|
||||
let user = await gateway.client.users.get(d.user_id)
|
||||
if (user === undefined) {
|
||||
if (gateway.client.fetchUncachedReactions === true) {
|
||||
user = await gateway.client.users.fetch(d.user_id)
|
||||
if (user === undefined) return
|
||||
} else return
|
||||
}
|
||||
|
||||
let reaction = await message.reactions.get(d.emoji.id)
|
||||
if (reaction === undefined) {
|
||||
await message.reactions.set(d.emoji.id, {
|
||||
count: 1,
|
||||
emoji: d.emoji,
|
||||
me: d.user_id === gateway.client.user?.id,
|
||||
})
|
||||
reaction = ((await message.reactions.get(
|
||||
d.emoji.id
|
||||
)) as unknown) as MessageReaction
|
||||
}
|
||||
|
||||
const rawUser = ((await gateway.client.users.get(
|
||||
d.user_id
|
||||
)) as unknown) as UserPayload
|
||||
|
||||
reaction.users.set(rawUser.id, rawUser)
|
||||
|
||||
gateway.client.emit('messageReactionAdd', reaction, user)
|
||||
}
|
36
src/gateway/handlers/messageReactionRemove.ts
Normal file
36
src/gateway/handlers/messageReactionRemove.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { Gateway, GatewayEventHandler } from '../index.ts'
|
||||
import { MessageReactionRemovePayload } from '../../types/gateway.ts'
|
||||
import { TextChannel } from '../../structures/textChannel.ts'
|
||||
|
||||
export const messageReactionRemove: GatewayEventHandler = async (
|
||||
gateway: Gateway,
|
||||
d: MessageReactionRemovePayload
|
||||
) => {
|
||||
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
|
||||
if (channel === undefined)
|
||||
channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id)
|
||||
if (channel === undefined) return
|
||||
|
||||
let message = await channel.messages.get(d.message_id)
|
||||
if (message === undefined) {
|
||||
if (gateway.client.fetchUncachedReactions === true) {
|
||||
message = await channel.messages.fetch(d.message_id)
|
||||
if (message === undefined) return
|
||||
} else return
|
||||
}
|
||||
|
||||
let user = await gateway.client.users.get(d.user_id)
|
||||
if (user === undefined) {
|
||||
if (gateway.client.fetchUncachedReactions === true) {
|
||||
user = await gateway.client.users.fetch(d.user_id)
|
||||
if (user === undefined) return
|
||||
} else return
|
||||
}
|
||||
|
||||
const reaction = await message.reactions.get(d.emoji.id)
|
||||
if (reaction === undefined) return
|
||||
|
||||
reaction.users.delete(d.user_id)
|
||||
|
||||
gateway.client.emit('messageReactionRemove', reaction, user)
|
||||
}
|
25
src/gateway/handlers/messageReactionRemoveAll.ts
Normal file
25
src/gateway/handlers/messageReactionRemoveAll.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { Gateway, GatewayEventHandler } from '../index.ts'
|
||||
import { MessageReactionRemoveAllPayload } from '../../types/gateway.ts'
|
||||
import { TextChannel } from '../../structures/textChannel.ts'
|
||||
|
||||
export const messageReactionRemoveAll: GatewayEventHandler = async (
|
||||
gateway: Gateway,
|
||||
d: MessageReactionRemoveAllPayload
|
||||
) => {
|
||||
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
|
||||
if (channel === undefined)
|
||||
channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id)
|
||||
if (channel === undefined) return
|
||||
|
||||
let message = await channel.messages.get(d.message_id)
|
||||
if (message === undefined) {
|
||||
if (gateway.client.fetchUncachedReactions === true) {
|
||||
message = await channel.messages.fetch(d.message_id)
|
||||
if (message === undefined) return
|
||||
} else return
|
||||
}
|
||||
|
||||
await message.reactions.flush()
|
||||
|
||||
gateway.client.emit('messageReactionRemoveAll', message)
|
||||
}
|
28
src/gateway/handlers/messageReactionRemoveEmoji.ts
Normal file
28
src/gateway/handlers/messageReactionRemoveEmoji.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { Gateway, GatewayEventHandler } from '../index.ts'
|
||||
import { MessageReactionRemoveEmojiPayload } from '../../types/gateway.ts'
|
||||
import { TextChannel } from '../../structures/textChannel.ts'
|
||||
|
||||
export const messageReactionRemoveEmoji: GatewayEventHandler = async (
|
||||
gateway: Gateway,
|
||||
d: MessageReactionRemoveEmojiPayload
|
||||
) => {
|
||||
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
|
||||
if (channel === undefined)
|
||||
channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id)
|
||||
if (channel === undefined) return
|
||||
|
||||
let message = await channel.messages.get(d.message_id)
|
||||
if (message === undefined) {
|
||||
if (gateway.client.fetchUncachedReactions === true) {
|
||||
message = await channel.messages.fetch(d.message_id)
|
||||
if (message === undefined) return
|
||||
} else return
|
||||
}
|
||||
|
||||
const reaction = await message.reactions.get(d.emoji.id)
|
||||
if (reaction === undefined) return
|
||||
|
||||
await reaction.users.flush()
|
||||
|
||||
gateway.client.emit('messageReactionRemoveEmoji', message, reaction.emoji)
|
||||
}
|
6
src/gateway/handlers/presenceUpdate.ts
Normal file
6
src/gateway/handlers/presenceUpdate.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { Gateway, GatewayEventHandler } from '../index.ts'
|
||||
|
||||
export const presenceUpdate: GatewayEventHandler = async (
|
||||
gateway: Gateway,
|
||||
d: any
|
||||
) => {}
|
44
src/managers/messageReactions.ts
Normal file
44
src/managers/messageReactions.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
import { Client } from '../models/client.ts'
|
||||
import { Emoji } from '../structures/emoji.ts'
|
||||
import { Guild } from '../structures/guild.ts'
|
||||
import { Message } from '../structures/message.ts'
|
||||
import { MessageReaction } from '../structures/messageReaction.ts'
|
||||
import { Reaction } from '../types/channel.ts'
|
||||
import { BaseManager } from './base.ts'
|
||||
|
||||
export class MessageReactionsManager extends BaseManager<
|
||||
Reaction,
|
||||
MessageReaction
|
||||
> {
|
||||
message: Message
|
||||
|
||||
constructor(client: Client, message: Message) {
|
||||
super(client, `reactions:${message.id}`, Guild)
|
||||
this.message = message
|
||||
}
|
||||
|
||||
async get(id: string): Promise<MessageReaction | undefined> {
|
||||
const raw = await this._get(id)
|
||||
if (raw === undefined) return
|
||||
|
||||
let emoji = await this.client.emojis.get(raw.emoji.id)
|
||||
if (emoji === undefined) emoji = new Emoji(this.client, raw.emoji)
|
||||
|
||||
const reaction = new MessageReaction(this.client, raw, this.message, emoji)
|
||||
return reaction
|
||||
}
|
||||
|
||||
async set(key: string, value: Reaction): Promise<any> {
|
||||
return this.client.cache.set(
|
||||
this.cacheName,
|
||||
key,
|
||||
value,
|
||||
this.client.reactionCacheLifetime
|
||||
)
|
||||
}
|
||||
|
||||
async flush(): Promise<any> {
|
||||
await this.client.cache.deleteCache(`reaction_users:${this.message.id}`)
|
||||
return this.client.cache.deleteCache(this.cacheName)
|
||||
}
|
||||
}
|
13
src/managers/reactionUsers.ts
Normal file
13
src/managers/reactionUsers.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { Client } from '../models/client.ts'
|
||||
import { MessageReaction } from '../structures/messageReaction.ts'
|
||||
import { UserManager } from './users.ts'
|
||||
|
||||
export class ReactionUsersManager extends UserManager {
|
||||
reaction: MessageReaction
|
||||
|
||||
constructor(client: Client, reaction: MessageReaction) {
|
||||
super(client)
|
||||
this.cacheName = `reaction_users:${reaction.message.id}`
|
||||
this.reaction = reaction
|
||||
}
|
||||
}
|
|
@ -7,12 +7,10 @@ import { DefaultCacheAdapter, ICacheAdapter } from './cacheAdapter.ts'
|
|||
import { UserManager } from '../managers/users.ts'
|
||||
import { GuildManager } from '../managers/guilds.ts'
|
||||
import { ChannelsManager } from '../managers/channels.ts'
|
||||
import {
|
||||
ClientPresence
|
||||
} from '../structures/presence.ts'
|
||||
import { ClientPresence } from '../structures/presence.ts'
|
||||
import { EmojisManager } from '../managers/emojis.ts'
|
||||
import { ActivityGame, ClientActivity } from "../types/presence.ts"
|
||||
import { ClientEvents } from "../gateway/handlers/index.ts"
|
||||
import { ActivityGame, ClientActivity } from '../types/presence.ts'
|
||||
import { ClientEvents } from '../gateway/handlers/index.ts'
|
||||
// import { Application } from "../../mod.ts"
|
||||
|
||||
/** Some Client Options to modify behaviour */
|
||||
|
@ -22,9 +20,9 @@ export interface ClientOptions {
|
|||
/** Gateway Intents */
|
||||
intents?: GatewayIntents[]
|
||||
/** Cache Adapter to use, defaults to Collections one */
|
||||
cache?: ICacheAdapter,
|
||||
cache?: ICacheAdapter
|
||||
/** Force New Session and don't use cached Session (by persistent caching) */
|
||||
forceNewSession?: boolean,
|
||||
forceNewSession?: boolean
|
||||
/** Startup presence of client */
|
||||
presence?: ClientPresence | ClientActivity | ActivityGame
|
||||
/** Whether it's a bot user or not? Use this if selfbot! */
|
||||
|
@ -33,19 +31,21 @@ export interface ClientOptions {
|
|||
canary?: boolean
|
||||
/** Time till which Messages are to be cached, in MS. Default is 3600000 */
|
||||
messageCacheLifetime?: number
|
||||
/** Time till which Message Reactions are to be cached, in MS. Default is 3600000 */
|
||||
reactionCacheLifetime?: number
|
||||
/** Whether to fetch Uncached Message of Reaction or not? */
|
||||
fetchUncachedReactions?: boolean
|
||||
}
|
||||
|
||||
export declare interface Client {
|
||||
on: <U extends string>(
|
||||
event: U, listener: ClientEvents[U]
|
||||
) => this
|
||||
on: <U extends string>(event: U, listener: ClientEvents[U]) => this
|
||||
|
||||
emit: <U extends string>(
|
||||
event: U, ...args: Parameters<ClientEvents[U]>
|
||||
event: U,
|
||||
...args: Parameters<ClientEvents[U]>
|
||||
) => boolean
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Discord Client.
|
||||
*/
|
||||
|
@ -68,12 +68,16 @@ export class Client extends EventEmitter {
|
|||
forceNewSession?: boolean
|
||||
/** Time till messages to stay cached, in MS. */
|
||||
messageCacheLifetime: number = 3600000
|
||||
/** Time till messages to stay cached, in MS. */
|
||||
reactionCacheLifetime: number = 3600000
|
||||
/** Whether to fetch Uncached Message of Reaction or not? */
|
||||
fetchUncachedReactions: boolean = false
|
||||
|
||||
users: UserManager = new UserManager(this)
|
||||
guilds: GuildManager = new GuildManager(this)
|
||||
channels: ChannelsManager = new ChannelsManager(this)
|
||||
emojis: EmojisManager = new EmojisManager(this)
|
||||
|
||||
|
||||
/** Whether this client will login as bot user or not */
|
||||
bot: boolean = true
|
||||
/** Whether the REST Manager will use Canary API or not */
|
||||
|
@ -81,7 +85,7 @@ export class Client extends EventEmitter {
|
|||
/** Client's presence. Startup one if set before connecting */
|
||||
presence: ClientPresence = new ClientPresence()
|
||||
|
||||
constructor (options: ClientOptions = {}) {
|
||||
constructor(options: ClientOptions = {}) {
|
||||
super()
|
||||
this.token = options.token
|
||||
this.intents = options.intents
|
||||
|
@ -94,17 +98,22 @@ export class Client extends EventEmitter {
|
|||
: new ClientPresence(options.presence)
|
||||
if (options.bot === false) this.bot = false
|
||||
if (options.canary === true) this.canary = true
|
||||
if (options.messageCacheLifetime !== undefined) this.messageCacheLifetime = options.messageCacheLifetime
|
||||
if (options.messageCacheLifetime !== undefined)
|
||||
this.messageCacheLifetime = options.messageCacheLifetime
|
||||
if (options.reactionCacheLifetime !== undefined)
|
||||
this.reactionCacheLifetime = options.reactionCacheLifetime
|
||||
if (options.fetchUncachedReactions === true)
|
||||
this.fetchUncachedReactions = true
|
||||
}
|
||||
|
||||
/** Set Cache Adapter */
|
||||
setAdapter (adapter: ICacheAdapter): Client {
|
||||
setAdapter(adapter: ICacheAdapter): Client {
|
||||
this.cache = adapter
|
||||
return this
|
||||
}
|
||||
|
||||
/** Change Presence of Client */
|
||||
setPresence (presence: ClientPresence | ClientActivity | ActivityGame): void {
|
||||
setPresence(presence: ClientPresence | ClientActivity | ActivityGame): void {
|
||||
if (presence instanceof ClientPresence) {
|
||||
this.presence = presence
|
||||
} else this.presence = new ClientPresence(presence)
|
||||
|
@ -112,7 +121,7 @@ export class Client extends EventEmitter {
|
|||
}
|
||||
|
||||
/** Emit debug event */
|
||||
debug (tag: string, msg: string): void {
|
||||
debug(tag: string, msg: string): void {
|
||||
this.emit('debug', `[${tag}] ${msg}`)
|
||||
}
|
||||
|
||||
|
@ -124,7 +133,7 @@ export class Client extends EventEmitter {
|
|||
* @param token Your token. This is required.
|
||||
* @param intents Gateway intents in array. This is required.
|
||||
*/
|
||||
connect (token?: string, intents?: GatewayIntents[]): void {
|
||||
connect(token?: string, intents?: GatewayIntents[]): void {
|
||||
if (token === undefined && this.token !== undefined) token = this.token
|
||||
else if (this.token === undefined && token !== undefined) {
|
||||
this.token = token
|
||||
|
|
|
@ -1,120 +1,129 @@
|
|||
import { Base } from './base.ts'
|
||||
import {
|
||||
Attachment,
|
||||
ChannelMention,
|
||||
MessageActivity,
|
||||
MessageApplication,
|
||||
MessageOption,
|
||||
MessagePayload,
|
||||
MessageReference,
|
||||
Reaction
|
||||
} from '../types/channel.ts'
|
||||
import { Client } from '../models/client.ts'
|
||||
import { User } from './user.ts'
|
||||
import { Member } from './member.ts'
|
||||
import { Embed } from './embed.ts'
|
||||
import { CHANNEL_MESSAGE } from '../types/endpoint.ts'
|
||||
import { MessageMentions } from './messageMentions.ts'
|
||||
import { TextChannel } from './textChannel.ts'
|
||||
import { Guild } from './guild.ts'
|
||||
|
||||
type AllMessageOptions = MessageOption | Embed
|
||||
|
||||
export class Message extends Base {
|
||||
id: string
|
||||
channelID: string
|
||||
channel: TextChannel
|
||||
guildID?: string
|
||||
guild?: Guild
|
||||
author: User
|
||||
member?: Member
|
||||
content: string
|
||||
timestamp: string
|
||||
editedTimestamp?: string
|
||||
tts: boolean
|
||||
mentionEveryone: boolean
|
||||
mentions: MessageMentions
|
||||
mentionRoles: string[]
|
||||
mentionChannels?: ChannelMention[]
|
||||
attachments: Attachment[]
|
||||
embeds: Embed[]
|
||||
reactions?: Reaction[]
|
||||
nonce?: string | number
|
||||
pinned: boolean
|
||||
webhookID?: string
|
||||
type: number
|
||||
activity?: MessageActivity
|
||||
application?: MessageApplication
|
||||
messageReference?: MessageReference
|
||||
flags?: number
|
||||
|
||||
constructor (
|
||||
client: Client,
|
||||
data: MessagePayload,
|
||||
channel: TextChannel,
|
||||
author: User
|
||||
) {
|
||||
super(client)
|
||||
this.id = data.id
|
||||
this.channelID = data.channel_id
|
||||
this.guildID = data.guild_id
|
||||
this.author = author
|
||||
this.content = data.content
|
||||
this.timestamp = data.timestamp
|
||||
this.editedTimestamp = data.edited_timestamp
|
||||
this.tts = data.tts
|
||||
this.mentionEveryone = data.mention_everyone
|
||||
this.mentions = new MessageMentions(this.client, this)
|
||||
this.mentionRoles = data.mention_roles
|
||||
this.mentionChannels = data.mention_channels
|
||||
this.attachments = data.attachments
|
||||
this.embeds = data.embeds.map(v => new Embed(v))
|
||||
this.reactions = data.reactions
|
||||
this.nonce = data.nonce
|
||||
this.pinned = data.pinned
|
||||
this.webhookID = data.webhook_id
|
||||
this.type = data.type
|
||||
this.activity = data.activity
|
||||
this.application = data.application
|
||||
this.messageReference = data.message_reference
|
||||
this.flags = data.flags
|
||||
this.channel = channel
|
||||
}
|
||||
|
||||
protected readFromData (data: MessagePayload): void {
|
||||
super.readFromData(data)
|
||||
this.channelID = data.channel_id ?? this.channelID
|
||||
this.guildID = data.guild_id ?? this.guildID
|
||||
this.content = data.content ?? this.content
|
||||
this.timestamp = data.timestamp ?? this.timestamp
|
||||
this.editedTimestamp = data.edited_timestamp ?? this.editedTimestamp
|
||||
this.tts = data.tts ?? this.tts
|
||||
this.mentionEveryone = data.mention_everyone ?? this.mentionEveryone
|
||||
this.mentionRoles = data.mention_roles ?? this.mentionRoles
|
||||
this.mentionChannels = data.mention_channels ?? this.mentionChannels
|
||||
this.attachments = data.attachments ?? this.attachments
|
||||
this.embeds = data.embeds.map(v => new Embed(v)) ?? this.embeds
|
||||
this.reactions = data.reactions ?? this.reactions
|
||||
this.nonce = data.nonce ?? this.nonce
|
||||
this.pinned = data.pinned ?? this.pinned
|
||||
this.webhookID = data.webhook_id ?? this.webhookID
|
||||
this.type = data.type ?? this.type
|
||||
this.activity = data.activity ?? this.activity
|
||||
this.application = data.application ?? this.application
|
||||
this.messageReference = data.message_reference ?? this.messageReference
|
||||
this.flags = data.flags ?? this.flags
|
||||
}
|
||||
|
||||
async edit (text?: string, option?: MessageOption): Promise<Message> {
|
||||
return this.channel.editMessage(this.id, text, option)
|
||||
}
|
||||
|
||||
/** These will **not** work in all servers, as this feature is coming slowly. */
|
||||
async reply(text?: string | AllMessageOptions, option?: AllMessageOptions): Promise<Message> {
|
||||
return this.channel.send(text, option, this)
|
||||
}
|
||||
|
||||
async delete (): Promise<void> {
|
||||
return this.client.rest.delete(CHANNEL_MESSAGE(this.channelID, this.id))
|
||||
}
|
||||
}
|
||||
import { Base } from './base.ts'
|
||||
import {
|
||||
Attachment,
|
||||
ChannelMention,
|
||||
MessageActivity,
|
||||
MessageApplication,
|
||||
MessageOption,
|
||||
MessagePayload,
|
||||
MessageReference,
|
||||
} from '../types/channel.ts'
|
||||
import { Client } from '../models/client.ts'
|
||||
import { User } from './user.ts'
|
||||
import { Member } from './member.ts'
|
||||
import { Embed } from './embed.ts'
|
||||
import { CHANNEL_MESSAGE } from '../types/endpoint.ts'
|
||||
import { MessageMentions } from './messageMentions.ts'
|
||||
import { TextChannel } from './textChannel.ts'
|
||||
import { Guild } from './guild.ts'
|
||||
import { MessageReactionsManager } from '../managers/messageReactions.ts'
|
||||
|
||||
type AllMessageOptions = MessageOption | Embed
|
||||
|
||||
export class Message extends Base {
|
||||
id: string
|
||||
channelID: string
|
||||
channel: TextChannel
|
||||
guildID?: string
|
||||
guild?: Guild
|
||||
author: User
|
||||
member?: Member
|
||||
content: string
|
||||
timestamp: string
|
||||
editedTimestamp?: string
|
||||
tts: boolean
|
||||
mentionEveryone: boolean
|
||||
mentions: MessageMentions
|
||||
mentionRoles: string[]
|
||||
mentionChannels?: ChannelMention[]
|
||||
attachments: Attachment[]
|
||||
embeds: Embed[]
|
||||
reactions: MessageReactionsManager
|
||||
nonce?: string | number
|
||||
pinned: boolean
|
||||
webhookID?: string
|
||||
type: number
|
||||
activity?: MessageActivity
|
||||
application?: MessageApplication
|
||||
messageReference?: MessageReference
|
||||
flags?: number
|
||||
|
||||
constructor(
|
||||
client: Client,
|
||||
data: MessagePayload,
|
||||
channel: TextChannel,
|
||||
author: User
|
||||
) {
|
||||
super(client)
|
||||
this.id = data.id
|
||||
this.channelID = data.channel_id
|
||||
this.guildID = data.guild_id
|
||||
this.author = author
|
||||
this.content = data.content
|
||||
this.timestamp = data.timestamp
|
||||
this.editedTimestamp = data.edited_timestamp
|
||||
this.tts = data.tts
|
||||
this.mentionEveryone = data.mention_everyone
|
||||
this.mentions = new MessageMentions(this.client, this)
|
||||
this.mentionRoles = data.mention_roles
|
||||
this.mentionChannels = data.mention_channels
|
||||
this.attachments = data.attachments
|
||||
this.embeds = data.embeds.map((v) => new Embed(v))
|
||||
this.reactions = new MessageReactionsManager(this.client, this)
|
||||
this.nonce = data.nonce
|
||||
this.pinned = data.pinned
|
||||
this.webhookID = data.webhook_id
|
||||
this.type = data.type
|
||||
this.activity = data.activity
|
||||
this.application = data.application
|
||||
this.messageReference = data.message_reference
|
||||
this.flags = data.flags
|
||||
this.channel = channel
|
||||
}
|
||||
|
||||
protected readFromData(data: MessagePayload): void {
|
||||
super.readFromData(data)
|
||||
this.channelID = data.channel_id ?? this.channelID
|
||||
this.guildID = data.guild_id ?? this.guildID
|
||||
this.content = data.content ?? this.content
|
||||
this.timestamp = data.timestamp ?? this.timestamp
|
||||
this.editedTimestamp = data.edited_timestamp ?? this.editedTimestamp
|
||||
this.tts = data.tts ?? this.tts
|
||||
this.mentionEveryone = data.mention_everyone ?? this.mentionEveryone
|
||||
this.mentionRoles = data.mention_roles ?? this.mentionRoles
|
||||
this.mentionChannels = data.mention_channels ?? this.mentionChannels
|
||||
this.attachments = data.attachments ?? this.attachments
|
||||
this.embeds = data.embeds.map((v) => new Embed(v)) ?? this.embeds
|
||||
this.nonce = data.nonce ?? this.nonce
|
||||
this.pinned = data.pinned ?? this.pinned
|
||||
this.webhookID = data.webhook_id ?? this.webhookID
|
||||
this.type = data.type ?? this.type
|
||||
this.activity = data.activity ?? this.activity
|
||||
this.application = data.application ?? this.application
|
||||
this.messageReference = data.message_reference ?? this.messageReference
|
||||
this.flags = data.flags ?? this.flags
|
||||
}
|
||||
|
||||
/** Edit this message. */
|
||||
async edit(text?: string, option?: MessageOption): Promise<Message> {
|
||||
if (
|
||||
this.client.user !== undefined &&
|
||||
this.author.id !== this.client.user?.id
|
||||
)
|
||||
throw new Error("Cannot edit other users' messages")
|
||||
return this.channel.editMessage(this.id, text, option)
|
||||
}
|
||||
|
||||
/** Create a Reply to this Message. */
|
||||
async reply(
|
||||
text?: string | AllMessageOptions,
|
||||
option?: AllMessageOptions
|
||||
): Promise<Message> {
|
||||
return this.channel.send(text, option, this)
|
||||
}
|
||||
|
||||
/** Delete the Message. */
|
||||
async delete(): Promise<void> {
|
||||
return this.client.rest.delete(CHANNEL_MESSAGE(this.channelID, this.id))
|
||||
}
|
||||
}
|
||||
|
|
28
src/structures/messageReaction.ts
Normal file
28
src/structures/messageReaction.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import { ReactionUsersManager } from '../managers/reactionUsers.ts'
|
||||
import { Client } from '../models/client.ts'
|
||||
import { Reaction } from '../types/channel.ts'
|
||||
import { Base } from './base.ts'
|
||||
import { Emoji } from './emoji.ts'
|
||||
import { Message } from './message.ts'
|
||||
|
||||
export class MessageReaction extends Base {
|
||||
message: Message
|
||||
count: number = 0
|
||||
emoji: Emoji
|
||||
me: boolean = false
|
||||
users: ReactionUsersManager
|
||||
|
||||
constructor(client: Client, data: Reaction, message: Message, emoji: Emoji) {
|
||||
super(client, data)
|
||||
this.message = message
|
||||
this.emoji = emoji
|
||||
this.count = data.count
|
||||
this.me = data.me
|
||||
this.users = new ReactionUsersManager(client, this)
|
||||
}
|
||||
|
||||
fromPayload(data: Reaction): void {
|
||||
this.count = data.count
|
||||
this.me = data.me
|
||||
}
|
||||
}
|
|
@ -118,6 +118,22 @@ client.on('voiceStateRemove', (state) => {
|
|||
console.log('VC Leave', state)
|
||||
})
|
||||
|
||||
client.on('messageReactionAdd', (reaction, user) => {
|
||||
console.log(`${user.tag} reacted with ${reaction.emoji.name}`)
|
||||
})
|
||||
|
||||
client.on('messageReactionRemove', (reaction, user) => {
|
||||
console.log(`${user.tag} removed reaction ${reaction.emoji.name}`)
|
||||
})
|
||||
|
||||
client.on('messageReactionRemoveEmoji', (message, emoji) => {
|
||||
console.log(`All ${emoji.name} emoji reactions removed from ${message.id}`)
|
||||
})
|
||||
|
||||
client.on('messageReactionRemoveAll', (message) => {
|
||||
console.log(`All reactions remove from Message: ${message.id}`)
|
||||
})
|
||||
|
||||
// client.on('raw', (evt: string) => console.log(`EVENT: ${evt}`))
|
||||
|
||||
const files = Deno.readDirSync('./src/test/cmds')
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway
|
||||
// https://discord.com/developers/docs/topics/gateway#commands-and-events-gateway-events
|
||||
import { Guild } from "../structures/guild.ts"
|
||||
import { Member } from "../structures/member.ts"
|
||||
import { Guild } from '../structures/guild.ts'
|
||||
import { Member } from '../structures/member.ts'
|
||||
import { EmojiPayload } from './emoji.ts'
|
||||
import { MemberPayload } from './guild.ts'
|
||||
import {
|
||||
ActivityGame,
|
||||
ActivityPayload,
|
||||
StatusType,
|
||||
ClientStatus
|
||||
ClientStatus,
|
||||
} from './presence.ts'
|
||||
import { RolePayload } from './role.ts'
|
||||
import { UserPayload } from './user.ts'
|
||||
|
@ -27,7 +27,7 @@ export enum GatewayOpcodes { // 문서를 확인해본 결과 Opcode 5번은 비
|
|||
REQUEST_GUILD_MEMBERS = 8,
|
||||
INVALID_SESSION = 9,
|
||||
HELLO = 10,
|
||||
HEARTBEAT_ACK = 11
|
||||
HEARTBEAT_ACK = 11,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,7 @@ export enum GatewayCloseCodes {
|
|||
SHARDING_REQUIRED = 4011,
|
||||
INVALID_API_VERSION = 4012,
|
||||
INVALID_INTENTS = 4013,
|
||||
DISALLOWED_INTENTS = 4014
|
||||
DISALLOWED_INTENTS = 4014,
|
||||
}
|
||||
|
||||
export enum GatewayIntents {
|
||||
|
@ -65,7 +65,7 @@ export enum GatewayIntents {
|
|||
GUILD_MESSAGE_TYPING = 1 << 11,
|
||||
DIRECT_MESSAGES = 1 << 12,
|
||||
DIRECT_MESSAGE_REACTIONS = 1 << 13,
|
||||
DIRECT_MESSAGE_TYPING = 1 << 13
|
||||
DIRECT_MESSAGE_TYPING = 1 << 13,
|
||||
}
|
||||
|
||||
export enum GatewayEvents {
|
||||
|
@ -105,7 +105,7 @@ export enum GatewayEvents {
|
|||
User_Update = 'USER_UPDATE',
|
||||
Voice_Server_Update = 'VOICE_SERVER_UPDATE',
|
||||
Voice_State_Update = 'VOICE_STATE_UPDATE',
|
||||
Webhooks_Update = 'WEBHOOKS_UPDATE'
|
||||
Webhooks_Update = 'WEBHOOKS_UPDATE',
|
||||
}
|
||||
|
||||
export interface IdentityPayload {
|
||||
|
@ -290,6 +290,13 @@ export interface MessageReactionRemoveAllPayload {
|
|||
message_id: string
|
||||
}
|
||||
|
||||
export interface MessageReactionRemoveEmojiPayload {
|
||||
channel_id: string
|
||||
message_id: string
|
||||
guild_id?: string
|
||||
emoji: EmojiPayload
|
||||
}
|
||||
|
||||
export interface PresenceUpdatePayload {
|
||||
user: UserPayload
|
||||
guild_id: string
|
||||
|
@ -335,4 +342,4 @@ export interface TypingStartPayload {
|
|||
export interface TypingStartGuildData {
|
||||
guild: Guild
|
||||
member: Member
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue