Skip to content

Commit d3aece8

Browse files
authored
I'm so random and quirky lol (#121)
1 parent 342215d commit d3aece8

File tree

8 files changed

+117
-73
lines changed

8 files changed

+117
-73
lines changed

.gitignore

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
node_modules/
22
out/
3-
.env
3+
dump.rdb
4+
45
src/test.ts
56
src/test.js
6-
data.json
7-
application.yml
87
logs/
9-
dump.rdb
10-
11-
# directory to store git patches
128
.patches
9+
10+
.env
11+
data.json
12+
application.yml
13+
.command_hash

.vscode/settings.json

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
},
4646
"files.exclude": {
4747
"out/**": true,
48+
".command_hash": true,
4849
},
4950
"git.branchPrefix": "feat/",
5051
"git.branchProtection": [ "main" ],

src/bot.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,16 @@ async function init()
5656
console.log(`• Registered ${k.green(evts.length)} client ${autoPlural("event", evts)}`);
5757
printDbgItmList(evts.map(e => e.constructor.name ?? e.names.join("&")));
5858

59-
await registerCommands(cl);
60-
6159
user.setPresence({
6260
status: "online",
6361
activities: [{ type: ActivityType.Watching, name: "ur mom" }],
6462
});
6563

64+
await Promise.all([ registerCommands(cl), doContestStuff(cl) ]);
65+
6666
console.log(`• Active in ${k.green(guilds.cache.size)} guild${guilds.cache.size != 1 ? "s" : ""}`);
6767
printDbgItmList(guilds.cache.map(g => g.name), 4);
6868

69-
await doContestStuff(cl);
7069

7170
clientReadyInitLava(cl);
7271

@@ -186,7 +185,7 @@ async function registerCommands(client: Client)
186185
* Prints a styled list of items to the console
187186
* @param limit Max amount of items per line
188187
*/
189-
function printDbgItmList(list: string[] | Stringifiable[], limit = 6)
188+
function printDbgItmList(list: string[] | Stringifiable[], limit = 10)
190189
{
191190
let msg = "";
192191

src/commands/fun/Coinflip.ts

+18-12
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import { ApplicationCommandOptionType, CommandInteraction, EmbedBuilder } from "
22
import { randRange } from "svcorelib";
33
import { Command } from "@src/Command";
44
import { settings } from "@src/settings";
5-
6-
// idx 0: heads, idx 1: tails - TODO: make some sexy emoji for this specifically maybe?
7-
const coins = ["🇭","🇹"];
5+
import { autoPlural } from "@src/utils";
86

97
export class Coinflip extends Command {
10-
constructor()
11-
{
8+
readonly COINS = [
9+
{ name: "Heads", emoji: "🇭" },
10+
{ name: "Tails", emoji: "🇹" },
11+
];
12+
13+
constructor() {
1214
super({
1315
name: "coinflip",
1416
desc: "Flips one or multiple coins",
@@ -20,7 +22,6 @@ export class Coinflip extends Command {
2022
desc: "How many coins to flip.",
2123
type: ApplicationCommandOptionType.Integer,
2224
min: 1,
23-
max: 50,
2425
}
2526
]
2627
});
@@ -31,16 +32,21 @@ export class Coinflip extends Command {
3132

3233
let replyText = "";
3334

34-
if(amount > 1)
35-
{
35+
if(amount > 1) {
3636
const flips = [];
3737
for(let i = 0; i < amount; i++)
38-
flips.push(coins[randRange(0, 1)]);
38+
flips.push(randRange(0, 1));
3939

40-
replyText = `Flipped ${amount} coin${amount != 1 ? "s" : ""}. Result:\n\n${flips.join(" ")}`;
40+
replyText = [
41+
`Flipped ${amount} ${autoPlural("coin", amount)}. Result:`,
42+
`> ${this.COINS[0].emoji} Heads: **${flips.filter(f => f === 0)}**`,
43+
`> ${this.COINS[1].emoji} Tails: **${flips.filter(f => f === 1)}**`
44+
].join("\n");
45+
}
46+
else {
47+
const coin = this.COINS[randRange(0, 1)];
48+
replyText = `You flipped a coin.\nIt landed on **${coin.emoji} ${coin.name}**`;
4149
}
42-
else
43-
replyText = `You flipped a coin: ${coins[randRange(0, 1)]}`;
4450

4551
const embed = new EmbedBuilder()
4652
.setColor(settings.embedColors.default)

src/commands/fun/Contest/Contest.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class Contest extends Command
2626
},
2727
{
2828
name: "current",
29-
desc: "Get the currently active contest in the server",
29+
desc: "Shows the currently active contest of the server",
3030
},
3131
{
3232
name: "list",
@@ -55,7 +55,7 @@ export class Contest extends Command
5555
required: true
5656
}
5757
],
58-
perms: ["ADMINISTRATOR"]
58+
perms: ["MANAGE_CHANNELS"]
5959
},
6060
{
6161
name: "set_role",
@@ -68,7 +68,7 @@ export class Contest extends Command
6868
required: true,
6969
}
7070
],
71-
perms: ["ADMINISTRATOR"]
71+
perms: ["MANAGE_ROLES"]
7272
},
7373
{
7474
name: "submit",
@@ -94,13 +94,13 @@ export class Contest extends Command
9494
args: [
9595
{
9696
name: "contest_id",
97-
desc: "ID of contest you want to vote on",
97+
desc: "The ID of the contest you want to submit your vote to",
9898
type: ApplicationCommandOptionType.Number,
9999
required: true,
100100
},
101101
{
102102
name: "contestant",
103-
desc: "Contestant you want to vote for",
103+
desc: "The contestant you want to vote for",
104104
type: ApplicationCommandOptionType.User,
105105
required: true,
106106
}
@@ -112,13 +112,13 @@ export class Contest extends Command
112112
args: [
113113
{
114114
name: "contest_id",
115-
desc: "ID of contest you want to remove the vote from",
115+
desc: "The ID of the contest you want to remove your vote from",
116116
type: ApplicationCommandOptionType.Number,
117117
required: true,
118118
},
119119
{
120120
name: "contestant",
121-
desc: "Contestant you want to remove the vote from",
121+
desc: "The contestant you want to remove the vote from",
122122
type: ApplicationCommandOptionType.User,
123123
required: true,
124124
}
@@ -142,13 +142,13 @@ export class Contest extends Command
142142
args: [
143143
{
144144
name: "contest_id",
145-
desc: "ID of contest you want your submissions removed from",
145+
desc: "The ID of the contest you want the submission removed from",
146146
type: ApplicationCommandOptionType.Number,
147147
required: true,
148148
},
149149
{
150150
name: "user",
151-
desc: "User you want to delete the submission of",
151+
desc: "The contestant you want to delete the submission of",
152152
type: ApplicationCommandOptionType.User,
153153
required: true,
154154
},
@@ -207,7 +207,7 @@ export class Contest extends Command
207207
return await this.editReply(int, embedify("There's no currently active contest"));
208208
}
209209

210-
const embedDesc = `${contest.description}\n\nuse \`/contest submit ${contest.id}\` to submit your entry\n\n24 hour voting period will start after the deadline`;
210+
const embedDesc = `${contest.description}\n\nuse \`/contest submit contest_id:${contest.id}\` to submit your entry\n\n24 hour voting period will start after the deadline`;
211211

212212
const embed = new EmbedBuilder()
213213
.setTitle(contest.name)
@@ -269,7 +269,7 @@ export class Contest extends Command
269269
const field1Name = didContestEnd ? "Started" : "Start";
270270
const field2Name = didContestEnd ? "Ended" : "End";
271271

272-
const embedDesc = didContestEnd ? contest.description : `${contest.description}\n\nuse \`/contest submit ${contest.id}\` to submit your entry\n\n24 hour voting period will start after the deadline`;
272+
const embedDesc = didContestEnd ? contest.description : `${contest.description}\n\nuse \`/contest submit contest_id:${contest.id}\` to submit your entry\n\n24 hour voting period will start after the deadline`;
273273

274274
const embed = new EmbedBuilder()
275275
.setTitle(contest.name)

src/commands/fun/Contest/functions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function runStartingContestsJobs(cl: Client, starting: (StartingContest & { guil
4141
starting.forEach(contest => {
4242
const timeTillStart = contest.startDate.getTime() - new Date().getTime();
4343

44-
const description = `${contest.description}\n\n\n\nuse \`/contest submit ${contest.id}\` to submit your entry\n\n24 hour voting period will start after the deadline`;
44+
const description = `${contest.description}\n\n\n\nuse \`/contest submit contest_id:${contest.id}\` to submit your entry\n\n24 hour voting period will start after the deadline`;
4545

4646
const embed = new EmbedBuilder()
4747
.setAuthor({ name: "Contest Started!" })

src/commands/util/Reminder.ts

+27-20
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { Tuple } from "@src/types";
1111
/** Max reminders per user (global) */
1212
const reminderLimit = 10;
1313
const reminderCheckInterval = 2000;
14+
/** To not exceed the embed limits */
15+
const maxNameLength = 250;
1416

1517
export class Reminder extends Command
1618
{
@@ -98,7 +100,7 @@ export class Reminder extends Command
98100
},
99101
{
100102
name: "expiry",
101-
desc: "UTC, 24 hours. Format: YYYY-MM-DD hh:mm:ss",
103+
desc: "UTC, 24 hours. Format: YYYY-MM-DD hh:mm:ss (or) YYYY-MM-DD hh:mm",
102104
type: ApplicationCommandOptionType.String,
103105
required: true,
104106
},
@@ -121,7 +123,7 @@ export class Reminder extends Command
121123
},
122124
{
123125
name: "expiry",
124-
desc: "UTC, 24 hours. Format: hh:mm:ss OR hh:mm",
126+
desc: "UTC, 24 hours. Format: hh:mm:ss (or) hh:mm",
125127
type: ApplicationCommandOptionType.String,
126128
required: true,
127129
},
@@ -178,6 +180,9 @@ export class Reminder extends Command
178180
const tooSoon = () => this.reply(int, embedify("Please enter an expiry that's at least five seconds from now.", settings.embedColors.error), true);
179181

180182
const setNewReminder = async (name: string, dueTimestamp: Date, ephemeral: boolean) => {
183+
if(name.length > maxNameLength)
184+
return this.reply(int, embedify(`Please enter a name that's not longer than ${maxNameLength} characters`, settings.embedColors.error));
185+
181186
await this.deferReply(int, ephemeral);
182187

183188
const reminders = await getReminders(user.id);
@@ -202,7 +207,7 @@ export class Reminder extends Command
202207
private: guild?.id ? ephemeral : true,
203208
});
204209

205-
return await this.editReply(int, embedify(`I've set a reminder with the name \`${name}\` (ID \`${reminderId}\`)\nDue: ${time(toUnix10(dueTimestamp), "f")}\n\nTo list your reminders, use \`/reminder list\``, settings.embedColors.success));
210+
return await this.editReply(int, embedify(`I've set the following reminder:\n> ${name}\n> Due: ${time(toUnix10(dueTimestamp), "f")}\n\nID: \`${reminderId}\` • To list your reminders use \`/reminder list\``, settings.embedColors.success));
206211
};
207212

208213
switch(opt.name)
@@ -243,15 +248,17 @@ export class Reminder extends Command
243248
expiry = (int.options.get("expiry", true).value as string).trim(),
244249
ephemeral = int.options.get("private")?.value as boolean ?? false;
245250

246-
const expiryRegex = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2})[\s,]+(\d{1,2})[:](\d{1,2})[:](\d{1,2})$/;
251+
const expiryRegex = /^(\d{4})[-/](\d{1,2})[-/](\d{1,2})[\s,]+(\d{1,2})[:](\d{1,2})([:](\d{1,2}))?$/;
247252

248253
if(!expiry.match(expiryRegex))
249-
return this.reply(int, embedify("Please enter the expiry date and time in the following format (24 hours, UTC):\n`YYYY-MM-DD hh:mm:ss`", settings.embedColors.error), true);
254+
return this.reply(int, embedify("Please enter the expiry date and time in one of the following formats (24 hours, UTC):\n`YYYY-MM-DD hh:mm:ss` **or** `YYYY-MM-DD hh:mm`", settings.embedColors.error), true);
250255

251256
// match() above makes sure this exec() can't return null
252257
const [, ...timeComponents] = expiryRegex.exec(expiry) as unknown as Tuple<string, 7>;
253258

254-
const [year, month, day, hour, minute, second] = timeComponents.slice(0, 6).map(c => Number(c));
259+
const [year, month, day, hour, minute, second] = timeComponents
260+
.slice(0, 6)
261+
.map(c => !c ? 0 : (c.includes(":") ? Number(c.substring(1)) : Number(c)));
255262

256263
const dueTimestamp = Date.UTC(year, month - 1, day, hour, minute, second);
257264

@@ -272,7 +279,7 @@ export class Reminder extends Command
272279
const expiryRegex = /^(\d{1,2})[:](\d{1,2})([:](\d{1,2}))?$/;
273280

274281
if(!expiry.match(expiryRegex))
275-
return this.reply(int, embedify("Please enter the expiry time in one of the following formats (24 hours, UTC):\n`hh:mm:ss` or `hh:mm`", settings.embedColors.error), true);
282+
return this.reply(int, embedify("Please enter the expiry time in one of the following formats (24 hours, UTC):\n`hh:mm:ss` **or** `hh:mm`", settings.embedColors.error), true);
276283

277284
// match() above makes sure this exec() can't return null
278285
const [, ...timeComponents] = expiryRegex.exec(expiry) as unknown as Tuple<string, 7>;
@@ -302,25 +309,23 @@ export class Reminder extends Command
302309
if(!reminders || reminders.length === 0)
303310
return await this.editReply(int, embedify("You don't have any active reminders.\nCreate a new one with `/reminder set`", settings.embedColors.error));
304311

305-
const getReminderStr = (reminders: ReminderObj[]) => reminders.reduce((acc, cur, i) => acc + `> \`${cur.reminderId}\` : ${cur.name}\n> ${time(toUnix10(cur.dueTimestamp), "f")}${i !== reminders.length - 1 ? "\n\n" : ""}`, "");
306-
const getReminderEbd = (remStr: string, curPage?: number, maxPage?: number) =>
307-
{
312+
const iconURL = user.avatarURL({ extension: "png", size: 512 }) ?? undefined;
313+
314+
const getReminderStr = (reminders: ReminderObj[]) => reminders.reduce((acc, cur, i) =>
315+
acc + `> ${cur.name.replace(/\n/gm, "\n> ")}\n> ID: \`${cur.reminderId}\` • ${time(toUnix10(cur.dueTimestamp), "f")}${i !== reminders.length - 1 ? "\n\n" : ""}`
316+
, "");
317+
const getReminderEbd = (remStr: string, curPage?: number, maxPage?: number) => {
308318
const ebd = new EmbedBuilder()
309319
.setTitle("Your reminders:")
310320
.setDescription(remStr + "\n\nTo delete a reminder, use `/reminder delete`")
311-
.setAuthor({
312-
name: user.username,
313-
iconURL: avatar ?? undefined,
314-
})
321+
.setAuthor({ name: user.username, iconURL })
315322
.setColor(settings.embedColors.default);
316323

317324
curPage && maxPage && ebd.setFooter({ text: `Page ${curPage}/${maxPage}` });
318325

319326
return ebd;
320327
};
321328

322-
const avatar = user.avatarURL({ extension: "png", size: 512 });
323-
324329
const remStr = getReminderStr(reminders);
325330

326331
const remindersPerPage = 8;
@@ -459,11 +464,13 @@ export class Reminder extends Command
459464

460465
const promises: Promise<void>[] = [];
461466

467+
// TODO: add buttons to reinstate the reminder and add more time to it
468+
// e.g.: [+5m] [+10m] [+1h] [+3h] [+12h]
462469
const getExpiredEbd = ({ name }: ReminderObj) => new EmbedBuilder()
463-
.setTitle("Reminder")
464-
.setColor(settings.embedColors.default)
465-
.setDescription(`The following reminder has expired:\n>>> ${name}`);
470+
.setDescription(`Your reminder has expired:\n> ${name.replace(/\n/gm, "\n> ")}`)
471+
.setColor(settings.embedColors.default);
466472

473+
// TODO: add logger
467474
const reminderError = (err: Error) => console.error(k.red("Error while checking expired reminders:\n"), err);
468475

469476
/** Sends the expiry reminder in the guild and channel it was created in, but only if it is not private */
@@ -478,7 +485,7 @@ export class Reminder extends Command
478485
if(chan && [ChannelType.GuildText, ChannelType.GuildPublicThread, ChannelType.GuildPrivateThread, ChannelType.GuildForum].includes(chan.type))
479486
{
480487
const c = chan as TextBasedChannel;
481-
c.send({ content: `<@${rem.userId}>`, embeds: [ getExpiredEbd(rem) ] });
488+
c.send({ content: `Reminder! <@${rem.userId}>`, embeds: [ getExpiredEbd(rem) ] });
482489
}
483490
}
484491
catch(err) {

0 commit comments

Comments
 (0)