goat
command
autolink
Auto-download & send videos silently (no messages)
0
views
0
likes
0
installs
raw source
const fs = require("fs");
const path = require("path");
const os = require("os");
const axios = require("axios");
const API_BASE = "https://yt-dl-new-vshv.onrender.com";
module.exports = {
config: {
name: "autolink",
version: "2.0",
author: "EryXenX",
countDown: 5,
role: 0,
shortDescription: "Auto-download & send videos silently (no messages)",
category: "media",
},
onStart: async function () {},
onChat: async function ({ api, event }) {
const threadID = event.threadID;
const messageID = event.messageID;
const message = event.body || "";
const linkMatches = message.match(/(https?:\/\/[^\s]+)/g);
if (!linkMatches || linkMatches.length === 0) return;
const uniqueLinks = [...new Set(linkMatches)];
const supportedLinks = uniqueLinks.filter(detectPlatform);
if (supportedLinks.length === 0) return;
api.setMessageReaction("⏳", messageID, () => {}, true);
let successCount = 0;
let failCount = 0;
for (const url of supportedLinks) {
const platform = detectPlatform(url);
const filePath = path.join(os.tmpdir(), `autolink_${Date.now()}_${Math.floor(Math.random() * 1e6)}.mp4`);
try {
const { data } = await axios.get(`${API_BASE}/api/download`, {
params: { url },
timeout: 60000
});
if (!data || !data.status) {
console.error(`[autolink] API returned failure for ${platform}: ${JSON.stringify(data)}`);
throw new Error("api_failure");
}
const candidates = collectUrlCandidates(data.result);
if (candidates.length === 0) {
console.error(`[autolink] No video URL candidates for ${platform}: ${JSON.stringify(data.result)}`);
throw new Error("extract_failure");
}
let downloaded = false;
let lastErr = null;
for (const videoUrl of candidates) {
try {
const response = await axios.get(videoUrl, {
responseType: "stream",
timeout: 120000,
headers: {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
"Referer": getReferer(platform)
}
});
await new Promise((resolve, reject) => {
const writer = fs.createWriteStream(filePath);
response.data.pipe(writer);
writer.on("finish", resolve);
writer.on("error", reject);
});
const stats = fs.statSync(filePath);
if (stats.size < 50 * 1024) {
fs.unlinkSync(filePath);
console.error(`[autolink] Candidate too small for ${platform} (${videoUrl}): ${stats.size} bytes`);
continue;
}
downloaded = true;
break;
} catch (err) {
lastErr = err;
console.error(`[autolink] Candidate failed for ${platform} (${videoUrl}): ${err.message}`);
if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
}
}
if (!downloaded) {
throw lastErr || new Error("all_candidates_failed");
}
const stats = fs.statSync(filePath);
const fileSizeInMB = stats.size / (1024 * 1024);
if (fileSizeInMB > 25) {
fs.unlinkSync(filePath);
failCount++;
continue;
}
const title = extractTitle(data.result);
await api.sendMessage(
{
body:
`📥 ᴠɪᴅᴇᴏ ᴅᴏᴡɴʟᴏᴀᴅᴇᴅ
━━━━━━━━━━━━━━━
🎬 ᴛɪᴛʟᴇ: ${title || "Video File"}
📦 sɪᴢᴇ: ${fileSizeInMB.toFixed(2)} MB
━━━━━━━━━━━━━━━`,
attachment: fs.createReadStream(filePath)
},
threadID,
() => fs.unlinkSync(filePath)
);
successCount++;
} catch (err) {
console.error(`[autolink] Failed for ${platform} (${url}): ${err.message}`);
if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
failCount++;
}
}
const finalReaction =
successCount > 0 && failCount === 0 ? "✅" :
successCount > 0 ? "⚠️" : "❌";
api.setMessageReaction(finalReaction, messageID, () => {}, true);
}
};
function getReferer(platform) {
if (platform === "tiktok") return "https://www.tiktok.com/";
if (platform === "instagram") return "https://www.instagram.com/";
if (platform === "facebook") return "https://www.facebook.com/";
if (platform === "youtube") return "https://www.youtube.com/";
return "";
}
function detectPlatform(url) {
if (/instagram\.com/i.test(url)) return "instagram";
if (/tiktok\.com/i.test(url)) return "tiktok";
if (/facebook\.com|fb\.watch/i.test(url)) return "facebook";
if (/youtube\.com|youtu\.be/i.test(url)) return "youtube";
return null;
}
const EXCLUDE_KEY_RE = /thumbnail|thumb|cover|music|audio|avatar|image|photo/i;
const HIGH_PRIORITY_KEY_RE = /^(hd|nowm|no_watermark|normal_video|video_hd|download|downloadurl|play|playaddr)$/i;
const MID_PRIORITY_KEY_RE = /^(video|sd|url|link)$/i;
function collectUrlCandidates(result) {
const found = [];
function visit(node, key) {
if (node === null || node === undefined) return;
if (typeof node === "string") {
if (/^https?:\/\//.test(node) && !(key && EXCLUDE_KEY_RE.test(key))) {
let rank = 2;
if (key && HIGH_PRIORITY_KEY_RE.test(key)) rank = 0;
else if (key && MID_PRIORITY_KEY_RE.test(key)) rank = 1;
found.push({ url: node, rank });
}
return;
}
if (Array.isArray(node)) {
for (const item of node) visit(item, key);
return;
}
if (typeof node === "object") {
for (const childKey of Object.keys(node)) {
if (EXCLUDE_KEY_RE.test(childKey)) continue;
visit(node[childKey], childKey);
}
}
}
visit(result, null);
found.sort((a, b) => a.rank - b.rank);
const seen = new Set();
const unique = [];
for (const item of found) {
if (!seen.has(item.url)) {
seen.add(item.url);
unique.push(item.url);
}
}
return unique;
}
function extractTitle(result) {
function walk(node) {
if (!node) return null;
if (Array.isArray(node)) {
for (const item of node) {
const found = walk(item);
if (found) return found;
}
return null;
}
if (typeof node === "object") {
if (typeof node.title === "string") return node.title;
if (typeof node.caption === "string") return node.caption;
for (const key of Object.keys(node)) {
const found = walk(node[key]);
if (found) return found;
}
}
return null;
}
return walk(result);
}