mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-03 05:26:07 +00:00
new select menus (#122)
This commit is contained in:
parent
6a5fce0f58
commit
f6b745c726
@ -79,6 +79,14 @@ export enum MessageComponentTypes {
|
|||||||
SelectMenu = 3,
|
SelectMenu = 3,
|
||||||
/** A text input object */
|
/** A text input object */
|
||||||
InputText = 4,
|
InputText = 4,
|
||||||
|
/** A select menu for picking from users */
|
||||||
|
UserSelect = 5,
|
||||||
|
/** A select menu for picking from roles */
|
||||||
|
RoleSelect = 6,
|
||||||
|
/** A select menu for picking from users and roles */
|
||||||
|
MentionableSelect = 7,
|
||||||
|
/** A select menu for picking from channels */
|
||||||
|
ChannelSelect = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum TextStyles {
|
export enum TextStyles {
|
||||||
@ -1260,20 +1268,20 @@ export type MakeRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] };
|
|||||||
// THANK YOU YUI FOR SHARING THIS!
|
// THANK YOU YUI FOR SHARING THIS!
|
||||||
export type CamelCase<S extends string> =
|
export type CamelCase<S extends string> =
|
||||||
S extends `${infer P1}_${infer P2}${infer P3}`
|
S extends `${infer P1}_${infer P2}${infer P3}`
|
||||||
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
|
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
|
||||||
: Lowercase<S>;
|
: Lowercase<S>;
|
||||||
export type Camelize<T> = {
|
export type Camelize<T> = {
|
||||||
// eslint-disable-next-line @typescript-eslint/array-type
|
// eslint-disable-next-line @typescript-eslint/array-type
|
||||||
[K in keyof T as CamelCase<string & K>]: T[K] extends Array<infer U>
|
[K in keyof T as CamelCase<string & K>]: T[K] extends Array<infer U>
|
||||||
? // eslint-disable-next-line @typescript-eslint/ban-types
|
? // eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
U extends {}
|
U extends {}
|
||||||
? // eslint-disable-next-line @typescript-eslint/array-type
|
? // eslint-disable-next-line @typescript-eslint/array-type
|
||||||
Array<Camelize<U>>
|
Array<Camelize<U>>
|
||||||
: T[K]
|
: T[K]
|
||||||
: // eslint-disable-next-line @typescript-eslint/ban-types
|
: // eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
T[K] extends {}
|
T[K] extends {}
|
||||||
? Camelize<T[K]>
|
? Camelize<T[K]>
|
||||||
: never;
|
: never;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PickPartial<T, K extends keyof T> = {
|
export type PickPartial<T, K extends keyof T> = {
|
||||||
|
@ -1187,7 +1187,11 @@ export interface DiscordActionRow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DiscordSelectMenuComponent {
|
export interface DiscordSelectMenuComponent {
|
||||||
type: MessageComponentTypes.SelectMenu;
|
type: MessageComponentTypes.SelectMenu |
|
||||||
|
MessageComponentTypes.RoleSelect |
|
||||||
|
MessageComponentTypes.UserSelect |
|
||||||
|
MessageComponentTypes.MentionableSelect |
|
||||||
|
MessageComponentTypes.ChannelSelect;
|
||||||
/** A custom identifier for this component. Maximum 100 characters. */
|
/** A custom identifier for this component. Maximum 100 characters. */
|
||||||
custom_id: string;
|
custom_id: string;
|
||||||
/** A custom placeholder text if nothing is selected. Maximum 150 characters. */
|
/** A custom placeholder text if nothing is selected. Maximum 150 characters. */
|
||||||
@ -2396,8 +2400,8 @@ export interface DiscordGuildMemberUpdate {
|
|||||||
/** https://discord.com/developers/docs/topics/gateway#message-reaction-remove-all */
|
/** https://discord.com/developers/docs/topics/gateway#message-reaction-remove-all */
|
||||||
export interface DiscordMessageReactionRemoveAll
|
export interface DiscordMessageReactionRemoveAll
|
||||||
extends Pick<
|
extends Pick<
|
||||||
DiscordMessageReactionAdd,
|
DiscordMessageReactionAdd,
|
||||||
'channel_id' | 'message_id' | 'guild_id'
|
'channel_id' | 'message_id' | 'guild_id'
|
||||||
> { }
|
> { }
|
||||||
|
|
||||||
// TODO: add docs link
|
// TODO: add docs link
|
||||||
|
@ -223,6 +223,10 @@ export class ActionRow extends BaseComponent implements ActionRowComponent {
|
|||||||
}
|
}
|
||||||
return new Button(session, component);
|
return new Button(session, component);
|
||||||
case MessageComponentTypes.SelectMenu:
|
case MessageComponentTypes.SelectMenu:
|
||||||
|
case MessageComponentTypes.RoleSelect:
|
||||||
|
case MessageComponentTypes.UserSelect:
|
||||||
|
case MessageComponentTypes.MentionableSelect:
|
||||||
|
case MessageComponentTypes.ChannelSelect:
|
||||||
return new SelectMenu(session, component);
|
return new SelectMenu(session, component);
|
||||||
case MessageComponentTypes.InputText:
|
case MessageComponentTypes.InputText:
|
||||||
return new TextInput(
|
return new TextInput(
|
||||||
@ -257,6 +261,10 @@ export class ComponentFactory {
|
|||||||
}
|
}
|
||||||
return new Button(session, component);
|
return new Button(session, component);
|
||||||
case MessageComponentTypes.SelectMenu:
|
case MessageComponentTypes.SelectMenu:
|
||||||
|
case MessageComponentTypes.RoleSelect:
|
||||||
|
case MessageComponentTypes.UserSelect:
|
||||||
|
case MessageComponentTypes.MentionableSelect:
|
||||||
|
case MessageComponentTypes.ChannelSelect:
|
||||||
return new SelectMenu(session, component);
|
return new SelectMenu(session, component);
|
||||||
case MessageComponentTypes.InputText:
|
case MessageComponentTypes.InputText:
|
||||||
return new TextInput(
|
return new TextInput(
|
||||||
|
@ -3,91 +3,101 @@ import type { ComponentEmoji } from '@biscuitland/core';
|
|||||||
import { MessageComponentTypes } from '@biscuitland/api-types';
|
import { MessageComponentTypes } from '@biscuitland/api-types';
|
||||||
|
|
||||||
export class SelectMenuOptionBuilder {
|
export class SelectMenuOptionBuilder {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.#data = {} as DiscordSelectOption;
|
this.#data = {} as DiscordSelectOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
#data: DiscordSelectOption;
|
#data: DiscordSelectOption;
|
||||||
|
|
||||||
setLabel(label: string): SelectMenuOptionBuilder {
|
setLabel(label: string): SelectMenuOptionBuilder {
|
||||||
this.#data.label = label;
|
this.#data.label = label;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setValue(value: string): SelectMenuOptionBuilder {
|
setValue(value: string): SelectMenuOptionBuilder {
|
||||||
this.#data.value = value;
|
this.#data.value = value;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setDescription(description: string): SelectMenuOptionBuilder {
|
setDescription(description: string): SelectMenuOptionBuilder {
|
||||||
this.#data.description = description;
|
this.#data.description = description;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefault(Default = true): SelectMenuOptionBuilder {
|
setDefault(Default = true): SelectMenuOptionBuilder {
|
||||||
this.#data.default = Default;
|
this.#data.default = Default;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setEmoji(emoji: ComponentEmoji): SelectMenuOptionBuilder {
|
setEmoji(emoji: ComponentEmoji): SelectMenuOptionBuilder {
|
||||||
this.#data.emoji = emoji;
|
this.#data.emoji = emoji;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): DiscordSelectOption {
|
toJSON(): DiscordSelectOption {
|
||||||
return { ...this.#data };
|
return { ...this.#data };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SelectMenuBuilder {
|
export class SelectMenuBuilder {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.#data = {} as DiscordSelectMenuComponent;
|
this.#data = {} as DiscordSelectMenuComponent;
|
||||||
this.type = MessageComponentTypes.SelectMenu;
|
this.type = MessageComponentTypes.SelectMenu;
|
||||||
this.options = [];
|
this.options = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
#data: DiscordSelectMenuComponent;
|
#data: DiscordSelectMenuComponent;
|
||||||
type: MessageComponentTypes.SelectMenu;
|
type: MessageComponentTypes.SelectMenu |
|
||||||
options: SelectMenuOptionBuilder[];
|
MessageComponentTypes.RoleSelect |
|
||||||
|
MessageComponentTypes.UserSelect |
|
||||||
|
MessageComponentTypes.MentionableSelect |
|
||||||
|
MessageComponentTypes.ChannelSelect;
|
||||||
|
|
||||||
setPlaceholder(placeholder: string): this {
|
options: SelectMenuOptionBuilder[];
|
||||||
this.#data.placeholder = placeholder;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
setValues(max?: number, min?: number): this {
|
setType(type: this['type']) {
|
||||||
this.#data.max_values = max;
|
this.type = type;
|
||||||
this.#data.min_values = min;
|
return this;
|
||||||
return this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
setDisabled(disabled = true): this {
|
setPlaceholder(placeholder: string): this {
|
||||||
this.#data.disabled = disabled;
|
this.#data.placeholder = placeholder;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCustomId(id: string): this {
|
setValues(max?: number, min?: number): this {
|
||||||
this.#data.custom_id = id;
|
this.#data.max_values = max;
|
||||||
return this;
|
this.#data.min_values = min;
|
||||||
}
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
setOptions(...options: SelectMenuOptionBuilder[]): this {
|
setDisabled(disabled = true): this {
|
||||||
this.options.splice(
|
this.#data.disabled = disabled;
|
||||||
0,
|
return this;
|
||||||
this.options.length,
|
}
|
||||||
...options,
|
|
||||||
);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
addOptions(...options: SelectMenuOptionBuilder[]): this {
|
setCustomId(id: string): this {
|
||||||
this.options.push(
|
this.#data.custom_id = id;
|
||||||
...options,
|
return this;
|
||||||
);
|
}
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(): DiscordSelectMenuComponent {
|
setOptions(...options: SelectMenuOptionBuilder[]): this {
|
||||||
return { ...this.#data, type: this.type, options: this.options.map(option => option.toJSON()) };
|
this.options.splice(
|
||||||
}
|
0,
|
||||||
|
this.options.length,
|
||||||
|
...options,
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addOptions(...options: SelectMenuOptionBuilder[]): this {
|
||||||
|
this.options.push(
|
||||||
|
...options,
|
||||||
|
);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(): DiscordSelectMenuComponent {
|
||||||
|
return { ...this.#data, type: this.type, options: this.options.map(option => option.toJSON()) };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ export class DefaultRestAdapter implements RestAdapter {
|
|||||||
private url: string;
|
private url: string;
|
||||||
|
|
||||||
constructor(options: DefaultRestOptions) {
|
constructor(options: DefaultRestOptions) {
|
||||||
this.options = Object.assign(Object.create(DefaultRestAdapter.DEFAULTS), options);
|
this.options = Object.assign({}, DefaultRestAdapter.DEFAULTS, options);
|
||||||
|
|
||||||
if (this.options.url) {
|
if (this.options.url) {
|
||||||
this.url = `${options.url}/v${this.options.version}`;
|
this.url = `${options.url}/v${this.options.version}`;
|
||||||
|
@ -30,10 +30,10 @@ export class ShardManager {
|
|||||||
}
|
}
|
||||||
>();
|
>();
|
||||||
|
|
||||||
readonly shards = new Map<number, Shard>();
|
readonly shards = new Map<number, Shard>();
|
||||||
|
|
||||||
constructor(options: ShardManagerOptions) {
|
constructor(options: ShardManagerOptions) {
|
||||||
this.options = Options({}, ShardManager.DEFAULTS, options);
|
this.options = Options(ShardManager.DEFAULTS, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invokes internal processing and respawns shards */
|
/** Invokes internal processing and respawns shards */
|
||||||
@ -59,11 +59,11 @@ export class ShardManager {
|
|||||||
|
|
||||||
/** Create the start sequence of the shards inside the buckets. */
|
/** Create the start sequence of the shards inside the buckets. */
|
||||||
for (let i = 0; i < gateway.shards; i++) {
|
for (let i = 0; i < gateway.shards; i++) {
|
||||||
const bucketID = i % gateway.session_start_limit.max_concurrency;
|
const bucketID = i % gateway.session_start_limit.max_concurrency;
|
||||||
const bucket = this.buckets.get(bucketID);
|
const bucket = this.buckets.get(bucketID);
|
||||||
|
|
||||||
if (bucket) {
|
if (bucket) {
|
||||||
const workerID = Math.floor(i / workers.shards);
|
const workerID = Math.floor(i / workers.shards);
|
||||||
const worker = bucket.workers.find(w => w.id === workerID);
|
const worker = bucket.workers.find(w => w.id === workerID);
|
||||||
|
|
||||||
if (worker) {
|
if (worker) {
|
||||||
@ -75,22 +75,22 @@ export class ShardManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Route all shards to workers */
|
/** Route all shards to workers */
|
||||||
this.buckets.forEach(async bucket => {
|
this.buckets.forEach(async bucket => {
|
||||||
for (const worker of bucket.workers) {
|
for (const worker of bucket.workers) {
|
||||||
|
|
||||||
for (const id of worker.queue) {
|
for (const id of worker.queue) {
|
||||||
await this.connect(id);
|
await this.connect(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invokes the bucket to prepare the connection to the shard */
|
/** Invokes the bucket to prepare the connection to the shard */
|
||||||
private async connect(id: number): Promise<Shard> {
|
private async connect(id: number): Promise<Shard> {
|
||||||
const { gateway } = this.options;
|
const { gateway } = this.options;
|
||||||
|
|
||||||
let shard = this.shards.get(id);
|
let shard = this.shards.get(id);
|
||||||
|
|
||||||
if (!shard) {
|
if (!shard) {
|
||||||
shard = new Shard({
|
shard = new Shard({
|
||||||
@ -107,8 +107,8 @@ export class ShardManager {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleIdentify: async (id: number) => {
|
handleIdentify: async (id: number) => {
|
||||||
await this.buckets.get(id % gateway.session_start_limit.max_concurrency)!.leak.acquire(1); // remove await?
|
await this.buckets.get(id % gateway.session_start_limit.max_concurrency)!.leak.acquire(1); // remove await?
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.shards.set(id, shard);
|
this.shards.set(id, shard);
|
||||||
|
@ -27,7 +27,7 @@ export class Shard {
|
|||||||
resumeURL: string | null = null;
|
resumeURL: string | null = null;
|
||||||
sessionID: string | null = null;
|
sessionID: string | null = null;
|
||||||
|
|
||||||
sequence = 0 ;
|
sequence = 0;
|
||||||
|
|
||||||
resolves: Map<string, (payload?: unknown) => void> = new Map();
|
resolves: Map<string, (payload?: unknown) => void> = new Map();
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ export class Shard {
|
|||||||
ws: WebSocket | null = null;
|
ws: WebSocket | null = null;
|
||||||
|
|
||||||
constructor(options: ShardOptions) {
|
constructor(options: ShardOptions) {
|
||||||
this.options = Options({}, Shard.DEFAULTS, options);
|
this.options = Options(Shard.DEFAULTS, options);
|
||||||
|
|
||||||
this.bucket = createLeakyBucket({
|
this.bucket = createLeakyBucket({
|
||||||
max: 120,
|
max: 120,
|
||||||
@ -78,7 +78,7 @@ export class Shard {
|
|||||||
this.heartbeatInterval = null;
|
this.heartbeatInterval = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
|
if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ export class Shard {
|
|||||||
setTimeout(() => resolve(true), this.options.shards.timeout);
|
setTimeout(() => resolve(true), this.options.shards.timeout);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
identify() {
|
identify() {
|
||||||
this.status = 'Identifying';
|
this.status = 'Identifying';
|
||||||
@ -110,14 +110,14 @@ export class Shard {
|
|||||||
op: GatewayOpcodes.Identify,
|
op: GatewayOpcodes.Identify,
|
||||||
d: {
|
d: {
|
||||||
token: `Bot ${this.options.config.token}`,
|
token: `Bot ${this.options.config.token}`,
|
||||||
compress: false,
|
compress: false,
|
||||||
properties: {
|
properties: {
|
||||||
os: 'linux',
|
os: 'linux',
|
||||||
device: 'Biscuit',
|
device: 'Biscuit',
|
||||||
browser: 'Biscuit'
|
browser: 'Biscuit'
|
||||||
},
|
},
|
||||||
intents: this.options.config.intents,
|
intents: this.options.config.intents,
|
||||||
shard: [this.options.id, this.options.gateway.shards],
|
shard: [this.options.id, this.options.gateway.shards],
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -203,7 +203,7 @@ export class Shard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async onMessage(data: any, isBinary: boolean) {
|
private async onMessage(data: any, isBinary: boolean) {
|
||||||
const payload = this.pack(data as Buffer | ArrayBuffer, isBinary);
|
const payload = this.pack(data as Buffer | ArrayBuffer, isBinary);
|
||||||
|
|
||||||
if (payload.s != null) {
|
if (payload.s != null) {
|
||||||
this.sequence = payload.s;
|
this.sequence = payload.s;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user