feat(commands): replace texts with events, add whitelisting
This commit is contained in:
parent
f6393c8226
commit
7835162fd5
15 changed files with 238 additions and 142 deletions
|
@ -3,6 +3,7 @@ import { GuildPayload } from '../../types/guild.ts'
|
||||||
import { Gateway, GatewayEventHandler } from '../index.ts'
|
import { Gateway, GatewayEventHandler } from '../index.ts'
|
||||||
|
|
||||||
export const ready: GatewayEventHandler = async (gateway: Gateway, d: any) => {
|
export const ready: GatewayEventHandler = async (gateway: Gateway, d: any) => {
|
||||||
|
await gateway.client.guilds.flush()
|
||||||
gateway.client.user = new User(gateway.client, d.user)
|
gateway.client.user = new User(gateway.client, d.user)
|
||||||
gateway.sessionID = d.session_id
|
gateway.sessionID = d.session_id
|
||||||
gateway.debug(`Received READY. Session: ${gateway.sessionID}`)
|
gateway.debug(`Received READY. Session: ${gateway.sessionID}`)
|
||||||
|
|
|
@ -20,7 +20,7 @@ export class MemberRolesManager extends BaseChildManager<
|
||||||
async get (id: string): Promise<Role | undefined> {
|
async get (id: string): Promise<Role | undefined> {
|
||||||
const res = await this.parent.get(id)
|
const res = await this.parent.get(id)
|
||||||
const mem = await (this.parent as any).guild.members._get(this.member.id) as MemberPayload
|
const mem = await (this.parent as any).guild.members._get(this.member.id) as MemberPayload
|
||||||
if (res !== undefined && mem.roles.includes(res.id) === true) return res
|
if (res !== undefined && (mem.roles.includes(res.id) === true || res.id === this.member.guild.id)) return res
|
||||||
else return undefined
|
else return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ export class MemberRolesManager extends BaseChildManager<
|
||||||
const arr = (await this.parent.array()) as Role[]
|
const arr = (await this.parent.array()) as Role[]
|
||||||
const mem = await (this.parent as any).guild.members._get(this.member.id) as MemberPayload
|
const mem = await (this.parent as any).guild.members._get(this.member.id) as MemberPayload
|
||||||
return arr.filter(
|
return arr.filter(
|
||||||
(c: any) => mem.roles.includes(c.id)
|
(c: any) => mem.roles.includes(c.id) as boolean || c.id === this.member.guild.id
|
||||||
) as any
|
) as any
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { Member } from '../structures/member.ts'
|
||||||
import { GUILD_MEMBER } from '../types/endpoint.ts'
|
import { GUILD_MEMBER } from '../types/endpoint.ts'
|
||||||
import { MemberPayload } from '../types/guild.ts'
|
import { MemberPayload } from '../types/guild.ts'
|
||||||
import { BaseManager } from './base.ts'
|
import { BaseManager } from './base.ts'
|
||||||
|
import { Permissions } from "../utils/permissions.ts"
|
||||||
|
|
||||||
export class MembersManager extends BaseManager<MemberPayload, Member> {
|
export class MembersManager extends BaseManager<MemberPayload, Member> {
|
||||||
guild: Guild
|
guild: Guild
|
||||||
|
@ -14,11 +15,17 @@ export class MembersManager extends BaseManager<MemberPayload, Member> {
|
||||||
this.guild = guild
|
this.guild = guild
|
||||||
}
|
}
|
||||||
|
|
||||||
async get (key: string): Promise<Member | undefined> {
|
async get(key: string): Promise<Member | undefined> {
|
||||||
const raw = await this._get(key)
|
const raw = await this._get(key)
|
||||||
if (raw === undefined) return
|
if (raw === undefined) return
|
||||||
const user = new User(this.client, raw.user)
|
const user = new User(this.client, raw.user)
|
||||||
const res = new this.DataType(this.client, raw, user, this.guild)
|
const roles = await this.guild.roles.array()
|
||||||
|
let permissions = new Permissions(Permissions.DEFAULT)
|
||||||
|
if (roles !== undefined) {
|
||||||
|
const mRoles = roles.filter(r => raw.roles.includes(r.id) as boolean || r.id === this.guild.id)
|
||||||
|
permissions = new Permissions(mRoles.map(r => r.permissions))
|
||||||
|
}
|
||||||
|
const res = new this.DataType(this.client, raw, user, this.guild, permissions)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +34,13 @@ export class MembersManager extends BaseManager<MemberPayload, Member> {
|
||||||
this.client.rest.get(GUILD_MEMBER(this.guild.id, id)).then(async data => {
|
this.client.rest.get(GUILD_MEMBER(this.guild.id, id)).then(async data => {
|
||||||
await this.set(id, data as MemberPayload)
|
await this.set(id, data as MemberPayload)
|
||||||
const user: User = new User(this.client, data.user)
|
const user: User = new User(this.client, data.user)
|
||||||
const res = new Member(this.client, data as MemberPayload, user, this.guild)
|
const roles = await this.guild.roles.array()
|
||||||
|
let permissions = new Permissions(Permissions.DEFAULT)
|
||||||
|
if (roles !== undefined) {
|
||||||
|
const mRoles = roles.filter(r => data.roles.includes(r.id) as boolean || r.id === this.guild.id)
|
||||||
|
permissions = new Permissions(mRoles.map(r => r.permissions))
|
||||||
|
}
|
||||||
|
const res = new Member(this.client, data as MemberPayload, user, this.guild, permissions)
|
||||||
resolve(res)
|
resolve(res)
|
||||||
}).catch(e => reject(e))
|
}).catch(e => reject(e))
|
||||||
})
|
})
|
||||||
|
|
|
@ -46,6 +46,16 @@ export class Command {
|
||||||
args?: number | boolean
|
args?: number | boolean
|
||||||
/** Permission(s) required for using Command */
|
/** Permission(s) required for using Command */
|
||||||
permissions?: string | string[]
|
permissions?: string | string[]
|
||||||
|
/** Permission(s) bot will need in order to execute Command */
|
||||||
|
botPermissions?: string | string[]
|
||||||
|
/** Role(s) user will require in order to use Command. List or one of ID or name */
|
||||||
|
roles?: string | string[]
|
||||||
|
/** Whitelisted Guilds. Only these Guild(s) can execute Command. (List or one of IDs) */
|
||||||
|
whitelistedGuilds?: string | string[]
|
||||||
|
/** Whitelisted Channels. Command can be executed only in these channels. (List or one of IDs) */
|
||||||
|
whitelistedChannels?: string | string[]
|
||||||
|
/** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */
|
||||||
|
whitelistedUsers?: string | string[]
|
||||||
/** Whether the Command can only be used in Guild (if allowed in DMs) */
|
/** Whether the Command can only be used in Guild (if allowed in DMs) */
|
||||||
guildOnly?: boolean
|
guildOnly?: boolean
|
||||||
/** Whether the Command can only be used in Bot's DMs (if allowed) */
|
/** Whether the Command can only be used in Bot's DMs (if allowed) */
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Message } from "../../mod.ts"
|
import { Message } from "../../mod.ts"
|
||||||
import { Embed } from "../structures/embed.ts"
|
|
||||||
import { awaitSync } from "../utils/mixedPromise.ts"
|
import { awaitSync } from "../utils/mixedPromise.ts"
|
||||||
import { Client, ClientOptions } from './client.ts'
|
import { Client, ClientOptions } from './client.ts'
|
||||||
import { CommandContext, CommandsManager, parseCommand } from './command.ts'
|
import { CommandContext, CommandsManager, parseCommand } from './command.ts'
|
||||||
|
@ -23,33 +22,6 @@ export interface CommandClientOptions extends ClientOptions {
|
||||||
caseSensitive?: boolean
|
caseSensitive?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandText = string | Embed
|
|
||||||
|
|
||||||
export interface CommandTexts {
|
|
||||||
GUILD_ONLY?: CommandText
|
|
||||||
OWNER_ONLY?: CommandText
|
|
||||||
DMS_ONLY?: CommandText
|
|
||||||
ERROR?: CommandText
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DefaultCommandTexts: CommandTexts = {
|
|
||||||
GUILD_ONLY: 'This command can only be used in a Server!',
|
|
||||||
OWNER_ONLY: 'This command can only be used by Bot Owners!',
|
|
||||||
DMS_ONLY: "This command can only be used in Bot's DMs!",
|
|
||||||
ERROR: 'An error occured while executing command!'
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Replaces {
|
|
||||||
[name: string]: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const massReplace = (text: string, replaces: Replaces): string => {
|
|
||||||
Object.entries(replaces).forEach(replace => {
|
|
||||||
text = text.replace(new RegExp(`{{${replace[0]}}}`, 'g'), replace[1])
|
|
||||||
})
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CommandClient extends Client implements CommandClientOptions {
|
export class CommandClient extends Client implements CommandClientOptions {
|
||||||
prefix: string | string[]
|
prefix: string | string[]
|
||||||
mentionPrefix: boolean
|
mentionPrefix: boolean
|
||||||
|
@ -66,7 +38,6 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
caseSensitive: boolean
|
caseSensitive: boolean
|
||||||
extensions: ExtensionsManager = new ExtensionsManager(this)
|
extensions: ExtensionsManager = new ExtensionsManager(this)
|
||||||
commands: CommandsManager = new CommandsManager(this)
|
commands: CommandsManager = new CommandsManager(this)
|
||||||
texts: CommandTexts = DefaultCommandTexts
|
|
||||||
|
|
||||||
constructor(options: CommandClientOptions) {
|
constructor(options: CommandClientOptions) {
|
||||||
super(options)
|
super(options)
|
||||||
|
@ -162,31 +133,9 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
|
|
||||||
if (command === undefined) return
|
if (command === undefined) return
|
||||||
|
|
||||||
const baseReplaces: Replaces = {
|
if (command.whitelistedGuilds !== undefined && msg.guild !== undefined && command.whitelistedGuilds.includes(msg.guild.id) === false) return;
|
||||||
command: command.name,
|
if (command.whitelistedChannels !== undefined && command.whitelistedChannels.includes(msg.channel.id) === false) return;
|
||||||
nameUsed: parsed.name,
|
if (command.whitelistedUsers !== undefined && command.whitelistedUsers.includes(msg.author.id) === false) return;
|
||||||
prefix,
|
|
||||||
username: msg.author.username,
|
|
||||||
tag: msg.author.tag,
|
|
||||||
mention: msg.author.mention,
|
|
||||||
id: msg.author.id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.guildOnly === true && msg.guild === undefined) {
|
|
||||||
if (this.texts.GUILD_ONLY !== undefined)
|
|
||||||
return this.sendProcessedText(msg, this.texts.GUILD_ONLY, baseReplaces)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (command.dmOnly === true && msg.guild !== undefined) {
|
|
||||||
if (this.texts.DMS_ONLY !== undefined)
|
|
||||||
return this.sendProcessedText(msg, this.texts.DMS_ONLY, baseReplaces)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (command.ownerOnly === true && !this.owners.includes(msg.author.id)) {
|
|
||||||
if (this.texts.OWNER_ONLY !== undefined)
|
|
||||||
return this.sendProcessedText(msg, this.texts.OWNER_ONLY, baseReplaces)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const ctx: CommandContext = {
|
const ctx: CommandContext = {
|
||||||
client: this,
|
client: this,
|
||||||
|
@ -201,6 +150,22 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
guild: msg.guild
|
guild: msg.guild
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (command.guildOnly === true && msg.guild === undefined) return this.emit('commandGuildOnly', { ctx, command })
|
||||||
|
if (command.dmOnly === true && msg.guild !== undefined) return this.emit('commandDmOnly', { ctx, command })
|
||||||
|
if (command.ownerOnly === true && !this.owners.includes(msg.author.id)) return this.emit('commandOwnerOnly', { ctx, command })
|
||||||
|
|
||||||
|
if (command.permissions !== undefined && msg.guild !== undefined) {
|
||||||
|
const missing: string[] = []
|
||||||
|
let perms: string[] = []
|
||||||
|
if (typeof command.permissions === 'string') perms = [command.permissions]
|
||||||
|
else perms = command.permissions
|
||||||
|
for (const perm of perms) {
|
||||||
|
const has = msg.member?.permissions.has(perm)
|
||||||
|
if (has !== true) missing.push(perm)
|
||||||
|
}
|
||||||
|
if (missing.length !== 0) return this.emit('commandMissingPermissions', { command, missing, ctx })
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.emit('commandUsed', { context: ctx })
|
this.emit('commandUsed', { context: ctx })
|
||||||
|
|
||||||
|
@ -210,30 +175,7 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
const result = await awaitSync(command.execute(ctx))
|
const result = await awaitSync(command.execute(ctx))
|
||||||
command.afterExecute(ctx, result)
|
command.afterExecute(ctx, result)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (this.texts.ERROR !== undefined)
|
this.emit('commandError', { command, parsed, error: e, ctx })
|
||||||
this.sendProcessedText(
|
|
||||||
msg,
|
|
||||||
this.texts.ERROR,
|
|
||||||
Object.assign(baseReplaces, { error: e.message })
|
|
||||||
)
|
|
||||||
this.emit('commandError', { command, parsed, error: e })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendProcessedText(msg: Message, text: CommandText, replaces: Replaces): any {
|
|
||||||
if (typeof text === 'string') {
|
|
||||||
text = massReplace(text, replaces)
|
|
||||||
return msg.channel.send(text)
|
|
||||||
} else {
|
|
||||||
if (text.description !== undefined)
|
|
||||||
text.description = massReplace(text.description, replaces)
|
|
||||||
if (text.title !== undefined)
|
|
||||||
text.description = massReplace(text.title, replaces)
|
|
||||||
if (text.author?.name !== undefined)
|
|
||||||
text.description = massReplace(text.author.name, replaces)
|
|
||||||
if (text.footer?.text !== undefined)
|
|
||||||
text.description = massReplace(text.footer.text, replaces)
|
|
||||||
return msg.channel.send(text)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { GuildChannelsManager } from '../managers/guildChannels.ts'
|
||||||
import { MembersManager } from '../managers/members.ts'
|
import { MembersManager } from '../managers/members.ts'
|
||||||
import { Role } from './role.ts'
|
import { Role } from './role.ts'
|
||||||
import { GuildEmojisManager } from '../managers/guildEmojis.ts'
|
import { GuildEmojisManager } from '../managers/guildEmojis.ts'
|
||||||
|
import { Member } from "./member.ts"
|
||||||
|
|
||||||
export class Guild extends Base {
|
export class Guild extends Base {
|
||||||
id: string
|
id: string
|
||||||
|
@ -214,4 +215,10 @@ export class Guild extends Base {
|
||||||
async getEveryoneRole (): Promise<Role> {
|
async getEveryoneRole (): Promise<Role> {
|
||||||
return (await this.roles.array().then(arr => arr?.sort((b, a) => a.position - b.position)[0]) as any) as Role
|
return (await this.roles.array().then(arr => arr?.sort((b, a) => a.position - b.position)[0]) as any) as Role
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async me(): Promise<Member> {
|
||||||
|
const get = await this.members.get(this.client.user?.id as string)
|
||||||
|
if (get === undefined) throw new Error('Guild#me is not cached')
|
||||||
|
return get
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { MemberRolesManager } from "../managers/memberRoles.ts"
|
import { MemberRolesManager } from "../managers/memberRoles.ts"
|
||||||
import { Client } from '../models/client.ts'
|
import { Client } from '../models/client.ts'
|
||||||
import { MemberPayload } from '../types/guild.ts'
|
import { MemberPayload } from '../types/guild.ts'
|
||||||
|
import { Permissions } from "../utils/permissions.ts"
|
||||||
import { Base } from './base.ts'
|
import { Base } from './base.ts'
|
||||||
import { Guild } from "./guild.ts"
|
import { Guild } from "./guild.ts"
|
||||||
import { User } from './user.ts'
|
import { User } from './user.ts'
|
||||||
|
@ -15,13 +16,12 @@ export class Member extends Base {
|
||||||
deaf: boolean
|
deaf: boolean
|
||||||
mute: boolean
|
mute: boolean
|
||||||
guild: Guild
|
guild: Guild
|
||||||
|
permissions: Permissions
|
||||||
|
|
||||||
constructor (client: Client, data: MemberPayload, user: User, guild: Guild) {
|
constructor (client: Client, data: MemberPayload, user: User, guild: Guild, perms?: Permissions) {
|
||||||
super(client)
|
super(client)
|
||||||
this.id = data.user.id
|
this.id = data.user.id
|
||||||
this.user = user
|
this.user = user
|
||||||
// this.user =
|
|
||||||
// cache.get('user', data.user.id) ?? new User(this.client, data.user)
|
|
||||||
this.nick = data.nick
|
this.nick = data.nick
|
||||||
this.guild = guild
|
this.guild = guild
|
||||||
this.roles = new MemberRolesManager(this.client, this.guild.roles, this)
|
this.roles = new MemberRolesManager(this.client, this.guild.roles, this)
|
||||||
|
@ -29,8 +29,8 @@ export class Member extends Base {
|
||||||
this.premiumSince = data.premium_since
|
this.premiumSince = data.premium_since
|
||||||
this.deaf = data.deaf
|
this.deaf = data.deaf
|
||||||
this.mute = data.mute
|
this.mute = data.mute
|
||||||
// TODO: Cache in Gateway Event Code
|
if (perms !== undefined) this.permissions = perms
|
||||||
// cache.set('member', this.id, this)
|
else this.permissions = new Permissions(Permissions.DEFAULT)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected readFromData (data: MemberPayload): void {
|
protected readFromData (data: MemberPayload): void {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Client } from '../models/client.ts'
|
import { Client } from '../models/client.ts'
|
||||||
import { Base } from './base.ts'
|
import { Base } from './base.ts'
|
||||||
import { RolePayload } from '../types/role.ts'
|
import { RolePayload } from '../types/role.ts'
|
||||||
|
import { Permissions } from "../utils/permissions.ts"
|
||||||
|
|
||||||
export class Role extends Base {
|
export class Role extends Base {
|
||||||
id: string
|
id: string
|
||||||
|
@ -8,7 +9,7 @@ export class Role extends Base {
|
||||||
color: number
|
color: number
|
||||||
hoist: boolean
|
hoist: boolean
|
||||||
position: number
|
position: number
|
||||||
permissions: string
|
permissions: Permissions
|
||||||
managed: boolean
|
managed: boolean
|
||||||
mentionable: boolean
|
mentionable: boolean
|
||||||
|
|
||||||
|
@ -25,11 +26,9 @@ export class Role extends Base {
|
||||||
this.color = data.color
|
this.color = data.color
|
||||||
this.hoist = data.hoist
|
this.hoist = data.hoist
|
||||||
this.position = data.position
|
this.position = data.position
|
||||||
this.permissions = data.permissions
|
this.permissions = new Permissions(data.permissions)
|
||||||
this.managed = data.managed
|
this.managed = data.managed
|
||||||
this.mentionable = data.mentionable
|
this.mentionable = data.mentionable
|
||||||
// TODO: Cache in Gateway Event Code
|
|
||||||
// cache.set('role', this.id, this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected readFromData (data: RolePayload): void {
|
protected readFromData (data: RolePayload): void {
|
||||||
|
@ -38,7 +37,7 @@ export class Role extends Base {
|
||||||
this.color = data.color ?? this.color
|
this.color = data.color ?? this.color
|
||||||
this.hoist = data.hoist ?? this.hoist
|
this.hoist = data.hoist ?? this.hoist
|
||||||
this.position = data.position ?? this.position
|
this.position = data.position ?? this.position
|
||||||
this.permissions = data.permissions ?? this.permissions
|
this.permissions = new Permissions(data.permissions) ?? this.permissions
|
||||||
this.managed = data.managed ?? this.managed
|
this.managed = data.managed ?? this.managed
|
||||||
this.mentionable = data.mentionable ?? this.mentionable
|
this.mentionable = data.mentionable ?? this.mentionable
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Client } from '../models/client.ts'
|
import { Client } from '../models/client.ts'
|
||||||
import { UserPayload } from '../types/user.ts'
|
import { UserPayload } from '../types/user.ts'
|
||||||
|
import { UserFlagsManager } from "../utils/userFlags.ts"
|
||||||
import { Base } from './base.ts'
|
import { Base } from './base.ts'
|
||||||
|
|
||||||
export class User extends Base {
|
export class User extends Base {
|
||||||
|
@ -13,9 +14,9 @@ export class User extends Base {
|
||||||
locale?: string
|
locale?: string
|
||||||
verified?: boolean
|
verified?: boolean
|
||||||
email?: string
|
email?: string
|
||||||
flags?: number
|
flags?: UserFlagsManager
|
||||||
premiumType?: 0 | 1 | 2
|
premiumType?: 0 | 1 | 2
|
||||||
publicFlags?: number
|
publicFlags?: UserFlagsManager
|
||||||
|
|
||||||
get tag (): string {
|
get tag (): string {
|
||||||
return `${this.username}#${this.discriminator}`
|
return `${this.username}#${this.discriminator}`
|
||||||
|
@ -41,11 +42,9 @@ export class User extends Base {
|
||||||
this.locale = data.locale
|
this.locale = data.locale
|
||||||
this.verified = data.verified
|
this.verified = data.verified
|
||||||
this.email = data.email
|
this.email = data.email
|
||||||
this.flags = data.flags
|
this.flags = new UserFlagsManager(data.flags)
|
||||||
this.premiumType = data.premium_type
|
this.premiumType = data.premium_type
|
||||||
this.publicFlags = data.public_flags
|
this.publicFlags = new UserFlagsManager(data.public_flags)
|
||||||
// TODO: Cache in Gateway Event Code
|
|
||||||
// cache.set('user', this.id, this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected readFromData (data: UserPayload): void {
|
protected readFromData (data: UserPayload): void {
|
||||||
|
@ -59,9 +58,9 @@ export class User extends Base {
|
||||||
this.locale = data.locale ?? this.locale
|
this.locale = data.locale ?? this.locale
|
||||||
this.verified = data.verified ?? this.verified
|
this.verified = data.verified ?? this.verified
|
||||||
this.email = data.email ?? this.email
|
this.email = data.email ?? this.email
|
||||||
this.flags = data.flags ?? this.flags
|
this.flags = new UserFlagsManager(data.flags) ?? this.flags
|
||||||
this.premiumType = data.premium_type ?? this.premiumType
|
this.premiumType = data.premium_type ?? this.premiumType
|
||||||
this.publicFlags = data.public_flags ?? this.publicFlags
|
this.publicFlags = new UserFlagsManager(data.public_flags) ?? this.publicFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
toString (): string {
|
toString (): string {
|
||||||
|
|
|
@ -13,6 +13,7 @@ export default class UserinfoCommand extends Command {
|
||||||
.setAuthor({ name: member.user.tag })
|
.setAuthor({ name: member.user.tag })
|
||||||
.addField("ID", member.id)
|
.addField("ID", member.id)
|
||||||
.addField("Roles", roles.map(r => r.name).join(", "))
|
.addField("Roles", roles.map(r => r.name).join(", "))
|
||||||
|
.addField('Permissions', JSON.stringify(member.permissions.has('ADMINISTRATOR')))
|
||||||
.setColor(0xff00ff)
|
.setColor(0xff00ff)
|
||||||
ctx.channel.send(embed)
|
ctx.channel.send(embed)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,35 @@
|
||||||
// https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags
|
// https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags
|
||||||
|
|
||||||
enum PermissionFlags {
|
export const PermissionFlags: { [key: string]: number } = {
|
||||||
CREATE_INSTANT_INVITE = 0x00000001,
|
CREATE_INSTANT_INVITE: 1 << 0,
|
||||||
|
KICK_MEMBERS: 1 << 1,
|
||||||
KICK_MEMBERS = 0x00000002,
|
BAN_MEMBERS: 1 << 2,
|
||||||
BAN_MEMBERS = 0x00000004,
|
ADMINISTRATOR: 1 << 3,
|
||||||
ADMINISTRATOR = 0x00000008,
|
MANAGE_CHANNELS: 1 << 4,
|
||||||
MANAGE_CHANNELS = 0x00000010,
|
MANAGE_GUILD: 1 << 5,
|
||||||
MANAGE_GUILD = 0x00000020,
|
ADD_REACTIONS: 1 << 6,
|
||||||
|
VIEW_AUDIT_LOG: 1 << 7,
|
||||||
ADD_REACTIONS = 0x00000040,
|
PRIORITY_SPEAKER: 1 << 8,
|
||||||
VIEW_AUDIT_LOG = 0x00000080,
|
STREAM: 1 << 9,
|
||||||
PRIORITY_SPEAKER = 0x00000100,
|
VIEW_CHANNEL: 1 << 10,
|
||||||
STREAM = 0x00000200,
|
SEND_MESSAGES: 1 << 11,
|
||||||
|
SEND_TTS_MESSAGES: 1 << 12,
|
||||||
VIEW_CHANNEL = 0x00000400,
|
MANAGE_MESSAGES: 1 << 13,
|
||||||
SEND_MESSAGES = 0x00000800,
|
EMBED_LINKS: 1 << 14,
|
||||||
SEND_TTS_MESSAGES = 0x00001000,
|
ATTACH_FILES: 1 << 15,
|
||||||
MANAGE_MESSAGES = 0x00002000,
|
READ_MESSAGE_HISTORY: 1 << 16,
|
||||||
|
MENTION_EVERYONE: 1 << 17,
|
||||||
EMBED_LINKS = 0x00004000,
|
USE_EXTERNAL_EMOJIS: 1 << 18,
|
||||||
ATTACH_FILES = 0x00008000,
|
VIEW_GUILD_INSIGHTS: 1 << 19,
|
||||||
READ_MESSAGE_HISTORY = 0x00010000,
|
CONNECT: 1 << 20,
|
||||||
MENTION_EVERYONE = 0x00020000,
|
SPEAK: 1 << 21,
|
||||||
USE_EXTERNAL_EMOJIS = 0x00040000,
|
MUTE_MEMBERS: 1 << 22,
|
||||||
VIEW_GUILD_INSIGHTS = 0x00080000,
|
DEAFEN_MEMBERS: 1 << 23,
|
||||||
|
MOVE_MEMBERS: 1 << 24,
|
||||||
CONNECT = 0x00100000,
|
USE_VAD: 1 << 25,
|
||||||
SPEAK = 0x00200000,
|
CHANGE_NICKNAME: 1 << 26,
|
||||||
MUTE_MEMBERS = 0x00400000,
|
MANAGE_NICKNAMES: 1 << 27,
|
||||||
DEAFEN_MEMBERS = 0x00800000,
|
MANAGE_ROLES: 1 << 28,
|
||||||
MOVE_MEMBERS = 0x01000000,
|
MANAGE_WEBHOOKS: 1 << 29,
|
||||||
USE_VAD = 0x02000000,
|
MANAGE_EMOJIS: 1 << 30,
|
||||||
|
}
|
||||||
CHANGE_NICKNAME = 0x04000000,
|
|
||||||
MANAGE_NICKNAMES = 0x08000000,
|
|
||||||
MANAGE_ROLES = 0x10000000,
|
|
||||||
MANAGE_WEBHOOKS = 0x20000000,
|
|
||||||
MANAGE_EMOJIS = 0x40000000
|
|
||||||
}
|
|
||||||
|
|
||||||
export { PermissionFlags }
|
|
16
src/types/userFlags.ts
Normal file
16
src/types/userFlags.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
export const UserFlags = {
|
||||||
|
DISCORD_EMPLOYEE: 1 << 0,
|
||||||
|
PARTNERED_SERVER_OWNER: 1 << 1,
|
||||||
|
DISCORD_PARTNER: 1 << 1,
|
||||||
|
HYPESQUAD_EVENTS: 1 << 2,
|
||||||
|
BUGHUNTER_LEVEL_1: 1 << 3,
|
||||||
|
HOUSE_BRAVERY: 1 << 6,
|
||||||
|
HOUSE_BRILLIANCE: 1 << 7,
|
||||||
|
HOUSE_BALANCE: 1 << 8,
|
||||||
|
EARLY_SUPPORTER: 1 << 9,
|
||||||
|
TEAM_USER: 1 << 10,
|
||||||
|
SYSTEM: 1 << 12,
|
||||||
|
BUGHUNTER_LEVEL_2: 1 << 14,
|
||||||
|
VERIFIED_BOT: 1 << 16,
|
||||||
|
EARLY_VERIFIED_DEVELOPER: 1 << 17
|
||||||
|
}
|
86
src/utils/bitfield.ts
Normal file
86
src/utils/bitfield.ts
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// Ported from https://github.com/discordjs/discord.js/blob/master/src/util/BitField.js
|
||||||
|
export type BitFieldResolvable = number | BitField | string | BitField[]
|
||||||
|
|
||||||
|
export class BitField {
|
||||||
|
flags: { [name: string]: number } = {}
|
||||||
|
bitfield: any
|
||||||
|
|
||||||
|
constructor(flags: { [name: string]: number }, bits: any) {
|
||||||
|
this.flags = flags
|
||||||
|
this.bitfield = BitField.resolve(this.flags, bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
any(bit: BitFieldResolvable): boolean {
|
||||||
|
return (this.bitfield & BitField.resolve(this.flags, bit)) !== 0
|
||||||
|
}
|
||||||
|
|
||||||
|
equals(bit: BitFieldResolvable): boolean {
|
||||||
|
return this.bitfield === BitField.resolve(this.flags, bit)
|
||||||
|
}
|
||||||
|
|
||||||
|
has(bit: BitFieldResolvable, ...args: any[]): boolean {
|
||||||
|
if (Array.isArray(bit)) return bit.every(p => this.has(p))
|
||||||
|
return (this.bitfield & BitField.resolve(this.flags, bit)) === bit
|
||||||
|
}
|
||||||
|
|
||||||
|
missing(bits: any, ...hasParams: any[]): string[] {
|
||||||
|
if (!Array.isArray(bits)) bits = new BitField(this.flags, bits).toArray(false)
|
||||||
|
return bits.filter((p: any) => !this.has(p, ...hasParams))
|
||||||
|
}
|
||||||
|
|
||||||
|
freeze(): Readonly<BitField> {
|
||||||
|
return Object.freeze(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
add(...bits: BitFieldResolvable[]): BitField {
|
||||||
|
let total = 0
|
||||||
|
for (const bit of bits) {
|
||||||
|
total |= BitField.resolve(this.flags, bit)
|
||||||
|
}
|
||||||
|
if (Object.isFrozen(this)) return new BitField(this.flags, this.bitfield | total)
|
||||||
|
this.bitfield |= total
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(...bits: BitFieldResolvable[]): BitField {
|
||||||
|
let total = 0
|
||||||
|
for (const bit of bits) {
|
||||||
|
total |= BitField.resolve(this.flags, bit)
|
||||||
|
}
|
||||||
|
if (Object.isFrozen(this)) return new BitField(this.flags, this.bitfield & ~total)
|
||||||
|
this.bitfield &= ~total
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize(...hasParams: any[]): { [key: string]: any } {
|
||||||
|
const serialized: { [key: string]: any } = {}
|
||||||
|
for (const [flag, bit] of Object.entries(this.flags)) serialized[flag] = this.has(BitField.resolve(this.flags, bit), ...hasParams)
|
||||||
|
return serialized
|
||||||
|
}
|
||||||
|
|
||||||
|
toArray(...hasParams: any[]): string[] {
|
||||||
|
return Object.keys(this.flags).filter(bit => this.has(BitField.resolve(this.flags, bit), ...hasParams))
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(): any {
|
||||||
|
return this.bitfield
|
||||||
|
}
|
||||||
|
|
||||||
|
valueOf(): any {
|
||||||
|
return this.bitfield
|
||||||
|
}
|
||||||
|
|
||||||
|
*[Symbol.iterator](): any {
|
||||||
|
yield* this.toArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
static resolve(flags: any, bit: BitFieldResolvable = 0): number {
|
||||||
|
if (typeof bit === 'string' && !isNaN(parseInt(bit))) return parseInt(bit)
|
||||||
|
if (typeof bit === 'number' && bit >= 0) return bit
|
||||||
|
if (bit instanceof BitField) return this.resolve(flags, bit.bitfield)
|
||||||
|
if (Array.isArray(bit)) return bit.map(p => this.resolve(flags, p)).reduce((prev, p) => prev | p, 0)
|
||||||
|
if (typeof bit === 'string' && typeof flags[bit] !== 'undefined') return flags[bit]
|
||||||
|
const error = new RangeError('BITFIELD_INVALID')
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
22
src/utils/permissions.ts
Normal file
22
src/utils/permissions.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Ported from https://github.com/discordjs/discord.js/blob/master/src/util/Permissions.js
|
||||||
|
import { PermissionFlags } from "../types/permissionFlags.ts"
|
||||||
|
import { BitField } from "./bitfield.ts"
|
||||||
|
|
||||||
|
export type PermissionResolvable = string | number | Permissions | PermissionResolvable[]
|
||||||
|
|
||||||
|
export class Permissions extends BitField {
|
||||||
|
static DEFAULT = 104324673
|
||||||
|
static ALL = Object.values(PermissionFlags).reduce((all, p) => all | p, 0)
|
||||||
|
|
||||||
|
constructor(bits: any) {
|
||||||
|
super(PermissionFlags, bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
any(permission: PermissionResolvable, checkAdmin = true): boolean {
|
||||||
|
return (checkAdmin && super.has(this.flags.ADMINISTRATOR)) || super.any(permission as any)
|
||||||
|
}
|
||||||
|
|
||||||
|
has(permission: PermissionResolvable, checkAdmin = true): boolean {
|
||||||
|
return (checkAdmin && super.has(this.flags.ADMINISTRATOR)) || super.has(permission as any)
|
||||||
|
}
|
||||||
|
}
|
8
src/utils/userFlags.ts
Normal file
8
src/utils/userFlags.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { UserFlags } from "../types/userFlags.ts";
|
||||||
|
import { BitField } from "./bitfield.ts";
|
||||||
|
|
||||||
|
export class UserFlagsManager extends BitField {
|
||||||
|
constructor(bits: any) {
|
||||||
|
super(UserFlags, bits)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue