first commit

This commit is contained in:
synt-xerror
2026-04-14 21:15:05 -03:00
commit eecef0be88
44 changed files with 1372 additions and 0 deletions

109
video/index.js Normal file
View File

@@ -0,0 +1,109 @@
/**
* plugins/video/index.js
*
* Downloads video via yt-dlp and sends to chat.
* All processing (download + send + cleanup) is here.
*/
import { spawn } from "child_process";
import fs from "fs";
import path from "path";
import os from "os";
import { enqueue } from "../../download/queue.js";
import { CMD_PREFIX } from "../../config.js";
import { createPluginI18n } from "../../utils/pluginI18n.js";
const { t } = createPluginI18n(import.meta.url);
fs.mkdirSync("logs", { recursive: true });
const logStream = fs.createWriteStream("logs/video-error.log", { flags: "a" });
logStream.on("error", err => console.error("[logStream]", err));
const DOWNLOADS_DIR = path.resolve("downloads");
const YT_DLP = os.platform() === "win32" ? ".\\bin\\yt-dlp.exe" : "./bin/yt-dlp";
const ARGS_BASE = [
"--extractor-args", "youtube:player_client=android",
"--print", "after_move:filepath",
"--cookies", "cookies.txt",
"--add-header", "User-Agent:Mozilla/5.0",
"--add-header", "Referer:https://www.youtube.com/",
"--retries", "4",
"--fragment-retries", "5",
"--socket-timeout", "15",
"--sleep-interval", "1",
"--max-sleep-interval", "4",
"--no-playlist",
"-f", "bv+ba/best",
];
function downloadVideo(url, id) {
return new Promise((resolve, reject) => {
// Isolated folder just for this download
const tmpDir = path.join(DOWNLOADS_DIR, id);
fs.mkdirSync(tmpDir, { recursive: true });
const output = path.join(tmpDir, "%(title).80s.%(ext)s");
const proc = spawn(YT_DLP, [...ARGS_BASE, "--output", output, url]);
let stdout = "";
proc.on("error", err => reject(new Error(
err.code === "EACCES" ? t("error.noPermission")
: err.code === "ENOENT" ? t("error.notFound")
: `${t("error.startError")} ${err.message}`
)));
proc.stdout.on("data", d => { stdout += d.toString(); });
proc.stderr.on("data", d => logStream.write(d));
proc.on("close", code => {
if (code !== 0) {
fs.rmSync(tmpDir, { recursive: true, force: true });
return reject(new Error(t("error.downloadFailed")));
}
// Try stdout path first
let filePath = stdout.trim().split("\n").filter(Boolean).at(-1);
// Fallback: get the single file inside the isolated folder
if (!filePath || !fs.existsSync(filePath)) {
const files = fs.readdirSync(tmpDir).filter(f => !f.endsWith(".part"));
filePath = files.length === 1 ? path.join(tmpDir, files[0]) : null;
}
if (!filePath) {
fs.rmSync(tmpDir, { recursive: true, force: true });
return reject(new Error(t("error.fileNotFound")));
}
resolve({ filePath, tmpDir });
});
});
}
export default async function ({ msg, api }) {
if (!msg.is(CMD_PREFIX + "video")) return;
const url = msg.args[1];
if (!url) {
await msg.reply(`${t("noUrl")} \`${CMD_PREFIX}video https://youtube.com/...\``);
return;
}
await msg.reply(t("downloading"));
const id = `video-${Date.now()}`;
enqueue(
async () => {
const { filePath, tmpDir } = await downloadVideo(url, id);
await api.sendVideo(filePath);
fs.rmSync(tmpDir, { recursive: true, force: true });
api.log.info(`${CMD_PREFIX}video completed → ${url}`);
},
async () => {
await msg.reply(t("error.generic"));
}
);
}

12
video/locale/en.json Normal file
View File

@@ -0,0 +1,12 @@
{
"noUrl": "Please provide a URL.",
"downloading": "Downloading video...",
"error": {
"noPermission": "yt-dlp: permission denied",
"notFound": "yt-dlp: not found",
"startError": "Failed to start download:",
"downloadFailed": "Download failed. Check the URL.",
"fileNotFound": "Downloaded file not found.",
"generic": "Failed to download video. Try again later."
}
}

12
video/locale/es.json Normal file
View File

@@ -0,0 +1,12 @@
{
"noUrl": "Por favor, proporciona una URL.",
"downloading": "Descargando video...",
"error": {
"noPermission": "yt-dlp: permiso denegado",
"notFound": "yt-dlp: no encontrado",
"startError": "Error al iniciar descarga:",
"downloadFailed": "Descarga fallida. Verifica la URL.",
"fileNotFound": "Archivo descargado no encontrado.",
"generic": "Error al descargar video. Intenta de nuevo más tarde."
}
}

12
video/locale/pt.json Normal file
View File

@@ -0,0 +1,12 @@
{
"noUrl": "Por favor, forneça uma URL.",
"downloading": "Baixando vídeo...",
"error": {
"noPermission": "yt-dlp: permissão negada",
"notFound": "yt-dlp: não encontrado",
"startError": "Falha ao iniciar download:",
"downloadFailed": "Download falhou. Verifique a URL.",
"fileNotFound": "Arquivo baixado não encontrado.",
"generic": "Falha ao baixar vídeo. Tente novamente mais tarde."
}
}

7
video/manyplug.json Normal file
View File

@@ -0,0 +1,7 @@
{
"name": "video",
"version": "1.0.0",
"category": "media",
"service": false,
"dependencies": {}
}