Merge branch 'stage-instance-struct'

This commit is contained in:
Yuzu 2022-07-03 23:15:02 -05:00
commit e170994ad3
9 changed files with 190 additions and 69 deletions

2
mod.ts
View File

@ -13,12 +13,14 @@ export * from "./structures/WelcomeChannel.ts";
export * from "./structures/WelcomeScreen.ts";
export * from "./structures/channels/BaseChannel.ts";
export * from "./structures/channels/BaseVoiceChannel.ts";
export * from "./structures/channels/ChannelFactory.ts";
export * from "./structures/channels/DMChannel.ts";
export * from "./structures/channels/GuildChannel.ts";
export * from "./structures/channels/NewsChannel.ts";
export * from "./structures/channels/TextChannel.ts";
export * from "./structures/channels/ThreadChannel.ts";
export * from "./structures/channels/StageChannel.ts";
export * from "./structures/channels/VoiceChannel.ts";
export * from "./structures/components/ActionRowComponent.ts";

View File

@ -0,0 +1,61 @@
import type { Model } from "./Base.ts";
import type { Session } from "../session/Session.ts";
import type { Snowflake } from "../util/Snowflake.ts";
import type { DiscordStageInstance as DiscordAutoClosingStageInstance } from "../vendor/external.ts";
import * as Routes from "../util/Routes.ts";
interface DiscordStageInstance extends DiscordAutoClosingStageInstance {
privacy_level: PrivacyLevels;
discoverable_disabled: boolean;
guild_scheduled_event_id: Snowflake;
}
export enum PrivacyLevels {
Public = 1,
GuildOnly = 2,
}
export class StageInstance implements Model {
constructor(session: Session, data: DiscordStageInstance) {
this.session = session;
this.id = data.id;
this.channelId = data.channel_id;
this.guildId = data.guild_id;
this.topic = data.topic;
this.privacyLevel = data.privacy_level;
this.discoverableDisabled = data.discoverable_disabled;
this.guildScheduledEventId = data.guild_scheduled_event_id;
}
readonly session: Session;
readonly id: Snowflake;
channelId: Snowflake;
guildId: Snowflake;
topic: string;
// TODO: see if this works
privacyLevel: PrivacyLevels;
discoverableDisabled: boolean;
guildScheduledEventId: Snowflake;
async edit(options: { topic?: string, privacyLevel?: PrivacyLevels }) {
const stageInstance = await this.session.rest.runMethod<DiscordStageInstance>(
this.session.rest,
"PATCH",
Routes.STAGE_INSTANCE(this.id),
{
topic: options.topic,
privacy_level: options.privacyLevel
}
);
return new StageInstance(this.session, stageInstance);
}
async delete() {
await this.session.rest.runMethod<undefined>(this.session.rest, "DELETE", Routes.STAGE_INSTANCE(this.id));
}
}
export default StageInstance;

View File

@ -0,0 +1,62 @@
import type { Snowflake } from "../../util/Snowflake.ts";
import type { Session } from "../../session/Session.ts";
import type { ChannelTypes, DiscordChannel, VideoQualityModes } from "../../vendor/external.ts";
import { GatewayOpcodes } from "../../vendor/external.ts";
import { calculateShardId } from "../../vendor/gateway/calculateShardId.ts";
import GuildChannel from "./GuildChannel.ts";
/**
* @link https://discord.com/developers/docs/topics/gateway#update-voice-state
*/
export interface UpdateVoiceState {
guildId: string;
channelId?: string;
selfMute: boolean;
selfDeaf: boolean;
}
export abstract class BaseVoiceChannel extends GuildChannel {
constructor(session: Session, data: DiscordChannel, guildId: Snowflake) {
super(session, data, guildId);
this.bitRate = data.bitrate;
this.userLimit = data.user_limit ?? 0;
this.videoQuality = data.video_quality_mode;
this.nsfw = !!data.nsfw;
this.type = data.type as number;
if (data.rtc_region) {
this.rtcRegion = data.rtc_region;
}
}
override type: ChannelTypes.GuildVoice | ChannelTypes.GuildStageVoice;
bitRate?: number;
userLimit: number;
rtcRegion?: Snowflake;
videoQuality?: VideoQualityModes;
nsfw: boolean;
/**
* This function was gathered from Discordeno it may not work
*/
async connect(options?: UpdateVoiceState) {
const shardId = calculateShardId(this.session.gateway, BigInt(super.guildId));
const shard = this.session.gateway.manager.shards.get(shardId);
if (!shard) {
throw new Error(`Shard (id: ${shardId} not found`);
}
await shard.send({
op: GatewayOpcodes.VoiceStateUpdate,
d: {
guild_id: super.guildId,
channel_id: super.id,
self_mute: Boolean(options?.selfMute),
self_deaf: options?.selfDeaf ?? true,
},
});
}
}
export default BaseVoiceChannel;

View File

@ -7,13 +7,15 @@ import VoiceChannel from "./VoiceChannel.ts";
import DMChannel from "./DMChannel.ts";
import NewsChannel from "./NewsChannel.ts";
import ThreadChannel from "./ThreadChannel.ts";
import StageChannel from "./StageChannel.ts";
export type Channel =
| TextChannel
| VoiceChannel
| DMChannel
| NewsChannel
| ThreadChannel;
| ThreadChannel
| StageChannel;
export class ChannelFactory {
static from(session: Session, channel: DiscordChannel): Channel {
@ -27,6 +29,8 @@ export class ChannelFactory {
return new DMChannel(session, channel);
case ChannelTypes.GuildVoice:
return new VoiceChannel(session, channel, channel.guild_id!);
case ChannelTypes.GuildStageVoice:
return new StageChannel(session, channel, channel.guild_id!);
default:
if (textBasedChannels.includes(channel.type)) {
return new TextChannel(session, channel);

View File

@ -0,0 +1,16 @@
import type { Snowflake } from "../../util/Snowflake.ts";
import type { Session } from "../../session/Session.ts";
import type { ChannelTypes, DiscordChannel } from "../../vendor/external.ts";
import BaseVoiceChannel from "./BaseVoiceChannel.ts";
export class StageChannel extends BaseVoiceChannel {
constructor(session: Session, data: DiscordChannel, guildId: Snowflake) {
super(session, data, guildId);
this.type = data.type as number;
this.topic = data.topic ? data.topic : undefined;
}
override type: ChannelTypes.GuildStageVoice;
topic?: string;
}
export default StageChannel;

View File

@ -44,6 +44,7 @@ export const textBasedChannels = [
ChannelTypes.GuildPrivateThread,
ChannelTypes.GuildPublicThread,
ChannelTypes.GuildNews,
ChannelTypes.GuildVoice,
ChannelTypes.GuildText,
];
@ -53,6 +54,7 @@ export type TextBasedChannels =
| ChannelTypes.GuildPrivateThread
| ChannelTypes.GuildPublicThread
| ChannelTypes.GuildNews
| ChannelTypes.GuildVoice
| ChannelTypes.GuildText;
export class TextChannel {
@ -85,21 +87,28 @@ export class TextChannel {
/**
* Mixin
*/
static applyTo(klass: Function) {
klass.prototype.fetchPins = TextChannel.prototype.fetchPins;
klass.prototype.createInvite = TextChannel.prototype.createInvite;
klass.prototype.fetchMessages = TextChannel.prototype.fetchMessages;
klass.prototype.sendTyping = TextChannel.prototype.sendTyping;
klass.prototype.pinMessage = TextChannel.prototype.pinMessage;
klass.prototype.unpinMessage = TextChannel.prototype.unpinMessage;
klass.prototype.addReaction = TextChannel.prototype.addReaction;
klass.prototype.removeReaction = TextChannel.prototype.removeReaction;
klass.prototype.removeReactionEmoji = TextChannel.prototype.removeReactionEmoji;
klass.prototype.nukeReactions = TextChannel.prototype.nukeReactions;
klass.prototype.fetchReactions = TextChannel.prototype.fetchReactions;
klass.prototype.sendMessage = TextChannel.prototype.sendMessage;
klass.prototype.editMessage = TextChannel.prototype.editMessage;
klass.prototype.createWebhook = TextChannel.prototype.createWebhook;
static applyTo(klass: Function, ignore: Array<keyof TextChannel> = []) {
const methods: Array<keyof TextChannel> = [
"fetchPins",
"createInvite",
"fetchMessages",
"sendTyping",
"pinMessage",
"unpinMessage",
"addReaction",
"removeReaction",
"nukeReactions",
"fetchPins",
"sendMessage",
"editMessage",
"createWebhook",
];
for (const method of methods) {
if (ignore.includes(method)) continue;
klass.prototype[method] = TextChannel.prototype[method];
}
}
async fetchPins(): Promise<Message[] | []> {

View File

@ -1,60 +1,19 @@
import type { Snowflake } from "../../util/Snowflake.ts";
import type { Session } from "../../session/Session.ts";
import type { DiscordChannel, VideoQualityModes } from "../../vendor/external.ts";
import { GatewayOpcodes } from "../../vendor/external.ts";
import { calculateShardId } from "../../vendor/gateway/calculateShardId.ts";
import GuildChannel from "./GuildChannel.ts";
import type { ChannelTypes, DiscordChannel } from "../../vendor/external.ts";
import BaseVoiceChannel from "./BaseVoiceChannel.ts";
import TextChannel from "./TextChannel.ts";
/**
* @link https://discord.com/developers/docs/topics/gateway#update-voice-state
*/
export interface UpdateVoiceState {
guildId: string;
channelId?: string;
selfMute: boolean;
selfDeaf: boolean;
}
export class VoiceChannel extends GuildChannel {
export class VoiceChannel extends BaseVoiceChannel {
constructor(session: Session, data: DiscordChannel, guildId: Snowflake) {
super(session, data, guildId);
this.bitRate = data.bitrate;
this.userLimit = data.user_limit ?? 0;
this.videoQuality = data.video_quality_mode;
this.nsfw = !!data.nsfw;
if (data.rtc_region) {
this.rtcRegion = data.rtc_region;
}
}
bitRate?: number;
userLimit: number;
rtcRegion?: Snowflake;
videoQuality?: VideoQualityModes;
nsfw: boolean;
/**
* This function was gathered from Discordeno it may not work
*/
async connect(options?: UpdateVoiceState) {
const shardId = calculateShardId(this.session.gateway, BigInt(super.guildId));
const shard = this.session.gateway.manager.shards.get(shardId);
if (!shard) {
throw new Error(`Shard (id: ${shardId} not found`);
}
await shard.send({
op: GatewayOpcodes.VoiceStateUpdate,
d: {
guild_id: super.guildId,
channel_id: super.id,
self_mute: Boolean(options?.selfMute),
self_deaf: options?.selfDeaf ?? true,
},
});
this.type = data.type as number;
}
override type: ChannelTypes.GuildVoice;
}
export interface VoiceChannel extends TextChannel, BaseVoiceChannel {}
TextChannel.applyTo(VoiceChannel);
export default VoiceChannel;

View File

@ -128,7 +128,7 @@ export interface GuildCreateOptionsChannel {
nsfw?: boolean;
bitrate?: number;
userLimit?: number;
region?: string | null;
rtcRegion?: string | null;
videoQualityMode?: VideoQualityModes;
permissionOverwrites?: MakeRequired<Partial<DiscordOverwrite>, "id">[];
rateLimitPerUser?: number;
@ -527,7 +527,7 @@ export class Guild extends BaseGuild implements Model {
bitrate: channel.bitrate,
parent_id: channel.parentId,
permission_overwrites: channel.permissionOverwrites,
region: channel.region,
rtc_region: channel.rtcRegion,
user_limit: channel.userLimit,
video_quality_mode: channel.videoQualityMode,
rate_limit_per_user: channel.rateLimitPerUser,

View File

@ -303,3 +303,11 @@ export function THREAD_ARCHIVED_PRIVATE_JOINED(channelId: Snowflake, options?: L
export function FORUM_START(channelId: Snowflake) {
return `/channels/${channelId}/threads?has_message=true`;
}
export function STAGE_INSTANCES() {
return `/stage-instances`;
}
export function STAGE_INSTANCE(channelId: Snowflake) {
return `/stage-instances/${channelId}`;
}