Skip to content

Commit e81054f

Browse files
committed
feat: bug fixes and improvements
1 parent eaffa14 commit e81054f

10 files changed

Lines changed: 80 additions & 75 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Canis supports multiple AI providers out of the box:
3232
- Redis/Valkey
3333
- WhatsApp Account
3434
- Chrome browser
35+
- FFMPEG
3536

3637
## Getting started
3738

package-lock.json

Lines changed: 9 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
"redis": "^5.6.0",
4444
"systeminformation": "^5.27.7",
4545
"whatsapp-web.js": "^1.31.0",
46-
"youtubei.js": "^14.0.0"
46+
"youtubei.js": "^15.0.0"
4747
},
4848
"devDependencies": {
4949
"@types/dotenv": "^6.1.1",

src/commands/fork.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Message } from "../../types/message"
1+
import { Message } from "../../types/message";
22

33
export const info = {
44
command: "fork",
@@ -12,7 +12,18 @@ export const info = {
1212
export default async function (msg: Message) {
1313
if (!/^fork$/i.test(msg.body)) return;
1414

15-
await msg.reply(
16-
"Fork this bot at https://github.com/mrepol742/project-canis or contribute to the project by submitting issues or pull requests."
17-
);
15+
const text = `
16+
\`Canis for WhatsApp\`
17+
mrepol742/project-canis
18+
19+
\`Canis for Telegram\`
20+
mrepol742/project-canis-ts
21+
22+
This bot is not affiliated, endorsed, partner, or connected to Meta.
23+
Use it at your own RISK.
24+
25+
Type \`Legal\` for more information.
26+
`;
27+
28+
await msg.reply(text);
1829
}

src/commands/legal.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ export default async function (msg: Message) {
2525
\`dcma\`
2626
Display the DCMA policy of the bot.
2727
28+
\`license\`
29+
Display the License of the bot.
30+
2831
\`contact\`
2932
mrepol742@gmail.com
3033
`;

src/commands/license.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Message } from "../../types/message";
2+
import log from "../components/utils/log";
3+
4+
export const info = {
5+
command: "license",
6+
description: "Display the License of the bot.",
7+
usage: "license",
8+
example: "license",
9+
role: "legal",
10+
cooldown: 5000,
11+
};
12+
13+
export default async function (msg: Message) {
14+
if (!/^license/i.test(msg.body)) return;
15+
16+
const text = `
17+
\`License\`
18+
MIT License with Commons Clause and Commercial Licensing
19+
20+
Copyright (c) 2025 Melvin Jones Repol
21+
22+
Permission is hereby granted, free of charge, to use, copy, modify, and distribute the software under the MIT License, with the following additional condition:
23+
24+
1. **Commercial Use Restriction**: You may not use the software for commercial purposes unless you obtain a commercial license. Commercial use includes, but is not limited to, the use of the software as part of any service offered for a fee, or any use that generates revenue either directly or indirectly.
25+
26+
2. **Commercial Licensing**: To use this software for commercial purposes, you must obtain a commercial license by paying the required fee. For licensing inquiries, pricing, and terms, please contact mrepol742@gmail.com.
27+
28+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29+
`;
30+
31+
await msg.reply(text);
32+
}

src/commands/play.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { MessageMedia } from "whatsapp-web.js";
2-
import { Message } from "../../types/message"
2+
import { Message } from "../../types/message";
33
import fs from "fs";
4+
import path from "path";
45
import { exec } from "child_process";
56
// fallback import for compatibility
67
// youtubei.js currently does not support ESM directly
@@ -40,7 +41,7 @@ export default async function play(msg: Message) {
4041
// Only allow audios shorter than 10 minutes (600 seconds)
4142
if (audio.length && audio.length.seconds > 600) {
4243
await msg.reply(
43-
"Sorry, only videos shorter than 10 minutes can be downloaded."
44+
"Sorry, only videos shorter than 10 minutes can be downloaded.",
4445
);
4546
return;
4647
}
@@ -59,31 +60,29 @@ export default async function play(msg: Message) {
5960
}
6061

6162
const tempDir = "./.temp";
62-
await fs.mkdirSync(tempDir, { recursive: true });
63-
64-
const tempPath = `${tempDir}/${audio.id}.mp4`;
63+
await fs.promises.mkdir(tempDir, { recursive: true });
64+
const tempPath = path.join(tempDir, `${audio.id}.mp4`);
6565
let writeStream = fs.createWriteStream(tempPath);
6666

6767
for await (const chunk of Utils.streamToIterable(stream)) {
6868
writeStream.write(chunk);
6969
}
7070

7171
await execPromise(
72-
`ffmpeg -y -i "${tempPath}" -vn -ar 44100 -ac 2 -b:a 192k "${tempPath}.mp3"`
72+
`ffmpeg -y -i "${tempPath}" -vn -ar 44100 -ac 2 -b:a 192k "${tempPath}.mp3"`,
7373
);
7474

7575
const audioBuffer = fs.readFileSync(tempPath + ".mp3");
7676
const media = new MessageMedia(
7777
"audio/mpeg",
7878
audioBuffer.toString("base64"),
79-
`${audio.title}.mp3`
79+
`${audio.title}.mp3`,
8080
);
8181

8282
await msg.reply(media, msg.from, {
8383
caption: audio.title,
8484
sendAudioAsVoice: true,
8585
});
8686

87-
await fs.promises.unlink(tempPath);
88-
await fs.promises.unlink(tempPath + ".mp3");
87+
Promise.all([fs.promises.unlink(tempPath), fs.promises.unlink(tempPath)]);
8988
}

src/commands/reload.ts

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { Message } from "../../types/message"
1+
import { Message } from "../../types/message";
22
import axios from "axios";
33
import log from "../components/utils/log";
44
import fs from "fs";
55
import path from "path";
6-
import { commands } from "../index";
6+
import { commands, commandDirs } from "../index";
77
import Loader from "../components/utils/cmd/loader";
88

99
export const info = {
@@ -24,23 +24,13 @@ export default async function (msg: Message) {
2424
return;
2525
}
2626

27-
const basePath = path.join(__dirname, "..", "commands");
28-
29-
const commandDirs = [
30-
basePath,
31-
path.join(basePath, "private"),
32-
];
33-
3427
const possibleExtensions = [".ts", ".js"];
3528
let found = false;
3629

3730
for (const ext of possibleExtensions) {
3831
for (const dir of commandDirs) {
39-
const filePath = path.join(dir, `${query}${ext}`);
40-
if (fs.existsSync(filePath)) {
41-
Loader(`${query}${ext}`, dir);
42-
found = true;
43-
}
32+
Loader(`${query}${ext}`, dir);
33+
found = true;
4434
}
4535
}
4636

@@ -49,14 +39,14 @@ export default async function (msg: Message) {
4939
`
5040
\`Failed to load\`
5141
${query}
52-
`
42+
`,
5343
);
5444
if (found)
5545
await msg.reply(
5646
`
5747
\`Successfully reloaded\`
5848
${query}
59-
`
49+
`,
6050
);
6151
return;
6252
}
@@ -65,18 +55,11 @@ export default async function (msg: Message) {
6555
let count = 0;
6656
const newCommands: string[] = [];
6757
const removeCommands: string[] = [];
68-
const basePath = path.join(__dirname, "..", "commands");
69-
70-
const commandDirs = [
71-
basePath,
72-
path.join(basePath, "private"),
73-
];
7458

7559
for (const dir of commandDirs) {
7660
const files = fs.readdirSync(dir);
7761
for (const file of files) {
7862
if (/\.js$|\.ts$/.test(file)) {
79-
const filePath = path.join(dir, file);
8063
const commandName = file.replace(/\.(js|ts)$/, "");
8164

8265
if (!commands[commandName]) {
@@ -85,7 +68,7 @@ export default async function (msg: Message) {
8568
removeCommands.push(commandName);
8669
}
8770

88-
await Loader(filePath, dir);
71+
await Loader(file, dir);
8972
count++;
9073
}
9174
}

src/commands/video.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,6 @@ export default async function (msg: Message) {
8282
await msg.reply(media, msg.from, {
8383
caption: `${video.title}`,
8484
});
85-
await fs.promises.unlink(tempPath);
86-
await fs.promises.unlink(tempPath + ".mp4");
85+
86+
Promise.all([fs.promises.unlink(tempPath), fs.promises.unlink(tempPath)]);
8787
}

src/commands/zsh.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default async function (msg: Message) {
2323
const execPromise = util.promisify(exec);
2424

2525
const { stdout, stderr } = await execPromise(query, {
26-
timeout: 10000,
26+
timeout: 60000,
2727
maxBuffer: 1024 * 1024,
2828
shell: process.env.SHELL || "/bin/zsh",
2929
});
@@ -32,13 +32,8 @@ export default async function (msg: Message) {
3232
response = response.slice(0, 4000) + "\n\n[Output truncated]";
3333
}
3434

35-
const text = `
36-
\`\`\`
37-
${response}
38-
\`\`\
39-
`;
4035
await Promise.all([
41-
msg.reply(text),
36+
msg.reply(response),
4237
logService(msg, query, response),
4338
log.warn("zsh", `Executed command: ${query}`),
4439
]);

0 commit comments

Comments
 (0)