Skip to content

Commit 3c4c7a5

Browse files
committed
Unbork callbacks
1 parent 9f8e36b commit 3c4c7a5

13 files changed

Lines changed: 114 additions & 64 deletions

File tree

backend/src/bot/plugin/core/command/about.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { ComponentTypes, type ContainerComponent } from "oceanic.js";
1+
import { ComponentTypes } from "oceanic.js";
22
import { bot } from "../../../index.ts";
33
import { coreConfig } from "../index.ts";
4-
import { defineCommand } from "../public/command.ts";
4+
import { defineCommand, type CommandContainerComponent } from "../public/command.ts";
55
import { permissionsGuard } from "../public/helper/commandGuards.ts";
66

77
const DESCRIPTION = `
@@ -38,7 +38,7 @@ export const aboutCommand = defineCommand({
3838

3939
uptimeString += uptime % 60 + " secs";
4040

41-
const container: ContainerComponent = {
41+
const container: CommandContainerComponent = {
4242
components: [],
4343
type: ComponentTypes.CONTAINER,
4444
};

backend/src/bot/plugin/core/commandEngine/handler/componentHandler.ts

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { ComponentInteraction, Guild, Member, MessageFlags, Shard, User, type AnyTextableGuildChannel, type MessageComponentTypes } from "oceanic.js";
1+
import { ComponentInteraction, ComponentTypes, Guild, Member, MessageFlags, Shard, User, type AnyTextableGuildChannel, type MessageComponentTypes } from "oceanic.js";
22
import { TTLMap } from "../../../../../common/ttlMap.ts";
3-
import type { ActionRowComponent, ComponentCallback, ComponentContext, Reply } from "../../public/command.ts";
3+
import type { AnyCommandComponentWithCallback, CommandActionRow, CommandComponent, CommandComponentCallback, CommandContainerComponent, CommandSectionComponent, ComponentContext, Reply } from "../../public/command.ts";
44
import { defineEventListener } from "../../public/eventListener.ts";
55
import { AUTO_DEFER_AFTER, STATE_CLEANUP_INTERVAL, STATE_EXPIRE_AFTER, transformReply } from "../index.ts";
66

77
interface ComponentData {
8-
callbacks: Map<string, Required<ComponentCallback>>;
8+
callbacks: Map<string, Required<CommandComponentCallback>>;
99
invokerID: string;
1010
}
1111

@@ -52,25 +52,49 @@ export const componentInterationHandler = defineEventListener("interactionCreate
5252
}
5353
});
5454

55-
export function listenForInteractions(messageID: string, invokerID: string, components: ActionRowComponent[][]): void {
55+
export function listenForInteractions(messageID: string, invokerID: string, components: CommandComponent[]): void {
5656
const callbacks: ComponentData["callbacks"] = new Map;
5757

58-
for (const row of components) {
59-
for (const component of row) {
60-
if (!("callback" in component))
61-
continue;
62-
63-
if (component.disabled)
64-
continue;
65-
66-
const { customID, callback, invokerOnly } = component;
67-
callbacks.set(customID, { callback, invokerOnly: invokerOnly ?? true });
58+
for (const component of components) {
59+
if (component.type === ComponentTypes.ACTION_ROW)
60+
putCallbacksForActionRow(callbacks, component);
61+
else if (component.type === ComponentTypes.SECTION)
62+
putCallbackForSection(callbacks, component);
63+
else if (component.type === ComponentTypes.CONTAINER) {
64+
putCallbacksForContainer(callbacks, component);
6865
}
6966
}
7067

7168
activeComponents.set(messageID, { callbacks, invokerID: invokerID });
7269
}
7370

71+
export function putCallbacksForActionRow(callbacks: ComponentData["callbacks"], row: CommandActionRow): void {
72+
for (const action of row.components)
73+
if ("callback" in action)
74+
putCallback(callbacks, action);
75+
}
76+
77+
export function putCallbackForSection(callbacks: ComponentData["callbacks"], section: CommandSectionComponent): void {
78+
if ("callback" in section.accessory)
79+
putCallback(callbacks, section.accessory);
80+
}
81+
export function putCallbacksForContainer(callbacks: ComponentData["callbacks"], section: CommandContainerComponent): void {
82+
for (const component of section.components) {
83+
if (component.type === ComponentTypes.ACTION_ROW)
84+
putCallbacksForActionRow(callbacks, component);
85+
else if (component.type === ComponentTypes.SECTION)
86+
putCallbackForSection(callbacks, component);
87+
}
88+
}
89+
90+
91+
export function putCallback(callbacks: ComponentData["callbacks"], component: AnyCommandComponentWithCallback): void {
92+
callbacks.set(
93+
component.customID,
94+
{ callback: component.callback, invokerOnly: component.invokerOnly ?? true }
95+
);
96+
}
97+
7498
export function unlistenForInteractions(messageID: string): void {
7599
activeComponents.delete(messageID);
76100
}

backend/src/bot/plugin/core/commandEngine/handler/prefixHandler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { STATE_CLEANUP_INTERVAL, STATE_EXPIRE_AFTER, transformReply } from "../i
1313
import { formatArgsParseError } from "../parsing/index.ts";
1414
import { readPrefixArgs, readPrefixName } from "../parsing/prefixParser.ts";
1515
import { StringReader } from "../parsing/stringReader.ts";
16-
import { unlistenForInteractions } from "./componentHandler.ts";
16+
import { listenForInteractions, unlistenForInteractions } from "./componentHandler.ts";
1717

1818
const logger = moduleLogger();
1919

@@ -189,8 +189,8 @@ class PrefixContext implements CommandContext {
189189
await this._response.edit(messageOptions);
190190
}
191191

192-
// if (typeof reply !== "string" && reply.components !== undefined)
193-
// listenForInteractions(this._response.id, this.message.author.id, reply.components);
192+
if (typeof reply !== "string" && reply.components !== undefined)
193+
listenForInteractions(this._response.id, this.message.author.id, reply.components);
194194
}
195195

196196
async _delete(): Promise<void> {

backend/src/bot/plugin/core/commandEngine/handler/slashHandler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { getCommands, getCommandsByName } from "../commandCache.ts";
1515
import { AUTO_DEFER_AFTER, transformReply } from "../index.ts";
1616
import { formatArgsParseError } from "../parsing/index.ts";
1717
import { readSlashArgs } from "../parsing/slashParser.ts";
18-
import { unlistenForInteractions } from "./componentHandler.ts";
18+
import { listenForInteractions, unlistenForInteractions } from "./componentHandler.ts";
1919

2020
const logger = moduleLogger();
2121

@@ -200,8 +200,8 @@ class SlashContext implements CommandContext {
200200
this._acked = true;
201201
}
202202

203-
// if (typeof reply !== "string" && reply.components !== undefined && this._responseID !== null)
204-
// listenForInteractions(this._responseID, this._interaction.user.id, reply.components);
203+
if (typeof reply !== "string" && reply.components !== undefined && this._responseID !== null)
204+
listenForInteractions(this._responseID, this._interaction.user.id, reply.components);
205205
}
206206

207207
_clearTimeout() {

backend/src/bot/plugin/core/public/command.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type AnyTextableGuildChannel, type CreateMessageOptions, Guild, Member, Message, type MessageComponent, Shard, User } from "oceanic.js";
1+
import { type ActionRowBase, type AnyTextableGuildChannel, type ButtonComponent, type ContainerComponent, type CreateMessageOptions, Guild, Member, Message, type MessageActionRow, type MessageComponent, type SectionComponent, type SelectMenuComponent, Shard, type TextButton, type ThumbnailComponent, User } from "oceanic.js";
22

33
type NameList = [string, ...string[]];
44

@@ -47,14 +47,39 @@ export interface ComponentContext extends BaseContext {
4747
edit(reply: Reply): Promise<void>;
4848
}
4949

50-
export type ReplyObject = Omit<CreateMessageOptions, "messageReference" | "tts" | "content"> & { components: MessageComponent[]; };
51-
export type Reply = ReplyObject | string;
50+
export type CommandComponent =
51+
| CommandActionRow
52+
| CommandSectionComponent
53+
| CommandContainerComponent
54+
| Exclude<MessageComponent, MessageActionRow | SectionComponent | ContainerComponent>;
55+
56+
export type CommandActionRow = ActionRowBase<CommandActionRowComponent>;
57+
export type CommandActionRowComponent = CommandButtonComponent | SelectMenuComponent;
58+
59+
export type CommandContainerComponent = ContainerComponent
60+
& {
61+
components: (
62+
| CommandActionRow
63+
| CommandSectionComponent
64+
| Exclude<ContainerComponent["components"][number], MessageActionRow | SectionComponent>
65+
)[];
66+
};
67+
68+
export type CommandSectionComponent = SectionComponent & { accessory: ThumbnailComponent | CommandButtonComponent; };
5269

53-
export interface ComponentCallback {
70+
export type CommandButtonComponent = CommandTextButton | Exclude<ButtonComponent, TextButton>;
71+
export type CommandTextButton = (TextButton & CommandComponentCallback);
72+
73+
export type AnyCommandComponentWithCallback = CommandTextButton;
74+
75+
export interface CommandComponentCallback {
5476
callback: (context: ComponentContext) => Promise<void>;
5577
invokerOnly?: boolean;
5678
}
5779

80+
export type ReplyObject = Omit<CreateMessageOptions, "messageReference" | "tts" | "content"> & { components: CommandComponent[]; };
81+
export type Reply = ReplyObject | string;
82+
5883
export const enum OptionType {
5984
Boolean,
6085
/**

backend/src/bot/plugin/core/public/helper/paginator.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { ButtonStyles, ComponentTypes, type ButtonComponent } from "oceanic.js";
2-
import type { BaseContext, CommandContext, ReplyObject } from "../command.ts";
1+
import { ButtonStyles, ComponentTypes } from "oceanic.js";
2+
import type { BaseContext, CommandContext, CommandTextButton, ReplyObject } from "../command.ts";
33

44
export interface Paginator<E, K> {
55
pageSize: number;
@@ -43,31 +43,31 @@ async function renderPaginator<E, K>(
4343

4444
const reply = await paginator.render(queryResult);
4545

46-
const prevButton: ButtonComponent = {
46+
const prevButton: CommandTextButton = {
4747
type: ComponentTypes.BUTTON,
4848
label: "←",
4949
customID: "paginator-prev",
5050
style: ButtonStyles.SECONDARY,
51-
// async callback(context) {
52-
// const firstItem = queryResult[0];
53-
// const before = firstItem !== undefined ? paginator.getKey(firstItem) : undefined;
51+
async callback(context) {
52+
const firstItem = queryResult[0];
53+
const before = firstItem !== undefined ? paginator.getKey(firstItem) : undefined;
5454

55-
// await context.edit(await renderPaginator(context, paginator, true, before, undefined));
56-
// },
55+
await context.edit(await renderPaginator(context, paginator, true, before, undefined));
56+
},
5757
disabled: after === undefined && (!hasMore || before === undefined)
5858
};
5959

60-
const nextButton: ButtonComponent = {
60+
const nextButton: CommandTextButton = {
6161
type: ComponentTypes.BUTTON,
6262
label: "→",
6363
customID: "paginator-next",
6464
style: ButtonStyles.SECONDARY,
65-
// async callback(context) {
66-
// const lastItem = queryResult[queryResult.length - 1];
67-
// const after = lastItem !== undefined ? paginator.getKey(lastItem) : undefined;
65+
async callback(context) {
66+
const lastItem = queryResult[queryResult.length - 1];
67+
const after = lastItem !== undefined ? paginator.getKey(lastItem) : undefined;
6868

69-
// await context.edit(await renderPaginator(context, paginator, false, undefined, after));
70-
// },
69+
await context.edit(await renderPaginator(context, paginator, false, undefined, after));
70+
},
7171
disabled: before === undefined && !hasMore,
7272
};
7373

backend/src/bot/plugin/moderation/command/case/caseList.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { ComponentTypes, type ContainerComponent } from "oceanic.js";
1+
import { ComponentTypes } from "oceanic.js";
22
import { getCases, type CaseInfo } from "../../../../../db/moderation/cases.ts";
3-
import { defineCommand, OptionType, type BaseContext, type ReplyObject } from "../../../core/public/command.ts";
3+
import { defineCommand, OptionType, type BaseContext, type CommandContainerComponent, type ReplyObject } from "../../../core/public/command.ts";
44
import { permissionsGuard } from "../../../core/public/helper/commandGuards.ts";
55
import { respondWithPaginator, type PaginatorQuery } from "../../../core/public/helper/paginator.ts";
66
import { resolvePermissions } from "../../../core/public/permissionResolution.ts";
@@ -67,7 +67,7 @@ async function lookUpCases(
6767
}
6868

6969
async function renderCases(cases: CaseInfo[], compact: boolean): Promise<ReplyObject> {
70-
const container: ContainerComponent = {
70+
const container: CommandContainerComponent = {
7171
components: [],
7272
type: ComponentTypes.CONTAINER,
7373
};
@@ -77,8 +77,6 @@ async function renderCases(cases: CaseInfo[], compact: boolean): Promise<ReplyOb
7777
type: ComponentTypes.TEXT_DISPLAY
7878
});
7979

80-
const now = Date.now();
81-
8280
if (compact) {
8381
let content = "";
8482

backend/src/bot/plugin/moderation/command/case/caseShow.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { ComponentTypes, type ContainerComponent } from "oceanic.js";
1+
import { ComponentTypes } from "oceanic.js";
22
import { getCase } from "../../../../../db/moderation/cases.ts";
3-
import { OptionType, defineCommand } from "../../../core/public/command.ts";
3+
import { OptionType, defineCommand, type CommandContainerComponent } from "../../../core/public/command.ts";
44
import { permissionsGuard } from "../../../core/public/helper/commandGuards.ts";
55
import { icons } from "../../../core/public/icons.ts";
66
import { formatCaseDescription, formatCaseFields } from "../../helper/cases.ts";
@@ -27,7 +27,7 @@ export const caseShowCommand = defineCommand({
2727
return;
2828
}
2929

30-
const container: ContainerComponent = {
30+
const container: CommandContainerComponent = {
3131
components: [],
3232
type: ComponentTypes.CONTAINER,
3333
};

backend/src/bot/plugin/reminders/command/reminderList.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { ComponentTypes, type ContainerComponent } from "oceanic.js";
1+
import { ComponentTypes } from "oceanic.js";
22
import { dateToUnixSeconds } from "../../../../common/time.ts";
33
import { getReminders, type Reminder } from "../../../../db/reminders/reminders.ts";
4-
import { defineCommand, type BaseContext, type ReplyObject } from "../../core/public/command.ts";
4+
import { defineCommand, type BaseContext, type CommandContainerComponent, type ReplyObject } from "../../core/public/command.ts";
55
import { permissionsGuard } from "../../core/public/helper/commandGuards.ts";
66
import { respondWithPaginator, type PaginatorQuery } from "../../core/public/helper/paginator.ts";
77
import { icons } from "../../core/public/icons.ts";
@@ -53,7 +53,7 @@ async function renderReminders(reminders: Reminder[]): Promise<ReplyObject> {
5353
};
5454
}
5555

56-
const container: ContainerComponent = {
56+
const container: CommandContainerComponent = {
5757
components: [],
5858
type: ComponentTypes.CONTAINER,
5959
};

backend/src/bot/plugin/util/command/invite/friend.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { ComponentTypes, type ContainerComponent, type TextDisplayComponent, type User } from "oceanic.js";
1+
import { ComponentTypes, type TextDisplayComponent, type User } from "oceanic.js";
22
import { dateToUnixSeconds } from "../../../../../common/time.ts";
3+
import type { CommandContainerComponent } from "../../../core/public/command.ts";
34

4-
export function renderFriendInvite(inviter: User, expiresAt: Date | undefined, hideImages: boolean): ContainerComponent {
5-
const result: ContainerComponent = {
5+
export function renderFriendInvite(inviter: User, expiresAt: Date | undefined, hideImages: boolean): CommandContainerComponent {
6+
const result: CommandContainerComponent = {
67
components: [],
78
type: ComponentTypes.CONTAINER,
89
};

0 commit comments

Comments
 (0)