Skip to content

Commit 85deb3b

Browse files
feat: queue list command
1 parent aba1e36 commit 85deb3b

File tree

7 files changed

+121
-12
lines changed

7 files changed

+121
-12
lines changed

src/framework/typescript/queues/Queue.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ export type QueueOptions<T extends StorableData> = {
2222
abstract class Queue<T extends StorableData = StorableData> extends HasApplication {
2323
public static readonly uniqueName: string = "";
2424
public readonly data: T;
25-
protected readonly guildId: Snowflake;
26-
protected readonly userId: Snowflake;
27-
protected readonly channelId?: Snowflake;
28-
protected readonly messageId?: Snowflake;
25+
public readonly guildId: Snowflake;
26+
public readonly userId: Snowflake;
27+
public readonly channelId?: Snowflake;
28+
public readonly messageId?: Snowflake;
29+
public readonly runsAt: Date;
30+
public readonly repeat?: boolean;
2931
protected readonly manager: QueueManager;
30-
protected readonly runsAt: Date;
31-
protected readonly repeat?: boolean;
32-
private _isExecuting: boolean = false;
3332

33+
private _isExecuting: boolean = false;
3434
private _createdAt?: Date;
3535
private _updatedAt?: Date;
3636
private _id?: number;
@@ -116,6 +116,14 @@ abstract class Queue<T extends StorableData = StorableData> extends HasApplicati
116116
return id;
117117
}
118118

119+
public get createdAt() {
120+
return this._createdAt;
121+
}
122+
123+
public get updatedAt() {
124+
return this._updatedAt;
125+
}
126+
119127
public async delete() {
120128
requireNonNull(this._id, "Queue ID must be set to delete");
121129

src/framework/typescript/queues/QueueManager.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { HasApplication } from "../types/HasApplication";
2-
import type { QueueOptions, StorableData } from "./Queue";
32
import type Queue from "./Queue";
3+
import type { QueueOptions, StorableData } from "./Queue";
44

55
export type QueueClass<T extends StorableData = StorableData> = typeof Queue<T>;
66
export type QueueConstructor<T extends StorableData = StorableData> = new (
@@ -28,6 +28,10 @@ class QueueManager extends HasApplication {
2828
return this.queueClasses.get(name) as QueueConstructor<StorableData> | undefined;
2929
}
3030

31+
public getJobs(): ReadonlyMap<number, Queue> {
32+
return this.scheduledQueues;
33+
}
34+
3135
public create<T extends StorableData>(
3236
queue: string | QueueClass,
3337
options: QueueOptions<T>
@@ -44,7 +48,10 @@ class QueueManager extends HasApplication {
4448
return new QueueClass(this.application, this, options);
4549
}
4650

47-
public async bulkCancel<T extends StorableData>(type: QueueClass<T>, filter: (queue: Queue<NoInfer<T>>) => boolean) {
51+
public async bulkCancel<T extends StorableData>(
52+
type: QueueClass<T>,
53+
filter: (queue: Queue<NoInfer<T>>) => boolean
54+
) {
4855
for (const queue of this.scheduledQueues.values()) {
4956
// noinspection SuspiciousTypeOfGuard
5057
if (queue instanceof type && filter(queue as Queue<NoInfer<T>>)) {

src/framework/typescript/utils/embeds.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { Client, Snowflake } from "discord.js";
12
import { MessageType, type GuildBasedChannel, type Message, type User } from "discord.js";
23

34
export function userInfo(user: User) {
@@ -11,3 +12,11 @@ export function channelInfo(channel: GuildBasedChannel) {
1112
export function messageInfo(message: Message) {
1213
return `ID: ${message.id}\nType: ${MessageType[message.type]}\nURL: ${message.url}`;
1314
}
15+
16+
export function shortUserInfo(client: Client, userId: Snowflake) {
17+
if (userId === client.user!.id) {
18+
return "System";
19+
}
20+
21+
return `<@${userId}> [\`${userId}\`]`;
22+
}

src/main/typescript/commands/automation/QueueAddCommand.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ class QueueAddCommand extends Command {
5050

5151
public override async execute(context: Context, args: QueueAddCommandArgs): Promise<void> {
5252
const { command, runAfter } = args;
53-
const commandName = command.slice(0, Math.max(command.indexOf(" "), command.indexOf("\n")));
53+
const spaceIndex = command.indexOf(" ");
54+
const newLineIndex = command.indexOf("\n");
55+
const index =
56+
spaceIndex === -1 || newLineIndex === -1
57+
? Math.max(spaceIndex, newLineIndex)
58+
: Math.min(spaceIndex, newLineIndex);
59+
const commandName = command.slice(0, index === -1 ? command.length : index);
5460

5561
if (!this.commandManager.commands.has(commandName)) {
5662
return void context.error(
@@ -79,6 +85,7 @@ class QueueAddCommand extends Command {
7985
fromInteraction: context.isChatInput()
8086
},
8187
guildId: context.guildId,
88+
userId: context.userId,
8289
runsAt: new Date(Date.now() + runAfter.toMilliseconds())
8390
})
8491
.schedule();
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { Command } from "@framework/commands/Command";
2+
import type Context from "@framework/commands/Context";
3+
import { Inject } from "@framework/container/Inject";
4+
import Pagination from "@framework/pagination/Pagination";
5+
import Queue from "@framework/queues/Queue";
6+
import { shortUserInfo } from "@framework/utils/embeds";
7+
import { Colors } from "@main/constants/Colors";
8+
import QueueService from "@main/services/QueueService";
9+
import { PermissionFlagsBits, inlineCode, italic, time } from "discord.js";
10+
11+
// type QueueListCommandArgs = {
12+
// id: number
13+
// };
14+
15+
// @TakesArgument<QueueListCommandArgs>({
16+
// names: ["id"],
17+
// types: [IntegerArgument],
18+
// optional: false,
19+
// errorMessages: [{
20+
// [ErrorType.Required]: "You must provide a Queued Job ID!",
21+
// }],
22+
// })
23+
class QueueListCommand extends Command {
24+
public override readonly name = "queue::list";
25+
public override readonly description: string = "List all queued jobs in this server.";
26+
public override readonly defer = true;
27+
public override readonly permissions = [PermissionFlagsBits.ManageGuild];
28+
29+
@Inject()
30+
private readonly queueService!: QueueService;
31+
32+
public override async execute(context: Context): Promise<void> {
33+
const jobs = this.queueService.getJobs();
34+
35+
if (jobs.size === 0) {
36+
return void (await context.error("There are currently no queued jobs in this server."));
37+
}
38+
39+
const pagination: Pagination<Queue> = Pagination.withData(jobs.values())
40+
.setLimit(5)
41+
.setMaxTimeout(Pagination.DEFAULT_TIMEOUT)
42+
.setMessageOptionsBuilder(({ data, maxPages, page }) => {
43+
let description = "";
44+
45+
for (const queue of data) {
46+
description += `### Job #${queue.id}\n`;
47+
description += `**Type:** ${inlineCode((queue.constructor as unknown as { uniqueName: string }).uniqueName)}\n`;
48+
description += `**Created By:** ${queue.userId ? (queue.userId === "0" ? "[Unknown]" : shortUserInfo(this.application.client, queue.userId)) : italic("Unknown")}\n`;
49+
description += `**Creation Time:** ${queue.createdAt ? time(queue.createdAt, "R") : "`[Not yet created]`"}\n`;
50+
description += `**Execution:** ${time(queue.runsAt, "R")}\n\n`;
51+
}
52+
53+
return {
54+
embeds: [
55+
{
56+
author: {
57+
name: `Queues in ${context.guild.name}`,
58+
icon_url: context.guild.iconURL() ?? undefined
59+
},
60+
color: Colors.Primary,
61+
description,
62+
footer: {
63+
text: `Page ${page} of ${maxPages}${jobs.size} queues total`
64+
}
65+
}
66+
]
67+
};
68+
});
69+
70+
const reply = await context.reply(await pagination.getMessageOptions());
71+
pagination.setInitialMessage(reply);
72+
}
73+
}
74+
75+
export default QueueListCommand;

src/main/typescript/commands/moderation/InfractionListCommand.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ class InfractionListCommand extends Command {
5858
}
5959

6060
const pagination: Pagination<Infraction> = Pagination.withData(infractions)
61-
.setData(infractions)
62-
.setLimit(3)
61+
.setLimit(5)
6362
.setMaxTimeout(Pagination.DEFAULT_TIMEOUT)
6463
.setMessageOptionsBuilder(({ data, maxPages, page }) => {
6564
let description = "";

src/main/typescript/services/QueueService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ class QueueService extends Service implements HasEventListeners {
2020
this.queueManager.register(queue, name);
2121
}
2222

23+
public getJobs() {
24+
return this.queueManager.getJobs();
25+
}
26+
2327
public async sync(): Promise<void> {
2428
const queues = await this.application.prisma.queue.findMany({
2529
where: {

0 commit comments

Comments
 (0)