harmony/src/structures/channel.ts

350 lines
10 KiB
TypeScript

import { Client } from '../models/client.ts'
import {
ChannelPayload,
ChannelTypes,
ModifyChannelOption,
ModifyChannelPayload,
Overwrite,
OverwritePayload,
OverwriteAsArg,
OverrideType
} from '../types/channel.ts'
import { CHANNEL } from '../types/endpoint.ts'
import { GuildChannelPayloads, GuildChannels } from '../types/guild.ts'
import getChannelByType from '../utils/getChannelByType.ts'
import { Permissions } from '../utils/permissions.ts'
import { SnowflakeBase } from './base.ts'
import { Guild } from './guild.ts'
import { Member } from './member.ts'
import { Role } from './role.ts'
export class Channel extends SnowflakeBase {
type: ChannelTypes
id: string
static cacheName = 'channel'
get mention(): string {
return `<#${this.id}>`
}
constructor(client: Client, data: ChannelPayload) {
super(client, data)
this.type = data.type
this.id = data.id
}
readFromData(data: ChannelPayload): void {
this.type = data.type ?? this.type
this.id = data.id ?? this.id
}
}
export class GuildChannel extends Channel {
guildID: string
name: string
position: number
permissionOverwrites: OverwritePayload[]
guild: Guild
nsfw: boolean
parentID?: string
constructor(client: Client, data: GuildChannelPayloads, guild: Guild) {
super(client, data)
this.guildID = data.guild_id
this.name = data.name
this.guild = guild
this.position = data.position
this.permissionOverwrites = data.permission_overwrites
this.nsfw = data.nsfw
this.parentID = data.parent_id
}
readFromData(data: GuildChannelPayloads): void {
super.readFromData(data)
this.guildID = data.guild_id ?? this.guildID
this.name = data.name ?? this.name
this.position = data.position ?? this.position
this.permissionOverwrites =
data.permission_overwrites ?? this.permissionOverwrites
this.nsfw = data.nsfw ?? this.nsfw
this.parentID = data.parent_id ?? this.parentID
}
/** Get Permission Overties for a specific Member or Role */
async overwritesFor(target: Member | Role | string): Promise<Overwrite[]> {
const stringToObject =
typeof target === 'string'
? (await this.guild.members.get(target)) ??
(await this.guild.roles.get(target))
: target
if (stringToObject === undefined) {
throw new Error('Member or Role not found')
} else {
target = stringToObject
}
const roles =
target instanceof Member ? await target.roles.array() : undefined
const overwrites: Overwrite[] = []
for (const overwrite of this.permissionOverwrites) {
if (
overwrite.id === this.guild.id ||
roles?.some((e) => e.id === overwrite.id) === true ||
overwrite.id === target.id
) {
const id =
(await this.guild.members.get(overwrite.id)) ??
(await this.guild.roles.get(overwrite.id)) ??
overwrite.id
const allow = new Permissions(overwrite.allow)
const deny = new Permissions(overwrite.deny)
overwrites.push({
id,
type: overwrite.type,
allow,
deny
})
}
}
return overwrites
}
/** Get Permissions for a Member in this Channel */
async permissionsFor(target: Member | Role | string): Promise<Permissions> {
const id = typeof target === 'string' ? target : target.id
if (id === this.guild.ownerID) return new Permissions(Permissions.ALL)
const stringToObject =
typeof target === 'string'
? (await this.guild.members.get(target)) ??
(await this.guild.roles.get(target))
: target
if (stringToObject === undefined) {
throw new Error('Member or Role not found')
} else {
target = stringToObject
}
if (target.permissions.has('ADMINISTRATOR') === true)
return new Permissions(Permissions.ALL)
const overwrites = await this.overwritesFor(target)
const everyoneOW = overwrites.find((e) => e.id === this.guild.id)
const roleOWs = overwrites.filter((e) => e.type === 0)
const memberOWs = overwrites.filter((e) => e.type === 1)
return target.permissions
.remove(everyoneOW !== undefined ? Number(everyoneOW.deny) : 0)
.add(everyoneOW !== undefined ? Number(everyoneOW.allow) : 0)
.remove(roleOWs.length === 0 ? 0 : roleOWs.map((e) => Number(e.deny)))
.add(roleOWs.length === 0 ? 0 : roleOWs.map((e) => Number(e.allow)))
.remove(memberOWs.length === 0 ? 0 : memberOWs.map((e) => Number(e.deny)))
.add(memberOWs.length === 0 ? 0 : memberOWs.map((e) => Number(e.allow)))
}
async edit(options?: ModifyChannelOption): Promise<GuildChannels> {
const body: ModifyChannelPayload = {
name: options?.name,
position: options?.position,
permission_overwrites: options?.permissionOverwrites,
parent_id: options?.parentID,
nsfw: options?.nsfw
}
const resp = await this.client.rest.patch(CHANNEL(this.id), body)
return (
(getChannelByType(this.client, resp, this.guild) as
| GuildChannels
| undefined) ?? new GuildChannel(this.client, resp, this.guild)
)
}
/** Edit name of the channel */
async setName(name: string): Promise<GuildChannels> {
return await this.edit({ name })
}
/** Edit NSFW property of the channel */
async setNSFW(nsfw: boolean): Promise<GuildChannels> {
return await this.edit({ nsfw })
}
/** Set Permission Overwrites of the Channel */
async setOverwrites(overwrites: OverwriteAsArg[]): Promise<GuildChannels> {
const result = overwrites.map(
(overwrite): OverwritePayload => {
const id =
typeof overwrite.id === 'string' ? overwrite.id : overwrite.id.id
const allow =
typeof overwrite.allow === 'string'
? overwrite.allow
: overwrite.allow?.toJSON() ?? '0'
const deny =
typeof overwrite.deny === 'string'
? overwrite.deny
: overwrite.deny?.toJSON() ?? '0'
const type =
overwrite.id instanceof Role
? 0
: overwrite.id instanceof Member
? 1
: overwrite.type
if (type === undefined) {
throw new Error('Overwrite type is undefined.')
}
return {
id,
type,
allow,
deny
}
}
)
return await this.edit({ permissionOverwrites: result })
}
/** Add a Permission Overwrite */
async addOverwrite(overwrite: OverwriteAsArg): Promise<GuildChannels> {
const overwrites = this.permissionOverwrites
const id = typeof overwrite.id === 'string' ? overwrite.id : overwrite.id.id
const allow =
typeof overwrite.allow === 'string'
? overwrite.allow
: overwrite.allow?.toJSON() ?? '0'
const deny =
typeof overwrite.deny === 'string'
? overwrite.deny
: overwrite.deny?.toJSON() ?? '0'
const type =
overwrite.id instanceof Role
? 0
: overwrite.id instanceof Member
? 1
: overwrite.type
if (type === undefined) {
throw new Error('Overwrite type is undefined.')
}
overwrites.push({
id,
type,
allow,
deny
})
return await this.edit({ permissionOverwrites: overwrites })
}
/** Remove a Permission Overwrite */
async removeOverwrite(
target: Member | Role | string
): Promise<GuildChannels> {
target = typeof target === 'string' ? target : target.id
if (this.permissionOverwrites.find((e) => e.id === target) === undefined)
throw new Error('Permission Overwrite not found')
const overwrites = this.permissionOverwrites.filter((e) => e.id !== target)
return await this.edit({ permissionOverwrites: overwrites })
}
/** Edit a Permission Overwrite */
async editOverwrite(
overwrite: OverwriteAsArg,
{
overriteAllow = OverrideType.ADD,
overriteDeny = OverrideType.ADD
}: {
overriteAllow: OverrideType
overriteDeny: OverrideType
}
): Promise<GuildChannels> {
const id = typeof overwrite.id === 'string' ? overwrite.id : overwrite.id.id
const index = this.permissionOverwrites.findIndex((e) => e.id === id)
if (index < 0) throw new Error('Permission Overwrite not found')
const overwrites = this.permissionOverwrites
let allow: string
let deny: string
if (
overwrite.allow !== undefined &&
overriteAllow !== OverrideType.REPLACE
) {
switch (overriteAllow) {
case OverrideType.ADD: {
const originalAllow = new Permissions(overwrites[index].allow)
const newAllow = new Permissions(overwrite.allow)
allow = originalAllow.add([newAllow]).toJSON()
break
}
case OverrideType.REMOVE: {
const originalAllow = new Permissions(overwrites[index].allow)
const newAllow = new Permissions(overwrite.allow)
allow = originalAllow.remove([newAllow]).toJSON()
break
}
}
} else {
allow =
typeof overwrite.allow === 'string'
? overwrite.allow
: overwrite.allow?.toJSON() ?? overwrites[index].allow
}
if (overwrite.deny !== undefined && overriteDeny !== OverrideType.REPLACE) {
switch (overriteDeny) {
case OverrideType.ADD: {
const originalDeny = new Permissions(overwrites[index].deny)
const newDeny = new Permissions(overwrite.deny)
deny = originalDeny.add([newDeny]).toJSON()
break
}
case OverrideType.REMOVE: {
const originalDeny = new Permissions(overwrites[index].deny)
const newDeny = new Permissions(overwrite.deny)
deny = originalDeny.remove([newDeny]).toJSON()
break
}
}
} else {
deny =
typeof overwrite.deny === 'string'
? overwrite.deny
: overwrite.deny?.toJSON() ?? overwrites[index].deny
}
const type =
overwrite.id instanceof Role
? 0
: overwrite.id instanceof Member
? 1
: overwrite.type
if (type === undefined) {
throw new Error('Overwrite type is undefined.')
}
overwrites[index] = {
id,
type,
allow,
deny
}
return await this.edit({ permissionOverwrites: overwrites })
}
/** Edit position of the channel */
async setPosition(position: number): Promise<GuildChannels> {
return await this.edit({ position })
}
}