Add thumb fix + configure empty preview image

This commit is contained in:
FullGreaM 2025-11-09 14:51:51 +03:00
parent 13d3607a54
commit a47c8bb83a
4 changed files with 74 additions and 52 deletions

View File

@ -420,7 +420,7 @@ class TgBot {
{ {
type: "photo", type: "photo",
//media: info.thumbnail, //media: info.thumbnail,
media: "https://placekitten.com/500/350", media: config.emptyImage,
caption: info.title, caption: info.title,
}, },
{ {

View File

@ -8,6 +8,7 @@ const config = {
session: process.env.API_SESSION, session: process.env.API_SESSION,
chatId: +process.env.CHAT_ID, chatId: +process.env.CHAT_ID,
}, },
emptyImage: process.env.EMPTY_IMAGE_URL ?? "https://placekitten.com/500/350",
}; };
config.whitelist = [].concat( config.whitelist = [].concat(
process.env.WHITELIST?.split(/\s*,\s*/g).map((x) => +x) ?? [], process.env.WHITELIST?.split(/\s*,\s*/g).map((x) => +x) ?? [],

View File

@ -3,59 +3,16 @@ const { Readable } = require("stream");
const EventEmitter = require("events"); const EventEmitter = require("events");
const mime = require("mime"); const mime = require("mime");
const path = require("path"); const path = require("path");
const http = require("http");
const https = require("https");
const { URL } = require("url"); const { URL } = require("url");
const fs = require("fs"); const fs = require("fs");
const FFMPEG = require("./ffmpeg"); const FFMPEG = require("./ffmpeg");
const config = require("./config");
const { downloadFile, verifyThumbUrl } = require("./utils");
const formatsCache = new Map(); const formatsCache = new Map();
const infoCache = new Map(); const infoCache = new Map();
const d = r => console.debug("DEBUG:", r) || r; const d = r => console.debug("DEBUG:", r) || r;
async function downloadFile(fileUrl) {
return new Promise((resolve, reject) => {
try {
const url = new URL(fileUrl);
const protocol = url.protocol === "https:" ? https : http;
const extMatch = path.extname(url.pathname).split("?")[0];
const extension = extMatch ? extMatch.replace(".", "") : "tmp";
const filename = `${Date.now()}.${extension}`;
const savePath = path.join(__dirname, "tmp", filename);
fs.mkdirSync(path.dirname(savePath), { recursive: true });
const file = fs.createWriteStream(savePath);
protocol.get(fileUrl, (response) => {
if (response.statusCode !== 200) {
return reject(
new Error(`Failed to get '${fileUrl}' (${response.statusCode})`)
);
}
response.pipe(file);
file.on("finish", () => {
file.close();
/*setTimeout(() => {
fs.rm(savePath, () => {});
}, 60000);*/
resolve(savePath);
});
}).on("error", (err) => {
fs.unlinkSync(savePath);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
class YtdlUpdater extends EventEmitter { class YtdlUpdater extends EventEmitter {
constructor () { constructor () {
super(); super();
@ -172,12 +129,19 @@ class DownloadVideo {
console.error("yt-dlp error:", err.toString()); console.error("yt-dlp error:", err.toString());
}); });
child.on("close", code => { child.on("close", async code => {
if (code !== 0) return reject(new Error("yt-dlp failed to get info")); if (code !== 0) return reject(new Error("yt-dlp failed to get info"));
try { try {
const info = JSON.parse(data); const info = JSON.parse(data);
const thumbnails =
(await Promise.all(info.thumbnails.map(async thumbnail => {
const verified = await verifyThumbUrl(thumbnail.url);
if (!verified) return null;
return thumbnail;
}))).filter(x => x !== null);
resolve({ resolve({
id: info.id, id: info.id,
title: info.title, title: info.title,
@ -185,10 +149,10 @@ class DownloadVideo {
uploader: info.uploader, uploader: info.uploader,
duration: info.duration, duration: info.duration,
thumbnail: thumbnail:
info.thumbnails?.[info.thumbnails.length - 1]?.url || (thumbnails?.[thumbnails.length - 1]?.url ||
info.thumbnail, info.thumbnail) || config.emptyImage,
url: info.webpage_url, url: info.webpage_url,
thumbnails: info.thumbnails thumbnails
}); });
} catch (e) { } catch (e) {
reject(e); reject(e);
@ -314,7 +278,6 @@ class DownloadVideo {
"-f", ...flags, "-f", ...flags,
"-o", !isPath ? "-" : isStream, this.url, "-o", !isPath ? "-" : isStream, this.url,
]; ];
d("yt-dlp " + params.join(" "));
const child = spawn("yt-dlp", params, { const child = spawn("yt-dlp", params, {
env: { env: {
...process.env, ...process.env,

58
src/utils.js Normal file
View File

@ -0,0 +1,58 @@
const http = require("http");
const https = require("https");
const path = require("path");
const fs = require("fs");
async function downloadFile (fileUrl) {
return new Promise((resolve, reject) => {
try {
const url = new URL(fileUrl);
const protocol = url.protocol === "https:" ? https : http;
const extMatch = path.extname(url.pathname).split("?")[0];
const extension = extMatch ? extMatch.replace(".", "") : "tmp";
const filename = `${Date.now()}.${extension}`;
const savePath = path.join(__dirname, "tmp", filename);
fs.mkdirSync(path.dirname(savePath), { recursive: true });
const file = fs.createWriteStream(savePath);
protocol.get(fileUrl, (response) => {
if (response.statusCode !== 200) {
return reject(
new Error(`Failed to get '${fileUrl}' (${response.statusCode})`)
);
}
response.pipe(file);
file.on("finish", () => {
file.close();
/*setTimeout(() => {
fs.rm(savePath, () => {});
}, 60000);*/
resolve(savePath);
});
}).on("error", (err) => {
fs.unlinkSync(savePath);
reject(err);
});
} catch (err) {
reject(err);
}
});
}
async function verifyThumbUrl (fileUrl) {
try {
if (/\.webp$/m.test(fileUrl)) return false;
await downloadFile(fileUrl);
return true;
} catch (_) {
return false;
}
}
module.exports = { downloadFile, verifyThumbUrl };