Merge pull request 'video uploads to the server and returns a link to the user. and a fix on manager script, that now it update the registry with the content of manyplug, instead of just the version' (#1) from feat/video-server_and-manager-script into master

Reviewed-on: synt-xerror/manyplug-repo#1
This commit was merged in pull request #1.
This commit is contained in:
2026-04-21 10:28:05 -03:00
4 changed files with 67 additions and 21 deletions

View File

@@ -50,14 +50,14 @@ for (const entry of entries) {
version: manifest.version version: manifest.version
}); });
registry.plugins[pluginName] = manifest; registry.plugins[pluginName] = manifest;
} else if (existing.version !== manifest.version) { } else if (JSON.stringify(existing, Object.keys(existing).sort()) !== JSON.stringify(manifest, Object.keys(manifest).sort())) {
const oldVersion = existing.version; const oldVersion = existing.version;
existing.version = manifest.version; registry.plugins[pluginName] = manifest;
update.push({ update.push({
name: pluginName, name: pluginName,
oldVersion: oldVersion, oldVersion: oldVersion,
newVersion: existing.version newVersion: manifest.version
}); });
} }
} catch (err) { } catch (err) {

View File

@@ -1,16 +1,17 @@
{ {
"lastUpdated": "2026-04-21T05:56:16.900Z", "lastUpdated": "2026-04-21T13:23:13.743Z",
"plugins": { "plugins": {
"a": { "a": {
"name": "a", "name": "a",
"author": "freakk.dev", "author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)",
"version": "1.0.0", "version": "1.0.0",
"category": "humor", "category": "fun",
"service": false, "service": false,
"dependencies": {} "dependencies": {}
}, },
"adivinhacao": { "adivinhacao": {
"name": "adivinhacao", "name": "adivinhacao",
"author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)",
"version": "1.0.0", "version": "1.0.0",
"category": "games", "category": "games",
"service": false, "service": false,
@@ -18,6 +19,7 @@
}, },
"audio": { "audio": {
"name": "audio", "name": "audio",
"author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)",
"version": "1.0.0", "version": "1.0.0",
"category": "media", "category": "media",
"service": false, "service": false,
@@ -25,6 +27,7 @@
}, },
"figurinha": { "figurinha": {
"name": "figurinha", "name": "figurinha",
"author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)",
"version": "1.0.0", "version": "1.0.0",
"category": "media", "category": "media",
"service": false, "service": false,
@@ -34,6 +37,7 @@
}, },
"forca": { "forca": {
"name": "forca", "name": "forca",
"author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)",
"version": "1.0.0", "version": "1.0.0",
"category": "games", "category": "games",
"service": false, "service": false,
@@ -41,6 +45,7 @@
}, },
"many": { "many": {
"name": "many", "name": "many",
"author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)",
"version": "1.0.0", "version": "1.0.0",
"category": "utility", "category": "utility",
"service": false, "service": false,
@@ -48,10 +53,20 @@
}, },
"video": { "video": {
"name": "video", "name": "video",
"version": "1.0.0", "author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)",
"version": "2.0.0",
"category": "media", "category": "media",
"service": false, "service": false,
"dependencies": {} "externalDependencies": {
"yt-dlp": {
"command": "yt-dlp",
"optional": false
},
"ffmpeg": {
"command": "ffmpeg",
"optional": false
}
}
}, },
"obrigado": { "obrigado": {
"name": "obrigado", "name": "obrigado",

View File

@@ -1,14 +1,13 @@
/** /**
* plugins/video/index.js * plugins/video/index.js
* *
* Downloads video via yt-dlp and sends to chat. * Downloads video via yt-dlp and uploads to server.
* All processing (download + send + cleanup) is here. * All processing (download + upload + cleanup) is here.
*/ */
import { spawn } from "child_process"; import { spawn } from "child_process";
import fs from "fs"; import fs from "fs";
import path from "path"; import path from "path";
import os from "os";
import { enqueue } from "../../download/queue.js"; import { enqueue } from "../../download/queue.js";
import { CMD_PREFIX } from "../../config.js"; import { CMD_PREFIX } from "../../config.js";
import { createPluginI18n } from "../../utils/pluginI18n.js"; import { createPluginI18n } from "../../utils/pluginI18n.js";
@@ -20,7 +19,8 @@ const logStream = fs.createWriteStream("logs/video-error.log", { flags: "a" });
logStream.on("error", err => console.error("[logStream]", err)); logStream.on("error", err => console.error("[logStream]", err));
const DOWNLOADS_DIR = path.resolve("downloads"); const DOWNLOADS_DIR = path.resolve("downloads");
const YT_DLP = os.platform() === "win32" ? ".\\bin\\yt-dlp.exe" : "./bin/yt-dlp"; const YT_DLP = "yt-dlp";
const UPLOAD_URL = "http://maneos.net/upload";
const ARGS_BASE = [ const ARGS_BASE = [
"--extractor-args", "youtube:player_client=android", "--extractor-args", "youtube:player_client=android",
@@ -39,7 +39,6 @@ const ARGS_BASE = [
function downloadVideo(url, id) { function downloadVideo(url, id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// Isolated folder just for this download
const tmpDir = path.join(DOWNLOADS_DIR, id); const tmpDir = path.join(DOWNLOADS_DIR, id);
fs.mkdirSync(tmpDir, { recursive: true }); fs.mkdirSync(tmpDir, { recursive: true });
@@ -62,10 +61,8 @@ function downloadVideo(url, id) {
return reject(new Error(t("error.downloadFailed"))); return reject(new Error(t("error.downloadFailed")));
} }
// Try stdout path first
let filePath = stdout.trim().split("\n").filter(Boolean).at(-1); let filePath = stdout.trim().split("\n").filter(Boolean).at(-1);
// Fallback: get the single file inside the isolated folder
if (!filePath || !fs.existsSync(filePath)) { if (!filePath || !fs.existsSync(filePath)) {
const files = fs.readdirSync(tmpDir).filter(f => !f.endsWith(".part")); const files = fs.readdirSync(tmpDir).filter(f => !f.endsWith(".part"));
filePath = files.length === 1 ? path.join(tmpDir, files[0]) : null; filePath = files.length === 1 ? path.join(tmpDir, files[0]) : null;
@@ -81,6 +78,30 @@ function downloadVideo(url, id) {
}); });
} }
async function uploadToServer(filePath) {
const fileBuffer = fs.readFileSync(filePath);
const fileName = path.basename(filePath);
const formData = new FormData();
formData.append("file", new Blob([fileBuffer]), fileName);
const response = await fetch(UPLOAD_URL, {
method: "POST",
body: formData,
});
if (!response.ok) {
throw new Error(`Upload failed: ${response.status} ${response.statusText}`);
}
const result = await response.json();
if (!result.url) {
throw new Error("Server response missing url");
}
return result.url.startsWith("http") ? result.url : `http://maneos.net${result.url}`;
}
export default async function ({ msg, api }) { export default async function ({ msg, api }) {
if (!msg.is(CMD_PREFIX + "video")) return; if (!msg.is(CMD_PREFIX + "video")) return;
@@ -98,7 +119,8 @@ export default async function ({ msg, api }) {
enqueue( enqueue(
async () => { async () => {
const { filePath, tmpDir } = await downloadVideo(url, id); const { filePath, tmpDir } = await downloadVideo(url, id);
await api.sendVideo(filePath); const downloadUrl = await uploadToServer(filePath);
await msg.reply(downloadUrl);
fs.rmSync(tmpDir, { recursive: true, force: true }); fs.rmSync(tmpDir, { recursive: true, force: true });
api.log.info(`${CMD_PREFIX}video completed → ${url}`); api.log.info(`${CMD_PREFIX}video completed → ${url}`);
}, },
@@ -106,4 +128,4 @@ export default async function ({ msg, api }) {
await msg.reply(t("error.generic")); await msg.reply(t("error.generic"));
} }
); );
} }

View File

@@ -1,8 +1,17 @@
{ {
"name": "video", "name": "video",
"author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)", "author": "SyntaxError <dev@maneos.net> (https://git.maneos.net)",
"version": "1.0.0", "version": "2.0.0",
"category": "media", "category": "media",
"service": false, "service": false,
"dependencies": {} "externalDependencies": {
} "yt-dlp": {
"command": "yt-dlp",
"optional": false
},
"ffmpeg": {
"command": "ffmpeg",
"optional": false
}
}
}