Skip to content

Commit fb4a1a6

Browse files
committed
feat: add fbdl command
1 parent 73c2975 commit fb4a1a6

5 files changed

Lines changed: 80 additions & 2 deletions

File tree

package-lock.json

Lines changed: 10 additions & 0 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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"ai": "^5.0.0-canary.24",
3030
"axios": "^1.10.0",
3131
"dotenv": "^17.2.0",
32+
"fb-downloader-scrapper": "^3.0.1",
3233
"google-tts-api": "^2.0.2",
3334
"groq-sdk": "^0.27.0",
3435
"npmlog": "^7.0.1",

src/commands/fbdl.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Message, MessageMedia } from "whatsapp-web.js";
2+
import { getFbVideoInfo } from "fb-downloader-scrapper";
3+
import log from "../components/utils/log";
4+
import axios from "axios";
5+
import fs from "fs";
6+
7+
export const info = {
8+
command: "fbdl",
9+
description: "Download Facebook videos.",
10+
usage: "fbdl <facebook_url>",
11+
example: "fbdl https://www.facebook.com/watch?v=1234567890",
12+
role: "user",
13+
cooldown: 5000,
14+
};
15+
16+
export default async function (msg: Message) {
17+
const query = msg.body.replace(/^fbdl\b\s*/i, "").trim();
18+
if (query.length === 0) {
19+
await msg.reply("Please provide a facebook url.");
20+
return;
21+
}
22+
23+
const facebookUrlRegex =
24+
/^(https?:\/\/)?(www\.)?(facebook\.com|fb\.watch)\/[^\s]+$/i;
25+
if (!facebookUrlRegex.test(query)) {
26+
await msg.reply("Please provide a valid Facebook link.");
27+
return;
28+
}
29+
30+
getFbVideoInfo(query)
31+
.then(async (result) => {
32+
if (!result.url)
33+
return await msg.reply("No video found at the provided URL.");
34+
35+
await axios
36+
.get(result.hd, { responseType: "arraybuffer" })
37+
.then(async (response) => {
38+
const tempDir = "./.temp";
39+
await fs.mkdirSync(tempDir, { recursive: true });
40+
41+
const tempPath = `${tempDir}/fbdl_${Date.now()}.mp4`;
42+
await fs.writeFileSync(tempPath, response.data);
43+
44+
const audioBuffer = fs.readFileSync(tempPath);
45+
const media = new MessageMedia(
46+
"audio/mpeg",
47+
audioBuffer.toString("base64"),
48+
`${result.title}.mp4`
49+
);
50+
51+
await msg.reply(media, msg.from);
52+
await fs.promises.unlink(tempPath);
53+
})
54+
.catch(async (error) => {
55+
log.error("fbdl", `Error downloading video: ${error.message}`);
56+
await msg.reply("Error downloading video. Please try again later.");
57+
});
58+
})
59+
.catch(async (err) => {
60+
log.error("fbdl", `Error fetching video info: ${err.message}`);
61+
await msg.reply("Error fetching video info. Please try again later.");
62+
});
63+
}

src/commands/reload.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ export default async function (msg: Message) {
5050
delete require.cache[require.resolve(filePath)];
5151
const commandModule = require(filePath);
5252

53-
if (typeof commandModule.default === "function") {
53+
if (
54+
typeof commandModule.default === "function" &&
55+
commandModule.info &&
56+
commandModule.info.command
57+
) {
5458
commands[commandModule.info.command] = {
5559
command: commandModule.info.command,
5660
description: commandModule.info.description || "No description",

src/components/utils/rateLimiter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const rateLimitMap: Map<string, { timestamps: number[]; notified: boolean }> = new Map();
22
const LIMIT = 3;
3-
const WINDOW_MS = 600000;
3+
const WINDOW_MS = 60000;
44

55
/**
66
* Returns:

0 commit comments

Comments
 (0)