Skip to content

Commit dab1ecb

Browse files
committed
feat: more bug fixes
1 parent 70f96e5 commit dab1ecb

9 files changed

Lines changed: 126 additions & 105 deletions

File tree

src/commands/ai.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,13 @@ export default async function (msg: Message): Promise<void> {
3838
Available Commands:
3939
`;
4040

41+
const excludeAiCommands: string[] = ["mj", "obi", "naij", "chad", "sim"];
42+
4143
for (const key in commands) {
4244
const cmd = commands[key];
43-
if (cmd.role === "user")
45+
if (cmd.role === "user" && excludeAiCommands.includes(cmd.command)) {
4446
prompt += `\n${cmd.command} - ${cmd.description}\n${cmd.usage}\n`;
47+
}
4548
}
4649

4750
let text = await agentHandler(`${prompt}\nUser query: ${query}`);

src/components/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ async function client(): Promise<Client> {
6363
return newClient;
6464
}
6565

66-
function registerEvents(client: Client) {
66+
function registerEvents(client: Client): void {
6767
client.on("loading_screen", (percent: number, message: string) => {
6868
if (!isLoadingBarStarted) {
6969
loadingBar.start(100, 0, { message });

src/components/events/message.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ const commandPrefix: string = process.env.COMMAND_PREFIX || "!";
3030
const commandPrefixLess: boolean = process.env.COMMAND_PREFIX_LESS === "true";
3131

3232
export default async function (msg: Message, type: string): Promise<void> {
33-
// ignore message if it is older than 10 seconds
33+
// ignore message if it is older than 60 seconds
3434
if (!msg.body) return;
35-
if (msg.timestamp < Date.now() / 1000 - 10 && type === "create") return;
35+
if (msg.timestamp < Date.now() / 1000 - 60 && type === "create") return;
3636
if (msg.isGif || msg.isStatus || msg.broadcast || msg.isForwarded) return; // ignore them all
3737
const lid: string = msg.author
3838
? msg.author.split("@")[0]
@@ -141,8 +141,7 @@ export default async function (msg: Message, type: string): Promise<void> {
141141
}
142142

143143
const botId = (await client()).info.wid._serialized;
144-
145-
if (msg.mentionedIds.length == 0 && !msg.mentionedIds.includes(botId))
144+
if (msg.mentionedIds.length == 0 || !msg.mentionedIds.includes(botId))
146145
return;
147146

148147
if (msg.body === `@${botId}`) {

src/components/utils/cmd/loader.ts

Lines changed: 79 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import util from "util";
77
import { Message } from "../../../types/message";
88
const execPromise = util.promisify(exec);
99
const basePath = path.join(__dirname, "..", "..", "..", "commands");
10+
import * as Sentry from "@sentry/node";
1011

1112
export const commandDirs = [basePath, path.join(basePath, "private")];
1213
export const commands: Record<
@@ -41,6 +42,7 @@ async function ensureDependencies(
4142
if (stdout) log.info("npm", stdout);
4243
if (stderr) log.error("npm", stderr);
4344
} catch (err) {
45+
Sentry.captureException(err);
4446
log.error(
4547
"Loader",
4648
`Failed to install ${dep.name}@${dep.version}`,
@@ -55,92 +57,102 @@ export default async function loader(
5557
file: string,
5658
customPath: string,
5759
): Promise<void> {
58-
if (/\.js$|\.ts$/.test(file)) {
59-
const filePath = path.join(customPath, file);
60+
try {
61+
if (/\.js$|\.ts$/.test(file)) {
62+
const filePath = path.join(customPath, file);
6063

61-
const resolvedPath = path.resolve(filePath);
62-
if (require.cache[resolvedPath]) {
63-
delete require.cache[resolvedPath];
64-
}
65-
66-
try {
67-
await fs.access(resolvedPath);
68-
} catch {
69-
return;
70-
}
71-
72-
const commandModule = await import(filePath);
64+
const resolvedPath = path.resolve(filePath);
65+
if (require.cache[resolvedPath]) {
66+
delete require.cache[resolvedPath];
67+
}
7368

74-
if (
75-
typeof commandModule.default === "function" &&
76-
commandModule.info &&
77-
commandModule.info.command
78-
) {
79-
if (Array.isArray(commandModule.info.dependencies)) {
80-
await ensureDependencies(commandModule.info.dependencies);
69+
try {
70+
await fs.access(resolvedPath);
71+
} catch {
72+
return;
8173
}
8274

83-
commands[commandModule.info.command] = {
84-
command: commandModule.info.command,
85-
description: commandModule.info.description || "No description",
86-
usage: commandModule.info.usage || "No usage",
87-
example: commandModule.info.example || "No example",
88-
role: commandModule.info.role || "user",
89-
cooldown: commandModule.info.cooldown || 5000,
90-
exec: commandModule.default,
91-
};
75+
const commandModule = await import(filePath);
76+
77+
if (
78+
typeof commandModule.default === "function" &&
79+
commandModule.info &&
80+
commandModule.info.command
81+
) {
82+
if (Array.isArray(commandModule.info.dependencies)) {
83+
await ensureDependencies(commandModule.info.dependencies);
84+
}
85+
86+
commands[commandModule.info.command] = {
87+
command: commandModule.info.command,
88+
description: commandModule.info.description || "No description",
89+
usage: commandModule.info.usage || "No usage",
90+
example: commandModule.info.example || "No example",
91+
role: commandModule.info.role || "user",
92+
cooldown: commandModule.info.cooldown || 5000,
93+
exec: commandModule.default,
94+
};
95+
}
9296
}
97+
} catch (err) {
98+
Sentry.captureException(err);
99+
log.error("Loader", `Failed to load: ${file}`, err);
93100
}
94101
}
95102

96103
export async function mapCommands(): Promise<void> {
97104
let allFiles: [string, string][] = [];
98105

99-
for (const dir of commandDirs) {
100-
try {
101-
await fs.access(dir);
102-
const files = await fs.readdir(dir);
106+
try {
107+
for (const dir of commandDirs) {
108+
try {
109+
await fs.access(dir);
110+
const files = await fs.readdir(dir);
103111

104-
const validFiles = files.filter(
105-
(f) => f.endsWith(".js") || f.endsWith(".ts"),
106-
);
112+
const validFiles = files.filter(
113+
(f) => f.endsWith(".js") || f.endsWith(".ts"),
114+
);
107115

108-
const tuples: [string, string][] = validFiles.map(
109-
(f) => [f, dir] as [string, string],
110-
);
116+
const tuples: [string, string][] = validFiles.map(
117+
(f) => [f, dir] as [string, string],
118+
);
111119

112-
allFiles = [...allFiles, ...tuples];
113-
} catch (err: any) {
114-
if (err.code === "ENOENT") {
115-
console.log("");
116-
log.warn("Loader", `Directory not found: ${dir}`);
117-
} else {
118-
console.log("");
119-
log.warn("Loader", `Error reading directory ${dir}:`, err);
120+
allFiles = [...allFiles, ...tuples];
121+
} catch (err: any) {
122+
if (err.code === "ENOENT") {
123+
console.log("");
124+
log.warn("Loader", `Directory not found: ${dir}`);
125+
} else {
126+
console.log("");
127+
log.warn("Loader", `Error reading directory ${dir}:`, err);
128+
}
120129
}
121130
}
122-
}
123131

124-
const total = allFiles.length;
125-
if (total === 0) {
126-
log.info("Loader", "No commands found.");
127-
return;
128-
}
132+
const total = allFiles.length;
133+
if (total === 0) {
134+
log.info("Loader", "No commands found.");
135+
return;
136+
}
129137

130-
const bar = LoadingBar(
131-
"Loading Commands | {bar} | {value}/{total} {command}",
132-
);
133-
bar.start(total, 0, { command: "" });
138+
const bar = LoadingBar(
139+
"Loading Commands | {bar} | {value}/{total} {command}",
140+
);
141+
bar.start(total, 0, { command: "" });
134142

135-
for (const [file, dir] of allFiles) {
136-
try {
137-
await loader(file, dir);
138-
bar.increment({ command: file });
139-
} catch (err) {
140-
log.error("Loader", `Failed to load ${file}`, err);
141-
bar.increment({ command: file });
143+
for (const [file, dir] of allFiles) {
144+
try {
145+
await loader(file, dir);
146+
bar.increment({ command: file });
147+
} catch (err) {
148+
log.error("Loader", `Failed to load ${file}`, err);
149+
bar.increment({ command: file });
150+
}
142151
}
143-
}
144152

145-
bar.stop();
153+
bar.stop();
154+
} catch (err) {
155+
Sentry.captureException(err);
156+
log.error("Loader", "Failed to map commands:", err);
157+
}
146158
}
Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
import { watch } from "fs/promises";
22
import loader from "./loader";
33
import log from "../log";
4-
import path from "path";
4+
import * as Sentry from "@sentry/node";
55
import { commandDirs } from "./loader";
66

77
export default async function (): Promise<void> {
8-
for (const dir of commandDirs) {
9-
const watcher = watch(dir, { recursive: false });
8+
try {
9+
for (const dir of commandDirs) {
10+
const watcher = watch(dir, { recursive: false });
1011

11-
for await (const event of watcher) {
12-
const { eventType, filename } = event;
13-
if (filename && /\.(js|ts)$/.test(filename)) {
14-
try {
15-
await loader(filename, dir);
16-
log.info("Loader", `Reloaded command: ${filename}`);
17-
} catch (err) {
18-
log.error("Loader", `Failed to reload command: ${filename}`, err);
12+
for await (const event of watcher) {
13+
const { eventType, filename } = event;
14+
if (filename && /\.(js|ts)$/.test(filename)) {
15+
try {
16+
await loader(filename, dir);
17+
log.info("Loader", `Reloaded command: ${filename}`);
18+
} catch (err) {
19+
log.error("Loader", `Failed to reload command: ${filename}`, err);
20+
}
1921
}
2022
}
2123
}
24+
} catch (err) {
25+
Sentry.captureException(err);
26+
log.error("Loader", "Error on command watcher:", err);
2227
}
2328
}

src/components/utils/instantdl/downloader.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,23 @@ const youtubeShortsUrlRegex =
2323
/^(https?:\/\/)?(www\.)?youtube\.com\/shorts\/([A-Za-z0-9_-]{11})(\?[^\s#]*)?(#[^\s]*)?$/i;
2424

2525
export async function InstantDownloader(msg: Message): Promise<void> {
26-
try {
27-
const extractUrls = msg.body.match(/(https?:\/\/[^\s]+)/g);
28-
if (!extractUrls) return;
26+
const extractUrls = msg.body.match(/(https?:\/\/[^\s]+)/g);
27+
if (!extractUrls || extractUrls.length == 0) return;
28+
29+
const query = extractUrls[0];
30+
if (!facebookUrlRegex.test(query) && !youtubeShortsUrlRegex.test(query))
31+
return;
2932

30-
const query = extractUrls[Math.floor(Math.random() * extractUrls.length)];
31-
const key = `instantdownload:${md5FromUrl(query)}`;
33+
const key = `instantdownload:${md5FromUrl(query)}`;
3234

33-
if (facebookUrlRegex.test(query) || youtubeShortsUrlRegex.test(query)) {
34-
const isPending = await redis.get(key);
35-
if (isPending) {
36-
log.warn(
37-
"InstantDownload",
38-
`The video is already in pending: ${query}, key: ${key}`,
39-
);
40-
return;
41-
}
35+
try {
36+
const isPending = await redis.get(key);
37+
if (isPending) {
38+
log.warn(
39+
"InstantDownload",
40+
`The video is already in pending: ${query}, key: ${key}`,
41+
);
42+
return;
4243
}
4344

4445
const [video]: [Video | undefined, any] = await Promise.all([
@@ -60,13 +61,14 @@ export async function InstantDownloader(msg: Message): Promise<void> {
6061
return;
6162
}
6263

63-
await Promise.all([
64+
await Promise.allSettled([
6465
msg.reply(video.video, undefined, {
6566
caption: video.title ? he.decode(video.title) : "Instant Download",
6667
}),
6768
redis.del(key),
6869
]);
6970
} catch (err) {
71+
await redis.del(key);
7072
Sentry.captureException(err);
7173
log.error("InstantDownload", "Failed to download the video:", err);
7274
}

src/components/utils/quiz.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ export default async function (
3030
userInput === answer ||
3131
(question.choices && userInput === answerIndex.toString())
3232
) {
33-
await Promise.all([
33+
await Promise.allSettled([
3434
redis.del(key),
3535
msg.reply(done[Math.floor(Math.random() * done.length)]),
3636
addUserQuizPoints(msg, true),
3737
quoted.delete(true, true),
3838
log.info("QuizAnswered", "Correct", quoted.body),
3939
]);
4040
} else {
41-
await Promise.all([
41+
await Promise.allSettled([
4242
redis.del(key),
4343
msg.reply(wrong[Math.floor(Math.random() * wrong.length)]),
4444
addUserQuizPoints(msg, false),

src/components/utils/riddle.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ export default async function (
3434
}
3535

3636
if (isCorrect) {
37-
await Promise.all([
37+
await Promise.allSettled([
3838
redis.del(key),
3939
msg.reply(done[Math.floor(Math.random() * done.length)]),
4040
addUserQuizPoints(msg, true, 20),
4141
quoted.delete(true, true),
4242
log.info("RiddleAnswered", "Correct", quoted.body),
4343
]);
4444
} else {
45-
await Promise.all([
45+
await Promise.allSettled([
4646
redis.del(key),
4747
msg.reply(wrong[Math.floor(Math.random() * wrong.length)]),
4848
addUserQuizPoints(msg, false, 0.2),

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ async function main() {
3939
phishingSet = phishtank.getPhishingSet();
4040
await client();
4141

42-
mapCommands();
42+
await mapCommands();
4343
// Watch for changes
44-
if (autoReload) watcher();
44+
if (autoReload) await watcher();
4545
}
4646

4747
main();

0 commit comments

Comments
 (0)