Merge pull request #56 from DjDeveloperr/slash
feat: Slash Commands & Interactions [WIP?]
This commit is contained in:
commit
55ddc64187
23 changed files with 1282 additions and 105 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -113,3 +113,5 @@ src/test/config.ts
|
||||||
|
|
||||||
# macOS is shit xD
|
# macOS is shit xD
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
|
|
||||||
|
src/test/music.mp3
|
43
mod.ts
43
mod.ts
|
@ -2,7 +2,9 @@ export { GatewayIntents } from './src/types/gateway.ts'
|
||||||
export { default as EventEmitter } from 'https://deno.land/std@0.74.0/node/events.ts'
|
export { default as EventEmitter } from 'https://deno.land/std@0.74.0/node/events.ts'
|
||||||
export { Base } from './src/structures/base.ts'
|
export { Base } from './src/structures/base.ts'
|
||||||
export { Gateway } from './src/gateway/index.ts'
|
export { Gateway } from './src/gateway/index.ts'
|
||||||
|
export type { ClientEvents } from './src/gateway/handlers/index.ts'
|
||||||
export * from './src/models/client.ts'
|
export * from './src/models/client.ts'
|
||||||
|
export * from './src/models/slashClient.ts'
|
||||||
export { RESTManager } from './src/models/rest.ts'
|
export { RESTManager } from './src/models/rest.ts'
|
||||||
export * from './src/models/cacheAdapter.ts'
|
export * from './src/models/cacheAdapter.ts'
|
||||||
export {
|
export {
|
||||||
|
@ -18,6 +20,7 @@ export {
|
||||||
ExtensionCommands,
|
ExtensionCommands,
|
||||||
ExtensionsManager
|
ExtensionsManager
|
||||||
} from './src/models/extensions.ts'
|
} from './src/models/extensions.ts'
|
||||||
|
export { SlashModule } from './src/models/slashModule.ts'
|
||||||
export { CommandClient, command } from './src/models/commandClient.ts'
|
export { CommandClient, command } from './src/models/commandClient.ts'
|
||||||
export type { CommandClientOptions } from './src/models/commandClient.ts'
|
export type { CommandClientOptions } from './src/models/commandClient.ts'
|
||||||
export { BaseManager } from './src/managers/base.ts'
|
export { BaseManager } from './src/managers/base.ts'
|
||||||
|
@ -28,6 +31,8 @@ export { GatewayCache } from './src/managers/gatewayCache.ts'
|
||||||
export { GuildChannelsManager } from './src/managers/guildChannels.ts'
|
export { GuildChannelsManager } from './src/managers/guildChannels.ts'
|
||||||
export type { GuildChannel } from './src/managers/guildChannels.ts'
|
export type { GuildChannel } from './src/managers/guildChannels.ts'
|
||||||
export { GuildManager } from './src/managers/guilds.ts'
|
export { GuildManager } from './src/managers/guilds.ts'
|
||||||
|
export * from './src/structures/slash.ts'
|
||||||
|
export * from './src/types/slash.ts'
|
||||||
export { GuildEmojisManager } from './src/managers/guildEmojis.ts'
|
export { GuildEmojisManager } from './src/managers/guildEmojis.ts'
|
||||||
export { MembersManager } from './src/managers/members.ts'
|
export { MembersManager } from './src/managers/members.ts'
|
||||||
export { MessageReactionsManager } from './src/managers/messageReactions.ts'
|
export { MessageReactionsManager } from './src/managers/messageReactions.ts'
|
||||||
|
@ -80,3 +85,41 @@ export type {
|
||||||
StatusType
|
StatusType
|
||||||
} from './src/types/presence.ts'
|
} from './src/types/presence.ts'
|
||||||
export { ChannelTypes } from './src/types/channel.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'
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { webhooksUpdate } from './webhooksUpdate.ts'
|
||||||
import { messageDeleteBulk } from './messageDeleteBulk.ts'
|
import { messageDeleteBulk } from './messageDeleteBulk.ts'
|
||||||
import { userUpdate } from './userUpdate.ts'
|
import { userUpdate } from './userUpdate.ts'
|
||||||
import { typingStart } from './typingStart.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 { Guild } from '../../structures/guild.ts'
|
||||||
import { User } from '../../structures/user.ts'
|
import { User } from '../../structures/user.ts'
|
||||||
import { Emoji } from '../../structures/emoji.ts'
|
import { Emoji } from '../../structures/emoji.ts'
|
||||||
|
@ -53,6 +53,8 @@ import {
|
||||||
EveryChannelTypes,
|
EveryChannelTypes,
|
||||||
EveryTextChannelTypes
|
EveryTextChannelTypes
|
||||||
} from '../../utils/getChannelByType.ts'
|
} from '../../utils/getChannelByType.ts'
|
||||||
|
import { interactionCreate } from './interactionCreate.ts'
|
||||||
|
import { Interaction } from '../../structures/slash.ts'
|
||||||
|
|
||||||
export const gatewayHandlers: {
|
export const gatewayHandlers: {
|
||||||
[eventCode in GatewayEvents]: GatewayEventHandler | undefined
|
[eventCode in GatewayEvents]: GatewayEventHandler | undefined
|
||||||
|
@ -93,7 +95,8 @@ export const gatewayHandlers: {
|
||||||
USER_UPDATE: userUpdate,
|
USER_UPDATE: userUpdate,
|
||||||
VOICE_STATE_UPDATE: voiceStateUpdate,
|
VOICE_STATE_UPDATE: voiceStateUpdate,
|
||||||
VOICE_SERVER_UPDATE: voiceServerUpdate,
|
VOICE_SERVER_UPDATE: voiceServerUpdate,
|
||||||
WEBHOOKS_UPDATE: webhooksUpdate
|
WEBHOOKS_UPDATE: webhooksUpdate,
|
||||||
|
INTERACTION_CREATE: interactionCreate
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EventTypes {
|
export interface EventTypes {
|
||||||
|
@ -107,56 +110,227 @@ export interface VoiceServerUpdateData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientEvents extends EventTypes {
|
export interface ClientEvents extends EventTypes {
|
||||||
|
/** When Client has successfully connected to Discord */
|
||||||
ready: () => void
|
ready: () => void
|
||||||
|
/** When a successful reconnect has been made */
|
||||||
reconnect: () => void
|
reconnect: () => void
|
||||||
|
/** When a successful session resume has been done */
|
||||||
resumed: () => void
|
resumed: () => void
|
||||||
|
/**
|
||||||
|
* When a new Channel is created
|
||||||
|
* @param channel New Channel object
|
||||||
|
*/
|
||||||
channelCreate: (channel: EveryChannelTypes) => void
|
channelCreate: (channel: EveryChannelTypes) => void
|
||||||
|
/**
|
||||||
|
* When a Channel was deleted
|
||||||
|
* @param channel Channel object which was deleted
|
||||||
|
*/
|
||||||
channelDelete: (channel: EveryChannelTypes) => void
|
channelDelete: (channel: EveryChannelTypes) => void
|
||||||
|
/**
|
||||||
|
* Channel's Pinned Messages were updated
|
||||||
|
* @param before Channel object before update
|
||||||
|
* @param after Channel object after update
|
||||||
|
*/
|
||||||
channelPinsUpdate: (
|
channelPinsUpdate: (
|
||||||
before: EveryTextChannelTypes,
|
before: EveryTextChannelTypes,
|
||||||
after: EveryTextChannelTypes
|
after: EveryTextChannelTypes
|
||||||
) => void
|
) => void
|
||||||
|
/**
|
||||||
|
* A Channel was updated
|
||||||
|
* @param before Channel object before update
|
||||||
|
* @param after Channel object after update
|
||||||
|
*/
|
||||||
channelUpdate: (before: EveryChannelTypes, after: EveryChannelTypes) => void
|
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
|
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
|
guildBanRemove: (guild: Guild, user: User) => void
|
||||||
|
/**
|
||||||
|
* Client has joined a new Guild.
|
||||||
|
* @param guild The new Guild object
|
||||||
|
*/
|
||||||
guildCreate: (guild: Guild) => void
|
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
|
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
|
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
|
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
|
guildEmojiUpdate: (guild: Guild, before: Emoji, after: Emoji) => void
|
||||||
|
/**
|
||||||
|
* Guild's Integrations were updated
|
||||||
|
* @param guild The Guild object
|
||||||
|
*/
|
||||||
guildIntegrationsUpdate: (guild: Guild) => void
|
guildIntegrationsUpdate: (guild: Guild) => void
|
||||||
|
/**
|
||||||
|
* A new Member has joined a Guild
|
||||||
|
* @param member The Member object
|
||||||
|
*/
|
||||||
guildMemberAdd: (member: Member) => void
|
guildMemberAdd: (member: Member) => void
|
||||||
|
/**
|
||||||
|
* A Guild Member has either left or was kicked from Guild
|
||||||
|
* @param member The Member object
|
||||||
|
*/
|
||||||
guildMemberRemove: (member: Member) => void
|
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
|
guildMemberUpdate: (before: Member, after: Member) => void
|
||||||
|
/**
|
||||||
|
* A new Role was created in Guild
|
||||||
|
* @param role The new Role object
|
||||||
|
*/
|
||||||
guildRoleCreate: (role: Role) => void
|
guildRoleCreate: (role: Role) => void
|
||||||
|
/**
|
||||||
|
* A Role was deleted from the Guild
|
||||||
|
* @param role The Role object
|
||||||
|
*/
|
||||||
guildRoleDelete: (role: Role) => void
|
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
|
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
|
guildUpdate: (before: Guild, after: Guild) => void
|
||||||
|
/**
|
||||||
|
* A new Message was created (sent)
|
||||||
|
* @param message The new Message object
|
||||||
|
*/
|
||||||
messageCreate: (message: Message) => void
|
messageCreate: (message: Message) => void
|
||||||
|
/**
|
||||||
|
* A Message was deleted.
|
||||||
|
* @param message The Message object
|
||||||
|
*/
|
||||||
messageDelete: (message: Message) => void
|
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: (
|
messageDeleteBulk: (
|
||||||
channel: GuildTextChannel,
|
channel: GuildTextChannel,
|
||||||
messages: Collection<string, Message>,
|
messages: Collection<string, Message>,
|
||||||
uncached: Set<string>
|
uncached: Set<string>
|
||||||
) => void
|
) => 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
|
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
|
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
|
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
|
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
|
messageReactionRemoveEmoji: (message: Message, emoji: Emoji) => void
|
||||||
|
/**
|
||||||
|
* A User has started typing in a Text Channel
|
||||||
|
*/
|
||||||
typingStart: (
|
typingStart: (
|
||||||
user: User,
|
user: User,
|
||||||
channel: EveryChannelTypes,
|
channel: TextChannel,
|
||||||
at: Date,
|
at: Date,
|
||||||
guildData?: TypingStartGuildData
|
guildData?: TypingStartGuildData
|
||||||
) => void
|
) => void
|
||||||
|
/**
|
||||||
|
* A new Invite was created
|
||||||
|
* @param invite New Invite object
|
||||||
|
*/
|
||||||
inviteCreate: (invite: Invite) => void
|
inviteCreate: (invite: Invite) => void
|
||||||
|
/**
|
||||||
|
* An Invite was deleted
|
||||||
|
* @param invite Invite object
|
||||||
|
*/
|
||||||
inviteDelete: (invite: Invite) => void
|
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
|
userUpdate: (before: User, after: User) => void
|
||||||
|
/**
|
||||||
|
* Client has received credentials for establishing connection to Voice Server
|
||||||
|
*/
|
||||||
voiceServerUpdate: (data: VoiceServerUpdateData) => void
|
voiceServerUpdate: (data: VoiceServerUpdateData) => void
|
||||||
|
/**
|
||||||
|
* A User has joined a Voice Channel
|
||||||
|
*/
|
||||||
voiceStateAdd: (state: VoiceState) => void
|
voiceStateAdd: (state: VoiceState) => void
|
||||||
|
/**
|
||||||
|
* A User has left a Voice Channel
|
||||||
|
*/
|
||||||
voiceStateRemove: (state: VoiceState) => void
|
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
|
voiceStateUpdate: (state: VoiceState, after: VoiceState) => void
|
||||||
|
/**
|
||||||
|
* A User's presence has been updated
|
||||||
|
* @param presence New Presence
|
||||||
|
*/
|
||||||
presenceUpdate: (presence: Presence) => void
|
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
|
webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void
|
||||||
|
/**
|
||||||
|
* A Slash Command was triggered
|
||||||
|
*/
|
||||||
|
interactionCreate: (interaction: Interaction) => void
|
||||||
}
|
}
|
||||||
|
|
29
src/gateway/handlers/interactionCreate.ts
Normal file
29
src/gateway/handlers/interactionCreate.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { Member } from '../../structures/member.ts'
|
||||||
|
import { Interaction } from '../../structures/slash.ts'
|
||||||
|
import { GuildTextChannel } from '../../structures/textChannel.ts'
|
||||||
|
import { InteractionPayload } from '../../types/slash.ts'
|
||||||
|
import { Gateway, GatewayEventHandler } from '../index.ts'
|
||||||
|
|
||||||
|
export const interactionCreate: GatewayEventHandler = async (
|
||||||
|
gateway: Gateway,
|
||||||
|
d: InteractionPayload
|
||||||
|
) => {
|
||||||
|
const guild = await gateway.client.guilds.get(d.guild_id)
|
||||||
|
if (guild === undefined) return
|
||||||
|
|
||||||
|
await guild.members.set(d.member.user.id, d.member)
|
||||||
|
const member = ((await guild.members.get(
|
||||||
|
d.member.user.id
|
||||||
|
)) as unknown) as Member
|
||||||
|
|
||||||
|
const channel =
|
||||||
|
(await gateway.client.channels.get<GuildTextChannel>(d.channel_id)) ??
|
||||||
|
(await gateway.client.channels.fetch<GuildTextChannel>(d.channel_id))
|
||||||
|
|
||||||
|
const interaction = new Interaction(gateway.client, d, {
|
||||||
|
member,
|
||||||
|
guild,
|
||||||
|
channel
|
||||||
|
})
|
||||||
|
gateway.client.emit('interactionCreate', interaction)
|
||||||
|
}
|
|
@ -252,9 +252,9 @@ class Gateway {
|
||||||
const payload: IdentityPayload = {
|
const payload: IdentityPayload = {
|
||||||
token: this.token,
|
token: this.token,
|
||||||
properties: {
|
properties: {
|
||||||
$os: Deno.build.os,
|
$os: this.client.clientProperties.os ?? Deno.build.os,
|
||||||
$browser: 'harmony',
|
$browser: this.client.clientProperties.browser ?? 'harmony',
|
||||||
$device: 'harmony'
|
$device: this.client.clientProperties.device ?? 'harmony'
|
||||||
},
|
},
|
||||||
compress: true,
|
compress: true,
|
||||||
shard: [0, 1], // TODO: Make sharding possible
|
shard: [0, 1], // TODO: Make sharding possible
|
||||||
|
|
|
@ -12,6 +12,16 @@ import { EmojisManager } from '../managers/emojis.ts'
|
||||||
import { ActivityGame, ClientActivity } from '../types/presence.ts'
|
import { ActivityGame, ClientActivity } from '../types/presence.ts'
|
||||||
import { ClientEvents } from '../gateway/handlers/index.ts'
|
import { ClientEvents } from '../gateway/handlers/index.ts'
|
||||||
import { Extension } from './extensions.ts'
|
import { Extension } from './extensions.ts'
|
||||||
|
import { SlashClient } from './slashClient.ts'
|
||||||
|
import { Interaction } from '../structures/slash.ts'
|
||||||
|
import { SlashModule } from './slashModule.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 */
|
/** Some Client Options to modify behaviour */
|
||||||
export interface ClientOptions {
|
export interface ClientOptions {
|
||||||
|
@ -33,6 +43,10 @@ export interface ClientOptions {
|
||||||
reactionCacheLifetime?: number
|
reactionCacheLifetime?: number
|
||||||
/** Whether to fetch Uncached Message of Reaction or not? */
|
/** Whether to fetch Uncached Message of Reaction or not? */
|
||||||
fetchUncachedReactions?: boolean
|
fetchUncachedReactions?: boolean
|
||||||
|
/** Client Properties */
|
||||||
|
clientProperties?: ClientProperties
|
||||||
|
/** Enable/Disable Slash Commands Integration (enabled by default) */
|
||||||
|
enableSlash?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,6 +75,10 @@ export class Client extends EventEmitter {
|
||||||
reactionCacheLifetime: number = 3600000
|
reactionCacheLifetime: number = 3600000
|
||||||
/** Whether to fetch Uncached Message of Reaction or not? */
|
/** Whether to fetch Uncached Message of Reaction or not? */
|
||||||
fetchUncachedReactions: boolean = false
|
fetchUncachedReactions: boolean = false
|
||||||
|
/** Client Properties */
|
||||||
|
clientProperties: ClientProperties
|
||||||
|
/** Slash-Commands Management client */
|
||||||
|
slash: SlashClient
|
||||||
|
|
||||||
users: UsersManager = new UsersManager(this)
|
users: UsersManager = new UsersManager(this)
|
||||||
guilds: GuildManager = new GuildManager(this)
|
guilds: GuildManager = new GuildManager(this)
|
||||||
|
@ -72,6 +90,13 @@ export class Client extends EventEmitter {
|
||||||
/** Client's presence. Startup one if set before connecting */
|
/** Client's presence. Startup one if set before connecting */
|
||||||
presence: ClientPresence = new ClientPresence()
|
presence: ClientPresence = new ClientPresence()
|
||||||
_decoratedEvents?: { [name: string]: (...args: any[]) => any }
|
_decoratedEvents?: { [name: string]: (...args: any[]) => any }
|
||||||
|
_decoratedSlash?: Array<{
|
||||||
|
name: string
|
||||||
|
guild?: string
|
||||||
|
handler: (interaction: Interaction) => any
|
||||||
|
}>
|
||||||
|
|
||||||
|
_decoratedSlashModules?: SlashModule[]
|
||||||
|
|
||||||
private readonly _untypedOn = this.on
|
private readonly _untypedOn = this.on
|
||||||
|
|
||||||
|
@ -113,6 +138,19 @@ export class Client extends EventEmitter {
|
||||||
})
|
})
|
||||||
this._decoratedEvents = undefined
|
this._decoratedEvents = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.clientProperties =
|
||||||
|
options.clientProperties === undefined
|
||||||
|
? {
|
||||||
|
os: Deno.build.os,
|
||||||
|
browser: 'harmony',
|
||||||
|
device: 'harmony'
|
||||||
|
}
|
||||||
|
: options.clientProperties
|
||||||
|
|
||||||
|
this.slash = new SlashClient(this, {
|
||||||
|
enabled: options.enableSlash
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,7 +209,34 @@ export function event(name?: string) {
|
||||||
const listener = ((client as unknown) as {
|
const listener = ((client as unknown) as {
|
||||||
[name: string]: (...args: any[]) => any
|
[name: string]: (...args: any[]) => any
|
||||||
})[prop]
|
})[prop]
|
||||||
|
if (typeof listener !== 'function')
|
||||||
|
throw new Error('@event decorator requires a function')
|
||||||
if (client._decoratedEvents === undefined) client._decoratedEvents = {}
|
if (client._decoratedEvents === undefined) client._decoratedEvents = {}
|
||||||
client._decoratedEvents[name === undefined ? prop : name] = listener
|
client._decoratedEvents[name === undefined ? prop : name] = listener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function slash(name?: string, guild?: string) {
|
||||||
|
return function (client: Client | SlashModule, prop: string) {
|
||||||
|
if (client._decoratedSlash === undefined) client._decoratedSlash = []
|
||||||
|
const item = (client as { [name: string]: any })[prop]
|
||||||
|
if (typeof item !== 'function') {
|
||||||
|
client._decoratedSlash.push(item)
|
||||||
|
} else
|
||||||
|
client._decoratedSlash.push({
|
||||||
|
name: name ?? prop,
|
||||||
|
guild,
|
||||||
|
handler: item
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function slashModule() {
|
||||||
|
return function (client: Client, prop: string) {
|
||||||
|
if (client._decoratedSlashModules === undefined)
|
||||||
|
client._decoratedSlashModules = []
|
||||||
|
|
||||||
|
const mod = ((client as unknown) as { [key: string]: any })[prop]
|
||||||
|
client._decoratedSlashModules.push(mod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -383,18 +383,26 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
|
|
||||||
export function command(options?: CommandOptions) {
|
export function command(options?: CommandOptions) {
|
||||||
return function (target: CommandClient | Extension, name: string) {
|
return function (target: CommandClient | Extension, name: string) {
|
||||||
|
if (target._decoratedCommands === undefined) target._decoratedCommands = {}
|
||||||
|
|
||||||
|
const prop = ((target as unknown) as {
|
||||||
|
[name: string]: (ctx: CommandContext) => any
|
||||||
|
})[name]
|
||||||
|
|
||||||
|
if (prop instanceof Command) {
|
||||||
|
target._decoratedCommands[prop.name] = prop
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const command = new Command()
|
const command = new Command()
|
||||||
|
|
||||||
command.name = name
|
command.name = name
|
||||||
command.execute = ((target as unknown) as {
|
command.execute = prop
|
||||||
[name: string]: (ctx: CommandContext) => any
|
|
||||||
})[name]
|
|
||||||
|
|
||||||
if (options !== undefined) Object.assign(command, options)
|
if (options !== undefined) Object.assign(command, options)
|
||||||
|
|
||||||
if (target instanceof Extension) command.extension = target
|
if (target instanceof Extension) command.extension = target
|
||||||
|
|
||||||
if (target._decoratedCommands === undefined) target._decoratedCommands = {}
|
|
||||||
target._decoratedCommands[command.name] = command
|
target._decoratedCommands[command.name] = command
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,11 +277,11 @@ export class RESTManager {
|
||||||
message: body?.message,
|
message: body?.message,
|
||||||
errors: Object.fromEntries(
|
errors: Object.fromEntries(
|
||||||
Object.entries(
|
Object.entries(
|
||||||
body?.errors as {
|
(body?.errors as {
|
||||||
[name: string]: {
|
[name: string]: {
|
||||||
_errors: Array<{ code: string; message: string }>
|
_errors: Array<{ code: string; message: string }>
|
||||||
}
|
}
|
||||||
}
|
}) ?? {}
|
||||||
).map((entry) => {
|
).map((entry) => {
|
||||||
return [entry[0], entry[1]._errors]
|
return [entry[0], entry[1]._errors]
|
||||||
})
|
})
|
||||||
|
|
222
src/models/slashClient.ts
Normal file
222
src/models/slashClient.ts
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
import { Guild } from '../structures/guild.ts'
|
||||||
|
import { Interaction } from '../structures/slash.ts'
|
||||||
|
import {
|
||||||
|
APPLICATION_COMMAND,
|
||||||
|
APPLICATION_COMMANDS,
|
||||||
|
APPLICATION_GUILD_COMMAND,
|
||||||
|
APPLICATION_GUILD_COMMANDS
|
||||||
|
} from '../types/endpoint.ts'
|
||||||
|
import {
|
||||||
|
InteractionType,
|
||||||
|
SlashCommandOption,
|
||||||
|
SlashCommandPartial,
|
||||||
|
SlashCommandPayload
|
||||||
|
} from '../types/slash.ts'
|
||||||
|
import { Collection } from '../utils/collection.ts'
|
||||||
|
import { Client } from './client.ts'
|
||||||
|
|
||||||
|
export interface SlashOptions {
|
||||||
|
enabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SlashCommand {
|
||||||
|
slash: SlashCommandsManager
|
||||||
|
id: string
|
||||||
|
applicationID: string
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
options: SlashCommandOption[]
|
||||||
|
_guild?: string
|
||||||
|
|
||||||
|
constructor(manager: SlashCommandsManager, data: SlashCommandPayload) {
|
||||||
|
this.slash = manager
|
||||||
|
this.id = data.id
|
||||||
|
this.applicationID = data.application_id
|
||||||
|
this.name = data.name
|
||||||
|
this.description = data.description
|
||||||
|
this.options = data.options
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(): Promise<void> {
|
||||||
|
await this.slash.delete(this.id, this._guild)
|
||||||
|
}
|
||||||
|
|
||||||
|
async edit(data: SlashCommandPartial): Promise<void> {
|
||||||
|
await this.slash.edit(this.id, data, this._guild)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SlashCommandsManager {
|
||||||
|
client: Client
|
||||||
|
slash: SlashClient
|
||||||
|
|
||||||
|
constructor(client: Client) {
|
||||||
|
this.client = client
|
||||||
|
this.slash = client.slash
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get all Global Slash Commands */
|
||||||
|
async all(): Promise<Collection<string, SlashCommand>> {
|
||||||
|
const col = new Collection<string, SlashCommand>()
|
||||||
|
|
||||||
|
const res = (await this.client.rest.get(
|
||||||
|
APPLICATION_COMMANDS(this.client.user?.id as string)
|
||||||
|
)) as SlashCommandPayload[]
|
||||||
|
if (!Array.isArray(res)) return col
|
||||||
|
|
||||||
|
for (const raw of res) {
|
||||||
|
const cmd = new SlashCommand(this, raw)
|
||||||
|
col.set(raw.id, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return col
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get a Guild's Slash Commands */
|
||||||
|
async guild(
|
||||||
|
guild: Guild | string
|
||||||
|
): Promise<Collection<string, SlashCommand>> {
|
||||||
|
const col = new Collection<string, SlashCommand>()
|
||||||
|
|
||||||
|
const res = (await this.client.rest.get(
|
||||||
|
APPLICATION_GUILD_COMMANDS(
|
||||||
|
this.client.user?.id as string,
|
||||||
|
typeof guild === 'string' ? guild : guild.id
|
||||||
|
)
|
||||||
|
)) as SlashCommandPayload[]
|
||||||
|
if (!Array.isArray(res)) return col
|
||||||
|
|
||||||
|
for (const raw of res) {
|
||||||
|
const cmd = new SlashCommand(this, raw)
|
||||||
|
cmd._guild = typeof guild === 'string' ? guild : guild.id
|
||||||
|
col.set(raw.id, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return col
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a Slash Command (global or Guild) */
|
||||||
|
async create(
|
||||||
|
data: SlashCommandPartial,
|
||||||
|
guild?: Guild | string
|
||||||
|
): Promise<SlashCommand> {
|
||||||
|
const payload = await this.client.rest.post(
|
||||||
|
guild === undefined
|
||||||
|
? APPLICATION_COMMANDS(this.client.user?.id as string)
|
||||||
|
: APPLICATION_GUILD_COMMANDS(
|
||||||
|
this.client.user?.id as string,
|
||||||
|
typeof guild === 'string' ? guild : guild.id
|
||||||
|
),
|
||||||
|
data
|
||||||
|
)
|
||||||
|
|
||||||
|
const cmd = new SlashCommand(this, payload)
|
||||||
|
cmd._guild =
|
||||||
|
typeof guild === 'string' || guild === undefined ? guild : guild.id
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Edit a Slash Command (global or Guild) */
|
||||||
|
async edit(
|
||||||
|
id: string,
|
||||||
|
data: SlashCommandPartial,
|
||||||
|
guild?: Guild | string
|
||||||
|
): Promise<SlashCommandsManager> {
|
||||||
|
await this.client.rest.patch(
|
||||||
|
guild === undefined
|
||||||
|
? APPLICATION_COMMAND(this.client.user?.id as string, id)
|
||||||
|
: APPLICATION_GUILD_COMMAND(
|
||||||
|
this.client.user?.id as string,
|
||||||
|
typeof guild === 'string' ? guild : guild.id,
|
||||||
|
id
|
||||||
|
),
|
||||||
|
data
|
||||||
|
)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Delete a Slash Command (global or Guild) */
|
||||||
|
async delete(
|
||||||
|
id: string,
|
||||||
|
guild?: Guild | string
|
||||||
|
): Promise<SlashCommandsManager> {
|
||||||
|
await this.client.rest.delete(
|
||||||
|
guild === undefined
|
||||||
|
? APPLICATION_COMMAND(this.client.user?.id as string, id)
|
||||||
|
: APPLICATION_GUILD_COMMAND(
|
||||||
|
this.client.user?.id as string,
|
||||||
|
typeof guild === 'string' ? guild : guild.id,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SlashCommandHandlerCallback = (interaction: Interaction) => any
|
||||||
|
export interface SlashCommandHandler {
|
||||||
|
name: string
|
||||||
|
guild?: string
|
||||||
|
handler: SlashCommandHandlerCallback
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SlashClient {
|
||||||
|
client: Client
|
||||||
|
enabled: boolean = true
|
||||||
|
commands: SlashCommandsManager
|
||||||
|
handlers: SlashCommandHandler[] = []
|
||||||
|
|
||||||
|
constructor(client: Client, options?: SlashOptions) {
|
||||||
|
this.client = client
|
||||||
|
this.commands = new SlashCommandsManager(client)
|
||||||
|
|
||||||
|
if (options !== undefined) {
|
||||||
|
this.enabled = options.enabled ?? true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.client._decoratedSlash !== undefined) {
|
||||||
|
this.client._decoratedSlash.forEach((e) => {
|
||||||
|
this.handlers.push(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client.on('interactionCreate', (interaction) =>
|
||||||
|
this.process(interaction)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a new Slash Command Handler */
|
||||||
|
handle(
|
||||||
|
name: string,
|
||||||
|
handler: SlashCommandHandlerCallback,
|
||||||
|
guild?: string
|
||||||
|
): SlashClient {
|
||||||
|
this.handlers.push({
|
||||||
|
name,
|
||||||
|
guild,
|
||||||
|
handler
|
||||||
|
})
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Process an incoming Slash Command (interaction) */
|
||||||
|
private process(interaction: Interaction): void {
|
||||||
|
if (!this.enabled) return
|
||||||
|
|
||||||
|
if (interaction.type !== InteractionType.APPLICATION_COMMAND) return
|
||||||
|
|
||||||
|
let cmd
|
||||||
|
|
||||||
|
if (interaction.guild !== undefined)
|
||||||
|
cmd =
|
||||||
|
this.handlers.find(
|
||||||
|
(e) => e.guild !== undefined && e.name === interaction.name
|
||||||
|
) ?? this.handlers.find((e) => e.name === interaction.name)
|
||||||
|
else cmd = this.handlers.find((e) => e.name === interaction.name)
|
||||||
|
|
||||||
|
if (cmd === undefined) return
|
||||||
|
|
||||||
|
cmd.handler(interaction)
|
||||||
|
}
|
||||||
|
}
|
18
src/models/slashModule.ts
Normal file
18
src/models/slashModule.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { SlashCommandHandler } from './slashClient.ts'
|
||||||
|
|
||||||
|
export class SlashModule {
|
||||||
|
name: string = ''
|
||||||
|
commands: SlashCommandHandler[] = []
|
||||||
|
_decoratedSlash?: SlashCommandHandler[]
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
if (this._decoratedSlash !== undefined) {
|
||||||
|
this.commands = this._decoratedSlash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add(handler: SlashCommandHandler): SlashModule {
|
||||||
|
this.commands.push(handler)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,17 +50,23 @@ export class Presence extends Base {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface StatusPayload extends StatusUpdatePayload {
|
||||||
|
client_status?: ClientStatus
|
||||||
|
}
|
||||||
|
|
||||||
export class ClientPresence {
|
export class ClientPresence {
|
||||||
status: StatusType = 'online'
|
status: StatusType = 'online'
|
||||||
activity?: ActivityGame | ActivityGame[]
|
activity?: ActivityGame | ActivityGame[]
|
||||||
since?: number | null
|
since?: number | null
|
||||||
afk?: boolean
|
afk?: boolean
|
||||||
|
clientStatus?: ClientStatus
|
||||||
|
|
||||||
constructor(data?: ClientActivity | StatusUpdatePayload | ActivityGame) {
|
constructor(data?: ClientActivity | StatusPayload | 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)
|
||||||
} 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) {
|
} else if ((data as ActivityGame).name !== undefined) {
|
||||||
if (this.activity === undefined) {
|
if (this.activity === undefined) {
|
||||||
this.activity = data as ActivityGame
|
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.afk = payload.afk
|
||||||
this.activity = payload.activities ?? undefined
|
this.activity = payload.activities ?? undefined
|
||||||
this.since = payload.since
|
this.since = payload.since
|
||||||
this.status = payload.status
|
this.status = payload.status
|
||||||
|
// this.clientStatus = payload.client_status
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,12 +90,13 @@ export class ClientPresence {
|
||||||
return new ClientPresence().parse(payload)
|
return new ClientPresence().parse(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
create(): StatusUpdatePayload {
|
create(): StatusPayload {
|
||||||
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
|
||||||
|
// client_status: this.clientStatus
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,4 +152,13 @@ export class ClientPresence {
|
||||||
this.since = since
|
this.since = since
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setClientStatus(
|
||||||
|
// client: 'desktop' | 'web' | 'mobile',
|
||||||
|
// status: StatusType
|
||||||
|
// ): ClientPresence {
|
||||||
|
// if (this.clientStatus === undefined) this.clientStatus = {}
|
||||||
|
// this.clientStatus[client] = status
|
||||||
|
// return this
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
233
src/structures/slash.ts
Normal file
233
src/structures/slash.ts
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
import { Client } from '../models/client.ts'
|
||||||
|
import { MessageOption } from '../types/channel.ts'
|
||||||
|
import { INTERACTION_CALLBACK, WEBHOOK_MESSAGE } from '../types/endpoint.ts'
|
||||||
|
import {
|
||||||
|
InteractionData,
|
||||||
|
InteractionPayload,
|
||||||
|
InteractionResponsePayload,
|
||||||
|
InteractionResponseType
|
||||||
|
} from '../types/slash.ts'
|
||||||
|
import { Embed } from './embed.ts'
|
||||||
|
import { Guild } from './guild.ts'
|
||||||
|
import { Member } from './member.ts'
|
||||||
|
import { Message } from './message.ts'
|
||||||
|
import { GuildTextChannel, TextChannel } from './textChannel.ts'
|
||||||
|
import { User } from './user.ts'
|
||||||
|
import { Webhook } from './webhook.ts'
|
||||||
|
|
||||||
|
interface WebhookMessageOptions extends MessageOption {
|
||||||
|
embeds?: Embed[]
|
||||||
|
name?: string
|
||||||
|
avatar?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type AllWebhookMessageOptions = string | WebhookMessageOptions
|
||||||
|
|
||||||
|
export interface InteractionResponse {
|
||||||
|
type?: InteractionResponseType
|
||||||
|
content?: string
|
||||||
|
embeds?: Embed[]
|
||||||
|
tts?: boolean
|
||||||
|
flags?: number
|
||||||
|
temp?: boolean
|
||||||
|
allowedMentions?: {
|
||||||
|
parse?: string
|
||||||
|
roles?: string[]
|
||||||
|
users?: string[]
|
||||||
|
everyone?: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Interaction {
|
||||||
|
client: Client
|
||||||
|
type: number
|
||||||
|
token: string
|
||||||
|
id: string
|
||||||
|
data: InteractionData
|
||||||
|
channel: GuildTextChannel
|
||||||
|
guild: Guild
|
||||||
|
member: Member
|
||||||
|
_savedHook?: Webhook
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
client: Client,
|
||||||
|
data: InteractionPayload,
|
||||||
|
others: {
|
||||||
|
channel: GuildTextChannel
|
||||||
|
guild: Guild
|
||||||
|
member: Member
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
this.client = client
|
||||||
|
this.type = data.type
|
||||||
|
this.token = data.token
|
||||||
|
this.member = others.member
|
||||||
|
this.id = data.id
|
||||||
|
this.data = data.data
|
||||||
|
this.guild = others.guild
|
||||||
|
this.channel = others.channel
|
||||||
|
}
|
||||||
|
|
||||||
|
get user(): User {
|
||||||
|
return this.member.user
|
||||||
|
}
|
||||||
|
|
||||||
|
get name(): string {
|
||||||
|
return this.data.name
|
||||||
|
}
|
||||||
|
|
||||||
|
option<T = any>(name: string): T {
|
||||||
|
return this.data.options.find((e) => e.name === name)?.value
|
||||||
|
}
|
||||||
|
|
||||||
|
async respond(data: InteractionResponse): Promise<Interaction> {
|
||||||
|
const payload: InteractionResponsePayload = {
|
||||||
|
type: data.type ?? InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||||
|
data:
|
||||||
|
data.type === undefined ||
|
||||||
|
data.type === InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE ||
|
||||||
|
data.type === InteractionResponseType.CHANNEL_MESSAGE
|
||||||
|
? {
|
||||||
|
content: data.content ?? '',
|
||||||
|
embeds: data.embeds,
|
||||||
|
tts: data.tts ?? false,
|
||||||
|
flags: data.temp === true ? 64 : data.flags ?? undefined,
|
||||||
|
allowed_mentions: (data.allowedMentions ?? undefined) as any
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.client.rest.post(
|
||||||
|
INTERACTION_CALLBACK(this.id, this.token),
|
||||||
|
payload
|
||||||
|
)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
async editResponse(data: {
|
||||||
|
content?: string
|
||||||
|
embeds?: Embed[]
|
||||||
|
}): Promise<Interaction> {
|
||||||
|
const url = WEBHOOK_MESSAGE(
|
||||||
|
this.client.user?.id as string,
|
||||||
|
this.token,
|
||||||
|
'@original'
|
||||||
|
)
|
||||||
|
await this.client.rest.patch(url, {
|
||||||
|
content: data.content ?? '',
|
||||||
|
embeds: data.embeds ?? []
|
||||||
|
})
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteResponse(): Promise<Interaction> {
|
||||||
|
const url = WEBHOOK_MESSAGE(
|
||||||
|
this.client.user?.id as string,
|
||||||
|
this.token,
|
||||||
|
'@original'
|
||||||
|
)
|
||||||
|
await this.client.rest.delete(url)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
get url(): string {
|
||||||
|
return `https://discord.com/api/v8/webhooks/${this.client.user?.id}/${this.token}`
|
||||||
|
}
|
||||||
|
|
||||||
|
async send(
|
||||||
|
text?: string | AllWebhookMessageOptions,
|
||||||
|
option?: AllWebhookMessageOptions
|
||||||
|
): Promise<Message> {
|
||||||
|
if (typeof text === 'object') {
|
||||||
|
option = text
|
||||||
|
text = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text === undefined && option === undefined) {
|
||||||
|
throw new Error('Either text or option is necessary.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option instanceof Embed)
|
||||||
|
option = {
|
||||||
|
embeds: [option]
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload: any = {
|
||||||
|
content: text,
|
||||||
|
embeds:
|
||||||
|
(option as WebhookMessageOptions)?.embed !== undefined
|
||||||
|
? [(option as WebhookMessageOptions).embed]
|
||||||
|
: (option as WebhookMessageOptions)?.embeds !== undefined
|
||||||
|
? (option as WebhookMessageOptions).embeds
|
||||||
|
: undefined,
|
||||||
|
file: (option as WebhookMessageOptions)?.file,
|
||||||
|
tts: (option as WebhookMessageOptions)?.tts,
|
||||||
|
allowed_mentions: (option as WebhookMessageOptions)?.allowedMentions
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((option as WebhookMessageOptions)?.name !== undefined) {
|
||||||
|
payload.username = (option as WebhookMessageOptions)?.name
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((option as WebhookMessageOptions)?.avatar !== undefined) {
|
||||||
|
payload.avatar = (option as WebhookMessageOptions)?.avatar
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
payload.embeds !== undefined &&
|
||||||
|
payload.embeds instanceof Array &&
|
||||||
|
payload.embeds.length > 10
|
||||||
|
)
|
||||||
|
throw new Error(
|
||||||
|
`Cannot send more than 10 embeds through Interaction Webhook`
|
||||||
|
)
|
||||||
|
|
||||||
|
const resp = await this.client.rest.post(`${this.url}?wait=true`, payload)
|
||||||
|
|
||||||
|
const res = new Message(
|
||||||
|
this.client,
|
||||||
|
resp,
|
||||||
|
(this as unknown) as TextChannel,
|
||||||
|
(this as unknown) as User
|
||||||
|
)
|
||||||
|
await res.mentions.fromPayload(resp)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
async editMessage(
|
||||||
|
msg: Message | string,
|
||||||
|
data: {
|
||||||
|
content?: string
|
||||||
|
embeds?: Embed[]
|
||||||
|
file?: any
|
||||||
|
allowed_mentions?: {
|
||||||
|
parse?: string
|
||||||
|
roles?: string[]
|
||||||
|
users?: string[]
|
||||||
|
everyone?: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
): Promise<Interaction> {
|
||||||
|
await this.client.rest.patch(
|
||||||
|
WEBHOOK_MESSAGE(
|
||||||
|
this.client.user?.id as string,
|
||||||
|
this.token ?? this.client.token,
|
||||||
|
typeof msg === 'string' ? msg : msg.id
|
||||||
|
),
|
||||||
|
data
|
||||||
|
)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteMessage(msg: Message | string): Promise<Interaction> {
|
||||||
|
await this.client.rest.delete(
|
||||||
|
WEBHOOK_MESSAGE(
|
||||||
|
this.client.user?.id as string,
|
||||||
|
this.token ?? this.client.token,
|
||||||
|
typeof msg === 'string' ? msg : msg.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ export class VoiceState extends Base {
|
||||||
sessionID: string
|
sessionID: string
|
||||||
deaf: boolean
|
deaf: boolean
|
||||||
mute: boolean
|
mute: boolean
|
||||||
|
selfDeaf: boolean
|
||||||
|
selfMute: boolean
|
||||||
stream?: boolean
|
stream?: boolean
|
||||||
video: boolean
|
video: boolean
|
||||||
suppress: boolean
|
suppress: boolean
|
||||||
|
@ -38,8 +40,8 @@ export class VoiceState extends Base {
|
||||||
this.guild = _data.guild
|
this.guild = _data.guild
|
||||||
this.deaf = data.deaf
|
this.deaf = data.deaf
|
||||||
this.mute = data.mute
|
this.mute = data.mute
|
||||||
this.deaf = data.self_deaf
|
this.selfDeaf = data.self_deaf
|
||||||
this.mute = data.self_mute
|
this.selfMute = data.self_mute
|
||||||
this.stream = data.self_stream
|
this.stream = data.self_stream
|
||||||
this.video = data.self_video
|
this.video = data.self_video
|
||||||
this.suppress = data.suppress
|
this.suppress = data.suppress
|
||||||
|
@ -52,6 +54,8 @@ export class VoiceState extends Base {
|
||||||
this.mute = data.mute ?? this.mute
|
this.mute = data.mute ?? this.mute
|
||||||
this.deaf = data.self_deaf ?? this.deaf
|
this.deaf = data.self_deaf ?? this.deaf
|
||||||
this.mute = data.self_mute ?? this.mute
|
this.mute = data.self_mute ?? this.mute
|
||||||
|
this.selfDeaf = data.self_deaf ?? this.selfDeaf
|
||||||
|
this.selfMute = data.self_mute ?? this.selfMute
|
||||||
this.stream = data.self_stream ?? this.stream
|
this.stream = data.self_stream ?? this.stream
|
||||||
this.video = data.self_video ?? this.video
|
this.video = data.self_video ?? this.video
|
||||||
this.suppress = data.suppress ?? this.suppress
|
this.suppress = data.suppress ?? this.suppress
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { Message } from './message.ts'
|
||||||
import { TextChannel } from './textChannel.ts'
|
import { TextChannel } from './textChannel.ts'
|
||||||
import { User } from './user.ts'
|
import { User } from './user.ts'
|
||||||
import { fetchAuto } from 'https://raw.githubusercontent.com/DjDeveloperr/fetch-base64/main/mod.ts'
|
import { fetchAuto } from 'https://raw.githubusercontent.com/DjDeveloperr/fetch-base64/main/mod.ts'
|
||||||
|
import { WEBHOOK_MESSAGE } from '../types/endpoint.ts'
|
||||||
|
|
||||||
export interface WebhookMessageOptions extends MessageOption {
|
export interface WebhookMessageOptions extends MessageOption {
|
||||||
embeds?: Embed[]
|
embeds?: Embed[]
|
||||||
|
@ -191,4 +192,40 @@ export class Webhook {
|
||||||
if (resp.response.status !== 204) return false
|
if (resp.response.status !== 204) return false
|
||||||
else return true
|
else return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async editMessage(
|
||||||
|
message: string | Message,
|
||||||
|
data: {
|
||||||
|
content?: string
|
||||||
|
embeds?: Embed[]
|
||||||
|
file?: any
|
||||||
|
allowed_mentions?: {
|
||||||
|
parse?: string
|
||||||
|
roles?: string[]
|
||||||
|
users?: string[]
|
||||||
|
everyone?: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
): Promise<Webhook> {
|
||||||
|
await this.client?.rest.patch(
|
||||||
|
WEBHOOK_MESSAGE(
|
||||||
|
this.id,
|
||||||
|
(this.token ?? this.client.token) as string,
|
||||||
|
typeof message === 'string' ? message : message.id
|
||||||
|
),
|
||||||
|
data
|
||||||
|
)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteMessage(message: string | Message): Promise<Webhook> {
|
||||||
|
await this.client?.rest.delete(
|
||||||
|
WEBHOOK_MESSAGE(
|
||||||
|
this.id,
|
||||||
|
(this.token ?? this.client.token) as string,
|
||||||
|
typeof message === 'string' ? message : message.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {
|
||||||
Client,
|
Client,
|
||||||
Intents,
|
Intents,
|
||||||
Message,
|
Message,
|
||||||
ClientPresence,
|
|
||||||
Member,
|
Member,
|
||||||
Role,
|
Role,
|
||||||
GuildChannel,
|
GuildChannel,
|
||||||
|
@ -15,10 +14,9 @@ import {
|
||||||
import { TOKEN } from './config.ts'
|
import { TOKEN } from './config.ts'
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
presence: new ClientPresence({
|
clientProperties: {
|
||||||
name: 'Pokémon Sword',
|
browser: 'Discord iOS'
|
||||||
type: 'COMPETING'
|
}
|
||||||
})
|
|
||||||
// bot: false,
|
// bot: false,
|
||||||
// cache: new RedisCacheAdapter({
|
// cache: new RedisCacheAdapter({
|
||||||
// hostname: '127.0.0.1',
|
// hostname: '127.0.0.1',
|
||||||
|
|
137
src/test/music.ts
Normal file
137
src/test/music.ts
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
import {
|
||||||
|
CommandClient,
|
||||||
|
event,
|
||||||
|
Intents,
|
||||||
|
command,
|
||||||
|
CommandContext,
|
||||||
|
Extension,
|
||||||
|
Collection
|
||||||
|
} from '../../mod.ts'
|
||||||
|
import { LL_IP, LL_PASS, LL_PORT, TOKEN } from './config.ts'
|
||||||
|
import {
|
||||||
|
Manager,
|
||||||
|
Player
|
||||||
|
} from 'https://raw.githubusercontent.com/DjDeveloperr/lavaclient-deno/master/mod.ts'
|
||||||
|
|
||||||
|
export const nodes = [
|
||||||
|
{
|
||||||
|
id: 'main',
|
||||||
|
host: LL_IP,
|
||||||
|
port: LL_PORT,
|
||||||
|
password: LL_PASS
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
class MyClient extends CommandClient {
|
||||||
|
manager: Manager
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
prefix: ['.'],
|
||||||
|
caseSensitive: false
|
||||||
|
})
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
|
const client = this
|
||||||
|
|
||||||
|
this.manager = new Manager(nodes, {
|
||||||
|
send(id, payload) {
|
||||||
|
// Sharding not added yet
|
||||||
|
client.gateway?.send(payload)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.manager.on('socketError', ({ id }, error) =>
|
||||||
|
console.error(`${id} ran into an error`, error)
|
||||||
|
)
|
||||||
|
this.manager.on('socketReady', (node) =>
|
||||||
|
console.log(`${node.id} connected.`)
|
||||||
|
)
|
||||||
|
|
||||||
|
this.on('raw', (evt: string, d: any) => {
|
||||||
|
if (evt === 'VOICE_SERVER_UPDATE') this.manager.serverUpdate(d)
|
||||||
|
else if (evt === 'VOICE_STATE_UPDATE') this.manager.stateUpdate(d)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@event()
|
||||||
|
ready(): void {
|
||||||
|
console.log(`Logged in as ${this.user?.tag}!`)
|
||||||
|
this.manager.init(this.user?.id as string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const players = new Collection<string, Player>()
|
||||||
|
|
||||||
|
class VCExtension extends Extension {
|
||||||
|
name = 'VC'
|
||||||
|
subPrefix = 'vc'
|
||||||
|
|
||||||
|
@command()
|
||||||
|
async join(ctx: CommandContext): Promise<any> {
|
||||||
|
if (players.has(ctx.guild?.id as string) === true)
|
||||||
|
return ctx.message.reply(`Already playing in this server!`)
|
||||||
|
|
||||||
|
ctx.argString = ctx.argString.slice(4).trim()
|
||||||
|
|
||||||
|
if (ctx.argString === '')
|
||||||
|
return ctx.message.reply('You gave nothing to search.')
|
||||||
|
|
||||||
|
const userVS = await ctx.guild?.voiceStates.get(ctx.author.id)
|
||||||
|
if (userVS === undefined) {
|
||||||
|
ctx.message.reply("You're not in VC.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const player = (ctx.client as MyClient).manager.create(
|
||||||
|
ctx.guild?.id as string
|
||||||
|
)
|
||||||
|
|
||||||
|
await player.connect(userVS.channel?.id as string, { selfDeaf: true })
|
||||||
|
|
||||||
|
ctx.message.reply(`Joined VC channel - ${userVS.channel?.name}!`)
|
||||||
|
|
||||||
|
players.set(ctx.guild?.id as string, player)
|
||||||
|
|
||||||
|
ctx.channel.send(`Loading...`)
|
||||||
|
|
||||||
|
ctx.channel.send(`Searching for ${ctx.argString}...`)
|
||||||
|
|
||||||
|
const { track, info } = await player.manager
|
||||||
|
.search(`ytsearch:${ctx.argString}`)
|
||||||
|
.then((e) => e.tracks[0])
|
||||||
|
|
||||||
|
await player.play(track)
|
||||||
|
|
||||||
|
ctx.channel.send(`Now playing ${info.title}!`)
|
||||||
|
}
|
||||||
|
|
||||||
|
@command()
|
||||||
|
async leave(ctx: CommandContext): Promise<any> {
|
||||||
|
const userVS = await ctx.guild?.voiceStates.get(
|
||||||
|
(ctx.client.user?.id as unknown) as string
|
||||||
|
)
|
||||||
|
if (userVS === undefined) {
|
||||||
|
ctx.message.reply("I'm not in VC.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userVS.channel?.leave()
|
||||||
|
ctx.message.reply(`Left VC channel - ${userVS.channel?.name}!`)
|
||||||
|
|
||||||
|
if (players.has(ctx.guild?.id as string) !== true)
|
||||||
|
return ctx.message.reply('Not playing anything in this server.')
|
||||||
|
|
||||||
|
const player = (players.get(ctx.guild?.id as string) as unknown) as Player
|
||||||
|
await player.stop()
|
||||||
|
await player.destroy()
|
||||||
|
|
||||||
|
players.delete(ctx.guild?.id as string)
|
||||||
|
ctx.message.reply('Stopped player')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new MyClient()
|
||||||
|
|
||||||
|
client.extensions.load(VCExtension)
|
||||||
|
|
||||||
|
client.connect(TOKEN, Intents.None)
|
51
src/test/slash-cmd.ts
Normal file
51
src/test/slash-cmd.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import { TOKEN } from './config.ts'
|
||||||
|
|
||||||
|
export const CMD = {
|
||||||
|
name: 'blep',
|
||||||
|
description: 'Send a random adorable animal photo',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'animal',
|
||||||
|
description: 'The type of animal',
|
||||||
|
type: 3,
|
||||||
|
required: true,
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
name: 'Dog',
|
||||||
|
value: 'animal_dog'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Cat',
|
||||||
|
value: 'animal_dog'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Penguin',
|
||||||
|
value: 'animal_penguin'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'only_smol',
|
||||||
|
description: 'Whether to show only baby animals',
|
||||||
|
type: 5,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch('https://discord.com/api/v8/applications/783937840752099332/commands', {
|
||||||
|
fetch(
|
||||||
|
'https://discord.com/api/v8/applications/783937840752099332/guilds/783319033205751809/commands',
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(CMD),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Authorization:
|
||||||
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||||
|
'Bot ' + TOKEN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then(console.log)
|
96
src/test/slash.ts
Normal file
96
src/test/slash.ts
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import { Client, Intents, event, slash } from '../../mod.ts'
|
||||||
|
import { Embed } from '../structures/embed.ts'
|
||||||
|
import { Interaction } from '../structures/slash.ts'
|
||||||
|
import { TOKEN } from './config.ts'
|
||||||
|
|
||||||
|
export class MyClient extends Client {
|
||||||
|
@event()
|
||||||
|
ready(): void {
|
||||||
|
console.log(`Logged in as ${this.user?.tag}!`)
|
||||||
|
}
|
||||||
|
|
||||||
|
@slash()
|
||||||
|
send(d: Interaction): void {
|
||||||
|
d.respond({
|
||||||
|
content: d.data.options.find((e) => e.name === 'content')?.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@slash()
|
||||||
|
async eval(d: Interaction): Promise<void> {
|
||||||
|
if (
|
||||||
|
d.user.id !== '422957901716652033' &&
|
||||||
|
d.user.id !== '682849186227552266'
|
||||||
|
) {
|
||||||
|
d.respond({
|
||||||
|
content: 'This command can only be used by owner!'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const code = d.data.options.find((e) => e.name === 'code')
|
||||||
|
?.value as string
|
||||||
|
try {
|
||||||
|
// eslint-disable-next-line no-eval
|
||||||
|
let evaled = eval(code)
|
||||||
|
if (evaled instanceof Promise) evaled = await evaled
|
||||||
|
if (typeof evaled === 'object') evaled = Deno.inspect(evaled)
|
||||||
|
let res = `${evaled}`.substring(0, 1990)
|
||||||
|
while (client.token !== undefined && res.includes(client.token)) {
|
||||||
|
res = res.replace(client.token, '[REMOVED]')
|
||||||
|
}
|
||||||
|
d.respond({
|
||||||
|
content: '```js\n' + `${res}` + '\n```'
|
||||||
|
}).catch(() => {})
|
||||||
|
} catch (e) {
|
||||||
|
d.respond({
|
||||||
|
content: '```js\n' + `${e.stack}` + '\n```'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@slash()
|
||||||
|
async hug(d: Interaction): Promise<void> {
|
||||||
|
const id = d.data.options.find((e) => e.name === 'user')?.value as string
|
||||||
|
const user = (await client.users.get(id)) ?? (await client.users.fetch(id))
|
||||||
|
const url = await fetch('https://nekos.life/api/v2/img/hug')
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then((e) => e.url)
|
||||||
|
|
||||||
|
d.respond({
|
||||||
|
embeds: [
|
||||||
|
new Embed()
|
||||||
|
.setTitle(`${d.user.username} hugged ${user?.username}!`)
|
||||||
|
.setImage({ url })
|
||||||
|
.setColor(0x2f3136)
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@slash()
|
||||||
|
async kiss(d: Interaction): Promise<void> {
|
||||||
|
const id = d.data.options.find((e) => e.name === 'user')?.value as string
|
||||||
|
const user = (await client.users.get(id)) ?? (await client.users.fetch(id))
|
||||||
|
const url = await fetch('https://nekos.life/api/v2/img/kiss')
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then((e) => e.url)
|
||||||
|
|
||||||
|
d.respond({
|
||||||
|
embeds: [
|
||||||
|
new Embed()
|
||||||
|
.setTitle(`${d.user.username} kissed ${user?.username}!`)
|
||||||
|
.setImage({ url })
|
||||||
|
.setColor(0x2f3136)
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@slash('ping')
|
||||||
|
pingCmd(d: Interaction): void {
|
||||||
|
d.respond({
|
||||||
|
content: `Pong!`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new MyClient()
|
||||||
|
client.connect(TOKEN, Intents.None)
|
|
@ -191,81 +191,35 @@ const VOICE_REGIONS = (guildID: string): string =>
|
||||||
const CLIENT_USER = (): string =>
|
const CLIENT_USER = (): string =>
|
||||||
`${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me`
|
`${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me`
|
||||||
|
|
||||||
export default [
|
const APPLICATION_COMMANDS = (id: string): string =>
|
||||||
GUILDS,
|
`${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/commands`
|
||||||
GUILD,
|
|
||||||
GUILD_AUDIT_LOGS,
|
const APPLICATION_COMMAND = (id: string, cmdID: string): string =>
|
||||||
GUILD_WIDGET,
|
`${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/commands/${cmdID}`
|
||||||
GUILD_EMOJI,
|
|
||||||
GUILD_ROLE,
|
const APPLICATION_GUILD_COMMANDS = (id: string, guildID: string): string =>
|
||||||
GUILD_ROLES,
|
`${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/guilds/${guildID}/commands`
|
||||||
GUILD_INTEGRATION,
|
|
||||||
GUILD_INTEGRATIONS,
|
const APPLICATION_GUILD_COMMAND = (
|
||||||
GUILD_INTEGARTION_SYNC,
|
id: string,
|
||||||
GUILD_WIDGET_IMAGE,
|
guildID: string,
|
||||||
GUILD_BAN,
|
cmdID: string
|
||||||
GUILD_BANS,
|
): string =>
|
||||||
GUILD_CHANNEL,
|
`${DISCORD_API_URL}/v${DISCORD_API_VERSION}/applications/${id}/guilds/${guildID}/commands/${cmdID}`
|
||||||
GUILD_CHANNELS,
|
|
||||||
GUILD_MEMBER,
|
const WEBHOOK_MESSAGE = (id: string, token: string, msgID: string): string =>
|
||||||
CLIENT_USER,
|
`${DISCORD_API_URL}/v${DISCORD_API_VERSION}/webhooks/${id}/${token}/messages/${msgID}`
|
||||||
GUILD_MEMBERS,
|
|
||||||
GUILD_MEMBER_ROLE,
|
const INTERACTION_CALLBACK = (id: string, token: string): string =>
|
||||||
GUILD_INVITES,
|
`${DISCORD_API_URL}/v${DISCORD_API_VERSION}/interactions/${id}/${token}/callback`
|
||||||
GUILD_LEAVE,
|
|
||||||
GUILD_PRUNE,
|
|
||||||
GUILD_VANITY_URL,
|
|
||||||
GUILD_NICK,
|
|
||||||
GUILD_PREVIEW,
|
|
||||||
CHANNEL,
|
|
||||||
CHANNELS,
|
|
||||||
CHANNEL_MESSAGE,
|
|
||||||
CHANNEL_MESSAGES,
|
|
||||||
CHANNEL_CROSSPOST,
|
|
||||||
MESSAGE_REACTIONS,
|
|
||||||
MESSAGE_REACTION,
|
|
||||||
MESSAGE_REACTION_ME,
|
|
||||||
MESSAGE_REACTION_USER,
|
|
||||||
CHANNEL_BULK_DELETE,
|
|
||||||
CHANNEL_FOLLOW,
|
|
||||||
CHANNEL_INVITES,
|
|
||||||
CHANNEL_PIN,
|
|
||||||
CHANNEL_PINS,
|
|
||||||
CHANNEL_PERMISSION,
|
|
||||||
CHANNEL_TYPING,
|
|
||||||
GROUP_RECIPIENT,
|
|
||||||
CURRENT_USER,
|
|
||||||
CURRENT_USER_GUILDS,
|
|
||||||
USER_DM,
|
|
||||||
USER_CONNECTIONS,
|
|
||||||
LEAVE_GUILD,
|
|
||||||
USER,
|
|
||||||
CHANNEL_WEBHOOKS,
|
|
||||||
GUILD_WEBHOOK,
|
|
||||||
WEBHOOK,
|
|
||||||
WEBHOOK_WITH_TOKEN,
|
|
||||||
SLACK_WEBHOOK,
|
|
||||||
GITHUB_WEBHOOK,
|
|
||||||
GATEWAY,
|
|
||||||
GATEWAY_BOT,
|
|
||||||
CUSTOM_EMOJI,
|
|
||||||
GUILD_ICON,
|
|
||||||
GUILD_SPLASH,
|
|
||||||
GUILD_DISCOVERY_SPLASH,
|
|
||||||
GUILD_BANNER,
|
|
||||||
DEFAULT_USER_AVATAR,
|
|
||||||
USER_AVATAR,
|
|
||||||
APPLICATION_ASSET,
|
|
||||||
ACHIEVEMENT_ICON,
|
|
||||||
TEAM_ICON,
|
|
||||||
EMOJI,
|
|
||||||
GUILD_EMOJIS,
|
|
||||||
TEMPLATE,
|
|
||||||
INVITE,
|
|
||||||
VOICE_REGIONS
|
|
||||||
]
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
INTERACTION_CALLBACK,
|
||||||
|
APPLICATION_COMMAND,
|
||||||
|
APPLICATION_GUILD_COMMAND,
|
||||||
|
WEBHOOK_MESSAGE,
|
||||||
|
APPLICATION_COMMANDS,
|
||||||
|
APPLICATION_GUILD_COMMANDS,
|
||||||
GUILDS,
|
GUILDS,
|
||||||
GUILD,
|
GUILD,
|
||||||
GUILD_AUDIT_LOGS,
|
GUILD_AUDIT_LOGS,
|
||||||
|
|
|
@ -105,7 +105,8 @@ export enum GatewayEvents {
|
||||||
User_Update = 'USER_UPDATE',
|
User_Update = 'USER_UPDATE',
|
||||||
Voice_Server_Update = 'VOICE_SERVER_UPDATE',
|
Voice_Server_Update = 'VOICE_SERVER_UPDATE',
|
||||||
Voice_State_Update = 'VOICE_STATE_UPDATE',
|
Voice_State_Update = 'VOICE_STATE_UPDATE',
|
||||||
Webhooks_Update = 'WEBHOOKS_UPDATE'
|
Webhooks_Update = 'WEBHOOKS_UPDATE',
|
||||||
|
Interaction_Create = 'INTERACTION_CREATE'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IdentityPayload {
|
export interface IdentityPayload {
|
||||||
|
@ -120,11 +121,11 @@ export interface IdentityPayload {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IdentityConnection {
|
export interface IdentityConnection {
|
||||||
$os: 'darwin' | 'windows' | 'linux' | 'custom os'
|
$os: 'darwin' | 'windows' | 'linux' | 'custom os' | string
|
||||||
$browser: 'harmony' | 'Firefox'
|
$browser: 'harmony' | 'Firefox' | string
|
||||||
$device: 'harmony' | ''
|
$device: 'harmony' | string
|
||||||
$referrer?: ''
|
$referrer?: '' | string
|
||||||
$referring_domain?: ''
|
$referring_domain?: '' | string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Resume {
|
export interface Resume {
|
||||||
|
|
90
src/types/slash.ts
Normal file
90
src/types/slash.ts
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
import { EmbedPayload } from './channel.ts'
|
||||||
|
import { MemberPayload } from './guild.ts'
|
||||||
|
|
||||||
|
export interface InteractionOption {
|
||||||
|
name: string
|
||||||
|
value?: any
|
||||||
|
options?: any[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InteractionData {
|
||||||
|
name: string
|
||||||
|
id: string
|
||||||
|
options: InteractionOption[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum InteractionType {
|
||||||
|
PING = 1,
|
||||||
|
APPLICATION_COMMAND = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InteractionPayload {
|
||||||
|
type: InteractionType
|
||||||
|
token: string
|
||||||
|
member: MemberPayload
|
||||||
|
id: string
|
||||||
|
data: InteractionData
|
||||||
|
guild_id: string
|
||||||
|
channel_id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SlashCommandChoice {
|
||||||
|
name: string
|
||||||
|
value: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SlashCommandOptionType {
|
||||||
|
SUB_COMMAND = 1,
|
||||||
|
SUB_COMMAND_GROUP = 2,
|
||||||
|
STRING = 3,
|
||||||
|
INTEGER = 4,
|
||||||
|
BOOLEAN = 5,
|
||||||
|
USER = 6,
|
||||||
|
CHANNEL = 7,
|
||||||
|
ROLE = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SlashCommandOption {
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
type: SlashCommandOptionType
|
||||||
|
required: boolean
|
||||||
|
choices?: SlashCommandChoice[]
|
||||||
|
options?: SlashCommandOption[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SlashCommandPartial {
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
options: SlashCommandOption[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SlashCommandPayload extends SlashCommandPartial {
|
||||||
|
id: string
|
||||||
|
application_id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum InteractionResponseType {
|
||||||
|
PONG = 1,
|
||||||
|
ACKNOWLEDGE = 2,
|
||||||
|
CHANNEL_MESSAGE = 3,
|
||||||
|
CHANNEL_MESSAGE_WITH_SOURCE = 4,
|
||||||
|
ACK_WITH_SOURCE = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InteractionResponsePayload {
|
||||||
|
type: InteractionResponseType
|
||||||
|
data?: InteractionResponseDataPayload
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InteractionResponseDataPayload {
|
||||||
|
tts?: boolean
|
||||||
|
content: string
|
||||||
|
embeds?: EmbedPayload[]
|
||||||
|
allowed_mentions?: {
|
||||||
|
parse?: 'everyone' | 'users' | 'roles'
|
||||||
|
roles?: string[]
|
||||||
|
users?: string[]
|
||||||
|
}
|
||||||
|
flags?: number
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
export const UserFlags = {
|
export const UserFlags = {
|
||||||
DISCORD_EMPLOYEE: 1 << 0,
|
DISCORD_EMPLOYEE: 1 << 0,
|
||||||
PARTNERED_SERVER_OWNER: 1 << 1,
|
PARTNERED_SERVER_OWNER: 1 << 1,
|
||||||
DISCORD_PARTNER: 1 << 1,
|
|
||||||
HYPESQUAD_EVENTS: 1 << 2,
|
HYPESQUAD_EVENTS: 1 << 2,
|
||||||
BUGHUNTER_LEVEL_1: 1 << 3,
|
BUGHUNTER_LEVEL_1: 1 << 3,
|
||||||
HOUSE_BRAVERY: 1 << 6,
|
HOUSE_BRAVERY: 1 << 6,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// https://discord.com/developers/docs/topics/opcodes-and-status-codes#voice
|
|
||||||
import { MemberPayload } from './guild.ts'
|
import { MemberPayload } from './guild.ts'
|
||||||
|
|
||||||
export enum VoiceOpcodes { // add VoiceOpcodes - UnderC -
|
export enum VoiceOpcodes {
|
||||||
IDENTIFY = 0,
|
IDENTIFY = 0,
|
||||||
SELECT_PROTOCOL = 1,
|
SELECT_PROTOCOL = 1,
|
||||||
READY = 2,
|
READY = 2,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue