-
Notifications
You must be signed in to change notification settings - Fork 290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Huge Migration #17
base: master
Are you sure you want to change the base?
Huge Migration #17
Conversation
📝 WalkthroughWalkthroughThis pull request introduces a comprehensive refactoring of the project's data management approach, transitioning from a Sequelize-based database system to a file-based JSON storage mechanism. The changes span multiple files across the project, focusing on simplifying data persistence and reducing database dependencies. Key modifications include replacing database models with JSON file storage, updating import statements, and modifying functions to read, write, and manipulate data directly through file system operations. Changes
Poem
Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Docstrings generation was requested by @AstroX11. * #17 (comment) The following files were modified: * `.github/js/panel.js` * `bot/antidelete.js` * `bot/antilink.js` * `bot/antispam.js` * `bot/antiviewonce.js` * `bot/antiword.js` * `bot/autokick.js` * `bot/greetings.js` * `bot/group_events.js` * `bot/stickercmd.js` * `lib/events.js` * `lib/files.js` * `lib/logger.js` * `lib/message.js` * `lib/plugins.js` * `lib/session.js` * `plugins/afk.js` * `plugins/call.js` * `plugins/structure.js` * `sql/afk.js` * `sql/antibot.js` * `sql/anticall.js` * `sql/antidelete.js` * `sql/antilink.js` * `sql/antispam.js` * `sql/antivv.js` * `sql/antiword.js` * `sql/areact.js` * `sql/bgm.js` * `sql/config.js` * `sql/filters.js` * `sql/greetings.js` * `sql/mention.js` * `sql/notes.js` * `sql/plugins.js` * `sql/scheduler.js` * `sql/stickercmd.js`
Note We have generated docstrings for this pull request, at #18 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
🛑 Comments failed to post (208)
sql/areact.js (2)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol in Node.js built-in module imports
To explicitly indicate that you are importing Node.js built-in modules, you should prefix the module names with
'node:'
in your import statements. This is a recommended best practice in recent Node.js versions.Apply this diff to update the imports:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
6-8:
⚠️ Potential issueEnsure 'store' directory exists before writing 'areact.json'
If the
'store'
directory does not exist,fs.writeFileSync
will throw an error when attempting to write'areact.json'
. You need to ensure the directory exists before writing the file.Apply this diff to create the directory if it doesn't exist:
if (!fs.existsSync(store)) { + fs.mkdirSync(path.dirname(store), { recursive: true }); fs.writeFileSync(store, JSON.stringify({ status: false })); }
Committable suggestion skipped: line range outside the PR's diff.
sql/antidelete.js (1)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol in Node.js built-in module imports
To explicitly indicate that you are importing Node.js built-in modules, you should prefix the module names with
'node:'
in your import statements. This is a recommended best practice in recent Node.js versions.Apply this diff to update the imports:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
sql/antispam.js (2)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol in Node.js built-in module imports
To explicitly indicate that you are importing Node.js built-in modules, you should prefix the module names with
'node:'
in your import statements. This is a recommended best practice in recent Node.js versions.Apply this diff to update the imports:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path'; import { isJidGroup } from 'baileys';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
7-7:
⚠️ Potential issueEnsure 'store' directory exists before writing 'antispam.json'
If the
'store'
directory does not exist,fs.writeFileSync
will throw an error when attempting to write'antispam.json'
. You need to ensure the directory exists before writing the file.Apply this diff to create the directory if it doesn't exist and use proper braces:
-if (!fs.existsSync(store)) fs.writeFileSync(store, JSON.stringify({})); +if (!fs.existsSync(store)) { + fs.mkdirSync(path.dirname(store), { recursive: true }); + fs.writeFileSync(store, JSON.stringify({})); +}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!fs.existsSync(store)) { fs.mkdirSync(path.dirname(store), { recursive: true }); fs.writeFileSync(store, JSON.stringify({})); }
sql/antivv.js (4)
9-10: 🧹 Nitpick (assertive)
Use asynchronous file operations within async functions
The functions are marked
async
but use synchronous file operations likefs.readFileSync
andfs.writeFileSync
. This can block the event loop and degrade performance, especially under heavy load. Consider using asynchronous versions of these methods withawait
.Refactored code:
-const readDB = () => JSON.parse(fs.readFileSync(store, 'utf8')); +const readDB = async () => JSON.parse(await fs.promises.readFile(store, 'utf8')); -const writeDB = (data) => fs.writeFileSync(store, JSON.stringify(data, null, 2)); +const writeDB = async (data) => await fs.promises.writeFile(store, JSON.stringify(data, null, 2)); async function setViewOnce(status) { - const db = readDB(); + const db = await readDB(); db.isEnabled = status; - writeDB(db); + await writeDB(db); return true; } async function isViewOnceEnabled() { - const db = readDB(); + const db = await readDB(); return db.isEnabled; } async function setViewOnceType(type) { - const db = readDB(); + const db = await readDB(); db.type = type; - writeDB(db); + await writeDB(db); return true; } async function getSettings() { - const db = readDB(); + const db = await readDB(); return db; }Also applies to: 13-16, 20-21, 25-28, 32-33
9-10:
⚠️ Potential issueHandle JSON parsing errors to prevent crashes
When reading and parsing the JSON file, errors may occur if the file is corrupted or improperly formatted. Adding error handling ensures that the application can handle such situations gracefully.
Apply this diff:
-const readDB = () => JSON.parse(fs.readFileSync(store, 'utf8')); +const readDB = async () => { + try { + const data = await fs.promises.readFile(store, 'utf8'); + return JSON.parse(data); + } catch (error) { + console.error('Failed to read or parse the JSON file:', error); + return { type: 'all', isEnabled: false }; + } +};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const readDB = async () => { try { const data = await fs.promises.readFile(store, 'utf8'); return JSON.parse(data); } catch (error) { console.error('Failed to read or parse the JSON file:', error); return { type: 'all', isEnabled: false }; } }; const writeDB = (data) => fs.writeFileSync(store, JSON.stringify(data, null, 2));
6-7: 🧹 Nitpick (assertive)
Wrap single-statement 'if' blocks in curly braces for consistency
Even when an
if
block contains only a single statement, it's a good practice to enclose it in curly braces{}
. This improves readability and helps prevent errors if additional statements are added later.Apply this diff:
if (!fs.existsSync(store)) - fs.writeFileSync(store, JSON.stringify({ type: 'all', isEnabled: false })); +{ + fs.writeFileSync(store, JSON.stringify({ type: 'all', isEnabled: false })); +}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!fs.existsSync(store)) { fs.writeFileSync(store, JSON.stringify({ type: 'all', isEnabled: false })); }
1-2: 🛠️ Refactor suggestion
Use 'node:' protocol when importing Node.js built-in modules
According to best practices and the static analysis hints, it's recommended to use the
node:
protocol when importing Node.js built-in modules to make it explicit that they are core modules.Apply this diff to fix the issue:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
sql/afk.js (4)
7-8: 🧹 Nitpick (assertive)
Wrap single-statement 'if' blocks in curly braces for consistency
Including curly braces
{}
around single-statementif
blocks enhances readability and helps prevent future bugs if more statements are added.Apply this diff:
if (!fs.existsSync(store)) - fs.writeFileSync(store, JSON.stringify({ message: null, timestamp: null })); +{ + fs.writeFileSync(store, JSON.stringify({ message: null, timestamp: null })); +}Apply similar changes to other instances in the file.
Also applies to: 17-18, 25-26
9-12: 🧹 Nitpick (assertive)
Use asynchronous file operations within async functions
Using synchronous file operations like
fs.readFileSync
andfs.writeFileSync
inside async functions can block the event loop. It's better to use asynchronous methods withawait
to improve performance.Refactored code:
export async function getAfkMessage() { if (!fs.existsSync(store)) { - fs.writeFileSync(store, JSON.stringify({ message: null, timestamp: null })); + await fs.promises.writeFile(store, JSON.stringify({ message: null, timestamp: null })); } - const data = JSON.parse(fs.readFileSync(store, 'utf8')); + const data = JSON.parse(await fs.promises.readFile(store, 'utf8')); if (data.message && data.timestamp) { return { message: data.message, timestamp: data.timestamp }; } return null; } export const setAfkMessage = async (afkMessage, timestamp) => { if (!fs.existsSync(store)) { - fs.writeFileSync(store, JSON.stringify({ message: null, timestamp: null })); + await fs.promises.writeFile(store, JSON.stringify({ message: null, timestamp: null })); } const data = { message: afkMessage, timestamp }; - fs.writeFileSync(store, JSON.stringify(data, null, 2)); + await fs.promises.writeFile(store, JSON.stringify(data, null, 2)); return data; }; export const delAfkMessage = async () => { if (!fs.existsSync(store)) { - fs.writeFileSync(store, JSON.stringify({ message: null, timestamp: null })); + await fs.promises.writeFile(store, JSON.stringify({ message: null, timestamp: null })); } const data = { message: null, timestamp: null }; - fs.writeFileSync(store, JSON.stringify(data, null, 2)); + await fs.promises.writeFile(store, JSON.stringify(data, null, 2)); };Also applies to: 19-21, 27-28
9-12:
⚠️ Potential issueHandle JSON parsing errors to prevent crashes
Errors may occur when parsing the JSON file if it's corrupted or improperly formatted. Adding error handling will make the application more robust.
Apply this diff:
- const data = JSON.parse(fs.readFileSync(store, 'utf8')); + let data; + try { + data = JSON.parse(await fs.promises.readFile(store, 'utf8')); + } catch (error) { + console.error('Failed to read or parse the JSON file:', error); + data = { message: null, timestamp: null }; + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.let data; try { data = JSON.parse(await fs.promises.readFile(store, 'utf8')); } catch (error) { console.error('Failed to read or parse the JSON file:', error); data = { message: null, timestamp: null }; } if (data.message && data.timestamp) { return { message: data.message, timestamp: data.timestamp }; }
1-2: 🛠️ Refactor suggestion
Use 'node:' protocol when importing Node.js built-in modules
As per Node.js best practices and the static analysis hints, you should import built-in modules using the
node:
protocol to make it explicit.Apply this diff:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
sql/akick.js (4)
10-10: 🧹 Nitpick (assertive)
Wrap single-statement 'if' blocks in curly braces for consistency
Using curly braces
{}
around single-statementif
blocks improves readability and prevents potential issues if more statements are added later.Apply this diff:
if (!fs.existsSync(store)) - fs.writeFileSync(store, JSON.stringify([])); +{ + fs.writeFileSync(store, JSON.stringify([])); +}Apply similar changes to lines 21 and 31.
Also applies to: 21-21, 31-31
6-7: 🧹 Nitpick (assertive)
Use asynchronous file operations within async functions
Synchronous file operations inside async functions can block the event loop. It's advisable to use asynchronous methods with
await
to enhance performance.Refactored code:
-const readDB = () => JSON.parse(fs.readFileSync(store, 'utf8')); +const readDB = async () => JSON.parse(await fs.promises.readFile(store, 'utf8')); -const writeDB = (data) => fs.writeFileSync(store, JSON.stringify(data, null, 2)); +const writeDB = async (data) => await fs.promises.writeFile(store, JSON.stringify(data, null, 2)); export const addAKick = async (groupJid, userJid) => { if (!fs.existsSync(store)) { - fs.writeFileSync(store, JSON.stringify([])); + await fs.promises.writeFile(store, JSON.stringify([])); } - const data = readDB(); + const data = await readDB(); if (data.some((record) => record.groupJid === groupJid && record.userJid === userJid)) { return false; } data.push({ groupJid, userJid }); - writeDB(data); + await writeDB(data); return true; }; export const delKick = async (groupJid, userJid) => { if (!fs.existsSync(store)) { - fs.writeFileSync(store, JSON.stringify([])); + await fs.promises.writeFile(store, JSON.stringify([])); } - const data = readDB(); + const data = await readDB(); const filteredData = data.filter( (record) => !(record.groupJid === groupJid && record.userJid === userJid) ); - writeDB(filteredData); + await writeDB(filteredData); return data.length !== filteredData.length; }; export const getKicks = async (groupJid, userJid = null) => { if (!fs.existsSync(store)) { - fs.writeFileSync(store, JSON.stringify([])); + await fs.promises.writeFile(store, JSON.stringify([])); } - const data = readDB(); + const data = await readDB(); return data.filter( (record) => record.groupJid === groupJid && (!userJid || record.userJid === userJid) ); };Also applies to: 11-17, 22-27, 32-36
6-7:
⚠️ Potential issueHandle JSON parsing errors to prevent crashes
Parsing errors can occur if the JSON file is corrupted. Adding error handling makes the code more robust against such issues.
Apply this diff:
-const readDB = () => JSON.parse(fs.readFileSync(store, 'utf8')); +const readDB = async () => { + try { + const data = await fs.promises.readFile(store, 'utf8'); + return JSON.parse(data); + } catch (error) { + console.error('Failed to read or parse the JSON file:', error); + return []; + } +};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const readDB = async () => { try { const data = await fs.promises.readFile(store, 'utf8'); return JSON.parse(data); } catch (error) { console.error('Failed to read or parse the JSON file:', error); return []; } }; const writeDB = (data) => fs.writeFileSync(store, JSON.stringify(data, null, 2));
1-2: 🛠️ Refactor suggestion
Use 'node:' protocol when importing Node.js built-in modules
Following Node.js recommendations and the static analysis hints, import built-in modules using the
node:
protocol.Apply this diff:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
sql/antibot.js (3)
10-11: 🧹 Nitpick (assertive)
Refactor repeated file initialization checks
The checks to initialize the
antibotStore
file are repeated in multiple functions. Consider refactoring to initialize the file once or create a helper function to reduce code duplication.Apply this diff to refactor the initialization:
+// Ensure the antibotStore file exists +if (!fs.existsSync(antibotStore)) fs.writeFileSync(antibotStore, JSON.stringify([])); +// Optionally, create a helper function +const ensureStore = () => { + if (!fs.existsSync(antibotStore)) fs.writeFileSync(antibotStore, JSON.stringify([])); +}; async function setAntibot(jid, enabled) { - if (!fs.existsSync(antibotStore)) fs.writeFileSync(antibotStore, JSON.stringify([])); + ensureStore(); const data = readDB(); // ... } async function delAntibot(jid) { - if (!fs.existsSync(antibotStore)) fs.writeFileSync(antibotStore, JSON.stringify([])); + ensureStore(); const data = readDB(); // ... } async function getAntibot(jid) { - if (!fs.existsSync(antibotStore)) fs.writeFileSync(antibotStore, JSON.stringify([])); + ensureStore(); const data = readDB(); // ... }Also applies to: 25-26, 33-34
6-7: 🧹 Nitpick (assertive)
Add error handling for file operations
Currently, file reads and writes do not handle possible errors, which could lead to unhandled exceptions if the file is inaccessible or corrupted. Implement error handling to make the code more robust.
Consider wrapping file operations in try-catch blocks or using asynchronous versions with error callbacks.
const readDB = () => { + try { return JSON.parse(fs.readFileSync(antibotStore, 'utf8')); + } catch (error) { + console.error('Error reading antibotStore:', error); + return []; + } }; const writeDB = (data) => { + try { fs.writeFileSync(antibotStore, JSON.stringify(data, null, 2)); + } catch (error) { + console.error('Error writing to antibotStore:', error); + } };Also applies to: 10-11, 25-26, 33-34
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing Node.js built-in modules
For clarity and to signal that these modules are native to Node.js, it's recommended to use the 'node:' protocol in your import statements.
Apply this diff to update the imports:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
sql/ban.js (2)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing Node.js built-in modules
For clarity and to indicate that these are Node.js native modules, it's recommended to use the 'node:' protocol in import statements.
Apply this diff to update the imports:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
43-43: 🛠️ Refactor suggestion
Avoid reassigning function parameters
Reassigning the
jid
parameter can lead to unintended side effects and confusion. Instead, use a local variable to handle default values.Apply this diff to fix the issue:
export const isBanned = async (jid) => { - if (!jid) jid = ''; + const checkJid = jid || ''; const bannedUsers = await getBanned(); - return bannedUsers.includes(jid); + return bannedUsers.includes(checkJid); };📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.export const isBanned = async (jid) => { const checkJid = jid || ''; const bannedUsers = await getBanned(); return bannedUsers.includes(checkJid); };
🧰 Tools
🪛 Biome (1.9.4)
[error] 43-43: Reassigning a function parameter is confusing.
The parameter is declared here:
Use a local variable instead.
(lint/style/noParameterAssign)
sql/alive.js (3)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing Node.js built-in modules
To make it explicit that you're importing Node.js core modules, it's recommended to use the 'node:' protocol.
Apply this diff to update the imports:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
6-9: 🧹 Nitpick (assertive)
Add error handling for file operations
File operations like reading and writing to the JSON file might fail due to I/O errors. Adding error handling will make your code more robust.
Consider wrapping file operations in try-catch blocks:
const readDB = () => { + try { return JSON.parse(fs.readFileSync(store, 'utf8')); + } catch (error) { + console.error('Error reading alive.json:', error); + return { message: null }; + } }; const writeDB = (data) => { + try { fs.writeFileSync(store, JSON.stringify(data, null, 2)); + } catch (error) { + console.error('Error writing to alive.json:', error); + } };📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const store = path.join('store', 'alive.json'); const readDB = () => { try { return JSON.parse(fs.readFileSync(store, 'utf8')); } catch (error) { console.error('Error reading alive.json:', error); return { message: null }; } }; const writeDB = (data) => { try { fs.writeFileSync(store, JSON.stringify(data, null, 2)); } catch (error) { console.error('Error writing to alive.json:', error); } };
35-37:
⚠️ Potential issueMultiple replacements of '&facts' overwrite each other
You're replacing the '&facts' placeholder three times, which means only the last replacement (
XSTRO.rizz()
) will be used. To include all three pieces of information, consider using different placeholders or combining them.Apply this diff to fix the issue:
Option 1: Use different placeholders
.replace(/&facts/g, await XSTRO.facts()) - .replace(/&facts/g, await XSTRO.quotes()) - .replace(/&facts/g, await XSTRO.rizz()); + .replace(/"es/g, await XSTRO.quotes()) + .replace(/&rizz/g, await XSTRO.rizz());Then update your message template to include
&facts
,"es
, and&rizz
.Option 2: Combine the outputs
.replace(/&facts/g, - await XSTRO.facts()) - .replace(/&facts/g, await XSTRO.quotes()) - .replace(/&facts/g, await XSTRO.rizz()); + `${await XSTRO.facts()}\n${await XSTRO.quotes()}\n${await XSTRO.rizz()}` + );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements..replace(/&facts/g, await XSTRO.facts()) .replace(/"es/g, await XSTRO.quotes()) .replace(/&rizz/g, await XSTRO.rizz());
.replace(/&facts/g, `${await XSTRO.facts()}\n${await XSTRO.quotes()}\n${await XSTRO.rizz()}` );
sql/bgm.js (2)
1-1: 🛠️ Refactor suggestion
Use the 'node:' protocol when importing built-in modules
It's recommended to use the 'node:' protocol when importing Node.js built-in modules for clarity and explicitness.
Apply this diff to update the imports:
-import fs from 'fs'; +import fs from 'node:fs'; -import path from 'path'; +import path from 'node:path';Also applies to: 2-2
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
12-29: 🧹 Nitpick (assertive)
Remove unnecessary 'async' keywords from synchronous functions
The functions
addBgm
,getBgmResponse
,deleteBgm
, andgetBgmList
are declared asasync
but do not perform any asynchronous operations or containawait
expressions. Removing theasync
keyword improves readability and avoids confusion.Apply this diff to remove the
async
keyword:-async function addBgm(word, response) { +function addBgm(word, response) { // function body... } -async function getBgmResponse(word) { +function getBgmResponse(word) { // function body... } -async function deleteBgm(word) { +function deleteBgm(word) { // function body... } -async function getBgmList() { +function getBgmList() { // function body... }Also applies to: 33-40, 44-55, 61-62
sql/group_event.js (2)
1-1: 🛠️ Refactor suggestion
Use the 'node:' protocol when importing built-in modules
It's recommended to use the 'node:' protocol when importing Node.js built-in modules for clarity and explicitness.
Apply this diff to update the imports:
-import fs from 'fs'; +import fs from 'node:fs'; -import path from 'path'; +import path from 'node:path';Also applies to: 2-2
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
19-30: 🧹 Nitpick (assertive)
Remove unnecessary 'async' keywords from synchronous functions
The functions
enableGroupEvents
,disableGroupEvents
, andisGroupEventEnabled
are declared asasync
but do not perform any asynchronous operations or containawait
expressions. Removing theasync
keyword improves readability and avoids confusion.Apply this diff to remove the
async
keyword:-export const enableGroupEvents = async (jid) => { +export const enableGroupEvents = (jid) => { // function body... }; -export const disableGroupEvents = async (jid) => { +export const disableGroupEvents = (jid) => { // function body... }; -export const isGroupEventEnabled = async (jid) => { +export const isGroupEventEnabled = (jid) => { // function body... };Additionally, update the JSDoc comments to reflect that the functions return synchronous values:
- * @returns {Promise<boolean>} - Always returns true upon success. + * @returns {boolean} - Always returns true upon success.Apply this change to all relevant JSDoc comments.
Also applies to: 38-49, 57-60
sql/plugins.js (2)
1-1: 🛠️ Refactor suggestion
Use the 'node:' protocol when importing built-in modules
It's recommended to use the 'node:' protocol when importing Node.js built-in modules for clarity and explicitness.
Apply this diff to update the imports:
-import fs from 'fs'; +import fs from 'node:fs'; -import path from 'path'; +import path from 'node:path';Also applies to: 2-2
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
18-29: 🧹 Nitpick (assertive)
Remove unnecessary 'async' keywords from synchronous functions
The functions
addPlugin
,updatePlugin
,removePlugin
, andgetPlugins
are declared asasync
but do not perform any asynchronous operations or containawait
expressions. Removing theasync
keyword improves readability and avoids confusion.Apply this diff to remove the
async
keyword:-export async function addPlugin(name) { +export function addPlugin(name) { // function body... } -export async function updatePlugin(name, newName) { +export function updatePlugin(name, newName) { // function body... } -export async function removePlugin(name) { +export function removePlugin(name) { // function body... } -export async function getPlugins() { +export function getPlugins() { // function body... }Additionally, update the JSDoc comments to reflect that the functions return synchronous values.
Also applies to: 38-48, 57-66, 74-75
sql/stickercmd.js (3)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing Node.js built-in modules
To clearly indicate that the modules are Node.js built-ins and to enhance code readability, it's recommended to prefix the module names with the
'node:'
protocol.Apply this diff to update the import statements:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
65-83: 🧹 Nitpick (assertive)
Rename
isStickerCmd
to reflect its functionalityThe function
isStickerCmd
returns an object containingexists
andcommand
properties rather than a boolean value. To improve clarity, consider renaming the function togetStickerCmd
to better represent its purpose.Apply this diff to rename the function:
-export async function isStickerCmd(id) { +export async function getStickerCmd(id) {Ensure that all references to this function are updated accordingly throughout the codebase.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.export async function getStickerCmd(id) { const cmds = readStickerCmds(); const stickerCmd = cmds.find((stickerCmd) => stickerCmd.id === id); if (stickerCmd) { return { exists: true, command: { cmd: stickerCmd.cmd, id: stickerCmd.id, }, }; } return { exists: false, command: null, }; }
10-11: 🧹 Nitpick (assertive)
Consider using asynchronous file operations to prevent blocking the event loop
Using synchronous file operations like
fs.readFileSync
andfs.writeFileSync
can block the event loop, which may hinder performance, especially under heavy load or when scaling. Consider using asynchronous file operations to improve scalability and responsiveness.Apply this diff to refactor the file operations:
-const readStickerCmds = () => JSON.parse(fs.readFileSync(store, 'utf8')); -const writeStickerCmds = (cmds) => fs.writeFileSync(store, JSON.stringify(cmds, null, 2)); +const readStickerCmds = async () => JSON.parse(await fs.promises.readFile(store, 'utf8')); +const writeStickerCmds = async (cmds) => await fs.promises.writeFile(store, JSON.stringify(cmds, null, 2));Update the functions that call
readStickerCmds
andwriteStickerCmds
to handle the promises appropriately:-export async function setcmd(cmd, id) { +export async function setcmd(cmd, id) { + const cmds = await readStickerCmds(); // rest of the code📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const readStickerCmds = async () => JSON.parse(await fs.promises.readFile(store, 'utf8')); const writeStickerCmds = async (cmds) => await fs.promises.writeFile(store, JSON.stringify(cmds, null, 2));
sql/mention.js (2)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing Node.js built-in modules
To enhance clarity and explicitly indicate Node.js built-in modules, it's advisable to prefix the module names with the
'node:'
protocol.Apply this diff to update the import statements:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
10-11: 🧹 Nitpick (assertive)
Refactor synchronous file operations to asynchronous to improve performance
Synchronous file operations can block the event loop, potentially impacting the application's performance. Refactoring to use asynchronous file operations will enhance scalability and responsiveness.
Apply this diff to modify the file operations:
-const readMentions = () => JSON.parse(fs.readFileSync(store, 'utf8')); -const writeMentions = (mentions) => fs.writeFileSync(store, JSON.stringify(mentions, null, 2)); +const readMentions = async () => JSON.parse(await fs.promises.readFile(store, 'utf8')); +const writeMentions = async (mentions) => await fs.promises.writeFile(store, JSON.stringify(mentions, null, 2));Update the functions that use
readMentions
andwriteMentions
to handle the promises:-export async function setMention(jid, message) { +export async function setMention(jid, message) { + const mentions = await readMentions(); // rest of the codeCommittable suggestion skipped: line range outside the PR's diff.
sql/filters.js (2)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing Node.js built-in modules
By prefixing the module names with the
'node:'
protocol, you make it explicit that these are Node.js built-in modules, which improves code readability and maintainability.Apply this diff to update the import statements:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
10-11: 🧹 Nitpick (assertive)
Optimize file operations by switching to asynchronous methods
The use of synchronous methods like
fs.readFileSync
andfs.writeFileSync
can block the event loop and degrade performance under load. Refactoring to asynchronous methods will enhance the application's efficiency.Apply this diff to refactor the file operations:
-const readFilters = () => JSON.parse(fs.readFileSync(store, 'utf8')); -const writeFilters = (filters) => fs.writeFileSync(store, JSON.stringify(filters, null, 2)); +const readFilters = async () => JSON.parse(await fs.promises.readFile(store, 'utf8')); +const writeFilters = async (filters) => await fs.promises.writeFile(store, JSON.stringify(filters, null, 2));Adjust the functions that call
readFilters
andwriteFilters
to handle the asynchronous operations:-export async function addFilter(type, text, response) { +export async function addFilter(type, text, response) { + const filters = await readFilters(); // rest of the code📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const readFilters = async () => JSON.parse(await fs.promises.readFile(store, 'utf8')); const writeFilters = async (filters) => await fs.promises.writeFile(store, JSON.stringify(filters, null, 2));
plugins/misc.js (4)
65-72:
⚠️ Potential issueSanitize user input to prevent code injection attacks.
Evaluating user-provided expressions using
evaluate(match)
can lead to security vulnerabilities if the input is not properly sanitized, as it might execute arbitrary code.Implement input sanitization or limit the scope of allowed expressions:
async (message, match) => { if (!match) return await message.send('*Example: `.math 2 + 2`*'); const msg = await message.send('*Calculating...*'); try { + // Restrict allowed characters to prevent malicious input + if (!/^[0-9+\-*/().\s^%]*$/.test(match)) + throw new Error('Invalid characters in expression'); const result = evaluate(match); return await msg.edit(`Result: ${result}`); } catch { return await msg.edit(`_Syntax Error_`); } }Alternatively, consider using a safer evaluation method that doesn't execute arbitrary code.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!match) return await message.send('*Example: `.math 2 + 2`*'); const msg = await message.send('*Calculating...*'); try { // Restrict allowed characters to prevent malicious input if (!/^[0-9+\-*/().\s^%]*$/.test(match)) throw new Error('Invalid characters in expression'); const result = evaluate(match); return await msg.edit(`Result: ${result}`); } catch { return await msg.edit(`_Syntax Error_`); }
84-90: 🧹 Nitpick (assertive)
Handle cases where user status is not accessible and improve message clarity.
If the user's status or
setAt
date is not available, the bot should inform the user more clearly.Apply this diff to enhance the response:
async (message, match) => { const jid = await message.getUserJid(match); const { status, setAt } = await message.client.fetchStatus(jid); if (status && setAt) { - await message.send(`\`\`\`Bio: ${status}\nSetAt: ${setAt}\`\`\``); + const date = new Date(setAt).toLocaleString(); + await message.send(`*Bio:* ${status}\n*Set At:* ${date}`); } else { - message.send(`_User's settings doesn't allow me to_`); + await message.send(`*Unable to retrieve bio for this user.*`); } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const jid = await message.getUserJid(match); const { status, setAt } = await message.client.fetchStatus(jid); if (status && setAt) { const date = new Date(setAt).toLocaleString(); await message.send(`*Bio:* ${status}\n*Set At:* ${date}`); } else { await message.send(`*Unable to retrieve bio for this user.*`); }
29-35: 🛠️ Refactor suggestion
Validate URLs more robustly and handle errors gracefully.
The regular expression used for URL validation is too permissive and might accept invalid URLs. Additionally, if the URL is invalid or the media cannot be sent, the user won't receive feedback.
Consider using a more precise URL validation method and add error handling:
async (message, match) => { - if (!match || !/^https?:\/\/[^\s$.?#].[^\s]*$/.test(match)) + try { + new URL(match); + } catch { return message.send('*Please provide a valid URL.*'); } const url = extractUrlFromString(match); - return await message.client.sendMessage(message.jid, { + await message.client.sendMessage(message.jid, { video: { url: url }, caption: '*HERE WE GO*', }); + return; +} catch (error) { + await message.send('*Failed to send video. Please check the URL and try again.*'); +} }Committable suggestion skipped: line range outside the PR's diff.
13-18: 🧹 Nitpick (assertive)
Ensure consistent error messages and consider edge cases.
The command checks for empty input but does not handle inputs without the '|' separator, which is required by the
readmore
function. Additionally, the error messages use different styles ('*Give me text!*'
vs.'*Format: text1|text2*'
).Apply this diff to enhance input validation and unify error messages:
async (message, match) => { - if (!match) return await message.send('*Give me text!*'); + if (!match || !match.includes('|')) + return await message.send('*Please provide text in the format: text1|text2*'); const result = readmore(match); - if (!result) return await message.send('*Format: text1|text2*'); return await message.send(result); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async (message, match) => { if (!match || !match.includes('|')) return await message.send('*Please provide text in the format: text1|text2*'); const result = readmore(match); return await message.send(result); }
sql/notes.js (3)
1-2: 🧹 Nitpick (assertive)
Import Node.js built-in modules using the
node:
protocol.According to static analysis hints, using the
node:
protocol is more explicit and signals that the imported module belongs to Node.js.Apply this diff to update the import statements:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
85-87: 🧹 Nitpick (assertive)
Performance optimization: Use early return.
In
getNote
, the|| null
is unnecessary sincefind
returnsundefined
if no match is found.Simplify the return statement:
export async function getNote(id) { const notes = readNotes(); - return notes.find((note) => note.id === id) || null; + return notes.find((note) => note.id === id); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const notes = readNotes(); return notes.find((note) => note.id === id); }
22-26: 🛠️ Refactor suggestion
Ensure unique and incremental note IDs in concurrent environments.
Using
notes.length + 1
for theid
may result in duplicate IDs if notes are deleted or in a concurrent environment.Consider generating unique IDs using a UUID library or tracking the last used ID:
const newNote = { - id: notes.length + 1, // Auto-increment id based on the current notes length + id: Date.now(), // Use timestamp as a simple unique ID title, content, createdAt: new Date(), };Alternatively, maintain a separate file to track the last used ID.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.id: Date.now(), // Use timestamp as a simple unique ID title, content, createdAt: new Date(), };
sql/antiword.js (4)
96-99: 🧹 Nitpick (assertive)
Handle undefined return in
isAntiWordEnabled
.If
jid
is not provided, the function currently returnsundefined
. For consistency, it should returnfalse
or throw an error.Adjust the function to return
false
whenjid
is missing:async function isAntiWordEnabled(jid) { - if (!jid) return; + if (!jid) return false; const db = readDB(); const record = db.find((item) => item.jid === jid); return record ? record.status : false; }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!jid) return false; const db = readDB(); const record = db.find((item) => item.jid === jid); return record ? record.status : false;
14-21: 🛠️ Refactor suggestion
Prevent direct mutation of objects within arrays.
Modifying
record
directly can lead to unintended side effects if other references torecord
exist.Create a new object when updating
record
:if (!record) { record = { jid, status: action, words: [] }; db.push(record); } else { - record.status = action; + const updatedRecord = { ...record, status: action }; + const index = db.findIndex((item) => item.jid === jid); + db[index] = updatedRecord; }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.let record = db.find((item) => item.jid === jid); if (!record) { record = { jid, status: action, words: [] }; db.push(record); } else { const updatedRecord = { ...record, status: action }; const index = db.findIndex((item) => item.jid === jid); db[index] = updatedRecord; }
1-2: 🧹 Nitpick (assertive)
Import Node.js built-in modules using the
node:
protocol.As indicated by static analysis, updating the import statements enhances clarity.
Apply this diff:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
40-42: 🧹 Nitpick (assertive)
Ensure uniqueness when adding antiwords and handle case sensitivity.
When combining word lists, consider normalizing words to handle case differences and prevent duplicates.
Normalize words before merging:
const normalize = (word) => word.toLowerCase(); const uniqueWords = [ ...new Set([...record.words.map(normalize), ...words.map(normalize)]), ]; record.words = uniqueWords;Committable suggestion skipped: line range outside the PR's diff.
bot/schedule.js (2)
32-69: 🧹 Nitpick (assertive)
Refactor duplicated muting and unmuting logic into a single function
The muting and unmuting code blocks are almost identical, leading to code duplication. Refactoring them into a single function improves maintainability and reduces potential errors.
Consider applying the following refactor:
+const handleGroupSetting = async (schedule, isMuting) => { + try { + const setting = isMuting ? 'announcement' : 'not_announcement'; + await client.groupSettingUpdate(schedule.groupId, setting); + await addOrUpdateSchedule( + schedule.groupId, + schedule.muteTime, + schedule.unmuteTime, + !isMuting, + schedule.isScheduled + ); + const message = isMuting + ? '```Group has been muted, due to AutoMute```' + : '```Group is now unmuted, due to AutoUnMute```'; + await client.sendMessage(schedule.groupId, { text: message }); + } catch (error) { + const action = isMuting ? 'mute' : 'unmute'; + console.error(`Failed to ${action} group ${schedule.groupId}:`, error); + } +}; for (const schedule of schedules) { if (!schedule.isScheduled) continue; if (schedule.muteTime === currentTime && schedule.isMuted) { - try { - await client.groupSettingUpdate(schedule.groupId, 'announcement'); - await addOrUpdateSchedule( - schedule.groupId, - schedule.muteTime, - schedule.unmuteTime, - false, - schedule.isScheduled - ); - await client.sendMessage(schedule.groupId, { - text: '```Group has been muted, due to AutoMute```', - }); - } catch (error) { - console.error(`Failed to mute group ${schedule.groupId}:`, error); - } + await handleGroupSetting(schedule, true); } if (schedule.unmuteTime === currentTime && !schedule.isMuted) { - try { - await client.groupSettingUpdate(schedule.groupId, 'not_announcement'); - await addOrUpdateSchedule( - schedule.groupId, - schedule.muteTime, - schedule.unmuteTime, - true, - schedule.isScheduled - ); - await client.sendMessage(schedule.groupId, { - text: '```Group is now unmuted, due to AutoUnMute```', - }); - } catch (error) { - console.error(`Failed to unmute group ${schedule.groupId}:`, error); - } + await handleGroupSetting(schedule, false); } }
24-74:
⚠️ Potential issuePrevent overlapping executions by avoiding async functions inside
setInterval
Using an asynchronous function inside
setInterval
can lead to overlapping executions if the asynchronous tasks take longer than the interval duration. This can cause unexpected behavior and resource exhaustion.Consider refactoring to use
setTimeout
to schedule the next execution after the asynchronous task completes.Apply this refactor:
-export const schedules = async (msg) => { +export const schedules = (msg) => { const client = msg.client; - setInterval(async () => { + const scheduleHandler = async () => { try { const currentTime = getCurrentTime(); const schedules = await getAllSchedules(); for (const schedule of schedules) { if (!schedule.isScheduled) continue; if (schedule.muteTime === currentTime && schedule.isMuted) { // Muting logic // ... } if (schedule.unmuteTime === currentTime && !schedule.isMuted) { // Unmuting logic // ... } } } catch (error) { console.error('Error in schedule handler:', error); } + setTimeout(scheduleHandler, 10000); }; + scheduleHandler(); }Committable suggestion skipped: line range outside the PR's diff.
sql/scheduler.js (2)
10-11: 🛠️ Refactor suggestion
Prevent potential race conditions with concurrent file access
Using synchronous file operations without proper concurrency control can lead to race conditions if multiple operations access the
schedules.json
file simultaneously. This may cause data corruption or loss.Consider using asynchronous file operations and implementing a locking mechanism to handle concurrent access safely.
Refactor the code as follows:
-const readSchedules = () => JSON.parse(fs.readFileSync(store, 'utf8')); -const writeSchedules = (schedules) => fs.writeFileSync(store, JSON.stringify(schedules, null, 2)); +const readSchedules = async () => JSON.parse(await fs.promises.readFile(store, 'utf8')); +const writeSchedules = async (schedules) => await fs.promises.writeFile(store, JSON.stringify(schedules, null, 2)); export async function addOrUpdateSchedule( groupId, muteTime, unmuteTime, isMuted = false, isScheduled = false ) { - const schedules = readSchedules(); + const schedules = await readSchedules(); let schedule = schedules.find((schedule) => schedule.groupId === groupId); if (schedule) { // Update existing schedule schedule.muteTime = muteTime; schedule.unmuteTime = unmuteTime; schedule.isMuted = isMuted; schedule.isScheduled = isScheduled; } else { // Add new schedule schedule = { groupId, muteTime, unmuteTime, isMuted, isScheduled }; schedules.push(schedule); } - writeSchedules(schedules); + await writeSchedules(schedules); return schedule; }Note: Implementing proper concurrency handling, like file locking or queuing write operations, is crucial to ensure data integrity.
Also applies to: 29-45
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing Node.js built-in modules
Using the 'node:' protocol when importing Node.js built-in modules clarifies that these modules are core Node.js modules and not third-party packages.
Apply this diff to update the import statements:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
sql/config.js (6)
28-29: 🛠️ Refactor suggestion
Prevent potential race conditions in config file operations
Concurrent access to the
config.json
file without proper handling can lead to race conditions and data corruption. This is especially important if multiple parts of the application might read or write to the config simultaneously.Consider using asynchronous file operations and implementing locking mechanisms to ensure safe concurrent access.
Refactor the file operations:
-const readConfig = () => JSON.parse(fs.readFileSync(store, 'utf8')); -const writeConfig = (config) => fs.writeFileSync(store, JSON.stringify(config, null, 2)); +const readConfig = async () => { + try { + const data = await fs.promises.readFile(store, 'utf8'); + return JSON.parse(data); + } catch (error) { + // Handle error + } +}; +const writeConfig = async (config) => { + await fs.promises.writeFile(store, JSON.stringify(config, null, 2)); +}; // Update functions to use async/await async function updateConfig(field, value) { - let config = await ensureConfigExists(); + const config = await ensureConfigExists(); // ... } // Similarly update other functions that read/write configNote: Ensuring atomic write operations and possibly using a library for managing configuration files can help prevent such issues.
Also applies to: 52-109
28-29:
⚠️ Potential issueHandle potential JSON parsing errors in
readConfig
If
config.json
becomes corrupted or contains invalid JSON,JSON.parse
will throw an error, which can crash the application. It's important to handle this exception gracefully.Consider updating
readConfig
to handle parsing errors:-const readConfig = () => JSON.parse(fs.readFileSync(store, 'utf8')); +const readConfig = () => { + try { + return JSON.parse(fs.readFileSync(store, 'utf8')); + } catch (error) { + console.error('Failed to read or parse config.json:', error); + // Optionally reinitialize the config file with default values + const defaultConfig = { + autoRead: false, + autoStatusRead: false, + cmdReact: true, + cmdRead: false, + mode: false, + PREFIX: '.', + disabledCmds: [], + autolikestatus: false, + disablegc: false, + disabledm: false, + }; + writeConfig(defaultConfig); + return defaultConfig; + } +};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const readConfig = () => { try { return JSON.parse(fs.readFileSync(store, 'utf8')); } catch (error) { console.error('Failed to read or parse config.json:', error); // Optionally reinitialize the config file with default values const defaultConfig = { autoRead: false, autoStatusRead: false, cmdReact: true, cmdRead: false, mode: false, PREFIX: '.', disabledCmds: [], autolikestatus: false, disablegc: false, disabledm: false, }; writeConfig(defaultConfig); return defaultConfig; } }; const writeConfig = (config) => fs.writeFileSync(store, JSON.stringify(config, null, 2));
99-99: 🧹 Nitpick (assertive)
Use 'const' instead of 'let' for
config
variableThe
config
variable is not mutated after declaration. Usingconst
is more appropriate here.Apply this change:
- let config = await ensureConfigExists(); + const config = await ensureConfigExists();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const config = await ensureConfigExists();
🧰 Tools
🪛 Biome (1.9.4)
[error] 99-99: This let declares a variable that is only assigned once.
'config' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
52-52: 🧹 Nitpick (assertive)
Use 'const' instead of 'let' for variables not reassigned
The variable
config
is declared withlet
but is not reassigned in the scope. Usingconst
emphasizes that the variable is not intended to be reassigned.Apply this change:
- let config = await ensureConfigExists(); + const config = await ensureConfigExists();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const config = await ensureConfigExists();
🧰 Tools
🪛 Biome (1.9.4)
[error] 52-52: This let declares a variable that is only assigned once.
'config' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing Node.js built-in modules
Consistently using the 'node:' protocol when importing built-in modules enhances code clarity and prevents confusion with similarly named third-party modules.
Apply this diff:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
85-85: 🧹 Nitpick (assertive)
Use 'const' instead of 'let' for
config
variableSince
config
is not reassigned after its initial assignment, declaring it withconst
improves code readability and prevents accidental reassignment.Apply this change:
- let config = await ensureConfigExists(); + const config = await ensureConfigExists();📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const config = await ensureConfigExists();
🧰 Tools
🪛 Biome (1.9.4)
[error] 85-85: This let declares a variable that is only assigned once.
'config' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
sql/antilink.js (2)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing built-in modules
It's recommended to use the
'node:'
protocol when importing Node.js built-in modules for clarity and explicitness.Apply this diff to update the import statements:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
93-94: 🧹 Nitpick (assertive)
Simplify null checks using optional chaining
You can simplify the code by utilizing optional chaining to handle undefined properties more elegantly.
Apply this diff to improve the code:
-const groupConfig = (readDB()[jid] || {})[type]; +const groupConfig = readDB()[jid]?.[type];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const groupConfig = readDB()[jid]?.[type]; const newCount = (groupConfig?.warningCount || 0) + 1;
🧰 Tools
🪛 Biome (1.9.4)
[error] 93-93: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
sql/greetings.js (1)
1-2: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing built-in modules
It's recommended to use the
'node:'
protocol when importing Node.js built-in modules for clarity and explicitness.Apply this diff to update the import statements:
-import fs from 'fs'; -import path from 'path'; +import fs from 'node:fs'; +import path from 'node:path';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import fs from 'node:fs'; import path from 'node:path';
🧰 Tools
🪛 Biome (1.9.4)
[error] 1-1: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
[error] 2-2: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
lib/client.js (3)
11-11: 🧹 Nitpick (assertive)
Use 'node:' protocol when importing built-in modules
It's recommended to use the
'node:'
protocol when importing Node.js built-in modules for clarity and explicitness.Apply this diff to update the import statement:
-import { EventEmitter } from 'events'; +import { EventEmitter } from 'node:events';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import { EventEmitter } from 'node:events';
🧰 Tools
🪛 Biome (1.9.4)
[error] 11-11: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
99-105:
⚠️ Potential issueWrap variable declaration in switch case with a block
Declaring variables inside a
switch
case without wrapping them in a block can cause scope leakage, leading to unexpected behavior. To ensure proper scoping, wrap the case in braces.Apply this diff to fix the scoping issue:
case 'open': + { const web = version.join('.'); await conn.sendMessage(conn.user.id, { text: `\`\`\`Bot Connected\n${web}\`\`\``, }); console.log(`Connected`); + } break;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.{ const web = version.join('.'); await conn.sendMessage(conn.user.id, { text: `\`\`\`Bot Connected\n${web}\`\`\``, }); console.log(`Connected`); } break; }
🧰 Tools
🪛 Biome (1.9.4)
[error] 99-99: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
58-71: 🧹 Nitpick (assertive)
Avoid reassigning function parameters
Reassigning function parameters can lead to confusion and unexpected bugs. It's better to assign the new value to a local variable.
Apply this diff to avoid reassigning the
message
parameter:-patchMessageBeforeSending: (message) => { +patchMessageBeforeSending: (originalMessage) => { const requiresPatch = !!( - message.buttonsMessage || - message.templateMessage || - message.listMessage || - message.scheduledCallCreationMessage || - message.callLogMesssage + originalMessage.buttonsMessage || + originalMessage.templateMessage || + originalMessage.listMessage || + originalMessage.scheduledCallCreationMessage || + originalMessage.callLogMesssage ); if (requiresPatch) { - message = { + const patchedMessage = { viewOnceMessage: { message: { messageContextInfo: { deviceListMetadataVersion: 2, deviceListMetadata: {}, }, - ...message, + ...originalMessage, }, }, }; - return message; + return patchedMessage; } - return message; + return originalMessage; },📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const patchedMessage = { viewOnceMessage: { message: { messageContextInfo: { deviceListMetadataVersion: 2, deviceListMetadata: {}, }, ...originalMessage, }, }, }; } return originalMessage;
🧰 Tools
🪛 Biome (1.9.4)
[error] 58-58: Reassigning a function parameter is confusing.
The parameter is declared here:
Use a local variable instead.
(lint/style/noParameterAssign)
plugins/tools.js (6)
41-46:
⚠️ Potential issueAdd error handling for the 'remini' function in 'recolor' command
The
recolor
command lacks error handling for theremini
function call. If an error occurs during the recoloring process, it may result in an unhandled exception.Apply this diff to handle errors:
async (message) => { if (!message.reply_message?.image) return message.send('_Reply An Image_'); const img = await message.download(); - const recoloredImg = await remini(img, 'recolor'); - await message.send(recoloredImg); + try { + const recoloredImg = await remini(img, 'recolor'); + await message.send(recoloredImg); + } catch (error) { + await message.send('_Failed to recolor the image._'); + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async (message) => { if (!message.reply_message?.image) return message.send('_Reply An Image_'); const img = await message.download(); try { const recoloredImg = await remini(img, 'recolor'); await message.send(recoloredImg); } catch (error) { await message.send('_Failed to recolor the image._'); } }
71-84:
⚠️ Potential issueAdd error handling for file operations in 'upload' command
The
upload
command performs file download and upload without error handling. If either operation fails, it could lead to unhandled exceptions.Apply this diff to handle errors:
async (message) => { if ( !message.reply_message.image && !message.reply_message.video && !message.reply_message.audio && !message.reply_message.sticker && !message.reply_message.document ) { return message.send('_Reply A File_'); } - const data = await message.download(); - const url = await uploadFile(data); - await message.send(`*${url}*`); + try { + const data = await message.download(); + const url = await uploadFile(data); + await message.send(`*${url}*`); + } catch (error) { + await message.send('_Failed to upload the file._'); + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async (message) => { if ( !message.reply_message.image && !message.reply_message.video && !message.reply_message.audio && !message.reply_message.sticker && !message.reply_message.document ) { return message.send('_Reply A File_'); } try { const data = await message.download(); const url = await uploadFile(data); await message.send(`*${url}*`); } catch (error) { await message.send('_Failed to upload the file._'); } }
56-61:
⚠️ Potential issueAdd error handling for the 'remini' function in 'dehaze' command
Similarly, the
dehaze
command should handle potential errors from theremini
function to prevent unhandled exceptions.Apply this diff to handle errors:
async (message) => { if (!message.reply_message?.image) return message.send('_Reply An Image_'); const img = await message.download(); - const dehazedImg = await remini(img, 'dehaze'); - await message.send(dehazedImg); + try { + const dehazedImg = await remini(img, 'dehaze'); + await message.send(dehazedImg); + } catch (error) { + await message.send('_Failed to dehaze the image._'); + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async (message) => { if (!message.reply_message?.image) return message.send('_Reply An Image_'); const img = await message.download(); try { const dehazedImg = await remini(img, 'dehaze'); await message.send(dehazedImg); } catch (error) { await message.send('_Failed to dehaze the image._'); } }
95-102:
⚠️ Potential issueAdd error handling for network operations in 'getsticker' command
The
getsticker
command does not handle errors from network requests likeXSTRO.searchSticker
,getBuffer
, andcreateSticker
. Unhandled errors may cause the bot to crash or behave unexpectedly.Apply this diff to handle errors:
async (message, match) => { if (!match) return message.send('_Provide A Query_'); + try { const stickers = await XSTRO.searchSticker(match); for (const sticker of stickers) { const buffer = await getBuffer(sticker); const stickerUrl = await createSticker(buffer); await message.send(stickerUrl, { type: 'sticker' }); } + } catch (error) { + await message.send('_Failed to fetch stickers._'); + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!match) return message.send('_Provide A Query_'); try { const stickers = await XSTRO.searchSticker(match); for (const sticker of stickers) { const buffer = await getBuffer(sticker); const stickerUrl = await createSticker(buffer); await message.send(stickerUrl, { type: 'sticker' }); } } catch (error) { await message.send('_Failed to fetch stickers._'); } }
26-31:
⚠️ Potential issueAdd error handling for the 'remini' function in 'enhance' command
Currently, if the
remini
function fails, the error is not handled, which could lead to unhandled promise rejections and a poor user experience. It's important to catch any errors and inform the user appropriately.Apply this diff to handle errors:
async (message) => { if (!message.reply_message?.image) return message.send('_Reply An Image_'); const img = await message.download(); - const enhancedImg = await remini(img, 'enhance'); - await message.send(enhancedImg); + try { + const enhancedImg = await remini(img, 'enhance'); + await message.send(enhancedImg); + } catch (error) { + await message.send('_Failed to enhance the image._'); + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async (message) => { if (!message.reply_message?.image) return message.send('_Reply An Image_'); const img = await message.download(); try { const enhancedImg = await remini(img, 'enhance'); await message.send(enhancedImg); } catch (error) { await message.send('_Failed to enhance the image._'); } }
179-179: 🧹 Nitpick (assertive)
Use 'const' instead of 'let' for 'repoUrl'
The variable
repoUrl
is declared withlet
but is not reassigned after initialization. Usingconst
is preferable for variables that do not change, improving code readability and preventing accidental reassignments.Apply this diff to fix the issue:
- let repoUrl = match.endsWith('.git') ? match.replace('.git', '') : match; + const repoUrl = match.endsWith('.git') ? match.replace('.git', '') : match;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const repoUrl = match.endsWith('.git') ? match.replace('.git', '') : match;
🧰 Tools
🪛 Biome (1.9.4)
[error] 179-179: This let declares a variable that is only assigned once.
'repoUrl' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
plugins/add.js (2)
69-71: 🧹 Nitpick (assertive)
Consider simplifying the error message.
The current error message is verbose and could be more concise while maintaining clarity.
- '```Unable to send an Invite, this is because this person has not saved your contact, please do not misue this command, It Will Of Course Ban Your ACCOUNT!!!\n\nIf you are sure that indeed that this person has saved your number, then please do not use it yet```' + '```❌ Invite failed: Contact not saved\n\n⚠️ WARNING: Using this command with unsaved contacts can result in account ban!\n\n📝 Note: Even if you believe the contact is saved, please wait before retrying.```'
14-16: 🧹 Nitpick (assertive)
Consider enhancing the warning message visibility.
The warning about potential account bans is crucial. Consider making it more prominent by:
- Using a more attention-grabbing prefix (e.g., "🚨 CRITICAL WARNING")
- Adding line breaks for better readability
- await message.send( - `\`\`\`⚠️ Warning: Using this command improperly can lead to your account being banned! Ensure the recipient has saved your contact before proceeding. Misuse of this feature is strictly prohibited by whatsapp\`\`\`` - ); + await message.send( + `\`\`\`🚨 CRITICAL WARNING 🚨\n\nUsing this command improperly can lead to your account being banned!\n\n- Ensure the recipient has saved your contact\n- Misuse is strictly prohibited by WhatsApp\`\`\`` + );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.await message.send( `\`\`\`🚨 CRITICAL WARNING 🚨\n\nUsing this command improperly can lead to your account being banned!\n\n- Ensure the recipient has saved your contact\n- Misuse is strictly prohibited by WhatsApp\`\`\`` );
plugins/menu.js (1)
77-79: 🧹 Nitpick (assertive)
Improve variable declarations.
Declare variables separately and use
const
for variables that aren't reassigned.- if (command.pattern) cmd = command.pattern.toString().split(/\W+/)[1]; - desc = command.desc || false; + const cmd = command.pattern ? command.pattern.toString().split(/\W+/)[1] : undefined; + const desc = command.desc || false;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const cmd = command.pattern ? command.pattern.toString().split(/\W+/)[1] : undefined; const desc = command.desc || false; if (!command.dontAddCommandList && cmd !== undefined) cmdList.push({ cmd, desc });
🧰 Tools
🪛 Biome (1.9.4)
[error] 77-78: Declare variables separately
Unsafe fix: Break out into multiple declarations
(lint/style/useSingleVarDeclarator)
[error] 77-77: This let declares a variable that is only assigned once.
'cmdList' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
plugins/help.js (1)
84-86:
⚠️ Potential issueEnhance error handling for external API call.
The external API call needs better error handling and timeout management.
- const res = await getJson(`https://xstrosession.koyeb.app/pair?phone=${id}`); - if (!res.code) return message.send('*unable to get a pairing code, try again!*'); - return await msg.edit(`*${res.code}*`); + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 5000); + + const res = await getJson( + `https://xstrosession.koyeb.app/pair?phone=${id}`, + { signal: controller.signal } + ); + clearTimeout(timeoutId); + + if (!res.code) { + return message.send('*Unable to get a pairing code. Please try again later.*'); + } + return await msg.edit(`*Your pairing code: ${res.code}*`); + } catch (error) { + if (error.name === 'AbortError') { + return message.send('*Request timed out. Please try again.*'); + } + return message.send('*An error occurred while getting the pairing code.*'); + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); const res = await getJson( `https://xstrosession.koyeb.app/pair?phone=${id}`, { signal: controller.signal } ); clearTimeout(timeoutId); if (!res.code) { return message.send('*Unable to get a pairing code. Please try again later.*'); } return await msg.edit(`*Your pairing code: ${res.code}*`); } catch (error) { if (error.name === 'AbortError') { return message.send('*Request timed out. Please try again.*'); } return message.send('*An error occurred while getting the pairing code.*'); }
bot/chatbot.js (1)
1-1: 🧹 Nitpick (assertive)
Remove or update the placeholder comment.
The current comment doesn't provide any value. Consider either removing it or replacing it with proper documentation about the chatbot's functionality.
lib/devs.js (1)
2-6: 💡 Codebase verification
🛠️ Refactor suggestion
Move developer phone numbers to the
SUDO
environment variableThe codebase already supports storing admin phone numbers via the
SUDO
environment variable. Instead of hardcoding these numbers inlib/devs.js
, move them to this environment variable to improve security and maintainability.
- In
lib/devs.js
: Replace the hardcoded array with numbers fromprocess.env.SUDO
- In deployment: Set the
SUDO
environment variable with comma-separated phone numbers🔗 Analysis chain
Consider moving sensitive information to environment variables.
While the formatting changes improve readability, storing phone numbers directly in the source code poses a security risk. Consider moving these to environment variables or a secure configuration management system.
Let's check if these numbers are referenced elsewhere in the codebase:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for hardcoded phone numbers rg -l "['\"](2348|2347|9230)" --type jsLength of output: 67
Script:
#!/bin/bash # Check content of both files echo "=== lib/devs.js ===" cat lib/devs.js echo -e "\n=== sql/sudo.js ===" cat sql/sudo.js # Look for potential config files echo -e "\n=== Config Files ===" fd -e json -e env -e yaml -e yml -e configLength of output: 2793
Script:
#!/bin/bash # Check config files and documentation echo "=== app.json ===" cat app.json echo -e "\n=== render.yaml ===" cat render.yaml echo -e "\n=== Documentation ===" fd README.mdLength of output: 1903
.github/js/test.js (1)
3-5: 🧹 Nitpick (assertive)
Improve test coverage and remove hardcoded values.
Consider the following improvements:
- Add more test cases to verify the JSON storage functionality
- Remove hardcoded WhatsApp number from comments
- Add error handling test cases
.github/workflows/docker-image.yml (1)
16-16:
⚠️ Potential issueFix shell command quoting in Docker tag.
The current command is vulnerable to word splitting. Quote the date command substitution.
- run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) + run: docker build . --file Dockerfile --tag "my-image-name:$(date +%s)"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.run: docker build . --file Dockerfile --tag "my-image-name:$(date +%s)"
🧰 Tools
🪛 actionlint (1.7.4)
16-16: shellcheck reported issue in this script: SC2046:warning:1:54: Quote this to prevent word splitting
(shellcheck)
bot/antidelete.js (2)
11-15: 🧹 Nitpick (assertive)
⚠️ Potential issueImplementation missing for both chat types.
The handlers for both group and personal chats are missing. This could break the anti-delete functionality.
Would you like me to help implement these handlers based on the new JSON storage approach?
5-8:
⚠️ Potential issueAdd error handling for JSON operations.
The function lacks error handling for:
- JSON read operations in
getAntiDelete()
- Protocol message processing
export async function AntiDelete(msg) { - if (!(await getAntiDelete())) return; + try { + const antiDelete = await getAntiDelete(); + if (!antiDelete) return; + } catch (error) { + console.error('Failed to read anti-delete settings:', error); + return; + } if (!msg.message?.protocolMessage) return;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.export async function AntiDelete(msg) { try { const antiDelete = await getAntiDelete(); if (!antiDelete) return; } catch (error) { console.error('Failed to read anti-delete settings:', error); return; } if (!msg.message?.protocolMessage) return;
.github/workflows/label.yml (1)
14-16:
⚠️ Potential issueUpdate the labeler action version.
The current version of
actions/labeler@v4
is outdated. Consider updating to the latest version to ensure compatibility with GitHub Actions runners.- - uses: actions/labeler@v4 # Use the labeler action + - uses: actions/labeler@v5 # Use the labeler action📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.- uses: actions/labeler@v5 # Use the labeler action with: repo-token: '${{ secrets.GITHUB_TOKEN }}' # Access token for authentication
🧰 Tools
🪛 actionlint (1.7.4)
14-14: the runner of "actions/labeler@v4" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
bot/stickercmd.js (1)
13-19: 🧹 Nitpick (assertive)
Consider optimizing command lookup and adding error handling.
The current implementation has two potential improvements:
- Command name extraction could be cached to avoid repeated regex operations
- Command execution should include error handling
for (const command of commands) { - const commandName = command.pattern.toString().split(/\W+/)[2]; + const commandName = command.name || command.pattern.toString().split(/\W+/)[2]; if (commandName === data.command.cmd) { + try { await command.function(inst, msg.body); + } catch (error) { + console.error(`Error executing command ${commandName}:`, error); + } break; }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.for (const command of commands) { const commandName = command.name || command.pattern.toString().split(/\W+/)[2]; if (commandName === data.command.cmd) { try { await command.function(inst, msg.body); } catch (error) { console.error(`Error executing command ${commandName}:`, error); } break; } }
lib/files.js (1)
8-21: 🧹 Nitpick (assertive)
Enhance error handling and logging for plugin loading.
Consider the following improvements:
- Add directory existence check
- Provide more detailed error logging
- Track successful plugin loads
+ try { + await readdir(pluginsDir); + } catch (error) { + console.error(`Plugin directory not found: ${pluginsDir}`); + return; + } + + let loadedCount = 0; const files = await readdir(pluginsDir, { withFileTypes: true }); await Promise.all( files.map(async (file) => { const fullPath = join(pluginsDir, file.name); if (extname(file.name) === '.js') { try { const fileUrl = pathToFileURL(fullPath).href; await import(fileUrl); + loadedCount++; + console.log(`Loaded plugin: ${file.name}`); } catch (err) { - console.log('ERROR', `${file.name}: ${err.message}`); + console.error(`Failed to load plugin ${file.name}:`, err); } } }) ); - return console.log('Plugins Synced'); + return console.log(`Plugins Synced: ${loadedCount} plugins loaded successfully`);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { await readdir(pluginsDir); } catch (error) { console.error(`Plugin directory not found: ${pluginsDir}`); return; } let loadedCount = 0; const files = await readdir(pluginsDir, { withFileTypes: true }); await Promise.all( files.map(async (file) => { const fullPath = join(pluginsDir, file.name); if (extname(file.name) === '.js') { try { const fileUrl = pathToFileURL(fullPath).href; await import(fileUrl); loadedCount++; console.log(`Loaded plugin: ${file.name}`); } catch (err) { console.error(`Failed to load plugin ${file.name}:`, err); } } }) ); return console.log(`Plugins Synced: ${loadedCount} plugins loaded successfully`);
eslint.config.mjs (1)
1-1: 🧹 Nitpick (assertive)
Fix file extension mismatch.
The comment indicates
eslint.config.js
but the file is namedeslint.config.mjs
. Update the comment to match the actual filename.-// eslint.config.js +// eslint.config.mjs📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.// eslint.config.mjs
lib/events.js (1)
15-17: 🧹 Nitpick (assertive)
Use
const
for non-reassigned variables and combine task assignments.
- Use
const
instead oflet
fortasks
as it's never reassigned.- Consider combining the task assignments for better maintainability.
- let tasks = []; - const config = await getConfig(); - tasks.push(StickerCMD(msg), AntiViewOnce(msg), AntiSpammer(msg), updateGroupMetadata(msg.client)); + const config = await getConfig(); + const tasks = [ + StickerCMD(msg), + AntiViewOnce(msg), + AntiSpammer(msg), + updateGroupMetadata(msg.client), + ];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const config = await getConfig(); const tasks = [ StickerCMD(msg), AntiViewOnce(msg), AntiSpammer(msg), updateGroupMetadata(msg.client), ];
🧰 Tools
🪛 Biome (1.9.4)
[error] 15-15: This let declares a variable that is only assigned once.
'tasks' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
lib/logger.js (1)
8-19: 🧹 Nitpick (assertive)
Improve error handling and use optional chaining.
- Consider logging errors in the catch block instead of silently ignoring them.
- Use optional chaining for better readability.
try { const logger = require(lib); - if (logger && logger.createLogger) { + if (logger?.createLogger) { logger.createLogger = () => ({ info: () => {}, warn: () => {}, error: () => {}, debug: () => {}, }); } - } catch {} + } catch (error) { + console.debug(`Logger ${lib} not available:`, error.message); + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { const logger = require(lib); if (logger?.createLogger) { logger.createLogger = () => ({ info: () => {}, warn: () => {}, error: () => {}, debug: () => {}, }); } } catch (error) { console.debug(`Logger ${lib} not available:`, error.message); } });
🧰 Tools
🪛 Biome (1.9.4)
[error] 10-10: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
plugins/files.js (1)
15-20:
⚠️ Potential issueCritical: Add security measures for file access.
The current implementation has several security vulnerabilities:
- Path traversal: Users can access files outside the intended directory.
- No file size limits: Large files could cause memory issues.
- No file type restrictions: Sensitive files could be exposed.
const fileName = match?.trim(); if (!fileName) return message.send('_Please specify the file name. Example: file `config.js`_'); + // Prevent path traversal + if (fileName.includes('..') || !fileName.match(/^[\w.-]+$/)) { + return message.send('_Invalid file name. Only alphanumeric characters, dots, and hyphens are allowed._'); + } + // Restrict to specific directory + const allowedDir = path.join(process.cwd(), 'public'); const filePath = path.resolve(process.cwd(), fileName); + if (!filePath.startsWith(allowedDir)) { + return message.send('_Access denied: File must be in the public directory._'); + } if (!fs.existsSync(filePath)) { return message.send(`_The file "${fileName}" does not exist._`); } + // Add file size check + const stats = fs.statSync(filePath); + if (stats.size > 1024 * 1024) { // 1MB limit + return message.send('_File too large. Maximum size is 1MB._'); + }Committable suggestion skipped: line range outside the PR's diff.
bot/antiviewonce.js (2)
14-15: 🧹 Nitpick (assertive)
Consider optimizing message cloning.
Using
JSON.parse(JSON.stringify())
for deep cloning can be inefficient for large message objects. Consider using a more efficient cloning method likestructuredClone()
for better performance.- const modifiedMessage = JSON.parse(JSON.stringify(msg.message)); + const modifiedMessage = structuredClone(msg.message);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const modifiedMessage = structuredClone(msg.message); const messageType = Object.keys(modifiedMessage)[0];
18-18: 🧹 Nitpick (assertive)
Optimize property deletion for better performance.
The
delete
operator can impact performance. Consider setting the property toundefined
instead.- delete modifiedMessage[messageType].viewOnce; + modifiedMessage[messageType].viewOnce = undefined;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.modifiedMessage[messageType].viewOnce = undefined;
🧰 Tools
🪛 Biome (1.9.4)
[error] 18-18: Avoid the delete operator which can impact performance.
Unsafe fix: Use an undefined assignment instead.
(lint/performance/noDelete)
bot/autokick.js (1)
13-27:
⚠️ Potential issueAddress potential memory leaks and performance issues.
Several concerns need attention:
- The
setInterval
is never cleared, potentially causing memory leaks- Frequent group metadata fetches every 10 seconds could impact performance
- The
monitoredGroups
Set grows indefinitelyConsider implementing:
- Cleanup mechanism for intervals
- Caching for group metadata
- Mechanism to remove inactive groups
Here's a suggested implementation:
+ const intervals = new Map(); + export async function AutoKick(msg) { const groupId = msg.from; - if (!isJidGroup(groupId) || monitoredGroups.has(groupId)) return; + if (!isJidGroup(groupId) || intervals.has(groupId)) return; - monitoredGroups.add(groupId); - setInterval(async () => { + const interval = setInterval(async () => { const groupMeta = await msg.client.groupMetadata(groupId); + if (!groupMeta) { + clearInterval(interval); + intervals.delete(groupId); + return; + } // ... rest of the code }, 10000); + intervals.set(groupId, interval); }Committable suggestion skipped: line range outside the PR's diff.
bot/antiword.js (2)
7-7: 🧹 Nitpick (assertive)
Optimize permission checks.
Multiple async calls in the permission check could be combined for better performance.
- if (msg.sender === msg.user || (await isSudo(msg.sender)) || msg.isAdmin) return; + const [isUserSudo] = await Promise.all([isSudo(msg.sender)]); + if (msg.sender === msg.user || isUserSudo || msg.isAdmin) return;Committable suggestion skipped: line range outside the PR's diff.
12-14: 🧹 Nitpick (assertive)
Optimize word matching performance.
The current implementation checks each word individually, which could be inefficient for large lists. Consider using a RegExp for better performance.
- const un_allowed_words = badwords.words; - if (un_allowed_words.some((word) => msg.body.toLowerCase().includes(word.toLowerCase()))) { + const pattern = new RegExp(badwords.words.join('|'), 'i'); + if (pattern.test(msg.body)) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const pattern = new RegExp(badwords.words.join('|'), 'i'); if (pattern.test(msg.body)) { if (!msg.isBotAdmin) return;
lib/session.js (2)
14-18: 🧹 Nitpick (assertive)
Consider using async file operations
Synchronous file operations can block the event loop. Consider using async versions for better performance.
- mkdirSync('session', { recursive: true }); - writeFileSync(join('session', 'creds.json'), JSON.stringify(data.creds, null, 2)); + await mkdir('session', { recursive: true }); + await writeFile(join('session', 'creds.json'), JSON.stringify(data.creds, null, 2));Committable suggestion skipped: line range outside the PR's diff.
14-18:
⚠️ Potential issueAdd error handling for file operations
The file operations (
mkdirSync
,writeFileSync
) lack try-catch blocks. Failed writes could crash the application.Add error handling:
- mkdirSync('session', { recursive: true }); - writeFileSync(join('session', 'creds.json'), JSON.stringify(data.creds, null, 2)); - for (const [filename, syncKeyData] of Object.entries(data.syncKeys)) { - writeFileSync(join('session', filename), JSON.stringify(syncKeyData, null, 2)); - } + try { + mkdirSync('session', { recursive: true }); + writeFileSync(join('session', 'creds.json'), JSON.stringify(data.creds, null, 2)); + for (const [filename, syncKeyData] of Object.entries(data.syncKeys)) { + writeFileSync(join('session', filename), JSON.stringify(syncKeyData, null, 2)); + } + } catch (error) { + console.error('Failed to write session files:', error); + throw error; + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { mkdirSync('session', { recursive: true }); writeFileSync(join('session', 'creds.json'), JSON.stringify(data.creds, null, 2)); for (const [filename, syncKeyData] of Object.entries(data.syncKeys)) { writeFileSync(join('session', filename), JSON.stringify(syncKeyData, null, 2)); } } catch (error) { console.error('Failed to write session files:', error); throw error; }
.github/workflows/node.js.yml (2)
31-43: 🛠️ Refactor suggestion
Improve script execution security
The script execution lacks proper sandboxing and runs with full permissions.
Consider:
- Running in a container with limited permissions
- Adding timeout handling for the background process
- Implementing proper error handling for the kill command
27-29:
⚠️ Potential issueAdd checksum verification for downloaded script
Directly executing a downloaded script without verification is a security risk. Consider adding SHA256 checksum verification.
- name: Download panel.js run: | curl -L -o panel.js https://raw.githubusercontent.com/AstroX11/Xstro/master/.github/js/panel.js + echo "expected-sha256-hash panel.js" | sha256sum --check cat panel.js
Committable suggestion skipped: line range outside the PR's diff.
plugins/ads.js (2)
37-37: 🧹 Nitpick (assertive)
Use template literal for string concatenation
Replace string concatenation with template literal for better readability.
- return await message.send('```Shared to ' + groupIds.length + ' Groups.```'); + return await message.send(`\`\`\`Shared to ${groupIds.length} Groups.\`\`\``);🧰 Tools
🪛 Biome (1.9.4)
[error] 37-37: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
29-35: 🛠️ Refactor suggestion
Add rate limiting and batch processing
Current implementation might trigger spam detection or hit API limits. Consider implementing rate limiting and batch processing.
+ const BATCH_SIZE = 10; + const MAX_GROUPS_PER_HOUR = 50; + let processedCount = 0; for (const groupId of groupIds) { + if (processedCount >= MAX_GROUPS_PER_HOUR) { + await delay(3600000); // Wait 1 hour + processedCount = 0; + } + if (processedCount % BATCH_SIZE === 0) { + await delay(5000); // Longer delay between batches + } await delay(1500); await message.send(broadcastMessage, { jid: groupId, contextInfo: messageOptions, }); + processedCount++; }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const BATCH_SIZE = 10; const MAX_GROUPS_PER_HOUR = 50; let processedCount = 0; for (const groupId of groupIds) { if (processedCount >= MAX_GROUPS_PER_HOUR) { await delay(3600000); // Wait 1 hour processedCount = 0; } if (processedCount % BATCH_SIZE === 0) { await delay(5000); // Longer delay between batches } await delay(1500); await message.send(broadcastMessage, { jid: groupId, contextInfo: messageOptions, }); processedCount++; }
plugins/vars.js (1)
15-16:
⚠️ Potential issueAdd input validation for system variables
Current implementation lacks input validation, potentially allowing injection of malicious values.
const [key, value] = input.map((item) => item.trim()); + if (!/^[a-zA-Z0-9_]+$/.test(key)) { + return message.send('Invalid key format. Use only alphanumeric characters and underscore.'); + } + if (key.toLowerCase().includes('password') || key.toLowerCase().includes('token')) { + return message.send('Cannot set sensitive variables through this command.'); + } await manageVar({ command: 'set', key, value });Committable suggestion skipped: line range outside the PR's diff.
plugins/structure.js (2)
6-30: 🛠️ Refactor suggestion
Consider async implementation for large directories
Synchronous file operations can block the event loop when processing large directories.
Consider implementing an async version of the function:
async function getDirectoryStructureAsync(dir, prefix = '', isLast = true) { const files = await fs.promises.readdir(dir); let structure = ''; for (let i = 0; i < files.length; i++) { const file = files[i]; const isLastItem = i === files.length - 1; const filePath = path.join(dir, file); const stats = await fs.promises.stat(filePath); // ... rest of the logic ... } return structure; }
15-22: 🧹 Nitpick (assertive)
Move exclusion list to configuration
Hard-coded exclusion list makes it difficult to maintain and update.
+ const DEFAULT_EXCLUSIONS = [ + 'node_modules', + '.git', + '.env', + '.npm', + 'session' + ]; if ( - file === 'node_modules' || - file.startsWith('.git') || - file === '.env' || - file === '.npm' || - file === 'session' + DEFAULT_EXCLUSIONS.some(excluded => + excluded === file || (excluded.endsWith('*') && file.startsWith(excluded.slice(0, -1))) + ) )📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const DEFAULT_EXCLUSIONS = [ 'node_modules', '.git', '.env', '.npm', 'session' ]; if ( DEFAULT_EXCLUSIONS.some(excluded => excluded === file || (excluded.endsWith('*') && file.startsWith(excluded.slice(0, -1))) ) ) return;
app.json (2)
14-17: 🧹 Nitpick (assertive)
Consider enhancing SESSION_ID security guidance.
Add a comment in the description explaining the secure way to generate and handle the session ID to prevent unauthorized access.
"SESSION_ID": { - "description": "Session ID to Run Bot", + "description": "Session ID to Run Bot. Generate this securely and never share it.", "required": true },📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements."SESSION_ID": { "description": "Session ID to Run Bot. Generate this securely and never share it.", "required": true },
18-22: 🧹 Nitpick (assertive)
Add validation pattern for SUDO phone numbers.
Consider adding a pattern field to validate phone number format.
"SUDO": { "description": "Phone Number for Admin Users", + "pattern": "^[0-9]{10,15}$", "value": "", "required": false },
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements."SUDO": { "description": "Phone Number for Admin Users", "pattern": "^[0-9]{10,15}$", "value": "", "required": false },
plugins/ban.js (1)
44-46: 🧹 Nitpick (assertive)
Use template literal for better readability.
Replace string concatenation with template literal as suggested by static analysis.
- '*_Banned Users:_*\n' + bannedUsers.map((jid, index) => `${index + 1}. @${jid}`).join('\n'), + `*_Banned Users:_*\n${bannedUsers.map((jid, index) => `${index + 1}. @${jid}`).join('\n')}`,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.return message.send( `*_Banned Users:_*\n${bannedUsers.map((jid, index) => `${index + 1}. @${jid}`).join('\n')}`, { mentions }
🧰 Tools
🪛 Biome (1.9.4)
[error] 45-45: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
plugins/sudo.js (2)
42-43: 🛠️ Refactor suggestion
Improve error handling for getSudo response.
The string comparison for empty sudo list is fragile. Consider using a more robust check.
- if (sudoList === '_No Sudo Numbers_') return message.send('*_No Sudo Users_*'); + if (!sudoList || !sudoList.trim() || sudoList === '_No Sudo Numbers_') return message.send('*_No Sudo Users_*');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!sudoList || !sudoList.trim() || sudoList === '_No Sudo Numbers_') return message.send('*_No Sudo Users_*'); const sudoNumbers = sudoList.split('\n').map((number) => number.split('@')[0]);
44-48: 🧹 Nitpick (assertive)
Use template literals and simplify the code.
Improve readability and reduce complexity.
- const formattedSudoList = - '*_Sudo Users_*\n\n' + - sudoNumbers.map((number, index) => `${index + 1}. @${number}`).join('\n'); - const mentions = sudoNumbers.map((number) => `${number}@s.whatsapp.net`); - return message.send(formattedSudoList, { mentions: mentions }); + const mentions = sudoNumbers.map(number => `${number}@s.whatsapp.net`); + return message.send( + `*_Sudo Users_*\n\n${sudoNumbers.map((number, index) => `${index + 1}. @${number}`).join('\n')}`, + { mentions } + );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const mentions = sudoNumbers.map(number => `${number}@s.whatsapp.net`); return message.send( `*_Sudo Users_*\n\n${sudoNumbers.map((number, index) => `${index + 1}. @${number}`).join('\n')}`, { mentions } );
🧰 Tools
🪛 Biome (1.9.4)
[error] 45-46: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
plugins/call.js (2)
14-15:
⚠️ Potential issueAvoid parameter reassignment and add error handling.
The parameter reassignment and lack of validation could lead to runtime errors.
- match = match.split(';'); - console.log(timeToTimestamp(match[1])); + const [title, time] = match.split(';'); + if (!title || !time) { + return message.send(`_Invalid format. Use: ${prefix}call <title>;<time>_`); + } + const timestamp = timeToTimestamp(time);Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Reassigning a function parameter is confusing.
The parameter is declared here:
Use a local variable instead.
(lint/style/noParameterAssign)
39-52: 🛠️ Refactor suggestion
Improve time parsing robustness and timezone handling.
The current implementation has several potential issues:
- No timezone consideration
- Primitive parseInt usage
- Limited error handling
function timeToTimestamp(timeStr) { - const match = timeStr.match(/^(\d{1,2}):(\d{2})(am|pm)$/i); + const match = timeStr.trim().match(/^(\d{1,2}):(\d{2})\s*(am|pm)$/i); if (!match) throw new Error("Invalid time format. Use 'hh:mmam' or 'hh:mmpm'."); - let [_, hours, minutes, period] = match; - hours = parseInt(hours, 10); - minutes = parseInt(minutes, 10); + const [_, hoursStr, minutesStr, period] = match; + const hours = Number.parseInt(hoursStr, 10); + const minutes = Number.parseInt(minutesStr, 10); + + if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { + throw new Error('Invalid hours or minutes.'); + } if (period.toLowerCase() === 'pm' && hours !== 12) { hours += 12; } else if (period.toLowerCase() === 'am' && hours === 12) { hours = 0; } const now = new Date(); now.setHours(hours, minutes, 0, 0); + if (now < Date.now()) { + now.setDate(now.getDate() + 1); // Schedule for next day if time has passed + } return now.getTime(); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const match = timeStr.trim().match(/^(\d{1,2}):(\d{2})\s*(am|pm)$/i); if (!match) throw new Error("Invalid time format. Use 'hh:mmam' or 'hh:mmpm'."); const [_, hoursStr, minutesStr, period] = match; const hours = Number.parseInt(hoursStr, 10); const minutes = Number.parseInt(minutesStr, 10); if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { throw new Error('Invalid hours or minutes.'); } if (period.toLowerCase() === 'pm' && hours !== 12) { hours += 12; } else if (period.toLowerCase() === 'am' && hours === 12) { hours = 0; } const now = new Date(); now.setHours(hours, minutes, 0, 0); if (now < Date.now()) { now.setDate(now.getDate() + 1); // Schedule for next day if time has passed } return now.getTime();
🧰 Tools
🪛 Biome (1.9.4)
[error] 43-43: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.(lint/style/useNumberNamespace)
[error] 44-44: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.(lint/style/useNumberNamespace)
plugins/antiviewonce.js (2)
45-46:
⚠️ Potential issueFix inconsistent success message.
The success message doesn't reflect the actual command state.
await setViewOnce(cmd === 'on'); - return await message.send(`_AntiViewOnce turned On_`); + return await message.send(`_AntiViewOnce turned ${cmd.toUpperCase()}_`);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.await setViewOnce(cmd === 'on'); return await message.send(`_AntiViewOnce turned ${cmd.toUpperCase()}_`);
17-23: 🧹 Nitpick (assertive)
Use template literals for help message.
Improve readability and maintainability of the help message.
- return await message.send( - `\`\`\`Anti ViewOnce Settings\n\n` + - `${message.prefix}antivv on - Enable\n` + - `${message.prefix}antivv off - Disable\n` + - `${message.prefix}antivv set _[gc/dm/all]_ - Set chat type\n` + - `${message.prefix}antivv get - Check status\`\`\`` - ); + return await message.send( + `\`\`\`Anti ViewOnce Settings\n\n\ +${message.prefix}antivv on - Enable\n\ +${message.prefix}antivv off - Disable\n\ +${message.prefix}antivv set _[gc/dm/all]_ - Set chat type\n\ +${message.prefix}antivv get - Check status\`\`\`` + );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.return await message.send( `\`\`\`Anti ViewOnce Settings\n\n\ ${message.prefix}antivv on - Enable\n\ ${message.prefix}antivv off - Disable\n\ ${message.prefix}antivv set _[gc/dm/all]_ - Set chat type\n\ ${message.prefix}antivv get - Check status\`\`\`` );
🧰 Tools
🪛 Biome (1.9.4)
[error] 18-22: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
.github/workflows/stale.yml (1)
15-15: 🛠️ Refactor suggestion
Update actions/stale action to the latest version.
The current version of the stale action may be outdated. Consider updating to the latest version to ensure compatibility with GitHub Actions runners.
- - uses: actions/stale@v5 + - uses: actions/stale@v8📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.- uses: actions/stale@v8
🧰 Tools
🪛 actionlint (1.7.4)
15-15: the runner of "actions/stale@v5" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
SECURITY.md (1)
9-9:
⚠️ Potential issueUpdate version information in security policy.
The version information in the security policy (1.2.2) is outdated compared to package.json (1.2.3).
-| Latest (Main) | ✔ 1.2.2 | +| Latest (Main) | ✔ 1.2.3 |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.| Latest (Main) | ✔ 1.2.3 |
package.json (1)
42-45:
⚠️ Potential issueFix invalid package versions in devDependencies.
Several package versions specified don't exist:
- [email protected] (latest is 8.x)
- [email protected] (latest is 3.1.x)
- "eslint": "^9.18.0", - "eslint-config-prettier": "^10.0.1", - "eslint-plugin-prettier": "^5.2.2", - "prettier": "^3.4.2" + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.1.1"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements."eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", "prettier": "^3.1.1"
index.js (3)
48-48: 🛠️ Refactor suggestion
Add error handling for directory creation.
The
mkdir
operation could fail due to permissions or other I/O issues. Consider adding proper error handling:- await mkdir('store', { recursive: true }); + try { + await mkdir('store', { recursive: true }); + } catch (error) { + console.error('Failed to create store directory:', error); + process.exit(1); + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { await mkdir('store', { recursive: true }); } catch (error) { console.error('Failed to create store directory:', error); process.exit(1); }
6-6: 🧹 Nitpick (assertive)
Use the node: protocol for Node.js built-in modules.
For better clarity and to explicitly indicate this is a Node.js built-in module:
-import { mkdir } from 'fs/promises'; +import { mkdir } from 'node:fs/promises';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import { mkdir } from 'node:fs/promises';
🧰 Tools
🪛 Biome (1.9.4)
[error] 6-6: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
46-57: 🧹 Nitpick (assertive)
Consider potential race conditions in worker processes.
Multiple worker processes might attempt to create the 'store' directory simultaneously. While
mkdir
withrecursive: true
is idempotent, consider moving the directory creation to the master process.// In the master process section if (cluster.isMaster) { + try { + await mkdir('store', { recursive: true }); + } catch (error) { + console.error('Failed to create store directory:', error); + process.exit(1); + } let isRestarting = false; // ... rest of the codeCommittable suggestion skipped: line range outside the PR's diff.
bot/antispam.js (2)
18-19: 🧹 Nitpick (assertive)
Use atomic operations for Map updates.
The current implementation could lead to race conditions if multiple messages are processed simultaneously:
- const recentMessages = userMessages.filter((msgInfo) => now - msgInfo.timestamp <= 10000); - messageStore.set(senderKey, recentMessages); + const recentMessages = userMessages.filter((msgInfo) => now - msgInfo.timestamp <= 10000); + if (recentMessages.length > 0) { + messageStore.set(senderKey, recentMessages); + } else { + messageStore.delete(senderKey); + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const recentMessages = userMessages.filter((msgInfo) => now - msgInfo.timestamp <= 10000); if (recentMessages.length > 0) { messageStore.set(senderKey, recentMessages); } else { messageStore.delete(senderKey); }
15-16: 🛠️ Refactor suggestion
Implement message store cleanup to prevent memory leaks.
The
messageStore
Map could grow indefinitely as new messages are added. Consider implementing a cleanup mechanism:+ // Cleanup old messages (older than 1 hour) + const cleanupTime = now - 3600000; + for (const [key, messages] of messageStore.entries()) { + const validMessages = messages.filter(msg => msg.timestamp > cleanupTime); + if (validMessages.length === 0) { + messageStore.delete(key); + } else { + messageStore.set(key, validMessages); + } + } userMessages.push({ timestamp: now, key: msg.key });Committable suggestion skipped: line range outside the PR's diff.
plugins/stickercmd.js (1)
28-31: 🛠️ Refactor suggestion
Add error handling for Buffer operations.
The Buffer creation from fileSha256 could fail. Add proper error handling:
- const success = await setcmd( - match, - Buffer.from(message.data.quoted.message.stickerMessage.fileSha256).toString('hex') - ); + try { + const fileSha256 = message.data.quoted.message.stickerMessage.fileSha256; + if (!fileSha256) { + return await message.send('_Invalid sticker format_'); + } + const success = await setcmd( + match, + Buffer.from(fileSha256).toString('hex') + ); + if (success) { + return await message.send(`_Command "${match}" successfully set to the sticker._`); + } + await message.send('_Failed to set the command._'); + } catch (error) { + console.error('Failed to process sticker command:', error); + await message.send('_Failed to process sticker command_'); + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { const fileSha256 = message.data.quoted.message.stickerMessage.fileSha256; if (!fileSha256) { return await message.send('_Invalid sticker format_'); } const success = await setcmd( match, Buffer.from(fileSha256).toString('hex') ); if (success) { return await message.send(`_Command "${match}" successfully set to the sticker._`); } await message.send('_Failed to set the command._'); } catch (error) { console.error('Failed to process sticker command:', error); await message.send('_Failed to process sticker command_'); }
plugins/mention.js (2)
70-70: 🧹 Nitpick (assertive)
Use const instead of let for variables that aren't reassigned.
The
reply
variable is never reassigned, so it should useconst
:- let reply = await getMention(message.jid); + const reply = await getMention(message.jid);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const reply = await getMention(message.jid);
🧰 Tools
🪛 Biome (1.9.4)
[error] 70-70: This let declares a variable that is only assigned once.
'reply' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
73-75: 🛠️ Refactor suggestion
Improve error handling in try-catch block.
The current implementation silently ignores errors. Consider logging them or handling them appropriately:
try { if (!JSON.parse(reply)) return message.send(reply); - } catch {} + } catch (error) { + console.error('Failed to parse mention reply:', error); + return message.send('_Invalid mention reply format_'); + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { if (!JSON.parse(reply)) return message.send(reply); } catch (error) { console.error('Failed to parse mention reply:', error); return message.send('_Invalid mention reply format_'); }
plugins/updater.js (3)
46-51:
⚠️ Potential issueCritical: Add proper cleanup before process exit
The process is terminated without proper cleanup of resources or graceful shutdown of connections.
Add cleanup logic before process exit:
+ // Cleanup resources before exit + await message.client.end(); + // Allow time for connections to close + setTimeout(() => { process.exit(0); + }, 1000); - process.exit(0);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.exec(`npm install`, async (err, stdout, stderr) => { if (err) {
🧰 Tools
🪛 Biome (1.9.4)
[error] 48-48: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
61-67: 🧹 Nitpick (assertive)
Add retry mechanism for git operations
The git diff operation could fail due to temporary issues. Consider adding a retry mechanism.
try { - const diff = await git.diff([`master..origin/master`]); + const maxRetries = 3; + let retries = 0; + while (retries < maxRetries) { + try { + const diff = await git.diff([`master..origin/master`]); + return diff.includes('"dependencies":'); + } catch (error) { + retries++; + if (retries === maxRetries) throw error; + await new Promise(resolve => setTimeout(resolve, 1000 * retries)); + } + } - return diff.includes('"dependencies":'); } catch (error) { console.error('Error occurred while checking package.json:', error); return false; }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { const maxRetries = 3; let retries = 0; while (retries < maxRetries) { try { const diff = await git.diff([`master..origin/master`]); return diff.includes('"dependencies":'); } catch (error) { retries++; if (retries === maxRetries) throw error; await new Promise(resolve => setTimeout(resolve, 1000 * retries)); } } } catch (error) { console.error('Error occurred while checking package.json:', error); return false; }
38-41:
⚠️ Potential issueCritical: Sanitize user input before executing shell commands
The direct execution of shell commands with user-provided input poses a significant security risk. The
stderr
is properly handled, but the command itself needs sanitization.Consider using the following safer approach:
- exec(`git stash && git pull origin master`, async (err, stdout, stderr) => { + const gitCommands = ['git stash', 'git pull origin master']; + for (const cmd of gitCommands) { + try { + await new Promise((resolve, reject) => { + exec(cmd, (err, stdout, stderr) => { + if (err) reject(new Error(stderr)); + resolve(stdout); + }); + }); + } catch (error) { + return await message.send('```' + error.message + '```'); + } + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const gitCommands = ['git stash', 'git pull origin master']; for (const cmd of gitCommands) { try { await new Promise((resolve, reject) => { exec(cmd, (err, stdout, stderr) => { if (err) reject(new Error(stderr)); resolve(stdout); }); }); } catch (error) {
🧰 Tools
🪛 Biome (1.9.4)
[error] 40-40: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
plugins/antispam.js (2)
34-35:
⚠️ Potential issueAdd error handling for storage operations
The calls to
setAntiSpam
andgetAntiSpamMode
need proper error handling as they now interact with the file system.- const currentMode = await getAntiSpamMode(jid); + try { + const currentMode = await getAntiSpamMode(jid); + } catch (error) { + console.error('Failed to get antispam mode:', error); + return message.send('```Failed to get antispam configuration```'); + }Also applies to: 26-27
40-47: 🧹 Nitpick (assertive)
Implement atomic operations for file updates
The
setAntiSpam
operation could lead to race conditions when multiple users modify settings simultaneously.Consider implementing a file locking mechanism or using atomic operations for the JSON file updates. Would you like me to provide an implementation example?
plugins/warn.js (2)
15-17:
⚠️ Potential issueAdd validation for warning operations
The warning operations need proper validation and error handling for the JSON storage system.
- const { success, warnings } = await addWarn(jid); + try { + const { success, warnings } = await addWarn(jid); + if (typeof warnings !== 'number' || warnings < 0) { + throw new Error('Invalid warning count received'); + } + } catch (error) { + console.error('Failed to add warning:', error); + return await message.send('```Failed to add warning: Invalid data```'); + }
19-19: 🧹 Nitpick (assertive)
Use Number.parseInt with radix parameter
The
parseInt
function should include a radix parameter and use the Number namespace.- const warningCount = parseInt(warnings); + const warningCount = Number.parseInt(warnings, 10);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const warningCount = Number.parseInt(warnings, 10);
🧰 Tools
🪛 Biome (1.9.4)
[error] 19-19: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.(lint/style/useNumberNamespace)
plugins/autokick.js (2)
19-25:
⚠️ Potential issueAdd comprehensive error handling for storage operations
The auto-kick list modifications need proper error handling for file operations.
- const added = await addAKick(groupId, jid); + try { + const added = await addAKick(groupId, jid); + if (typeof added !== 'boolean') { + throw new Error('Invalid response from storage operation'); + } + } catch (error) { + console.error('Failed to modify auto-kick list:', error); + return message.send('```Failed to update auto-kick list```'); + }
69-74: 🛠️ Refactor suggestion
Validate data integrity before processing
The kicks array needs validation before processing to ensure data integrity.
if (kicks.length > 0) { + // Validate kick entries + const validKicks = kicks.filter(k => k && k.userJid && typeof k.userJid === 'string'); + if (validKicks.length !== kicks.length) { + console.warn('Some kick entries were invalid and filtered out'); + } return message.send( - `_Users in auto-kick list:_\n${kicks.map((k) => `• @${k.userJid.split('@')[0]}`).join('\n')}`, + `_Users in auto-kick list:_\n${validKicks.map((k) => `• @${k.userJid.split('@')[0]}`).join('\n')}`, - { mentions: [kicks] } + { mentions: validKicks.map(k => k.userJid) } ); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (kicks.length > 0) { // Validate kick entries const validKicks = kicks.filter(k => k && k.userJid && typeof k.userJid === 'string'); if (validKicks.length !== kicks.length) { console.warn('Some kick entries were invalid and filtered out'); } return message.send( `_Users in auto-kick list:_\n${validKicks.map((k) => `• @${k.userJid.split('@')[0]}`).join('\n')}`, { mentions: validKicks.map(k => k.userJid) } ); }
plugins/tag.js (2)
47-61:
⚠️ Potential issueAdd validation for message content and type
The message handling logic needs proper validation to prevent potential security issues.
if (objectAction) { + // Validate message type + const allowedTypes = ['conversation', 'extendedText', 'image', 'video']; + if (!allowedTypes.includes(typeOfMessage)) { + return message.send('```Unsupported message type```'); + } + let taggedMessage = { [typeOfMessage]: { - ...objectAction, + // Only spread known safe properties + ...(typeof objectAction === 'object' ? { + caption: objectAction.caption, + mimetype: objectAction.mimetype, + url: objectAction.url + } : {}), contextInfo: { ...objectAction.contextInfo, mentionedJid: objectAction.contextInfo?.mentionedJid || participantJids, }, }, };🧰 Tools
🪛 Biome (1.9.4)
[error] 48-48: This let declares a variable that is only assigned once.
'taggedMessage' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
12-13:
⚠️ Potential issueSanitize user input before processing
The message content needs to be sanitized to prevent potential XSS attacks.
- const msg = match || message.reply_message?.text; + const sanitizeMessage = (text) => { + if (typeof text !== 'string') return ''; + return text.replace(/[<>]/g, ''); // Basic XSS prevention + }; + const msg = sanitizeMessage(match || message.reply_message?.text); if (!msg) return message.send('_You must provide a reason for tagging everyone._');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const sanitizeMessage = (text) => { if (typeof text !== 'string') return ''; return text.replace(/[<>]/g, ''); // Basic XSS prevention }; const msg = sanitizeMessage(match || message.reply_message?.text); if (!msg) return message.send('_You must provide a reason for tagging everyone._');
lib/plugins.js (2)
18-18:
⚠️ Potential issueAdd error handling for getConfig call.
The database call could fail during the migration to JSON storage. Consider adding try-catch block to handle potential errors gracefully.
- const db = await getConfig(); + let db; + try { + db = await getConfig(); + } catch (error) { + console.error('Failed to load configuration:', error); + return; + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.let db; try { db = await getConfig(); } catch (error) { console.error('Failed to load configuration:', error); return; }
41-41: 🧹 Nitpick (assertive)
Remove redundant prefix check.
This check is redundant as we already verify the prefix in line 23.
- if (!prefixes.includes(prefix)) continue;
.github/js/panel.js (2)
20-23:
⚠️ Potential issueSecurity: Remove shell: true option.
Using
shell: true
is a security risk as it can lead to command injection vulnerabilities. Consider using array syntax for commands instead.- const cloneResult = spawnSync('git', ['clone', CONFIG.REPO_URL, CONFIG.PROJECT_DIR], { - stdio: 'inherit', - shell: true, // For Windows compatibility - }); + const cloneResult = spawnSync(process.platform === 'win32' ? 'git.exe' : 'git', + ['clone', CONFIG.REPO_URL, CONFIG.PROJECT_DIR], + { stdio: 'inherit' } + );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const cloneResult = spawnSync(process.platform === 'win32' ? 'git.exe' : 'git', ['clone', CONFIG.REPO_URL, CONFIG.PROJECT_DIR], { stdio: 'inherit' } );
30-34:
⚠️ Potential issueAdd input validation for SESSION_ID.
The SESSION_ID is written to .env file without validation, which could lead to injection vulnerabilities.
+ if (!/^[A-Za-z0-9+/=_-]+$/.test(CONFIG.SESSION_ID)) { + handleError('Invalid SESSION_ID format', new Error('SESSION_ID contains invalid characters')); + } try { writeFileSync(join(CONFIG.PROJECT_DIR, '.env'), `SESSION_ID=${CONFIG.SESSION_ID}`); } catch (error) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!/^[A-Za-z0-9+/=_-]+$/.test(CONFIG.SESSION_ID)) { handleError('Invalid SESSION_ID format', new Error('SESSION_ID contains invalid characters')); } try { writeFileSync(join(CONFIG.PROJECT_DIR, '.env'), `SESSION_ID=${CONFIG.SESSION_ID}`); } catch (error) { handleError('Failed to write .env file', error); }
plugins/antilink.js (1)
54-55:
⚠️ Potential issueRemove duplicate database call.
The
getAntilink
function is called twice with the same parameters.- const status = await getAntilink(jid, 'on'); - const actionConfig = await getAntilink(jid, 'on'); + const config = await getAntilink(jid, 'on'); return message.send( - `*_Antilink Configuration:_*\n` + - `Status: ${status ? 'ON' : 'OFF'}\n` + - `Action: ${actionConfig ? actionConfig.action : 'Not set'}` + `*_Antilink Configuration:_* +Status: ${config ? 'ON' : 'OFF'} +Action: ${config ? config.action : 'Not set'}` );Committable suggestion skipped: line range outside the PR's diff.
bot/anticall.js (2)
51-51: 🧹 Nitpick (assertive)
Update misleading comment.
The comment suggests country codes, but the implementation shows it's used for any number prefix matching.
- const bannedCountryCodes = antiCallConfig.jid; // Assuming this is an array of country codes + const bannedPrefixes = antiCallConfig.jid; // Array of number prefixes to block📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const bannedPrefixes = antiCallConfig.jid; // Array of number prefixes to block
12-13:
⚠️ Potential issueAdd error handling for database operation.
The getAntiCall operation could fail during the migration to JSON storage.
- const antiCallConfig = await getAntiCall(); - if (!antiCallConfig.on) return; // Exit if AntiCall is disabled + let antiCallConfig; + try { + antiCallConfig = await getAntiCall(); + } catch (error) { + console.error('Failed to get AntiCall config:', error); + return; + } + if (!antiCallConfig?.on) return; // Exit if AntiCall is disabled📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.let antiCallConfig; try { antiCallConfig = await getAntiCall(); } catch (error) { console.error('Failed to get AntiCall config:', error); return; } if (!antiCallConfig?.on) return; // Exit if AntiCall is disabled
.github/contributing.md (1)
11-14: 🧹 Nitpick (assertive)
Add blank lines around code blocks.
According to markdown best practices, fenced code blocks should be surrounded by blank lines for better readability.
Example fix for the first code block:
- Download your forked repository to your local machine: ```bash git clone https://github.com/<your-username>/Xstro.git cd Xstro ```Also applies to: 19-21, 23-25, 30-32, 48-51, 56-58
🧰 Tools
🪛 Markdownlint (0.37.0)
11-11: null
Fenced code blocks should be surrounded by blank lines(MD031, blanks-around-fences)
plugins/system.js (4)
69-73:
⚠️ Potential issueAdd error handling for logout operation.
The logout operation lacks error handling and could leave the bot in an inconsistent state if it fails.
async (message) => { await message.send('_logging out_'); await delay(3000); - await message.client.logout(); + try { + await message.client.logout(); + } catch (error) { + await message.send('Error during logout: ' + error.message); + throw error; + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async (message) => { await message.send('_logging out_'); await delay(3000); try { await message.client.logout(); } catch (error) { await message.send('Error during logout: ' + error.message); throw error; } }
117-117: 🧹 Nitpick (assertive)
Use template literals for string concatenation.
Replace string concatenation with template literals for better readability.
- await message.send('```' + response + '```'); + await message.send(`\`\`\`${response}\`\`\``);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.await message.send(`\`\`\`${response}\`\`\``);
🧰 Tools
🪛 Biome (1.9.4)
[error] 117-117: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
83-89:
⚠️ Potential issueAdd input validation for fetch command URL.
The fetch command accepts URLs without validation, which could lead to security vulnerabilities.
async (message, match) => { if (!match) return message.send('_I need a URL_'); const [mode, url] = match.split(';'); if (!url) return message.send('_Use: mode;url_'); + try { + const validUrl = new URL(url); + if (!['http:', 'https:'].includes(validUrl.protocol)) { + return message.send('_Invalid URL protocol. Only HTTP/HTTPS allowed_'); + } const data = mode === 'json' ? JSON.stringify(await getJson(url)) : await getBuffer(url); return await message.send(data, mode === 'json' ? { type: 'text' } : undefined); + } catch (error) { + return message.send('_Invalid URL format_'); + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async (message, match) => { if (!match) return message.send('_I need a URL_'); const [mode, url] = match.split(';'); if (!url) return message.send('_Use: mode;url_'); try { const validUrl = new URL(url); if (!['http:', 'https:'].includes(validUrl.protocol)) { return message.send('_Invalid URL protocol. Only HTTP/HTTPS allowed_'); } const data = mode === 'json' ? JSON.stringify(await getJson(url)) : await getBuffer(url); return await message.send(data, mode === 'json' ? { type: 'text' } : undefined); } catch (error) { return message.send('_Invalid URL format_'); } }
17-20: 🧹 Nitpick (assertive)
Potential race condition in ping command.
The performance measurement might be affected by the message sending delay. Consider measuring the round-trip time instead.
- const start = performance.now(); - const msg = await message.send('Testing Speed...'); - const end = performance.now(); - await msg.edit(font.tiny(`Pong! ${(end - start).toFixed(1)} ms`)); + const start = performance.now(); + await message.send('Testing Speed...').then(async (msg) => { + const end = performance.now(); + await msg.edit(font.tiny(`Pong! ${(end - start).toFixed(1)} ms`)); + });plugins/news.js (1)
12-18:
⚠️ Potential issueAdd error handling for news fetching.
The news fetching operation lacks error handling and could crash if the API fails.
async (message) => { + try { const res = await XSTRO.news(); + if (!res?.length) { + return message.send('No news available at the moment.'); + } let data = ''; for (const items of res) { data += `\`\`\`Title: ${items.title}\n\nDescription: ${items.description}\n\nlink: ${items.url}\`\`\`\n\n`; } return await message.send(data); + } catch (error) { + console.error('News fetch error:', error); + return message.send('Failed to fetch news. Please try again later.'); + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { const res = await XSTRO.news(); if (!res?.length) { return message.send('No news available at the moment.'); } let data = ''; for (const items of res) { data += `\`\`\`Title: ${items.title}\n\nDescription: ${items.description}\n\nlink: ${items.url}\`\`\`\n\n`; } return await message.send(data); } catch (error) { console.error('News fetch error:', error); return message.send('Failed to fetch news. Please try again later.'); }
bot/antilink.js (1)
14-15:
⚠️ Potential issueImprove URL detection regex.
The current regex might cause catastrophic backtracking with certain inputs. Consider using a more robust pattern.
- const urlRegex = /(https?:\/\/)?([a-z0-9-]+\.)+[a-z]{2,}(\/[^\s]*)?/i; + const urlRegex = /^(?:https?:\/\/)?(?:[\w-]+\.)+[a-z]{2,}(?:\/[^\s]*)?$/i;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const urlRegex = /^(?:https?:\/\/)?(?:[\w-]+\.)+[a-z]{2,}(?:\/[^\s]*)?$/i; return urlRegex.test(str);
sql/anticall.js (2)
6-11:
⚠️ Potential issueAdd directory creation and error handling for file operations.
File operations lack proper error handling and directory creation.
+const storeDir = 'store'; +if (!fs.existsSync(storeDir)) { + fs.mkdirSync(storeDir, { recursive: true }); +} + +try { if (!fs.existsSync(anticallStore)) { fs.writeFileSync( anticallStore, JSON.stringify({ id: 1, on: false, type: 'on', action: 'block', jid: null }) ); } +} catch (error) { + console.error('Failed to initialize anticall store:', error); + throw error; +}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const storeDir = 'store'; if (!fs.existsSync(storeDir)) { fs.mkdirSync(storeDir, { recursive: true }); } try { if (!fs.existsSync(anticallStore)) { fs.writeFileSync( anticallStore, JSON.stringify({ id: 1, on: false, type: 'on', action: 'block', jid: null }) ); } } catch (error) { console.error('Failed to initialize anticall store:', error); throw error; }
13-14:
⚠️ Potential issueAdd atomic file operations for data consistency.
Current file operations are not atomic and could lead to data corruption.
-const readDB = () => JSON.parse(fs.readFileSync(anticallStore, 'utf8')); -const writeDB = (data) => fs.writeFileSync(anticallStore, JSON.stringify(data, null, 2)); +const readDB = () => { + try { + return JSON.parse(fs.readFileSync(anticallStore, 'utf8')); + } catch (error) { + console.error('Failed to read anticall store:', error); + throw error; + } +}; + +const writeDB = (data) => { + const tempFile = `${anticallStore}.tmp`; + try { + fs.writeFileSync(tempFile, JSON.stringify(data, null, 2)); + fs.renameSync(tempFile, anticallStore); + } catch (error) { + if (fs.existsSync(tempFile)) { + fs.unlinkSync(tempFile); + } + console.error('Failed to write anticall store:', error); + throw error; + } +};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const readDB = () => { try { return JSON.parse(fs.readFileSync(anticallStore, 'utf8')); } catch (error) { console.error('Failed to read anticall store:', error); throw error; } }; const writeDB = (data) => { const tempFile = `${anticallStore}.tmp`; try { fs.writeFileSync(tempFile, JSON.stringify(data, null, 2)); fs.renameSync(tempFile, anticallStore); } catch (error) { if (fs.existsSync(tempFile)) { fs.unlinkSync(tempFile); } console.error('Failed to write anticall store:', error); throw error; } };
plugins/afk.js (1)
74-77:
⚠️ Potential issueAdd cleanup for AFK tracking cache.
The
afkTrack
object grows indefinitely as it stores timestamps for all senders.+const CLEANUP_INTERVAL = 3600000; // 1 hour +const MAX_CACHE_SIZE = 1000; + +// Add at the top of the file +setInterval(() => { + const now = Date.now(); + Object.keys(afkTrack).forEach(key => { + if (now - afkTrack[key] > CLEANUP_INTERVAL) { + delete afkTrack[key]; + } + }); +}, CLEANUP_INTERVAL); + const now = Date.now(); const lastMessageTime = afkTrack[message.sender] || 0; + +// Cleanup if cache gets too large +if (Object.keys(afkTrack).length > MAX_CACHE_SIZE) { + const oldestEntries = Object.entries(afkTrack) + .sort(([,a], [,b]) => a - b) + .slice(0, Math.floor(MAX_CACHE_SIZE / 2)); + oldestEntries.forEach(([key]) => delete afkTrack[key]); +} + if (now - lastMessageTime < 30000) return; afkTrack[message.sender] = now;Committable suggestion skipped: line range outside the PR's diff.
plugins/anticall.js (4)
60-60: 🧹 Nitpick (assertive)
Use const instead of let.
The variable
num
is never reassigned within the loop, making it a good candidate forconst
.- for (let num of numbersToCheck) { + for (const num of numbersToCheck) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.for (const num of numbersToCheck) {
🧰 Tools
🪛 Biome (1.9.4)
[error] 60-60: This let declares a variable that is only assigned once.
'num' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
80-80: 🧹 Nitpick (assertive)
Consider adding input validation for country codes.
The country code validation only checks length but doesn't verify if they are valid numeric codes.
Consider adding a regex pattern to validate that country codes contain only digits:
-.filter((code) => code.length > 0 && code.length <= 4); +.filter((code) => code.length > 0 && code.length <= 4 && /^\d+$/.test(code));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements..filter((code) => code.length > 0 && code.length <= 4 && /^\d+$/.test(code)); // Ensures codes are not longer than 4 characters
38-38: 🛠️ Refactor suggestion
Avoid reassigning function parameters.
The parameter
match
is being reassigned. This can lead to confusion and make the code harder to maintain.- match = match.split(','); + const parts = match.split(','); - const mode = match[0]; + const mode = parts[0];Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Biome (1.9.4)
[error] 38-38: Reassigning a function parameter is confusing.
The parameter is declared here:
Use a local variable instead.
(lint/style/noParameterAssign)
71-71: 💡 Codebase verification
Parameter order mismatch in addAntiCall call
The call at line 71 swaps the
type
andaction
parameters. Based on the function definition insql/anticall.js
, it should be:await addAntiCall(anticallConfig.type, mode, match.slice(1));🔗 Analysis chain
Verify consistency in addAntiCall parameters.
The
addAntiCall
function is called with different parameter orders in lines 43 and 71. This might indicate an inconsistency.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for all usages of addAntiCall to verify parameter consistency rg "addAntiCall\(" -A 1Length of output: 735
plugins/bgm.js (2)
102-108: 🧹 Nitpick (assertive)
Add rate limiting for automatic BGM responses.
The text event listener should implement rate limiting to prevent spam.
Consider implementing a cooldown mechanism for automatic BGM responses to prevent abuse.
58-60: 🛠️ Refactor suggestion
Potential race condition in audio message loading.
The code loads and relays audio messages without checking if the message is still available in storage.
const audioMessage = await message.client.loadMessage(messageId); - if (!audioMessage) return message.send('_Failed to load audio message_'); + if (!audioMessage?.message?.message) { + await deleteBgm(word); // Clean up invalid entry + return message.send('_Failed to load audio message_'); + }Committable suggestion skipped: line range outside the PR's diff.
plugins/schedule.js (2)
21-28:
⚠️ Potential issuePotential race condition in schedule updates.
The code retrieves and updates schedules in separate operations, which could lead to race conditions in concurrent updates.
Consider implementing atomic updates or using a locking mechanism to prevent concurrent modifications.
94-95: 🛠️ Refactor suggestion
Inconsistent admin check methods.
The file uses different methods for checking admin status:
message.isAdmin
vsmessage.isUserAdmin()
.- if (!message.isAdmin) return message.send('```You are not an Admin```'); - if (!message.isBotAdmin) return message.send('```I am not an Admin```'); + if (!(await message.isUserAdmin())) return message.send('```You are not an Admin```'); + if (!(await message.isBotAdmin())) return message.send('```I am not an Admin```');plugins/greetings.js (2)
71-71: 🛠️ Refactor suggestion
Avoid arbitrary delays.
The use of
delay(2000)
seems arbitrary and could affect user experience.Consider removing the delay or making it configurable if necessary.
57-59: 🧹 Nitpick (assertive)
Use template literals for string concatenation.
String concatenation with + operator should be replaced with template literals for better readability.
- return message.send( - '_Goodbye Messages Enabled, use ' + prefix + 'goodbye your message, to customize it_' - ); + return message.send( + `_Goodbye Messages Enabled, use ${prefix}goodbye your message, to customize it_` + );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.return message.send( `_Goodbye Messages Enabled, use ${prefix}goodbye your message, to customize it_` );
plugins/translate.js (2)
32-142: 🧹 Nitpick (assertive)
Consider moving language definitions to a separate file.
The large array of language definitions could be moved to a separate configuration file for better maintainability.
Consider creating a
config/languages.js
file to store the language definitions.
13-15: 🧹 Nitpick (assertive)
Optimize language code lookup.
The current implementation searches through the entire languages array for each translation. Consider using a Map for O(1) lookup.
+const languageMap = new Map( + languages.map(lang => { + const [name, code] = lang.split(' - '); + return [code.toLowerCase(), lang]; + }) +); + const targetLang = languages.find((lang) => lang.toLowerCase().endsWith(`- ${langCode.toLowerCase()}`) );Committable suggestion skipped: line range outside the PR's diff.
plugins/antiword.js (2)
24-24: 🧹 Nitpick (assertive)
Use template literals for string interpolation.
Replace string concatenation with template literals for better readability and maintainability.
- '_Please enable antiword first using "' + message.prefix + 'antiword on"_' + `_Please enable antiword first using "${message.prefix}antiword on"_` - '_Provide words to block. Usage: ' + message.prefix + 'antiword set word1,word2,word3_' + `_Provide words to block. Usage: ${message.prefix}antiword set word1,word2,word3_` - '```Usage:\n' + - '' + - message.prefix + - 'antiword on - Enable antiword\n' + - '' + - message.prefix + - 'antiword set word1,word2,word3 - Set blocked words\n' + - '' + - message.prefix + - 'antiword get - View current antiwords\n' + - '' + - message.prefix + - 'antiword del word1,word2 - Delete specific words```' + `\`\`\`Usage: +${message.prefix}antiword on - Enable antiword +${message.prefix}antiword set word1,word2,word3 - Set blocked words +${message.prefix}antiword get - View current antiwords +${message.prefix}antiword del word1,word2 - Delete specific words\`\`\``Also applies to: 31-31, 72-84
🧰 Tools
🪛 Biome (1.9.4)
[error] 24-24: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
33-37: 🧹 Nitpick (assertive)
Consider using Array.from() for Set conversion.
The current implementation uses spread operator with Set. While both approaches work, Array.from() can be more explicit about the intention.
- const uniqueWords = [...new Set(wordsToSet)]; + const uniqueWords = Array.from(new Set(wordsToSet));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const wordsToSet = args[0].split(',').map((word) => word.trim()); const uniqueWords = Array.from(new Set(wordsToSet)); const existingWords = antiwordStatus.words || []; const newWords = uniqueWords.filter((word) => !existingWords.includes(word)); if (newWords.length === 0)
plugins/notes.js (2)
32-33: 🧹 Nitpick (assertive)
Use Number namespace functions for better type safety.
Replace global parseInt and isNaN with their Number namespace equivalents for better type safety and consistency with modern JavaScript.
- const noteId = parseInt(match.trim()); - if (!noteId || isNaN(noteId)) return await message.send('*Format*: _.delnote id_'); + const noteId = Number.parseInt(match.trim(), 10); + if (!noteId || Number.isNaN(noteId)) return await message.send('*Format*: _.delnote id_'); - const updatedNote = await updateNote(parseInt(id), updates).catch(() => null); + const updatedNote = await updateNote(Number.parseInt(id, 10), updates).catch(() => null); - const noteId = parseInt(match.trim()); - if (!noteId || isNaN(noteId)) return await message.send('*Format*: _.cnote id_'); + const noteId = Number.parseInt(match.trim(), 10); + if (!noteId || Number.isNaN(noteId)) return await message.send('*Format*: _.cnote id_');Also applies to: 57-57, 87-88
🧰 Tools
🪛 Biome (1.9.4)
[error] 32-32: Use Number.parseInt instead of the equivalent global.
ES2015 moved some globals into the Number namespace for consistency.
Safe fix: Use Number.parseInt instead.(lint/style/useNumberNamespace)
[error] 33-33: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.
See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.(lint/suspicious/noGlobalIsNan)
16-17: 💡 Codebase verification
Consider using the cleanString utility for note content sanitization
The codebase already has a
cleanString
utility inutils/main.js
that removes ambiguous characters. Consider using it to sanitize note content before storage to prevent potential markdown injection attacks:
plugins/notes.js
: ApplycleanString
to both title and content in addNote and editNote handlers🔗 Analysis chain
Consider adding input sanitization for note content.
The word count check is good, but consider adding input sanitization to prevent potential XSS or injection attacks in note content.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check for potential XSS patterns in existing notes rg -l '<script|javascript:|data:text/html|vbscript:|livescript:|<img|<svg|onerror=|onload='Length of output: 110
Script:
#!/bin/bash # Check content of utils/convert.js cat utils/convert.js # Find where notes content is used/displayed rg -A 3 "content\s*=|content\." plugins/notes.js # Look for any sanitization functions rg -l "sanitize|escape|clean|purify"Length of output: 6583
Script:
#!/bin/bash # Check sanitization functions in utils/main.js cat utils/main.js # Find where notes are displayed/rendered rg -A 3 "displayNote|renderNote|showNote|message\.send.*note" # Look for addNote implementation ast-grep --pattern 'async function addNote'Length of output: 11119
plugins/chats.js (1)
61-70: 🧹 Nitpick (assertive)
Consider adding error logging for failed metadata retrieval.
While the error handling is present, adding error logging would help in debugging group metadata retrieval issues.
} catch (error) { + console.error(`Failed to fetch metadata for group: ${chat.jid}`, error); return `GROUP: Unknown Group Messages: ${chat.messageCount} Last Message: ${new Date(chat.lastMessageTimestamp).toLocaleString()}`; }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { const groupMetadata = await getGroupMetadata(chat.jid); return `GROUP: ${groupMetadata?.subject || 'Unknown Group'} Messages: ${chat.messageCount} Last Message: ${new Date(chat.lastMessageTimestamp).toLocaleString()}`; } catch (error) { console.error(`Failed to fetch metadata for group: ${chat.jid}`, error); return `GROUP: Unknown Group Messages: ${chat.messageCount} Last Message: ${new Date(chat.lastMessageTimestamp).toLocaleString()}`; }
bot/metadatagc.js (1)
108-137: 🧹 Nitpick (assertive)
Consider adding monitoring metrics for rate limits and retries.
The rate limiting implementation is robust. Consider adding monitoring metrics to track rate limit hits and retry counts for better observability.
export const updateGroupMetadata = async (client) => { const handler = new RateLimitHandler(); + let rateLimitHits = 0; + let totalRetries = 0; const updateGroups = async () => { try { const groups = await client.groupFetchAllParticipating(); if (!groups) { return; } const groupIds = Object.keys(groups); for (const jid of groupIds) { if (!handler.queue.has(jid)) { handler.queue.set(jid, 0); } } await handler.processQueue(client); } catch (error) { if (error?.data === 429) { + rateLimitHits++; await handler.delay(CONFIG.RATE_LIMIT_DELAY); } } + // Log metrics every interval + console.info(`Rate limit hits: ${rateLimitHits}, Total retries: ${totalRetries}`); }; await handler.delay(CONFIG.INITIAL_DELAY); await updateGroups(); setInterval(updateGroups, CONFIG.INITIAL_DELAY); };📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.export const updateGroupMetadata = async (client) => { const handler = new RateLimitHandler(); let rateLimitHits = 0; let totalRetries = 0; const updateGroups = async () => { try { const groups = await client.groupFetchAllParticipating(); if (!groups) { return; } const groupIds = Object.keys(groups); for (const jid of groupIds) { if (!handler.queue.has(jid)) { handler.queue.set(jid, 0); } } await handler.processQueue(client); } catch (error) { if (error?.data === 429) { rateLimitHits++; await handler.delay(CONFIG.RATE_LIMIT_DELAY); } } // Log metrics every interval console.info(`Rate limit hits: ${rateLimitHits}, Total retries: ${totalRetries}`); }; await handler.delay(CONFIG.INITIAL_DELAY); await updateGroups(); setInterval(updateGroups, CONFIG.INITIAL_DELAY); };
plugins/filters.js (2)
119-128: 🧹 Nitpick (assertive)
Consider adding rate limiting for filter responses.
The chat updates handler processes every message and responds immediately when a filter matches. This could potentially be abused to spam the chat.
Consider implementing:
- Rate limiting per user/group
- Cooldown period between filter responses
- Maximum responses per minute
34-42: 🛠️ Refactor suggestion
Add input validation for filter text and response.
The filter text and response are directly used without validation. Consider adding checks for:
- Maximum length limits
- Restricted characters or patterns
- Empty strings after trimming
const [text, response] = match.split(';'); if (!text || !response) return await message.send('Both text and response are required.'); +const trimmedText = text.trim(); +const trimmedResponse = response.trim(); +if (!trimmedText || !trimmedResponse) return await message.send('Text and response cannot be empty after trimming.'); +if (trimmedText.length > 100) return await message.send('Filter text cannot exceed 100 characters.'); +if (trimmedResponse.length > 1000) return await message.send('Filter response cannot exceed 1000 characters.'); -const result = await addFilter('dm', text.trim(), response.trim()); +const result = await addFilter('dm', trimmedText, trimmedResponse);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async (message, match) => { if (!match.includes(';')) return await message.send('Use the format: pfilter <text>;<response>'); const [text, response] = match.split(';'); if (!text || !response) return await message.send('Both text and response are required.'); const trimmedText = text.trim(); const trimmedResponse = response.trim(); if (!trimmedText || !trimmedResponse) return await message.send('Text and response cannot be empty after trimming.'); if (trimmedText.length > 100) return await message.send('Filter text cannot exceed 100 characters.'); if (trimmedResponse.length > 1000) return await message.send('Filter response cannot exceed 1000 characters.'); const result = await addFilter('dm', trimmedText, trimmedResponse); return await message.send(`\`\`\`${result}\`\`\``);
bot/greetings.js (2)
45-57: 🧹 Nitpick (assertive)
Optimize memory usage for large groups.
The current implementation loads all member profile pictures synchronously. For large groups, this could lead to high memory usage and slower performance.
Consider:
- Loading profile pictures asynchronously
- Implementing a cache for frequently accessed pictures
- Adding a limit to concurrent profile picture downloads
21-43:
⚠️ Potential issueAdd error handling for external API calls.
The XSTRO API calls for facts, quotes, and advice lack error handling. If any of these calls fail, the entire welcome message will fail.
- const facts = await XSTRO.facts(); - const quotes = await XSTRO.quotes(); - const advice = await XSTRO.advice(); + let facts = '', quotes = '', advice = ''; + try { + facts = await XSTRO.facts(); + } catch (error) { + console.error('Failed to fetch facts:', error); + facts = 'Interesting fact not available at the moment.'; + } + try { + quotes = await XSTRO.quotes(); + } catch (error) { + console.error('Failed to fetch quotes:', error); + quotes = 'Quote not available at the moment.'; + } + try { + advice = await XSTRO.advice(); + } catch (error) { + console.error('Failed to fetch advice:', error); + advice = 'Advice not available at the moment.'; + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.for (const newMember of update.participants) { const pp = await client.profilePictureUrl(newMember, 'image').catch(() => null); let message; if (!welcomesettings.message) { message = `@${newMember.split('@')[0]} welcome to ${groupInfo.subject}, Nice to meet you, we have ${groupInfo.size} group members now, @${groupInfo.subjectOwner.split('@')[0]} created this group on ${new Date(groupInfo.creation).toLocaleString('en-US', dateOptions)}, ${groupInfo.desc ? 'Read Group Description:\n\n' + groupInfo.desc : ''}`; } else { let facts = '', quotes = '', advice = ''; try { facts = await XSTRO.facts(); } catch (error) { console.error('Failed to fetch facts:', error); facts = 'Interesting fact not available at the moment.'; } try { quotes = await XSTRO.quotes(); } catch (error) { console.error('Failed to fetch quotes:', error); quotes = 'Quote not available at the moment.'; } try { advice = await XSTRO.advice(); } catch (error) { console.error('Failed to fetch advice:', error); advice = 'Advice not available at the moment.'; } message = welcomesettings.message .replace('@owner', `@${groupInfo.subjectOwner.split('@')[0]}`) .replace('@gname', groupInfo.subject) .replace('@created', new Date(groupInfo.creation * 1000).toLocaleString()) .replace('@user', `@${newMember.split('@')[0]}`) .replace('@gdesc', groupInfo.desc || 'No description') .replace('@members', groupInfo.size) .replace('@facts', facts) .replace('@quotes', quotes) .replace('@advice', advice) .replace('@pp', ''); }
🧰 Tools
🪛 Biome (1.9.4)
[error] 26-26: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
bot/group_events.js (2)
13-24: 🧹 Nitpick (assertive)
Reduce code duplication in message sending logic.
The message sending logic is duplicated across promote and demote handlers. Consider extracting this into a reusable function.
+async function sendGroupEventMessage(client, group, participant, promoter, pp, message) { + const messageContent = pp !== null + ? { + image: await getBuffer(pp), + caption: message, + mentions: [participant, promoter], + } + : { + text: message, + mentions: [participant, promoter], + }; + return await client.sendMessage(group, messageContent); +} // Usage in promote handler - if (pp !== null) { - await client.sendMessage(events.Group, { - image: await getBuffer(pp), - caption: `\`\`\`@${participant.split('@')[0]} congrats...`, - mentions: [participant, promoter], - }); - } else { - await client.sendMessage(events.Group, { - text: `\`\`\`@${participant.split('@')[0]} congrats...`, - mentions: [participant, promoter], - }); - } + await sendGroupEventMessage( + client, + events.Group, + participant, + promoter, + pp, + `\`\`\`@${participant.split('@')[0]} congrats...` + );Also applies to: 29-40
77-94: 🧹 Nitpick (assertive)
Add validation for ephemeral duration values.
The ephemeral duration check uses magic numbers. Consider using constants for better maintainability.
+const EPHEMERAL_DURATIONS = { + '86400': '24 hours', + '604800': '7 days', + '7776000': '90 days', +}; - if (update.ephemeralDuration === 86400) duration = '24 hours'; - if (update.ephemeralDuration === 604800) duration = '7 days'; - if (update.ephemeralDuration === 7776000) duration = '90 days'; + duration = EPHEMERAL_DURATIONS[update.ephemeralDuration] || 'invalid duration';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const EPHEMERAL_DURATIONS = { '86400': '24 hours', '604800': '7 days', '7776000': '90 days', }; if (typeof update.ephemeralDuration !== 'undefined') { let duration = ''; if (!update.ephemeralDuration) { return await client.sendMessage(update.id, { text: `\`\`\`@${update?.author ? update.author.split('@')[0] : 'Unknown'} has disabled disappearing messages\`\`\``, mentions: [update.author], }); } duration = EPHEMERAL_DURATIONS[update.ephemeralDuration] || 'invalid duration'; return await client.sendMessage(update.id, { text: `\`\`\`@${update.author.split('@')[0]} has set disappearing messages to ${duration}\`\`\``, mentions: [update.author], }); }
plugins/ai.js (3)
17-17:
⚠️ Potential issueSecurity: Encode URL parameters to prevent injection.
API endpoints are called with unencoded parameters, which could lead to URL injection vulnerabilities.
-await getJson(`https://bk9.fun/ai/chataibot?q=${match || message.reply_message.text}`) +await getJson(`https://bk9.fun/ai/chataibot?q=${encodeURIComponent(match || message.reply_message.text)}`)Apply similar changes to all API calls in the file.
Also applies to: 33-33, 50-50, 68-68, 82-82, 103-103, 124-124, 145-145, 164-164, 182-182
14-14: 🧹 Nitpick (assertive)
Use template literals instead of string concatenation.
Replace string concatenation with template literals for better readability.
-return message.send('_Hello there ' + pushName + '_'); +return message.send(`_Hello there ${pushName}_`);Also applies to: 98-98, 119-119, 140-140, 161-161, 178-178
🧰 Tools
🪛 Biome (1.9.4)
[error] 14-14: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
81-86:
⚠️ Potential issueAdd error handling for image generation.
The DALLE image generation lacks proper error handling and could fail silently.
async (message, match) => { if (!match) return message.send('_Give me a prompt!_'); - const res = await getBuffer(`https://bk9.fun/ai/magicstudio?prompt=${match}`); - return await message.send(res, { - caption: `_Here is your image for:_ ${match}`, - }); + try { + const msg = await message.send('_Generating image..._'); + const res = await getBuffer(`https://bk9.fun/ai/magicstudio?prompt=${encodeURIComponent(match)}`); + await message.send(res, { + caption: `_Here is your image for:_ ${match}`, + }); + return await msg.delete(); + } catch (error) { + return message.send('Failed to generate image. Please try again later.'); + } }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!match) return message.send('_Give me a prompt!_'); try { const msg = await message.send('_Generating image..._'); const res = await getBuffer(`https://bk9.fun/ai/magicstudio?prompt=${encodeURIComponent(match)}`); await message.send(res, { caption: `_Here is your image for:_ ${match}`, }); return await msg.delete(); } catch (error) { return message.send('Failed to generate image. Please try again later.'); } }
plugins/dev.js (3)
15-140: 🧹 Nitpick (assertive)
⚠️ Potential issueSecurity concern: Unsafe code execution.
The implementation uses
new Function()
for code execution, which poses security risks similar toeval()
. Consider implementing a more secure approach:
- Use a dedicated sandbox environment
- Implement strict input validation
- Limit available APIs and resources
🧰 Tools
🪛 Biome (1.9.4)
[error] 41-41: This let declares a variable that is only assigned once.
'importedModules' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
144-181:
⚠️ Potential issueCritical security vulnerability: Direct use of eval().
The direct use of
eval()
is highly dangerous as it can execute arbitrary code. This poses significant security risks:
- Remote Code Execution (RCE) vulnerability
- No sandboxing or isolation
- Access to sensitive context
Replace this implementation with a secure alternative that doesn't use
eval()
. Consider using:
- A dedicated code execution sandbox
- Static code analysis
- Restricted command execution
🧰 Tools
🪛 Biome (1.9.4)
[error] 155-155: eval() exposes to security risks and performance issues.
See the MDN web docs for more details.
Refactor the code so that it doesn't need to call eval().(lint/security/noGlobalEval)
41-41: 🧹 Nitpick (assertive)
Use const for variables that are not reassigned.
Replace
let
withconst
as the variable is only assigned once.-let importedModules = {}; +const importedModules = {};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const importedModules = {};
🧰 Tools
🪛 Biome (1.9.4)
[error] 41-41: This let declares a variable that is only assigned once.
'importedModules' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
readme.md (4)
52-54: 🧹 Nitpick (assertive)
Enhance deployment instructions clarity.
The deployment instructions for various platforms could be more detailed:
- Explain what each environment variable (
SESSION_ID
,BOT_INFO
, etc.) represents- Provide example values or format requirements
- Add troubleshooting steps for common deployment issues
Also applies to: 59-61, 66-72
79-79: 🧹 Nitpick (assertive)
Fix macOS capitalization.
Correct the capitalization of "MacOS" to "macOS" to align with Apple's official branding.
-### Windows/Linux/MacOS Deploy +### Windows/Linux/macOS Deploy📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.### Windows/Linux/macOS Deploy
🧰 Tools
🪛 LanguageTool
[grammar] ~79-~79: The operating system from Apple is written “macOS”.
Context: .../wiki/Panel-Support) ### Windows/Linux/MacOS Deploy #### 1. Install Node.js * **Wi...(MAC_OS)
61-61: 🧹 Nitpick (assertive)
Add hyphens to compound modifier.
Add hyphens to "pre and post" when used as a compound modifier before "deployment".
-alter the pre and post deployment process +alter the pre- and post-deployment process📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.* If you are not an advanced koyeb user, just tap on the `deploy` button, after you have filled the variables and aviod any necessary options that "may" or "will" alter the pre- and post-deployment process.
🧰 Tools
🪛 LanguageTool
[grammar] ~61-~61: It appears that hyphens are missing.
Context: ... options that "may" or "will" alter the pre and post deployment process. * Watch Video Tutorial ##...(PRE_AND_POST_NN)
55-55: 💡 Codebase verification
Empty video tutorial links should be removed
The verification confirms that there are three empty video tutorial links
[Watch Video Tutorial]()
in the deployment sections for Heroku, Koyeb, and Render. These placeholder links should be removed until actual tutorial videos are available to avoid misleading users.
- Line 55: Empty Heroku tutorial link
- Line 62: Empty Koyeb tutorial link
- Line 73: Empty Render tutorial link
🔗 Analysis chain
Add video tutorial links or remove placeholder references.
The documentation contains empty video tutorial links for Heroku, Koyeb, and Render deployments. Either provide the actual tutorial links or remove these references to avoid confusion.
Also applies to: 62-62, 73-73
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check if video tutorials exist in the repository fd -e mp4 -e webm -e mkv tutorialLength of output: 35
Script:
#!/bin/bash # Check the content of readme.md and look for video-related references echo "=== Readme Content ===" cat readme.md echo -e "\n=== Searching for video-related terms ===" rg -i "video|tutorial|watch" --type mdLength of output: 6794
🧰 Tools
🪛 Markdownlint (0.37.0)
55-55: null
No empty links(MD042, no-empty-links)
plugins/download.js (2)
17-17:
⚠️ Potential issueMove API credentials to environment variables.
The API key is hardcoded in the source code, which is a security risk. Move it to environment variables.
-const KEY = `free_key@maher_apis`; +const KEY = process.env.NEXORACLE_API_KEY;Also applies to: 29-29
146-147: 🧹 Nitpick (assertive)
Implement rate limiting for API calls.
Add rate limiting to prevent abuse of external APIs, especially for resource-intensive operations like media downloads.
Consider using a rate limiting library like
express-rate-limit
or implement a custom solution using a token bucket algorithm.Also applies to: 186-192
plugins/whatsapp.js (5)
69-85: 🧹 Nitpick (assertive)
Use const and add error handling.
The implementation can be improved by:
- Using
const
instead oflet
for thekey
variable- Adding proper error handling for message loading failures
bot( { pattern: 'quoted', public: false, type: 'whatsapp', desc: 'quoted message', }, async (message) => { if (!message.reply_message) return await message.send('```Reply A Message```'); - let key = message.reply_message.key.id; - let msg = await message.client.loadMessage(key); - if (!msg) return await message.send('```Xstro will not quoted Bot Message```'); - msg = await serialize(JSON.parse(JSON.stringify(msg.message)), message.client); - if (!msg.quoted) return await message.send('_No quoted message found_'); - await message.forward(message.jid, msg.quoted, { - quoted: msg.quoted, - }); + try { + const key = message.reply_message.key.id; + const msg = await message.client.loadMessage(key); + if (!msg) return await message.send('```Xstro will not quoted Bot Message```'); + const serializedMsg = await serialize(JSON.parse(JSON.stringify(msg.message)), message.client); + if (!serializedMsg.quoted) return await message.send('_No quoted message found_'); + await message.forward(message.jid, serializedMsg.quoted, { + quoted: serializedMsg.quoted, + }); + } catch (error) { + return await message.send('_Failed to process quoted message_'); + } } );🧰 Tools
🪛 Biome (1.9.4)
[error] 77-77: This let declares a variable that is only assigned once.
'key' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
4-4: 🛠️ Refactor suggestion
Remove unused import.
The
isJidBroadcast
import is not used in this file.-import { delay, isJidBroadcast, isJidGroup } from 'baileys'; +import { delay, isJidGroup } from 'baileys';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.import { delay, isJidGroup } from 'baileys';
6-17: 🧹 Nitpick (assertive)
Add error handling for network failures.
The
vv
command should handle potential network failures when downloading viewonce messages.bot( { pattern: 'vv', public: false, desc: 'Downloads A Viewonce Message', type: 'whatsapp', }, async (message) => { if (!message.reply_message.viewonce) return message.send('_Reply A Viewonce Message_'); - const res = await ModifyViewOnceMessage(message.id, message.client); - return message.client.relayMessage(message.jid, res.message, {}); + try { + const res = await ModifyViewOnceMessage(message.id, message.client); + return message.client.relayMessage(message.jid, res.message, {}); + } catch (error) { + return message.send('_Failed to download viewonce message_'); + } } );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.bot( { pattern: 'vv', public: false, desc: 'Downloads A Viewonce Message', type: 'whatsapp', }, async (message) => { if (!message.reply_message.viewonce) return message.send('_Reply A Viewonce Message_'); try { const res = await ModifyViewOnceMessage(message.id, message.client); return message.client.relayMessage(message.jid, res.message, {}); } catch (error) { return message.send('_Failed to download viewonce message_'); } }
20-36: 🧹 Nitpick (assertive)
Simplify media type check and add error handling.
The media type check can be simplified, and error handling should be added for conversion failures.
bot( { pattern: 'tovv', public: true, desc: 'Converts A Normal Media Message to ViewOnce', type: 'whatsapp', }, async (message) => { - if ( - !message.reply_message.video && - !message.reply_message.audio && - !message.reply_message.image - ) + const validTypes = ['video', 'audio', 'image']; + if (!validTypes.some(type => message.reply_message[type])) return message.send('_Reply an Image | Video | Audio_'); - const viewonceMessage = await convertNormalMessageToViewOnce(message.data.quoted.message); - return message.client.relayMessage(message.jid, viewonceMessage, {}); + try { + const viewonceMessage = await convertNormalMessageToViewOnce(message.data.quoted.message); + return message.client.relayMessage(message.jid, viewonceMessage, {}); + } catch (error) { + return message.send('_Failed to convert to viewonce message_'); + } } );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.bot( { pattern: 'tovv', public: true, desc: 'Converts A Normal Media Message to ViewOnce', type: 'whatsapp', }, async (message) => { const validTypes = ['video', 'audio', 'image']; if (!validTypes.some(type => message.reply_message[type])) return message.send('_Reply an Image | Video | Audio_'); try { const viewonceMessage = await convertNormalMessageToViewOnce(message.data.quoted.message); return message.client.relayMessage(message.jid, viewonceMessage, {}); } catch (error) { return message.send('_Failed to convert to viewonce message_'); } } );
214-237: 🧹 Nitpick (assertive)
Improve JID handling and add error handling.
The implementation can be improved by:
- Simplifying the JID validation logic
- Adding error handling for forwarding failures
bot( { pattern: 'forward', public: false, type: 'whatsapp', desc: 'Forwards A Replied Message', }, async (message, match) => { if (!message.reply_message) return message.send('_Reply A Message!_'); - let jid; - if (message.mention && message.mention[0]) { - jid = message.mention[0]; - } else if (isJidGroup(match)) { - return message.send('_Use Gforward command to forward to groups_'); - } else if (!isJidGroup(match)) { - jid = toJid(match); - } - if (!jid) return message.send('_You have to provide a number/tag someone_'); - const msg = message.data?.quoted; - await message.forward(jid, msg, { quoted: msg }); - return await message.send(`_Message forward to @${jid.split('@')[0]}_`, { - mentions: [jid], - }); + try { + const jid = message.mention?.[0] || (!isJidGroup(match) && toJid(match)); + if (!jid) return message.send('_You have to provide a number/tag someone_'); + if (isJidGroup(match)) return message.send('_Use Gforward command to forward to groups_'); + const msg = message.data?.quoted; + await message.forward(jid, msg, { quoted: msg }); + return await message.send(`_Message forwarded to @${jid.split('@')[0]}_`, { + mentions: [jid], + }); + } catch (error) { + return message.send('_Failed to forward message_'); + } } );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.bot( { pattern: 'forward', public: false, type: 'whatsapp', desc: 'Forwards A Replied Message', }, async (message, match) => { if (!message.reply_message) return message.send('_Reply A Message!_'); try { const jid = message.mention?.[0] || (!isJidGroup(match) && toJid(match)); if (!jid) return message.send('_You have to provide a number/tag someone_'); if (isJidGroup(match)) return message.send('_Use Gforward command to forward to groups_'); const msg = message.data?.quoted; await message.forward(jid, msg, { quoted: msg }); return await message.send(`_Message forwarded to @${jid.split('@')[0]}_`, { mentions: [jid], }); } catch (error) { return message.send('_Failed to forward message_'); } } );
🧰 Tools
🪛 Biome (1.9.4)
[error] 224-224: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
plugins/group.js (3)
86-86: 🛠️ Refactor suggestion
Replace unsafe isNaN with Number.isNaN.
The global
isNaN
function attempts type coercion and can lead to unexpected results.- if (!countryCode || isNaN(countryCode)) + if (!countryCode || Number.isNaN(Number(countryCode)))📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.if (!countryCode || Number.isNaN(Number(countryCode)))
🧰 Tools
🪛 Biome (1.9.4)
[error] 86-86: isNaN is unsafe. It attempts a type coercion. Use Number.isNaN instead.
See the MDN documentation for more details.
Unsafe fix: Use Number.isNaN instead.(lint/suspicious/noGlobalIsNan)
235-241: 🧹 Nitpick (assertive)
Use const for variables and improve array handling.
Multiple variables declared with
let
are never reassigned. Also, the array handling can be improved.- let [pollName, pollOptions] = match.split(';'); + const [pollName, pollOptions] = match.split(';'); if (!pollOptions) return await message.send(message.prefix + 'poll question;option1,option2,option3.....'); - let options = []; - for (let option of pollOptions.split(',')) - if (option && option.trim() !== '') options.push(option.trim()); + const options = pollOptions.split(',') + .map(option => option.trim()) + .filter(Boolean);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const [pollName, pollOptions] = match.split(';'); if (!pollOptions) return await message.send(message.prefix + 'poll question;option1,option2,option3.....'); const options = pollOptions.split(',') .map(option => option.trim()) .filter(Boolean); await message.client.sendMessage(message.jid, {
🧰 Tools
🪛 Biome (1.9.4)
[error] 237-237: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
[error] 235-235: This let declares some variables that are only assigned once.
'pollName' is never reassigned.
'pollOptions' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
[error] 238-238: This let declares a variable that is only assigned once.
'options' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
[error] 239-239: This let declares a variable that is only assigned once.
'option' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
387-391: 🧹 Nitpick (assertive)
Use const and array methods for request handling.
The request handling code can be improved using const and modern array methods.
- let requestJids = []; - for (let request of joinRequests) { - requestList += `@${request.jid.split('@')[0]}\n`; - requestJids.push(request.jid); - } + const requestJids = joinRequests.map(request => { + requestList += `@${request.jid.split('@')[0]}\n`; + return request.jid; + });Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Biome (1.9.4)
[error] 387-387: This let declares a variable that is only assigned once.
'requestJids' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
[error] 388-388: This let declares a variable that is only assigned once.
'request' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
plugins/areact.js (3)
39-1569: 🛠️ Refactor suggestion
Move emojis to a separate configuration file.
The large emoji array should be:
- Declared as a constant
- Moved to a separate configuration file
- Potentially categorized for better management
Create a new file
config/emojis.js
:export const emojis = { hearts: ['💘', '💝', '💖', /* ... */], faces: ['😀', '😃', '😄', /* ... */], // ... more categories };
26-36: 🛠️ Refactor suggestion
Add rate limiting to auto-react feature.
The auto-react feature should include rate limiting to prevent spam and excessive reactions.
bot( { on: 'text', dontAddCommandList: true, }, async (message) => { const autoReactSetting = await AutoReact.findOne(); if (autoReactSetting?.status) { + const lastReactTime = await message.client.getLastReactTime(message.jid); + const now = Date.now(); + if (lastReactTime && now - lastReactTime < 5000) return; // 5 seconds cooldown const emoji = getRandom(emojis); await message.react(emoji); + await message.client.setLastReactTime(message.jid, now); } } );Committable suggestion skipped: line range outside the PR's diff.
6-22: 🧹 Nitpick (assertive)
Improve areact command validation.
The areact command should validate the status input and provide better feedback.
bot( { pattern: 'areact', public: false, desc: 'Toggle Auto React On/Off', type: 'user', }, async (message, match) => { + if (!match || !['on', 'off'].includes(match.toLowerCase())) { + return message.send('_Usage: .areact on/off_'); + } - const status = match; - const newStatus = status === 'on'; + const newStatus = match.toLowerCase() === 'on'; const currentSetting = await AutoReact.findOne(); if (currentSetting) { await AutoReact.update({ status: newStatus }, { where: {} }); } else { await AutoReact.create({ status: newStatus }); } await message.send(`_Autoreact set to ${newStatus ? 'ON' : 'OFF'}._`); } );📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.{ pattern: 'areact', public: false, desc: 'Toggle Auto React On/Off', type: 'user', }, async (message, match) => { if (!match || !['on', 'off'].includes(match.toLowerCase())) { return message.send('_Usage: .areact on/off_'); } const newStatus = match.toLowerCase() === 'on'; const currentSetting = await AutoReact.findOne(); if (currentSetting) { await AutoReact.update({ status: newStatus }, { where: {} }); } else { await AutoReact.create({ status: newStatus }); } await message.send(`_Autoreact set to ${newStatus ? 'ON' : 'OFF'}._`); }
plugins/forex.js (1)
169-170:
⚠️ Potential issueFix incorrect API endpoints in fxasia and fxpacific commands.
Both commands are using the 'fxmajor' endpoint instead of their respective endpoints.
- const res = await XSTRO.forex('fxmajor'); + const res = await XSTRO.forex('fxasia');- const res = await XSTRO.forex('fxmajor'); + const res = await XSTRO.forex('fxpacific');Also applies to: 197-198
plugins/converter.js (1)
71-73:
⚠️ Potential issueFix undefined variable reference.
The
validDirections
array is referenced but not defined. This will cause a runtime error.+ const validDirections = ['left', 'right', 'vertical', 'horizontal']; if (!['left', 'right', 'vertical', 'horizontal'].includes(match)) { - return message.send(`_Usage: ${prefix}flip <${validDirections.join('/')}>`); + return message.send(`_Usage: ${prefix}flip <${['left', 'right', 'vertical', 'horizontal'].join('/')}>`); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const validDirections = ['left', 'right', 'vertical', 'horizontal']; if (!['left', 'right', 'vertical', 'horizontal'].includes(match)) { return message.send(`_Usage: ${prefix}flip <${['left', 'right', 'vertical', 'horizontal'].join('/')}>`); }
lib/class.js (1)
266-287: 🛠️ Refactor suggestion
Add cleanup for temporary files.
The
download
method creates temporary files but doesn't clean them up. This could lead to disk space issues over time.async download(file = false) { const buffer = await downloadMediaMessage( { key: this.data.quoted.key, message: this.data?.quoted?.message, }, 'buffer', {}, { logger: console, reuploadRequest: this.client.updateMediaMessage, } ); if (file) { const extension = await FileTypeFromBuffer(buffer); const filename = `${Date.now()}.${extension}`; const filepath = path.join(os.tmpdir(), filename); await fs.promises.writeFile(filepath, buffer); + // Schedule cleanup after a reasonable delay (e.g., 1 hour) + setTimeout(async () => { + try { + await fs.promises.unlink(filepath); + } catch (error) { + console.error(`Failed to cleanup temporary file ${filepath}:`, error); + } + }, 3600000); return filepath; } return buffer; }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.async download(file = false) { const buffer = await downloadMediaMessage( { key: this.data.quoted.key, message: this.data?.quoted?.message, }, 'buffer', {}, { logger: console, reuploadRequest: this.client.updateMediaMessage, } ); if (file) { const extension = await FileTypeFromBuffer(buffer); const filename = `${Date.now()}.${extension}`; const filepath = path.join(os.tmpdir(), filename); await fs.promises.writeFile(filepath, buffer); // Schedule cleanup after a reasonable delay (e.g., 1 hour) setTimeout(async () => { try { await fs.promises.unlink(filepath); } catch (error) { console.error(`Failed to cleanup temporary file ${filepath}:`, error); } }, 3600000); return filepath; } return buffer; }
plugins/config.js (3)
12-17: 🛠️ Refactor suggestion
Add error handling for database operations.
The commands make external calls to
getConfig()
andupdateConfig()
without proper error handling. This could lead to unhandled exceptions if the database operations fail.Example implementation:
async (message, match) => { try { const dbConfig = await getConfig(); // ... existing logic ... await updateConfig('key', value); return await message.send('Success message'); } catch (error) { console.error('Failed to update configuration:', error); return await message.send('_Failed to update configuration. Please try again._'); } }Also applies to: 27-35, 46-54, 65-73, 84-92, 103-111, 122-130, 141-146, 157-170, 181-190, 201-210, 221-230, 241-249, 260-268
163-168:
⚠️ Potential issueFix command validation in disable command.
The command filtering logic doesn't verify if the provided command exists. The
cmds
variable is never used to validate the command name.- const cmds = commands.filter( - (cmd) => - cmd.pattern && !cmd.dontAddCommandList && !cmd.pattern.toString().includes('undefined') - ); - if (!cmds) return await message.send('_Command not found_'); + const cmd = commands.find( + (cmd) => + cmd.pattern && + !cmd.dontAddCommandList && + !cmd.pattern.toString().includes('undefined') && + cmd.pattern.toString() === match + ); + if (!cmd) return await message.send('_Command not found_');📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.const cmd = commands.find( (cmd) => cmd.pattern && !cmd.dontAddCommandList && !cmd.pattern.toString().includes('undefined') && cmd.pattern.toString() === match ); if (!cmd) return await message.send('_Command not found_'); if (await isCmdDisabled(match)) return await message.send('_Command already disabled_');
129-130:
⚠️ Potential issueFix incorrect configuration key in cmdread command.
The command updates
cmdReact
instead ofcmdRead
in the database, which will cause unexpected behavior.- await updateConfig('cmdReact', newValue); + await updateConfig('cmdRead', newValue);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.await updateConfig('cmdRead', newValue); return await message.send(`_CmdRead set to ${newValue ? 'on' : 'off'}._`);
plugins/search.js (5)
15-15: 🧹 Nitpick (assertive)
Move API URL to configuration.
The API URL is hardcoded in the code. Consider moving it to a configuration file to make it easier to maintain and update.
36-54: 🧹 Nitpick (assertive)
Use const for variables that aren't reassigned.
The variables
imdbInfo
andforecastMessage
are never reassigned and should useconst
instead oflet
.- let imdbInfo = [ + const imdbInfo = [ // ... - let forecastMessage = forecast + const forecastMessage = forecastAlso applies to: 305-316
🧰 Tools
🪛 Biome (1.9.4)
[error] 36-36: This let declares a variable that is only assigned once.
'imdbInfo' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
34-34:
⚠️ Potential issueSecure API keys and sanitize user input.
Several security concerns need to be addressed:
- API keys are hardcoded in the code (e.g., OMDB API key, OpenWeatherMap API key)
- User input is used directly in API calls without proper sanitization
This could lead to API key exposure and potential injection attacks.
- Move API keys to environment variables:
- `http://www.omdbapi.com/?apikey=742b2d09&t=${encodeURIComponent(match)}&plot=full` + `http://www.omdbapi.com/?apikey=${process.env.OMDB_API_KEY}&t=${encodeURIComponent(match)}&plot=full`
- Add input validation and sanitization:
+ if (match.length > 100) return message.send('_Search query too long_'); + if (!/^[a-zA-Z0-9\s]+$/.test(match)) return message.send('_Invalid characters in search query_'); const res = await getJson(/* ... */);Also applies to: 70-70, 274-274
150-153: 🧹 Nitpick (assertive)
Use template literals instead of string concatenation.
Replace string concatenation with template literals for better readability.
- return message.send('_Please provide a zodiac sign_\nValid signs: ' + signs.join(', ')); + return message.send(`_Please provide a zodiac sign_\nValid signs: ${signs.join(', ')}`); - return message.send('_Invalid zodiac sign_\nValid signs: ' + signs.join(', ')); + return message.send(`_Invalid zodiac sign_\nValid signs: ${signs.join(', ')}`);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.return message.send(`_Please provide a zodiac sign_\nValid signs: ${signs.join(', ')}`); const sign = match.toLowerCase(); if (!signs.includes(sign)) return message.send(`_Invalid zodiac sign_\nValid signs: ${signs.join(', ')}`);
🧰 Tools
🪛 Biome (1.9.4)
[error] 150-150: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
[error] 153-153: Template literals are preferred over string concatenation.
Unsafe fix: Use a template literal.
(lint/style/useTemplate)
15-20:
⚠️ Potential issueAdd error handling for lyrics API call.
The external API call lacks error handling, which could lead to unhandled exceptions if the API is unavailable or returns an error.
- const res = await getJson(`https://itzpire.com/search/lyrics?query=${req}`); - const { title, album, thumb, lyrics } = res.data; - const image = await getBuffer(thumb); - return await message.send(image, { - caption: `*${title}*\n\`\`\`${album}\n\n${lyrics}\`\`\``, - }); + try { + const res = await getJson(`https://itzpire.com/search/lyrics?query=${req}`); + if (!res?.data) { + return await message.send('_No lyrics found_'); + } + const { title, album, thumb, lyrics } = res.data; + const image = await getBuffer(thumb); + return await message.send(image, { + caption: `*${title}*\n\`\`\`${album}\n\n${lyrics}\`\`\``, + }); + } catch (error) { + console.error('Failed to fetch lyrics:', error); + return await message.send('_Failed to fetch lyrics. Please try again._'); + }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.try { const res = await getJson(`https://itzpire.com/search/lyrics?query=${req}`); if (!res?.data) { return await message.send('_No lyrics found_'); } const { title, album, thumb, lyrics } = res.data; const image = await getBuffer(thumb); return await message.send(image, { caption: `*${title}*\n\`\`\`${album}\n\n${lyrics}\`\`\``, }); } catch (error) { console.error('Failed to fetch lyrics:', error); return await message.send('_Failed to fetch lyrics. Please try again._'); }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 15
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
bot/antidelete.js
(1 hunks)lib/client.js
(1 hunks)lib/events.js
(1 hunks)lib/message.js
(1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
lib/client.js
[error] 11-11: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.
(lint/style/useNodejsImportProtocol)
[error] 99-99: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 58-58: Reassigning a function parameter is confusing.
The parameter is declared here:
Use a local variable instead.
(lint/style/noParameterAssign)
lib/events.js
[error] 16-16: This let declares a variable that is only assigned once.
'tasks' is never reassigned.
Safe fix: Use const instead.
(lint/style/useConst)
bot/antidelete.js
Outdated
// console.log(msg.isProtocol); | ||
// console.log(store); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Eliminate unused commented-out code
The commented-out code in lines 14-16 is not needed and can be removed to keep the code clean.
Apply this diff to remove the unnecessary comments:
- // console.log(msg.isProtocol);
- // console.log(store);
bot/antidelete.js
Outdated
const client = msg.client; | ||
const store = await msg.client.loadMessage(msg.isProtocol.key.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Remove unused variables 'client' and 'store'
The variables client
and store
are assigned but not used within the function. Consider removing them to avoid confusion.
Apply this diff to remove the unused variables:
- const client = msg.client;
- const store = await msg.client.loadMessage(msg.isProtocol.key.id);
if (isGroup) { | ||
const metadata = await conn.groupMetadata(remoteJid); | ||
const participant = messages.key.participant; | ||
msg.isAdmin = !!metadata.participants.find((p) => p.id === participant)?.admin || false; | ||
msg.isBotAdmin = !!metadata.participants.find((p) => p.id === owner)?.admin || false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for group metadata fetch.
The groupMetadata
call could fail if the group doesn't exist or if there are network issues. Consider adding try-catch block:
if (isGroup) {
+ try {
const metadata = await conn.groupMetadata(remoteJid);
const participant = messages.key.participant;
msg.isAdmin = !!metadata.participants.find((p) => p.id === participant)?.admin || false;
msg.isBotAdmin = !!metadata.participants.find((p) => p.id === owner)?.admin || false;
+ } catch (error) {
+ console.error('Failed to fetch group metadata:', error);
+ msg.isAdmin = false;
+ msg.isBotAdmin = false;
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (isGroup) { | |
const metadata = await conn.groupMetadata(remoteJid); | |
const participant = messages.key.participant; | |
msg.isAdmin = !!metadata.participants.find((p) => p.id === participant)?.admin || false; | |
msg.isBotAdmin = !!metadata.participants.find((p) => p.id === owner)?.admin || false; | |
} | |
if (isGroup) { | |
try { | |
const metadata = await conn.groupMetadata(remoteJid); | |
const participant = messages.key.participant; | |
msg.isAdmin = !!metadata.participants.find((p) => p.id === participant)?.admin || false; | |
msg.isBotAdmin = !!metadata.participants.find((p) => p.id === owner)?.admin || false; | |
} catch (error) { | |
console.error('Failed to fetch group metadata:', error); | |
msg.isAdmin = false; | |
msg.isBotAdmin = false; | |
} | |
} |
await msg.send( | ||
`\`\`\`An Error Occurred while running ${cmd.pattern.toString().split(/\W+/)[2]} command!\`\`\`` | ||
); | ||
const name = cmd.pattern.toString().split(/\W+/)[1] || 'UNKNOWN CMD'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve command name extraction reliability.
The current regex pattern split might be fragile. Consider adding a fallback for command name extraction:
- const name = cmd.pattern.toString().split(/\W+/)[1] || 'UNKNOWN CMD';
+ const name = extractCommandName(cmd.pattern);
+function extractCommandName(pattern) {
+ try {
+ const matches = pattern.toString().match(/\w+/g);
+ return matches?.[1] || 'UNKNOWN CMD';
+ } catch {
+ return 'UNKNOWN CMD';
+ }
+}
Committable suggestion skipped: line range outside the PR's diff.
const quoted = | ||
messages.message?.[msg.type]?.contextInfo?.quotedMessage || | ||
normalizeMessageContent( | ||
normalizeMessageContent( | ||
messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.quotedMessage | ||
) | ||
); | ||
|
||
if (quoted) { | ||
const quotedMessage = normalizeMessageContent(quoted); | ||
const quotedType = getContentType(quotedMessage); | ||
const stanzaId = | ||
messages.message?.[msg.type]?.contextInfo?.stanzaId || | ||
normalizeMessageContent( | ||
normalizeMessageContent( | ||
messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.stanzaId | ||
) | ||
); | ||
msg.quoted = { | ||
key: { | ||
id: normalizeMessageContent(stanzaId) || null, | ||
fromMe: messages.message?.[msg.type]?.contextInfo?.participant === owner, | ||
remoteJid: msg.key.remoteJid, | ||
participant: isGroup | ||
? normalizeMessageContent(messages.message?.[InquotedType]?.contextInfo?.participant) | ||
: undefined | ||
}, | ||
message: quotedMessage, | ||
type: quotedType, | ||
viewonce: quotedMessage?.[quotedType]?.viewOnce || false, | ||
body: | ||
quotedMessage?.conversation || | ||
quotedMessage?.[quotedType]?.text || | ||
quotedMessage?.[quotedType]?.caption || | ||
false | ||
}; | ||
} else { | ||
msg.quoted = null; | ||
} | ||
if (quoted) { | ||
const quotedMessage = normalizeMessageContent(quoted); | ||
const quotedType = getContentType(quotedMessage); | ||
const stanzaId = | ||
messages.message?.[msg.type]?.contextInfo?.stanzaId || | ||
normalizeMessageContent( | ||
normalizeMessageContent( | ||
messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.stanzaId | ||
) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Extract helper functions for quoted message processing.
The repeated normalization calls and deep nesting make the code hard to follow. Consider extracting helper functions:
+function getQuotedMessage(messages, msgType, InquotedType, deepQuotedType) {
+ return messages.message?.[msgType]?.contextInfo?.quotedMessage ||
+ normalizeMessageContent(
+ normalizeMessageContent(
+ messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.quotedMessage
+ )
+ );
+}
+function getStanzaId(messages, msgType, InquotedType, deepQuotedType) {
+ return messages.message?.[msgType]?.contextInfo?.stanzaId ||
+ normalizeMessageContent(
+ normalizeMessageContent(
+ messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.stanzaId
+ )
+ );
+}
- const quoted = messages.message?.[msg.type]?.contextInfo?.quotedMessage ||
- normalizeMessageContent(
- normalizeMessageContent(
- messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.quotedMessage
- )
- );
+ const quoted = getQuotedMessage(messages, msg.type, InquotedType, deepQuotedType);
- const stanzaId = messages.message?.[msg.type]?.contextInfo?.stanzaId ||
- normalizeMessageContent(
- normalizeMessageContent(
- messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.stanzaId
- )
- );
+ const stanzaId = getStanzaId(messages, msg.type, InquotedType, deepQuotedType);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const quoted = | |
messages.message?.[msg.type]?.contextInfo?.quotedMessage || | |
normalizeMessageContent( | |
normalizeMessageContent( | |
messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.quotedMessage | |
) | |
); | |
if (quoted) { | |
const quotedMessage = normalizeMessageContent(quoted); | |
const quotedType = getContentType(quotedMessage); | |
const stanzaId = | |
messages.message?.[msg.type]?.contextInfo?.stanzaId || | |
normalizeMessageContent( | |
normalizeMessageContent( | |
messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.stanzaId | |
) | |
); | |
msg.quoted = { | |
key: { | |
id: normalizeMessageContent(stanzaId) || null, | |
fromMe: messages.message?.[msg.type]?.contextInfo?.participant === owner, | |
remoteJid: msg.key.remoteJid, | |
participant: isGroup | |
? normalizeMessageContent(messages.message?.[InquotedType]?.contextInfo?.participant) | |
: undefined | |
}, | |
message: quotedMessage, | |
type: quotedType, | |
viewonce: quotedMessage?.[quotedType]?.viewOnce || false, | |
body: | |
quotedMessage?.conversation || | |
quotedMessage?.[quotedType]?.text || | |
quotedMessage?.[quotedType]?.caption || | |
false | |
}; | |
} else { | |
msg.quoted = null; | |
} | |
if (quoted) { | |
const quotedMessage = normalizeMessageContent(quoted); | |
const quotedType = getContentType(quotedMessage); | |
const stanzaId = | |
messages.message?.[msg.type]?.contextInfo?.stanzaId || | |
normalizeMessageContent( | |
normalizeMessageContent( | |
messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.stanzaId | |
) | |
); | |
function getQuotedMessage(messages, msgType, InquotedType, deepQuotedType) { | |
return messages.message?.[msgType]?.contextInfo?.quotedMessage || | |
normalizeMessageContent( | |
normalizeMessageContent( | |
messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.quotedMessage | |
) | |
); | |
} | |
function getStanzaId(messages, msgType, InquotedType, deepQuotedType) { | |
return messages.message?.[msgType]?.contextInfo?.stanzaId || | |
normalizeMessageContent( | |
normalizeMessageContent( | |
messages.message?.[InquotedType]?.message?.[deepQuotedType]?.contextInfo?.stanzaId | |
) | |
); | |
} | |
const quoted = getQuotedMessage(messages, msg.type, InquotedType, deepQuotedType); | |
if (quoted) { | |
const quotedMessage = normalizeMessageContent(quoted); | |
const quotedType = getContentType(quotedMessage); | |
const stanzaId = getStanzaId(messages, msg.type, InquotedType, deepQuotedType); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AstroX11 Great! Feel free to implement the suggested changes to improve the code's readability. Let me know if you need any further assistance.
Necessary fix Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
lib/events.js
(1 hunks)
🔇 Additional comments (2)
lib/events.js (2)
23-23
: Function call update looks goodThe update to
updateGroupMetadata(msg.client)
reflects the change in the function's signature and uses the appropriate argument.
18-24
:⚠️ Potential issueCritical Issue: Functions executed before conditional checks leading to unintended side effects
The functions
StickerCMD(msg)
,AntiDelete(msg)
,AntiViewOnce(msg)
,AntiSpammer(msg)
, andupdateGroupMetadata(msg.client)
are being invoked immediately when pushed into thetasks
array. If any of these functions have side effects or consume resources, they will execute even if the subsequent conditional checks cause an early return from theupserts
function. This can lead to unintended behavior and performance issues.Apply this diff to move the function calls after the conditional checks:
export async function upserts(msg) { const tasks = []; const config = await getConfig(); + if (!msg.isGroup) { + if (config.disabledm && msg.from !== msg.user) return; + } + if (msg.isGroup) { + if (isJidGroup(msg.from) && config.disablegc) return; + } tasks.push( StickerCMD(msg), AntiDelete(msg), AntiViewOnce(msg), AntiSpammer(msg), updateGroupMetadata(msg.client) );Likely invalid or redundant comment.
if (msg.isGroup) { | ||
if (isJidGroup(msg.from) && config.disablegc) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Suggestion: Simplify redundant condition in group check
Inside the if (msg.isGroup)
block, the condition isJidGroup(msg.from)
may be redundant because msg.isGroup
is already true. Unless there are specific cases where msg.isGroup
is true but isJidGroup(msg.from)
is false, consider removing isJidGroup(msg.from)
to simplify the condition.
Apply this diff to simplify the condition:
if (msg.isGroup) {
- if (isJidGroup(msg.from) && config.disablegc) return;
+ if (config.disablegc) return;
tasks.push(Antilink(msg), schedules(msg), AntiWord(msg), AutoKick(msg));
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (msg.isGroup) { | |
if (isJidGroup(msg.from) && config.disablegc) return; | |
if (msg.isGroup) { | |
if (config.disablegc) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (4)
media/intro.mp4
is excluded by!**/*.mp4
media/logo.jpg
is excluded by!**/*.jpg
media/thumb.jpg
is excluded by!**/*.jpg
media/xstro.jpg
is excluded by!**/*.jpg
📒 Files selected for processing (4)
bot/antidelete.js
(1 hunks)lib/client.js
(1 hunks)lib/message.js
(1 hunks)lib/plugins.js
(1 hunks)
🧰 Additional context used
📓 Learnings (2)
lib/message.js (1)
Learnt from: AstroX11
PR: AstroX11/Xstro#17
File: lib/message.js:21-25
Timestamp: 2025-01-18T20:27:57.036Z
Learning: In the message serialization logic of Xstro, the sender property should be defined inline within the msg object using ternary operations, rather than being extracted to a separate helper function, to maintain the codebase's design pattern.
bot/antidelete.js (1)
Learnt from: AstroX11
PR: AstroX11/Xstro#17
File: bot/antidelete.js:7-11
Timestamp: 2025-01-18T20:25:38.168Z
Learning: Debug comments and commented-out code checks in the codebase should be preserved as they may serve as debugging checkpoints or document message flow.
🪛 Biome (1.9.4)
lib/client.js
[error] 11-11: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.
(lint/style/useNodejsImportProtocol)
[error] 100-100: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Unsafe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 58-58: Reassigning a function parameter is confusing.
The parameter is declared here:
Use a local variable instead.
(lint/style/noParameterAssign)
🔇 Additional comments (8)
lib/client.js (2)
11-11
: Use 'node:' protocol when importing Node.js built-in modulesThe
events
module is a Node.js built-in module. Importing it with thenode:
protocol explicitly indicates that it's a core module.- import { EventEmitter } from 'events'; + import { EventEmitter } from 'node:events';🧰 Tools
🪛 Biome (1.9.4)
[error] 11-11: A Node.js builtin module should be imported with the node: protocol.
Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.(lint/style/useNodejsImportProtocol)
33-33
: Verify proxy configuration reliabilityThe proxy configuration is dynamically fetched for each socket creation. This could potentially cause connection issues if the proxy service is unreliable.
Consider implementing a fallback mechanism or caching the proxy configuration:
- agent: new ProxyAgent(`http://${await proxy()}`), + const proxyUrl = await proxy(); + agent: proxyUrl ? new ProxyAgent(`http://${proxyUrl}`) : undefined,bot/antidelete.js (2)
5-11
: Well-structured guard clauses!The early return conditions are clear and effectively prevent unnecessary processing.
13-20
: 🧹 Nitpick (assertive)Optimize variable declarations.
The variables
client
andstore
are intermediary and could be removed. Consider destructuring directly:- const client = msg.client; - const messageId = msg?.message?.protocolMessage?.key.id; - const store = await client.loadMessage(messageId); - const sender = store.message.sender; - const deleted = msg?.sender; - const time = formatTime(Date.now()); - const message = store.message.message; - const chat = msg.isGroup ? msg.from : msg.user; + const messageId = msg?.message?.protocolMessage?.key.id; + const store = await msg.client.loadMessage(messageId); + const { sender, message: { message } } = store; + const deleted = msg?.sender; + const time = formatTime(Date.now()); + const chat = msg.isGroup ? msg.from : msg.user;Likely invalid or redundant comment.
lib/plugins.js (1)
6-12
: Clean command setup implementation!The command pattern and property initialization is well-structured.
lib/message.js (3)
10-14
: Well-structured sender determination logic!The inline ternary operations for sender determination maintain the codebase's design pattern.
36-41
: 🛠️ Refactor suggestionAdd error handling for group metadata fetch.
The group metadata fetch could fail if the group doesn't exist or if there are network issues. Consider adding a try-catch block:
if (isGroup) { + try { const metadata = await conn.groupMetadata(remoteJid); const participant = messages.key.participant; msg.isAdmin = !!metadata.participants.find((p) => p.id === participant)?.admin || false; msg.isBotAdmin = !!metadata.participants.find((p) => p.id === owner)?.admin || false; + } catch (error) { + console.error('Failed to fetch group metadata:', error); + msg.isAdmin = false; + msg.isBotAdmin = false; + } }Likely invalid or redundant comment.
143-143
: 🧹 Nitpick (assertive)Improve command name extraction reliability.
The current regex pattern split might be fragile. Consider adding a fallback for command name extraction:
- const name = cmd.pattern.toString().split(/\W+/)[1] || 'UNKNOWN CMD'; + const name = extractCommandName(cmd.pattern); + +function extractCommandName(pattern) { + try { + const matches = pattern.toString().match(/\w+/g); + return matches?.[1] || 'UNKNOWN CMD'; + } catch { + return 'UNKNOWN CMD'; + } +}Likely invalid or redundant comment.
const { autoRead, autoStatusRead, autolikestatus } = await getConfig(); | ||
|
||
for (const message of messages) { | ||
const msg = await serialize(JSON.parse(JSON.stringify(message, null, 2)), conn); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Optimize message serialization performance
The current implementation uses JSON.parse(JSON.stringify())
for deep cloning, which can be inefficient for large messages.
Consider using the imported deepClone
utility instead:
- const msg = await serialize(JSON.parse(JSON.stringify(message, null, 2)), conn);
+ const msg = await serialize(deepClone(message), conn);
Committable suggestion skipped: line range outside the PR's diff.
} | ||
} | ||
}; | ||
import { getAntiDelete } from '#sql'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Update import alias to reflect JSON storage.
The import alias #sql
is misleading since the project has transitioned from SQL to JSON storage. Consider updating the alias to better reflect its current implementation (e.g., #config
or #storage
).
const groupInfo = msg.isGroup | ||
? `*ɢʀᴏᴜᴘ:* ${(await client.groupMetadata(msg.from)).subject}\n` | ||
: ''; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for group metadata fetch.
The group metadata fetch could fail if the group doesn't exist or if there are network issues. Consider adding a try-catch block:
- const groupInfo = msg.isGroup
- ? `*ɢʀᴏᴜᴘ:* ${(await client.groupMetadata(msg.from)).subject}\n`
- : '';
+ let groupInfo = '';
+ if (msg.isGroup) {
+ try {
+ const metadata = await client.groupMetadata(msg.from);
+ groupInfo = `*ɢʀᴏᴜᴘ:* ${metadata.subject}\n`;
+ } catch (error) {
+ console.error('Failed to fetch group metadata:', error);
+ }
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const groupInfo = msg.isGroup | |
? `*ɢʀᴏᴜᴘ:* ${(await client.groupMetadata(msg.from)).subject}\n` | |
: ''; | |
let groupInfo = ''; | |
if (msg.isGroup) { | |
try { | |
const metadata = await client.groupMetadata(msg.from); | |
groupInfo = `*ɢʀᴏᴜᴘ:* ${metadata.subject}\n`; | |
} catch (error) { | |
console.error('Failed to fetch group metadata:', error); | |
} | |
} |
Fix all most all things
Summary by CodeRabbit
Release Notes
Code Quality and Maintenance
New Features
Performance and Stability
Documentation
This release focuses on improving code quality, adding utility features, and simplifying the project's data management approach.