Merge pull request #94 from Helloyunho/some-fixes

Fix Some Bugs and Add Some Useful Things
This commit is contained in:
DjDeveloper 2021-01-25 00:30:07 +05:30 committed by GitHub
commit 108bd3ea62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 301 additions and 47 deletions

10
mod.ts
View file

@ -102,12 +102,16 @@ export type {
MessageOptions
} from './src/types/channel.ts'
export type { EmojiPayload } from './src/types/emoji.ts'
export { Verification } from './src/types/guild.ts'
export type {
GuildBanPayload,
GuildFeatures,
GuildIntegrationPayload,
GuildPayload,
GuildChannels
GuildBanPayload,
GuildFeatures,
GuildChannels,
GuildCreateOptions,
GuildCreateChannelOptions,
GuildCreateRolePayload
} from './src/types/guild.ts'
export type { InvitePayload, PartialInvitePayload } from './src/types/invite.ts'
export { PermissionFlags } from './src/types/permissionFlags.ts'

View file

@ -70,45 +70,45 @@ export class GuildManager extends BaseManager<GuildPayload, Guild> {
if (options.icon !== undefined && !options.icon.startsWith('data:')) {
options.icon = await fetchAuto(options.icon)
}
if (options.roles !== undefined && options.roles[0].name !== '@everyone') {
options.roles.unshift({
id: Math.floor(Math.random() * 18392375458).toString(),
name: '@everyone'
})
}
const body: GuildCreatePayload = {
name: options.name,
region: options.region,
icon: options.icon,
verification_level: options.verificationLevel,
roles:
options.roles !== undefined
? options.roles.map((obj) => {
let result: GuildCreateRolePayload
if (obj instanceof Role) {
result = {
id: obj.id,
name: obj.name,
color: obj.color,
hoist: obj.hoist,
position: obj.position,
permissions: obj.permissions.bitfield.toString(),
managed: obj.managed,
mentionable: obj.mentionable
}
} else {
result = obj
}
roles: options.roles?.map((obj) => {
let result: GuildCreateRolePayload
if (obj instanceof Role) {
result = {
id: obj.id,
name: obj.name,
color: obj.color,
hoist: obj.hoist,
position: obj.position,
permissions: obj.permissions.bitfield.toString(),
managed: obj.managed,
mentionable: obj.mentionable
}
} else {
result = obj
}
return result
})
: undefined,
channels:
options.channels !== undefined
? options.channels.map(
(obj): GuildCreateChannelPayload => ({
id: obj.id,
name: obj.name,
type: obj.type,
parent_id: obj.parentID
})
)
: undefined,
return result
}),
channels: options.channels?.map(
(obj): GuildCreateChannelPayload => ({
id: obj.id,
name: obj.name,
type: obj.type,
parent_id: obj.parentID
})
),
afk_channel_id: options.afkChannelID,
afk_timeout: options.afkTimeout,
system_channel_id: options.systemChannelID

View file

@ -41,6 +41,12 @@ export class RolesManager extends BaseManager<RolePayload, Role> {
return new Role(this.client, raw, this.guild)
}
async array(): Promise<Role[]> {
let arr = await (this.client.cache.array(this.cacheName) as RolePayload[])
if (arr === undefined) arr = []
return arr.map((e) => new Role(this.client, e, this.guild))
}
async fromPayload(roles: RolePayload[]): Promise<boolean> {
for (const role of roles) {
await this.set(role.id, role)

View file

@ -144,7 +144,7 @@ export class Client extends HarmonyEventEmitter<ClientEvents> {
if (this.upSince === undefined) return 0
else {
const dif = Date.now() - this.upSince.getTime()
if (dif < 0) return dif
if (dif < 0) return 0
else return dif
}
}

View file

@ -28,8 +28,23 @@ export interface RequestHeaders {
[name: string]: string
}
export interface DiscordAPIErrorPayload {
url: string
status: number
method: string
code?: number
message?: string
errors: object
}
export class DiscordAPIError extends Error {
name = 'DiscordAPIError'
error?: DiscordAPIErrorPayload
constructor(message?: string, error?: DiscordAPIErrorPayload) {
super(message)
this.error = error
}
}
export interface QueuedItem {
@ -399,7 +414,7 @@ export class RESTManager {
)
// At this point we know it is error
const error: { [name: string]: any } = {
const error: DiscordAPIErrorPayload = {
url: response.url,
status,
method: data.method,
@ -443,9 +458,9 @@ export class RESTManager {
HttpResponseCode.MethodNotAllowed
].includes(status)
) {
reject(new DiscordAPIError(Deno.inspect(error)))
reject(new DiscordAPIError(Deno.inspect(error), error))
} else if (status === HttpResponseCode.GatewayUnavailable) {
reject(new DiscordAPIError(Deno.inspect(error)))
reject(new DiscordAPIError(Deno.inspect(error), error))
} else reject(new DiscordAPIError('Request - Unknown Error'))
}

View file

@ -378,9 +378,7 @@ export class SlashClient {
this.token = options.token
this.publicKey = options.publicKey
if (options !== undefined) {
this.enabled = options.enabled ?? true
}
this.enabled = options.enabled ?? true
if (this.client?._decoratedSlash !== undefined) {
this.client._decoratedSlash.forEach((e) => {

View file

@ -41,6 +41,7 @@ import { RequestMembersOptions } from '../gateway/index.ts'
import { GuildPresencesManager } from '../managers/presences.ts'
import { TemplatePayload } from '../types/template.ts'
import { Template } from './template.ts'
import { DiscordAPIError } from '../models/rest.ts'
export class GuildBan extends Base {
guild: Guild
@ -403,7 +404,22 @@ export class Guild extends Base {
/** Returns a partial invite object for guilds with that feature enabled. */
async getVanity(): Promise<{ code: string | null; uses: number }> {
return this.client.rest.api.guilds[this.id]['vanity-url'].get()
try {
const value = await this.client.rest.api.guilds[this.id][
'vanity-url'
].get()
return value
} catch (error) {
if (error instanceof DiscordAPIError) {
if (error.error?.code === 50020) {
return {
code: null,
uses: 0
}
}
}
throw error
}
}
/** Returns a PNG (URL) image widget for the guild. */
@ -446,7 +462,7 @@ export class Guild extends Base {
async syncTemplate(code: string): Promise<Template> {
const payload = await this.client.rest.api.guilds[this.id].templates[
code
].sync.put()
].put()
return new Template(this.client, payload)
}
@ -515,7 +531,7 @@ export class Guild extends Base {
async prune(options?: {
days?: number
computePruneCount: true | undefined
computePruneCount?: true
includeRoles?: Array<Role | string>
}): Promise<number>
async prune(options?: {
@ -525,7 +541,7 @@ export class Guild extends Base {
}): Promise<null>
async prune(options?: {
days?: number
computePruneCount?: boolean | undefined
computePruneCount?: boolean
includeRoles?: Array<Role | string>
}): Promise<number | null> {
const body: GuildBeginPrunePayload = {

View file

@ -3,6 +3,8 @@ import { Base } from './base.ts'
import { RoleModifyPayload, RolePayload } from '../types/role.ts'
import { Permissions } from '../utils/permissions.ts'
import { Guild } from './guild.ts'
import { Member } from './member.ts'
import { User } from './user.ts'
export class Role extends Base {
id: string
@ -50,6 +52,38 @@ export class Role extends Base {
this.mentionable = data.mentionable ?? this.mentionable
}
async addTo(member: Member | User | string): Promise<boolean> {
if (member instanceof User) {
member = member.id
}
if (typeof member === 'string') {
const tempMember = await this.guild.members.get(member)
if (tempMember === undefined) {
throw new Error(`Couldn't find the member ${member}.`)
} else {
member = tempMember
}
}
return member.roles.add(this.id)
}
async removeFrom(member: Member | User | string): Promise<boolean> {
if (member instanceof User) {
member = member.id
}
if (typeof member === 'string') {
const tempMember = await this.guild.members.get(member)
if (tempMember === undefined) {
throw new Error(`Couldn't find the member ${member}.`)
} else {
member = tempMember
}
}
return member.roles.remove(this.id)
}
async delete(): Promise<Role | undefined> {
return this.guild.roles.delete(this)
}

View file

@ -5,6 +5,7 @@ import { Base } from './base.ts'
import { ImageURL } from './cdn.ts'
import { ImageSize, ImageFormats } from '../types/cdn.ts'
import { DEFAULT_USER_AVATAR, USER_AVATAR } from '../types/endpoint.ts'
import { DMChannel } from './dmChannel.ts'
export class User extends Base {
id: string
@ -89,4 +90,8 @@ export class User extends Base {
toString(): string {
return this.mention
}
async getDMchannel(): Promise<DMChannel> {
return this.client.createDM(this)
}
}

137
src/test/guild.ts Normal file
View file

@ -0,0 +1,137 @@
import {
Client,
Intents
// Verification
// PermissionFlags,
// ChannelTypes,
// GuildCreateOptions
} from '../../mod.ts'
import { TOKEN } from './config.ts'
const client = new Client()
// client.on('guildLoaded', async (guild) => {
// if (guild.name === 'OH WOW') {
// guild.delete()
// }
// })
// client.on('ready', async () => {
// await new Promise((resolve, reject) => setTimeout(resolve, 1000))
// const body: GuildCreateOptions = {
// name: 'OH WOW',
// icon: 'https://helloyunho.xyz/_dist_/images/avatar.png',
// verificationLevel: Verification.NONE,
// roles: [
// {
// id: '1',
// name: 'a role',
// color: 0x103021,
// hoist: false,
// permissions: PermissionFlags.ADMINISTRATOR.toString(),
// mentionable: true
// }
// ],
// channels: [
// {
// name: 'fucking-awesome',
// type: ChannelTypes.GUILD_TEXT,
// id: '1'
// }
// ],
// systemChannelID: '1'
// }
// const guild = await client.guilds.create(body)
// const channels = await guild.channels.array()
// console.log(channels.length)
// const invite = await guild.invites.create(channels[0].id)
// console.log(invite.link)
// })
// client.on('guildLoaded', async (guild) => {
// if (guild.id === 'GUILD_ID') {
// // const roles = await guild.roles.array()
// // if (roles.length > 0) {
// // roles.forEach(async (role) => {
// // if (role.name !== '@everyone') {
// // role.addTo('USER_ID')
// // }
// // })
// // }
// // guild.edit({
// // name: 'OH BOI',
// // verificationLevel: Verification.MEDIUM
// // })
// // const role1 = await guild.roles.create({
// // name: 'IDK1'
// // })
// // const role2 = await guild.roles.create({
// // name: 'IDK2'
// // })
// // alert()
// // await guild.roles.editPositions(
// // {
// // id: role1.id,
// // position: 1
// // },
// // {
// // id: role2.id,
// // position: 2
// // }
// // )
// // alert()
// // role1.delete()
// // role2.delete()
// // const role = await guild.roles.create({
// // name: 'IDK'
// // })
// // alert()
// // await role.edit({
// // name: 'DUMB'
// // })
// // alert()
// // console.log(
// // await guild.getPruneCount({
// // days: 7,
// // includeRoles: ['ROLE_ID']
// // })
// // )
// // console.log(
// // await guild.prune({
// // days: 7,
// // includeRoles: ['ROLE_ID']
// // })
// // )
// // console.log(
// // await guild.prune({
// // days: 7,
// // computePruneCount: false,
// // includeRoles: ['ROLE_ID']
// // })
// // )
// // await guild.editWidget({
// // enabled: true,
// // channel: 'CHANNEL_ID'
// // })
// // console.log(await guild.getWidget())
// // console.log(await guild.getVanity())
// // console.log(await guild.getWidgetImageURL())
// }
// })
client.connect(TOKEN, Intents.All)

21
src/test/template.ts Normal file
View file

@ -0,0 +1,21 @@
import { Client, Intents } from '../../mod.ts'
import { TOKEN } from './config.ts'
const client = new Client()
client.on('guildLoaded', async (guild) => {
if (guild.id === 'GUILD_ID') {
console.log((await guild.syncTemplate('TEMPLATE_ID')).code)
console.log(
(
await guild.editTemplate('TEMPLATE_ID', {
name: 'asdf',
description: 'asdfasdfasdf'
})
).code
)
console.log((await guild.deleteTemplate('TEMPLATE_ID')).id)
}
})
client.connect(TOKEN, Intents.All)

14
src/test/user.ts Normal file
View file

@ -0,0 +1,14 @@
import { Client, Intents } from '../../mod.ts'
import { TOKEN } from './config.ts'
const client = new Client()
client.on('ready', async () => {
client.editUser({
username: 'Learning'
})
const channel = await client.createDM('USER_ID')
channel.send('nice')
})
client.connect(TOKEN, Intents.All)

View file

@ -192,7 +192,7 @@ export interface GuildCreatePayload {
}
export interface GuildCreateRolePayload {
id?: string
id: string
name: string
color?: number
hoist?: boolean

View file

@ -24,4 +24,8 @@ export class Snowflake {
get increment(): string {
return (this.snowflake & 0xfffn).toString()
}
get toString(): string {
return this.id
}
}