From 985453ff6029e36445365c2af476f5879eee1c33 Mon Sep 17 00:00:00 2001 From: Aleksei Rybin <0xalekseirybin@gmail.com> Date: Sun, 28 Jan 2024 15:42:01 +0700 Subject: [PATCH 1/2] Separate into modules --- package.json | 1 + src/bot.ts | 122 ++++++++++++++++++++++ src/env.ts | 5 +- src/filterMessages.ts | 84 +++++++++++++++ src/format.ts | 13 +++ src/index.ts | 234 ++---------------------------------------- src/senderBot.ts | 51 +++++++++ 7 files changed, 283 insertions(+), 227 deletions(-) create mode 100644 src/bot.ts create mode 100644 src/filterMessages.ts create mode 100644 src/format.ts create mode 100644 src/senderBot.ts diff --git a/package.json b/package.json index 773cf43..42ac805 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "pm2:start:watch": "pm2 start . --name 'forwarding-discord-telegram' --watch --exp-backoff-restart-delay=100", "pm2:stop": "pm2 stop .", "build": "tsc", + "build:watch": "tsc --watch", "format": "npx prettier --write .", "lint": "eslint ./" }, diff --git a/src/bot.ts b/src/bot.ts new file mode 100644 index 0000000..c6b76a7 --- /dev/null +++ b/src/bot.ts @@ -0,0 +1,122 @@ +import { Client } from "discord.js-selfbot-v13"; +import { Config } from "./config"; +import { filterMessages } from "./filterMessages"; +import { formatSize } from "./format"; +import { SenderBot } from "./senderBot"; + +export class Bot extends Client { + messagesToSend: string[] = []; + imagesToSend: string[] = []; + senderBot: SenderBot; + config: Config; + + constructor(config: Config, senderBot: SenderBot) { + super(); + + this.config = config; + this.senderBot = senderBot; + + this.on("ready", () => console.log(`Logged in as ${this.user?.tag}!`)); + + this.on("messageCreate", (message) => { + if (!filterMessages(message, this.config)) return; + + const date = new Date().toLocaleString("en-US", { + day: "2-digit", + year: "2-digit", + month: "2-digit", + hour: "2-digit", + minute: "2-digit", + second: "2-digit" + }); + + let render = ""; + + if (config.showDate) render += `[${date}] `; + if (config.showChat) + render += message.inGuild() + ? `[${message.guild.name} / ${message.channel.name} / ${message.author.tag}]: ` + : `[${message.author.tag}]: `; + + render += message.content; + + const allAttachments: string[] = []; + const images: string[] = []; + + const embeds = message.embeds.map((embed) => { + let stringEmbed = "Embed:\n"; + + if (embed.title) stringEmbed += ` Title: ${embed.title}\n`; + if (embed.description) + stringEmbed += ` Description: ${embed.description}\n`; + if (embed.url) stringEmbed += ` Url: ${embed.url}\n`; + if (embed.color) stringEmbed += ` Color: ${embed.color}\n`; + if (embed.timestamp) stringEmbed += ` Url: ${embed.timestamp}\n`; + + const allFields = [" Fields:\n"]; + + embed.fields.forEach((field) => { + let stringField = " Field:\n"; + + if (field.name) stringField += ` Name: ${field.name}\n`; + if (field.value) stringField += ` Value: ${field.value}\n`; + + allFields.push(stringField); + }); + + if (allFields.length != 1) stringEmbed += `${allFields.join("")}`; + if (embed.thumbnail) + stringEmbed += ` Thumbnail: ${embed.thumbnail.url}\n`; + if (embed.image) { + stringEmbed += ` Image: ${embed.image.url}\n`; + + if (config.imagesAsMedia ?? true) images.push(embed.image.url); + } + if (embed.video) stringEmbed += ` Video: ${embed.video.url}\n`; + if (embed.author) stringEmbed += ` Author: ${embed.author.name}\n`; + if (embed.footer) stringEmbed += ` Footer: ${embed.footer.iconURL}\n`; + + return stringEmbed; + }); + + if (embeds.length != 0) render += embeds.join(""); + + message.attachments.forEach((attachment) => { + if ( + (config.imagesAsMedia ?? true) && + attachment.contentType.startsWith("image") + ) + return images.push(attachment.url); + + allAttachments.push( + `Attachment:\n Name: ${attachment.name}\n${ + attachment.description + ? ` Description: ${attachment.description}\n` + : "" + } Size: ${formatSize(attachment.size)}\n Url: ${attachment.url}` + ); + }); + + if (allAttachments.length != 0) render += allAttachments.join(""); + + console.log(render); + + if (config.stackMessages) { + this.messagesToSend.push(render); + this.imagesToSend.push(...images); + + return; + } + + this.senderBot.sendData([render], images); + }); + + if (config.stackMessages) + setInterval(() => { + this.senderBot.sendData(this.messagesToSend, this.imagesToSend); + + this.messagesToSend.length = 0; + this.imagesToSend.length = 0; + }, 5000); + } +} diff --git a/src/env.ts b/src/env.ts index 4820cb9..aae3101 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,12 +1,13 @@ import dotenv from "dotenv"; +import { ChannelId } from "./config"; export interface Env { DISCORD_TOKEN: string; TELEGRAM_TOKEN: string; - TELEGRAM_CHAT_ID: string | number; + TELEGRAM_CHAT_ID: ChannelId; } -export function getEnv() { +export function getEnv(): Env { if (process.env.NODE_ENV != "production") dotenv.config(); return process.env as unknown as Env; diff --git a/src/filterMessages.ts b/src/filterMessages.ts new file mode 100644 index 0000000..ebd5238 --- /dev/null +++ b/src/filterMessages.ts @@ -0,0 +1,84 @@ +import { Message } from "discord.js-selfbot-v13"; +import { Config } from "./config"; + +export function filterMessages( + message: Message, + config: Config +): boolean { + if ( + config.mutedGuildsIds != undefined && + config.mutedGuildsIds?.length != 0 && + (config.mutedGuildsIds?.includes(message.guildId) || + config.mutedGuildsIds?.includes(Number(message.guildId))) + ) + return false; + + if ( + config.allowedGuildsIds != undefined && + config.allowedGuildsIds?.length != 0 && + !config.allowedGuildsIds?.includes(message.guildId) && + !config.allowedGuildsIds?.includes(Number(message.guildId)) + ) + return false; + + if ( + config.mutedChannelsIds != undefined && + config.mutedChannelsIds?.length != 0 && + (config.mutedChannelsIds?.includes(message.channel.id) || + config.mutedChannelsIds?.includes(Number(message.channel.id))) + ) + return false; + + if ( + config.allowedChannelsIds != undefined && + config.allowedChannelsIds?.length != 0 && + !config.allowedChannelsIds?.includes(message.channel.id) && + !config.allowedChannelsIds?.includes(Number(message.channel.id)) + ) + return false; + + if ( + config.mutedUsersIds != undefined && + config.mutedUsersIds?.length != 0 && + (config.mutedUsersIds?.includes(message.author.id) || + config.mutedUsersIds?.includes(Number(message.author.id))) + ) + return false; + + if ( + config.allowedUsersIds != undefined && + config.allowedUsersIds?.length != 0 && + !config.allowedUsersIds?.includes(message.author.id) && + !config.allowedUsersIds?.includes(Number(message.author.id)) + ) + return false; + + if ( + config.channelConfigs != undefined && + config.channelConfigs?.[message.channel.id] != undefined && + config.channelConfigs?.[message.channel.id]?.allowed != undefined && + config.channelConfigs?.[message.channel.id]?.allowed?.length != 0 && + !config.channelConfigs?.[message.channel.id]?.allowed?.includes( + message.author.id + ) && + !config.channelConfigs?.[message.channel.id]?.allowed?.includes( + Number(message.author.id) + ) + ) + return false; + + if ( + config.channelConfigs?.[message.channel.id] != undefined && + config.channelConfigs?.[message.channel.id]?.muted != undefined && + config.channelConfigs?.[message.channel.id]?.muted?.length != 0 && + (config.channelConfigs?.[message.channel.id]?.muted?.includes( + message.author.id + ) || + config.channelConfigs?.[message.channel.id]?.muted?.includes( + Number(message.author.id) + )) + ) + return false; + + return true; +} diff --git a/src/format.ts b/src/format.ts new file mode 100644 index 0000000..c38d22c --- /dev/null +++ b/src/format.ts @@ -0,0 +1,13 @@ +export function formatSize(length: number): string { + const SIZE_UNITS = ["Bytes", "KB", "MB", "GB", "TB", "PB"]; + + let i = 0; + + while ((length / 1000) | 0 && i < SIZE_UNITS.length - 1) { + length /= 1024; + + i++; + } + + return `${length.toFixed(2)} ${SIZE_UNITS[i]}`; +} diff --git a/src/index.ts b/src/index.ts index 9f5fc4b..47a0a4d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,7 @@ -import { autoRetry } from "@grammyjs/auto-retry"; -import { Client } from "discord.js-selfbot-v13"; -import { Bot, InputMediaBuilder } from "grammy"; +import { Bot } from "./bot"; import { getConfig } from "./config"; import { getEnv } from "./env"; +import { SenderBot } from "./senderBot"; const env = getEnv(); const config = getConfig(); @@ -11,228 +10,13 @@ let channelsToSend = config.outputChannels ?? []; if (env.TELEGRAM_CHAT_ID) channelsToSend = [env.TELEGRAM_CHAT_ID, ...channelsToSend]; -const client = new Client(); - -const bot = new Bot(env.TELEGRAM_TOKEN); -bot.api.config.use(autoRetry()); - -const messagesToSend: string[] = []; -const imagesToSend: string[] = []; - -client.on("ready", () => console.log(`Logged in as ${client.user?.tag}!`)); - -const SIZE_UNITS = ["Bytes", "KB", "MB", "GB", "TB", "PB"]; - -function formatSize(length: number) { - let i = 0; - - while ((length / 1000) | 0 && i < SIZE_UNITS.length - 1) { - length /= 1024; - - i++; - } - - return `${length.toFixed(2)} ${SIZE_UNITS[i]}`; -} - -client.on("messageCreate", (message) => { - // TODO: Please rewrite this mess - if ( - config.mutedGuildsIds != undefined && - config.mutedGuildsIds?.length != 0 && - (config.mutedGuildsIds?.includes(message.guildId) || - config.mutedGuildsIds?.includes(Number(message.guildId))) - ) - return; - - if ( - config.allowedGuildsIds != undefined && - config.allowedGuildsIds?.length != 0 && - !config.allowedGuildsIds?.includes(message.guildId) && - !config.allowedGuildsIds?.includes(Number(message.guildId)) - ) - return; - - if ( - config.mutedChannelsIds != undefined && - config.mutedChannelsIds?.length != 0 && - (config.mutedChannelsIds?.includes(message.channel.id) || - config.mutedChannelsIds?.includes(Number(message.channel.id))) +const client = new Bot( + config, + new SenderBot( + env.TELEGRAM_CHAT_ID.toString(), + channelsToSend, + config.disableLinkPreview ) - return; - - if ( - config.allowedChannelsIds != undefined && - config.allowedChannelsIds?.length != 0 && - !config.allowedChannelsIds?.includes(message.channel.id) && - !config.allowedChannelsIds?.includes(Number(message.channel.id)) - ) - return; - - if ( - config.mutedUsersIds != undefined && - config.mutedUsersIds?.length != 0 && - (config.mutedUsersIds?.includes(message.author.id) || - config.mutedUsersIds?.includes(Number(message.author.id))) - ) - return; - - if ( - config.allowedUsersIds != undefined && - config.allowedUsersIds?.length != 0 && - !config.allowedUsersIds?.includes(message.author.id) && - !config.allowedUsersIds?.includes(Number(message.author.id)) - ) - return; - - if ( - config.channelConfigs != undefined && - config.channelConfigs?.[message.channel.id] != undefined && - config.channelConfigs?.[message.channel.id]?.allowed != undefined && - config.channelConfigs?.[message.channel.id]?.allowed?.length != 0 && - !config.channelConfigs?.[message.channel.id]?.allowed?.includes( - message.author.id - ) && - !config.channelConfigs?.[message.channel.id]?.allowed?.includes( - Number(message.author.id) - ) - ) - return; - - if ( - config.channelConfigs?.[message.channel.id] != undefined && - config.channelConfigs?.[message.channel.id]?.muted != undefined && - config.channelConfigs?.[message.channel.id]?.muted?.length != 0 && - (config.channelConfigs?.[message.channel.id]?.muted?.includes( - message.author.id - ) || - config.channelConfigs?.[message.channel.id]?.muted?.includes( - Number(message.author.id) - )) - ) - return; - - const date = new Date().toLocaleString("en-US", { - day: "2-digit", - year: "2-digit", - month: "2-digit", - hour: "2-digit", - minute: "2-digit", - second: "2-digit" - }); - - let render = ""; - - if (config.showDate) render += `[${date}] `; - if (config.showChat) - render += message.inGuild() - ? `[${message.guild.name} / ${message.channel.name} / ${message.author.tag}]: ` - : `[${message.author.tag}]: `; - - render += message.content; - - const allAttachments: string[] = []; - const images: string[] = []; - - const embeds = message.embeds.map((embed) => { - let stringEmbed = "Embed:\n"; - - if (embed.title) stringEmbed += ` Title: ${embed.title}\n`; - if (embed.description) - stringEmbed += ` Description: ${embed.description}\n`; - if (embed.url) stringEmbed += ` Url: ${embed.url}\n`; - if (embed.color) stringEmbed += ` Color: ${embed.color}\n`; - if (embed.timestamp) stringEmbed += ` Url: ${embed.timestamp}\n`; - - const allFields = [" Fields:\n"]; - - embed.fields.forEach((field) => { - let stringField = " Field:\n"; - - if (field.name) stringField += ` Name: ${field.name}\n`; - if (field.value) stringField += ` Value: ${field.value}\n`; - - allFields.push(stringField); - }); - - if (allFields.length != 1) stringEmbed += `${allFields.join("")}`; - if (embed.thumbnail) stringEmbed += ` Thumbnail: ${embed.thumbnail.url}\n`; - if (embed.image) { - stringEmbed += ` Image: ${embed.image.url}\n`; - - if (config.imagesAsMedia ?? true) images.push(embed.image.url); - } - if (embed.video) stringEmbed += ` Video: ${embed.video.url}\n`; - if (embed.author) stringEmbed += ` Author: ${embed.author.name}\n`; - if (embed.footer) stringEmbed += ` Footer: ${embed.footer.iconURL}\n`; - - return stringEmbed; - }); - - if (embeds.length != 0) render += embeds.join(""); - - message.attachments.forEach((attachment) => { - if ( - (config.imagesAsMedia ?? true) && - attachment.contentType.startsWith("image") - ) - return images.push(attachment.url); - - allAttachments.push( - `Attachment:\n Name: ${attachment.name}\n${ - attachment.description ? ` Description: ${attachment.description}\n` : "" - } Size: ${formatSize(attachment.size)}\n Url: ${attachment.url}` - ); - }); - - if (allAttachments.length != 0) render += allAttachments.join(""); - - console.log(render); - - if (config.stackMessages) { - messagesToSend.push(render); - imagesToSend.push(...images); - - return; - } - - sendData([render], images); -}); - -bot.catch((err) => { - console.error(err); -}); - -async function sendData(messagesToSend: string[], imagesToSend: string[]) { - try { - if (messagesToSend.length != 0) { - channelsToSend.forEach(async (channel) => { - if (imagesToSend.length != 0) - await bot.api.sendMediaGroup( - channel, - imagesToSend.map((image) => InputMediaBuilder.photo(image)) - ); - - if (messagesToSend.length == 0 || messagesToSend.join("") == "") return; - - await bot.api.sendMessage(channel, messagesToSend.join("\n"), { - link_preview_options: { - is_disabled: config.disableLinkPreview - } - }); - }); - } - } catch (e) { - console.error(e); - } -} - -if (config.stackMessages) - setInterval(() => { - sendData(messagesToSend, imagesToSend); - - messagesToSend.length = 0; - imagesToSend.length = 0; - }, 5000); +); client.login(env.DISCORD_TOKEN); diff --git a/src/senderBot.ts b/src/senderBot.ts new file mode 100644 index 0000000..bc66958 --- /dev/null +++ b/src/senderBot.ts @@ -0,0 +1,51 @@ +import { autoRetry } from "@grammyjs/auto-retry"; +import { Bot, BotConfig, Context, InputMediaBuilder } from "grammy"; +import { ChannelId } from "./config"; + +export class SenderBot extends Bot { + chatsToSend: ChannelId[]; + disableLinkPreview: boolean; + + constructor( + token: string, + channelsToSend: ChannelId[], + disableLinkPreview: boolean, + config?: BotConfig + ) { + super(token, config); + + this.chatsToSend = channelsToSend; + this.disableLinkPreview = disableLinkPreview; + + this.api.config.use(autoRetry()); + + this.catch((err) => { + console.error(err); + }); + } + + async sendData(messagesToSend: string[], imagesToSend: string[]) { + try { + if (messagesToSend.length != 0) { + this.chatsToSend.forEach(async (chatId) => { + if (imagesToSend.length != 0) + await this.api.sendMediaGroup( + chatId, + imagesToSend.map((image) => InputMediaBuilder.photo(image)) + ); + + if (messagesToSend.length == 0 || messagesToSend.join("") == "") + return; + + await this.api.sendMessage(chatId, messagesToSend.join("\n"), { + link_preview_options: { + is_disabled: this.disableLinkPreview + } + }); + }); + } + } catch (e) { + console.error(e); + } + } +} From ec57198b9bbb345a513f848af4be115f29946bfd Mon Sep 17 00:00:00 2001 From: Aleksei Rybin <0xalekseirybin@gmail.com> Date: Sun, 28 Jan 2024 15:51:54 +0700 Subject: [PATCH 2/2] Use token instead of chat id... --- src/index.ts | 6 +----- src/senderBot.ts | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/index.ts b/src/index.ts index 47a0a4d..0731e8f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,11 +12,7 @@ if (env.TELEGRAM_CHAT_ID) const client = new Bot( config, - new SenderBot( - env.TELEGRAM_CHAT_ID.toString(), - channelsToSend, - config.disableLinkPreview - ) + new SenderBot(env.TELEGRAM_TOKEN, channelsToSend, config.disableLinkPreview) ); client.login(env.DISCORD_TOKEN); diff --git a/src/senderBot.ts b/src/senderBot.ts index bc66958..cd6434d 100644 --- a/src/senderBot.ts +++ b/src/senderBot.ts @@ -8,13 +8,13 @@ export class SenderBot extends Bot { constructor( token: string, - channelsToSend: ChannelId[], + chatsToSend: ChannelId[], disableLinkPreview: boolean, config?: BotConfig ) { super(token, config); - this.chatsToSend = channelsToSend; + this.chatsToSend = chatsToSend; this.disableLinkPreview = disableLinkPreview; this.api.config.use(autoRetry());