various fixes to get it working for myself

This commit is contained in:
eins
2026-01-23 08:44:46 +00:00
parent c198566474
commit a4f9c48e13
4 changed files with 122 additions and 88 deletions

15
debug/check_last_item.mjs Normal file
View File

@@ -0,0 +1,15 @@
import db from "../src/inc/sql.mjs";
(async () => {
try {
const item = (await db`select * from items order by id desc limit 1`)?.[0];
console.log("Last Item:", item);
if (item) {
const tags = await db`select * from tags_assign where item_id = ${item.id}`;
console.log("Tags:", tags);
}
} catch (err) {
console.error(err);
}
process.exit(0);
})();

View File

@@ -6,13 +6,14 @@ import { promises as fs } from "fs";
network: "console", network: "console",
message: _args.join(" "), message: _args.join(" "),
args: _args.slice(1), args: _args.slice(1),
channel: "console", channel: "#w0bm",
user: { user: {
prefix: "console!console@console", prefix: "console!console@console",
nick: "console", nick: "console",
username: "console", username: "console",
account: "console" account: "console"
}, },
raw: {},
reply: (...args) => console.log(args), reply: (...args) => console.log(args),
replyAction: (...args) => console.log(args), replyAction: (...args) => console.log(args),
replyNotice: (...args) => console.log(args) replyNotice: (...args) => console.log(args)
@@ -24,11 +25,14 @@ import { promises as fs } from "fs";
)).filter(t => t[0].call.test(_e.message)).map(t => ({ name: t[0].name, f: t[0].f })); )).filter(t => t[0].call.test(_e.message)).map(t => ({ name: t[0].name, f: t[0].f }));
try { try {
if(trigger.length === 0) if (trigger.length === 0)
return console.error("no matches"); return console.error("no matches");
console.log(`triggered > ${trigger[0].name} (${_e.message})`); for (const t of trigger) {
await trigger[0].f(_e); console.log(`triggered > ${t.name} (${_e.message})`);
} catch(err) { await t.f(_e);
}
} catch (err) {
console.error(err); console.error(err);
} }
process.exit(0);
})(); })();

3
init.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
npm i
npm start

View File

@@ -23,35 +23,35 @@ export default async bot => {
name: "parser", name: "parser",
call: regex.all, call: regex.all,
active: true, active: true,
f: e => { f: async e => {
const links = e.message.match(regex.all)?.filter(link => !link.includes(cfg.main.url.domain)) || []; const links = e.message.match(regex.all)?.filter(link => !link.includes(cfg.main.url.domain)) || [];
let repost; let repost;
if(e.media) if (e.media)
links.push(e.media); links.push(e.media);
if(links.length === 0) if (links.length === 0)
return false; return false;
if(e.message.match(/\!i(gnore)?\b/)) if (e.message.match(/\!i(gnore)?\b/))
return false; return false;
if(!e.channel.includes("w0bm") && (!e.message.match(/\!w(0bm)?\b/i) && (typeof e.raw.forward_from == 'undefined'))) if (!e.channel.includes("w0bm") && (!e.message.match(/\!w(0bm)?\b/i) && (typeof e.raw.forward_from == 'undefined')))
return false; return false;
if(e.type === 'tg' && // proto: tg if (e.type === 'tg' && // proto: tg
!e.message.match(/\!w(0bm)?\b/i) && // !w / !w0bm !e.message.match(/\!w(0bm)?\b/i) && // !w / !w0bm
!e.raw.forward_date && // is forwarded? !e.raw.forward_date && // is forwarded?
!mediagroupids.has(e.raw.media_group_id) // prepared mediagroup? !mediagroupids.has(e.raw.media_group_id) // prepared mediagroup?
) { ) {
return false; return false;
} }
else if(e.raw.media_group_id && e.message.match(/\!w(0bm)?\b/i)) { else if (e.raw.media_group_id && e.message.match(/\!w(0bm)?\b/i)) {
mediagroupids.add(e.raw.media_group_id); mediagroupids.add(e.raw.media_group_id);
} }
console.log(`parsing ${links.length} link${links.length > 1 ? "s" : ""}...`); console.log(`parsing ${links.length} link${links.length > 1 ? "s" : ""}...`);
links.forEach(async link => { for (const link of links) {
//if(regex.imgur.test(link)) //if(regex.imgur.test(link))
// return await e.reply(`fuck imgur... seriously`); // return await e.reply(`fuck imgur... seriously`);
@@ -63,7 +63,7 @@ export default async bot => {
// check repost (link) // check repost (link)
repost = await queue.checkrepostlink(link); repost = await queue.checkrepostlink(link);
if(repost) if (repost)
return await e.reply(`repost motherf0cker (link): ${cfg.main.url.full}/${repost}`); return await e.reply(`repost motherf0cker (link): ${cfg.main.url.full}/${repost}`);
// generate uuid // generate uuid
@@ -73,39 +73,41 @@ export default async bot => {
// read metadata // read metadata
let ext; let ext;
if(link.match(regex.instagram)) { const proxyArgs = cfg.main.socks ? `--proxy ${cfg.main.socks}` : '';
if (link.match(regex.instagram)) {
// is instagram // is instagram
try { try {
// @flummi -> is there a variable for the actual work directory so it doesn't have to be hardcoded? // @flummi -> is there a variable for the actual work directory so it doesn't have to be hardcoded?
const meta = JSON.parse((await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout); const meta = JSON.parse((await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext; ext = meta.ext;
} catch(err) { } catch (err) {
const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"]; const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"];
// this can be undefined for unsupported mime types, but will be caught in the general mime check below // this can be undefined for unsupported mime types, but will be caught in the general mime check below
ext = cfg.mimes[tmphead]; ext = cfg.mimes[tmphead];
} }
} }
else if(link.match(regex.imgur)) { else if (link.match(regex.imgur)) {
// imghure // imghure
ext = link.split('.').pop(); ext = link.split('.').pop();
} }
else if(link.match(regex.yt)) { else if (link.match(regex.yt)) {
//yt - fuck anti bot protection //yt - fuck anti bot protection
try { try {
const meta = JSON.parse((await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' -I 1 --skip-download --dump-json "${link}"`)).stdout); const meta = JSON.parse((await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' -I 1 --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext; ext = meta.ext;
} catch(err) { } catch (err) {
console.error("YT-DLP Error:", err);
const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"]; const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"];
// this can be undefined for unsupported mime types, but will be caught in the general mime check below // this can be undefined for unsupported mime types, but will be caught in the general mime check below
ext = cfg.mimes[tmphead]; ext = cfg.mimes[tmphead];
} }
} }
else if(link.match(regex.fourchan)) { else if (link.match(regex.fourchan)) {
//4chan - fuck cloudflare :) //4chan - fuck cloudflare :)
try { try {
const meta = JSON.parse((await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout); const meta = JSON.parse((await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext; ext = meta.ext;
} catch(err) { } catch (err) {
const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"]; const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"];
// this can be undefined for unsupported mime types, but will be caught in the general mime check below // this can be undefined for unsupported mime types, but will be caught in the general mime check below
ext = cfg.mimes[tmphead]; ext = cfg.mimes[tmphead];
@@ -117,14 +119,15 @@ export default async bot => {
try { try {
const meta = JSON.parse((await queue.exec(`yt-dlp -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout); const meta = JSON.parse((await queue.exec(`yt-dlp -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' --skip-download --dump-json "${link}"`)).stdout);
ext = meta.ext; ext = meta.ext;
} catch(err) { } catch (err) {
const tmphead = (await fetch(link, { method: "HEAD" })).headers["content-type"]; console.error('err:', err);
// this can be undefined for unsupported mime types, but will be caught in the general mime check below if (e.type == 'tg')
ext = cfg.mimes[tmphead]; return await e.editMessageText(msg.result.chat.id, msg.result.message_id, err);
return await e.reply('something went wrong lol / check maxfilesize?');
} }
} }
if(!Object.values(cfg.mimes).includes(ext?.toLowerCase())) { if (!Object.values(cfg.mimes).includes(ext?.toLowerCase())) {
return console.log('mime schmime ' + ext); return console.log('mime schmime ' + ext);
} }
@@ -136,44 +139,44 @@ export default async bot => {
const start = new Date(); const start = new Date();
let source; let source;
if(link.match(regex.instagram)) { if (link.match(regex.instagram)) {
try { try {
// add --cookies <path-to-cookies-file> on local instance if you want to avoid getting rate limited or optionally use a socks proxy from a network that is not being detected as a public network // add --cookies <path-to-cookies-file> on local instance if you want to avoid getting rate limited or optionally use a socks proxy from a network that is not being detected as a public network
source = (await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=1080]+ba/b[height<=1080] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim(); source = (await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=1080]+ba/b[height<=1080] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
} catch(err) { } catch (err) {
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "instagram dl error"); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "instagram dl error");
return await e.reply("instagram dl error", err); return await e.reply("instagram dl error", err);
} }
} }
else if(link.match(regex.imgur)) { else if (link.match(regex.imgur)) {
// imghure via torsocks // needs torsocks setup so this is optional // imghure via torsocks // needs torsocks setup so this is optional
try { try {
await queue.exec(`torsocks wget ${link} -O ./tmp/${uuid}.${ext}`); await queue.exec(`torsocks wget ${link} -O ./tmp/${uuid}.${ext}`);
source = `./tmp/${uuid}.${ext}`; source = `./tmp/${uuid}.${ext}`;
} catch(err) { } catch (err) {
console.error('err:', err); console.error('err:', err);
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, err); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, err);
return await e.reply('something went wrong lol'); return await e.reply('something went wrong lol');
} }
} }
else if(link.match(regex.yt)) { else if (link.match(regex.yt)) {
try { try {
// add --cookies <path-to-cookies-file> on local instance if you want to avoid getting rate limited or optionally use a socks proxy from a network that is not being detected as a public network // add --cookies <path-to-cookies-file> on local instance if you want to avoid getting rate limited or optionally use a socks proxy from a network that is not being detected as a public network
source = (await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" -I 1 --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim(); source = (await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" -I 1 --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
} catch(err) { } catch (err) {
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "yt dl error"); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "yt dl error");
return await e.reply("yt dl error", err); return await e.reply("yt dl error", err);
} }
} }
else if(link.match(regex.fourchan)) { else if (link.match(regex.fourchan)) {
// 4chan via proxy - fuck cloudflare // 4chan via proxy - fuck cloudflare
try { try {
source = (await queue.exec(`yt-dlp --proxy ${cfg.main.socks} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim(); source = (await queue.exec(`yt-dlp ${proxyArgs} -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
} catch(err) { } catch (err) {
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "yt dl error"); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "yt dl error");
return await e.reply("yt dl error", err); return await e.reply("yt dl error", err);
} }
@@ -182,23 +185,23 @@ export default async bot => {
// everything except the exceptions // everything except the exceptions
try { try {
source = (await queue.exec(`yt-dlp -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim(); source = (await queue.exec(`yt-dlp -f 'bv*[height<=720]+ba/b[height<=720] / wv*+ba/w' "${link}" --max-filesize ${maxfilesize / 1024}k --postprocessor-args "ffmpeg:-bitexact" -o "./tmp/${uuid}.%(ext)s" --print after_move:filepath --merge-output-format "mp4"`)).stdout.trim();
} catch(err) { } catch (err) {
console.error('err:', err); console.error('err:', err);
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, err); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, err);
return await e.reply('something went wrong lol / check maxfilesize?'); return await e.reply('something went wrong lol / check maxfilesize?');
} }
} }
// </download data> // </download data>
if(!source) { if (!source) {
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "something went wrong lol"); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "something went wrong lol");
return await e.reply("something went wrong lol"); return await e.reply("something went wrong lol");
} }
if(source.match(/larger than/)) { if (source.match(/larger than/)) {
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "too large lol"); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "too large lol");
return await e.reply("too large lol"); return await e.reply("too large lol");
} }
@@ -206,9 +209,9 @@ export default async bot => {
// filesize check // filesize check
const size = fs.statSync(source).size; const size = fs.statSync(source).size;
if(size > maxfilesize) { if (size > maxfilesize) {
await fs.promises.unlink(source).catch(_=>{}); await fs.promises.unlink(source).catch(_ => { });
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, `too large lol. (${lib.formatSize(size)} / ${lib.formatSize(maxfilesize)})`); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, `too large lol. (${lib.formatSize(size)} / ${lib.formatSize(maxfilesize)})`);
return await e.reply(`too large lol. (${lib.formatSize(size)} / ${lib.formatSize(maxfilesize)})`); return await e.reply(`too large lol. (${lib.formatSize(size)} / ${lib.formatSize(maxfilesize)})`);
} }
@@ -216,28 +219,28 @@ export default async bot => {
// mime check // mime check
let mime = (await queue.exec(`file --mime-type -b ${source}`)).stdout.trim(); let mime = (await queue.exec(`file --mime-type -b ${source}`)).stdout.trim();
try { try {
if(mime == 'video/x-matroska') { // mkv failsafe if (mime == 'video/x-matroska') { // mkv failsafe
await queue.exec(`ffmpeg -i ./tmp/${uuid}.mkv -codec copy ./tmp/${uuid}.mp4`); await queue.exec(`ffmpeg -i ./tmp/${uuid}.mkv -codec copy ./tmp/${uuid}.mp4`);
await fs.promises.unlink(source).catch(_=>{}); await fs.promises.unlink(source).catch(_ => { });
source = source.replace(/\.mkv$/, '.mp4'); source = source.replace(/\.mkv$/, '.mp4');
mime = 'video/mp4'; mime = 'video/mp4';
} }
if(source.match(/\.opus$/)) { // opus failsafe if (source.match(/\.opus$/)) { // opus failsafe
await queue.exec(`ffmpeg -i ./tmp/${uuid}.opus -codec copy ./tmp/${uuid}.ogg`); await queue.exec(`ffmpeg -i ./tmp/${uuid}.opus -codec copy ./tmp/${uuid}.ogg`);
await fs.promises.unlink(source); await fs.promises.unlink(source);
source = source.replace(/\.opus$/, '.ogg'); source = source.replace(/\.opus$/, '.ogg');
mime = 'audio/ogg'; mime = 'audio/ogg';
} }
} catch(err) { } catch (err) {
await fs.promises.unlink(source).catch(_=>{}); await fs.promises.unlink(source).catch(_ => { });
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "something went wrong lol"); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, "something went wrong lol");
return await e.reply("something went wrong lol"); return await e.reply("something went wrong lol");
} }
if(!Object.keys(cfg.mimes).includes(mime)) { if (!Object.keys(cfg.mimes).includes(mime)) {
await fs.promises.unlink(source).catch(_=>{}); await fs.promises.unlink(source).catch(_ => { });
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, `lol, go f0ck yourself (${mime})`); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, `lol, go f0ck yourself (${mime})`);
return await e.reply(`lol, go f0ck yourself (${mime})`); return await e.reply(`lol, go f0ck yourself (${mime})`);
} }
@@ -247,9 +250,9 @@ export default async bot => {
// check repost (checksum) // check repost (checksum)
repost = await queue.checkrepostsum(checksum); repost = await queue.checkrepostsum(checksum);
if(repost) { if (repost) {
await fs.promises.unlink(source).catch(_=>{}); await fs.promises.unlink(source).catch(_ => { });
if(e.type == 'tg') if (e.type == 'tg')
return await e.editMessageText(msg.result.chat.id, msg.result.message_id, `repost motherf0cker (checksum): ${cfg.main.url.full}/${repost}`); return await e.editMessageText(msg.result.chat.id, msg.result.message_id, `repost motherf0cker (checksum): ${cfg.main.url.full}/${repost}`);
return await e.reply(`repost motherf0cker (checksum): ${cfg.main.url.full}/${repost}`); return await e.reply(`repost motherf0cker (checksum): ${cfg.main.url.full}/${repost}`);
} }
@@ -257,7 +260,7 @@ export default async bot => {
const filename = path.basename(source); const filename = path.basename(source);
await fs.promises.copyFile(source, `./public/b/${filename}`); await fs.promises.copyFile(source, `./public/b/${filename}`);
await fs.promises.unlink(source).catch(_=>{}); await fs.promises.unlink(source).catch(_ => { });
// user alias // user alias
let username = e.user.nick || e.user.username; let username = e.user.nick || e.user.username;
@@ -268,13 +271,12 @@ export default async bot => {
where lower(user_alias.alias) ilike ${username} where lower(user_alias.alias) ilike ${username}
limit 1 limit 1
`)?.[0]?.user; `)?.[0]?.user;
if(alias) { if (alias) {
username = alias; username = alias;
} }
await db` await db`
insert into items ${ insert into items ${db({
db({
src: e.media ? "" : link, src: e.media ? "" : link,
dest: filename, dest: filename,
mime: mime, mime: mime,
@@ -291,10 +293,20 @@ export default async bot => {
const itemid = await queue.getItemID(filename); const itemid = await queue.getItemID(filename);
// auto-tag sfw
await db`
insert into tags_assign ${db({
item_id: itemid,
tag_id: 1, // sfw
user_id: 2 // f0ck
}, 'item_id', 'tag_id', 'user_id')
}
`;
// generate thumbnail // generate thumbnail
try { try {
await queue.genThumbnail(filename, mime, itemid, link); await queue.genThumbnail(filename, mime, itemid, link);
} catch(err) { } catch (err) {
await queue.exec(`magick ./mugge.png ./public/t/${itemid}.webp`); await queue.exec(`magick ./mugge.png ./public/t/${itemid}.webp`);
} }
@@ -315,13 +327,13 @@ export default async bot => {
let outputmsgirc = `[f0cked] link: ${cfg.main.url.full}/${itemid} | size: ${lib.formatSize(size)} | speed: ${speed}`; let outputmsgirc = `[f0cked] link: ${cfg.main.url.full}/${itemid} | size: ${lib.formatSize(size)} | speed: ${speed}`;
let outputmsgtg = `[f0cked] size: ${lib.formatSize(size)} | speed: ${speed}`; let outputmsgtg = `[f0cked] size: ${lib.formatSize(size)} | speed: ${speed}`;
if(tags?.length > 0) { if (tags?.length > 0) {
const tagstr = tags.join(', '); const tagstr = tags.join(', ');
outputmsgirc += ` | tags: ${tagstr}`; outputmsgirc += ` | tags: ${tagstr}`;
outputmsgtg += ` | tags: ${tagstr}`; outputmsgtg += ` | tags: ${tagstr}`;
} }
if(e.type == 'tg') { if (e.type == 'tg') {
await e.deleteMessage(msg.result.chat.id, msg.result.message_id); await e.deleteMessage(msg.result.chat.id, msg.result.message_id);
await e.reply(outputmsgtg, { await e.reply(outputmsgtg, {
reply_markup: JSON.stringify({ reply_markup: JSON.stringify({
@@ -339,7 +351,7 @@ export default async bot => {
else { else {
await e.reply(outputmsgirc); await e.reply(outputmsgirc);
} }
}); }
} }
}]; }];
}; };