From 3b06394e1d31bb2aeeb65f4be787786b99eaebfa Mon Sep 17 00:00:00 2001 From: Burtasov Date: Thu, 3 Aug 2023 18:49:44 +0100 Subject: [PATCH] feat: add channel post handling --- docs/Message Objects Examples.md | 20 +++++++- src/main.ts | 6 +++ src/settings/BotSettingsModal.ts | 20 ++++---- src/settings/Settings.ts | 7 ++- src/telegram/bot/bot.ts | 53 +++---------------- src/telegram/bot/message/getters.ts | 2 +- src/telegram/bot/message/handlers.ts | 76 +++++++++++++++++++++++----- 7 files changed, 113 insertions(+), 71 deletions(-) diff --git a/docs/Message Objects Examples.md b/docs/Message Objects Examples.md index 936af42..1c9f594 100644 --- a/docs/Message Objects Examples.md +++ b/docs/Message Objects Examples.md @@ -144,7 +144,7 @@ "is_bot": false, "first_name": "soberhacker", "username": "soberhacker", - "language_code": "ru" + "language_code": "en" }, "chat": { "id": -955999997, @@ -155,4 +155,22 @@ "date": 1689804496, "group_chat_created": true } +``` +###### example 4 Channel Post +```json +{ + "message_id": 10, + "sender_chat": { + "id": -1001909715512, + "title": "Telegram Sync Test Channel", + "type": "channel" + }, + "chat": { + "id": -1001909715512, + "title": "Telegram Sync Test Channel", + "type": "channel" + }, + "date": 1691018159, + "text": "ку" +} ``` \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index b72ce46..ea19d28 100644 --- a/src/main.ts +++ b/src/main.ts @@ -89,6 +89,12 @@ export default class TelegramSyncPlugin extends Plugin { async onload() { console.log(`Loading ${this.manifest.name} plugin`); await this.loadSettings(); + // TODO Remove allowedChatFromUsernames in 2024, because it is deprecated + if (this.settings.allowedChatFromUsernames.length != 0) { + this.settings.allowedChats = [...this.settings.allowedChatFromUsernames]; + this.settings.allowedChatFromUsernames = []; + await this.saveSettings(); + } // Add a settings tab for this plugin this.settingsTab = new TelegramSyncSettingTab(this); diff --git a/src/settings/BotSettingsModal.ts b/src/settings/BotSettingsModal.ts index cfeee3a..61c9290 100644 --- a/src/settings/BotSettingsModal.ts +++ b/src/settings/BotSettingsModal.ts @@ -14,7 +14,7 @@ export class BotSettingsModal extends Modal { this.botSettingsDiv = this.contentEl.createDiv(); this.botSettingsDiv.createEl("h4", { text: "Bot settings" }); this.addBotToken(); - this.addAllowedChatFromUsernamesSetting(); + this.addAllowedChatsSetting(); this.addDeviceId(); this.addFooterButtons(); } @@ -37,14 +37,16 @@ export class BotSettingsModal extends Modal { }); } - addAllowedChatFromUsernamesSetting() { - const allowedChatFromUsernamesSetting = new Setting(this.botSettingsDiv) - .setName("Allowed chat from usernames (required)") - .setDesc("Only messages from these usernames will be processed. At least your username must be entered.") + addAllowedChatsSetting() { + const allowedChatsSetting = new Setting(this.botSettingsDiv) + .setName("Allowed chats (required)") + .setDesc( + "Enter list of usernames or chat ids that should be processed. At least your username must be entered." + ) .addTextArea((text) => { const textArea = text - .setPlaceholder("example: soberhacker,username") - .setValue(this.plugin.settings.allowedChatFromUsernames.join(", ")) + .setPlaceholder("example: soberhacker,1227636") + .setValue(this.plugin.settings.allowedChats.join(", ")) .onChange(async (value: string) => { value = value.replace(/\s/g, ""); if (!value) { @@ -52,7 +54,7 @@ export class BotSettingsModal extends Modal { textArea.inputEl.style.borderWidth = "2px"; textArea.inputEl.style.borderStyle = "solid"; } - this.plugin.settings.allowedChatFromUsernames = value.split(","); + this.plugin.settings.allowedChats = value.split(","); }); }); // add link to Telegram FAQ about getting username @@ -62,7 +64,7 @@ export class BotSettingsModal extends Modal { href: "https://telegram.org/faq?setln=en#q-what-are-usernames-how-do-i-get-one", text: "Telegram FAQ", }); - allowedChatFromUsernamesSetting.descEl.appendChild(howDoIGetUsername); + allowedChatsSetting.descEl.appendChild(howDoIGetUsername); } addDeviceId() { diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index 8da8ff6..ccd3e6d 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -28,7 +28,8 @@ export interface TelegramSyncSettings { deleteMessagesFromTelegram: boolean; needToSaveFiles: boolean; newFilesLocation: string; - allowedChatFromUsernames: string[]; + allowedChatFromUsernames: string[]; // deprecated, use allowedChats + allowedChats: string[]; mainDeviceId: string; pluginVersion: string; telegramSessionType: Client.SessionType; @@ -44,7 +45,8 @@ export const DEFAULT_SETTINGS: TelegramSyncSettings = { deleteMessagesFromTelegram: false, needToSaveFiles: true, newFilesLocation: "", - allowedChatFromUsernames: [""], + allowedChatFromUsernames: [""], // deprecated, use allowedChats + allowedChats: [""], mainDeviceId: "", pluginVersion: "", telegramSessionType: "bot", @@ -109,6 +111,7 @@ export class TelegramSyncSettingTab extends PluginSettingTab { const botSettingsModal = new BotSettingsModal(this.plugin); botSettingsModal.onClose = async () => { if (botSettingsModal.saved) { + await this.plugin.saveSettings(); // Initialize the bot with the new token this.plugin.checkingBotConnection = true; try { diff --git a/src/telegram/bot/bot.ts b/src/telegram/bot/bot.ts index d3c2953..081de94 100644 --- a/src/telegram/bot/bot.ts +++ b/src/telegram/bot/bot.ts @@ -1,10 +1,8 @@ import TelegramBot from "node-telegram-bot-api"; import TelegramSyncPlugin from "src/main"; -import { _15sec, _1sec, displayAndLog, displayAndLogError, StatusMessages, _5sec } from "src/utils/logUtils"; -import { handleMessage, ifNewReleaseThenShowChanges } from "./message/handlers"; +import { _1sec, displayAndLog, displayAndLogError, StatusMessages, _5sec } from "src/utils/logUtils"; +import { handleMessageOrPost } from "./message/handlers"; import { reconnect } from "../user/user"; -import { getFileObject } from "./message/getters"; -import { enqueue } from "src/utils/queues"; // Initialize the Telegram bot and set up message handling export async function connect(plugin: TelegramSyncPlugin) { @@ -27,48 +25,13 @@ export async function connect(plugin: TelegramSyncPlugin) { handlePollingError(plugin, error); }); + // TODO handling channel posts + bot.on("channel_post", async (msg) => { + await handleMessageOrPost(plugin, msg, "post"); + }); + bot.on("message", async (msg) => { - if (!plugin.botConnected) { - plugin.botConnected = true; - plugin.lastPollingErrors = []; - } - - // if user disconnected and should be connected then reconnect it - if (!plugin.userConnected) await enqueue(plugin, plugin.restartTelegram, "user"); - - const { fileObject, fileType } = getFileObject(msg); - // skip system messages - - if (!msg.text && !fileType) { - displayAndLog(plugin, `Got a system message from Telegram Bot`, 0); - return; - } - let fileInfo = "binary"; - if (fileType && fileObject) - fileInfo = `${fileType} ${ - fileObject instanceof Array ? fileObject[0]?.file_unique_id : fileObject.file_unique_id - }`; - - displayAndLog(plugin, `Got a message from Telegram Bot: ${msg.text || fileInfo}`, 0); - - // Skip processing if the message is a "/start" command - // https://github.com/soberhacker/obsidian-telegram-sync/issues/109 - if (msg.text === "/start") { - return; - } - - // Store topic name if "/topicName " command - if (msg.text?.includes("/topicName")) { - await plugin.settingsTab.storeTopicName(msg); - return; - } - - try { - await handleMessage(plugin, msg); - await enqueue(ifNewReleaseThenShowChanges, plugin, msg); - } catch (error) { - await displayAndLogError(plugin, error, "", "", msg, _15sec); - } + await handleMessageOrPost(plugin, msg, "message"); }); try { diff --git a/src/telegram/bot/message/getters.ts b/src/telegram/bot/message/getters.ts index bbeaea6..a8e2e1f 100644 --- a/src/telegram/bot/message/getters.ts +++ b/src/telegram/bot/message/getters.ts @@ -130,7 +130,7 @@ export async function getTopic(plugin: TelegramSyncPlugin, msg: TelegramBot.Mess } if (!topic) { throw new Error( - `Telegram bot has a limitation to get topic names. if the topic name displays incorrect, set the name manually using bot command "/topicName NAME"` + "Telegram bot has a limitation to get topic names. if the topic name displays incorrect, set the name manually using bot command `/topicName NAME`" ); } return topic; diff --git a/src/telegram/bot/message/handlers.ts b/src/telegram/bot/message/handlers.ts index 68592de..3d85108 100644 --- a/src/telegram/bot/message/handlers.ts +++ b/src/telegram/bot/message/handlers.ts @@ -12,6 +12,69 @@ import { ProgressBarType, _3MB, createProgressBar, deleteProgressBar, updateProg import { getFileObject } from "./getters"; import { TFile } from "obsidian"; import { enqueue } from "src/utils/queues"; +import { _15sec, displayAndLog, displayAndLogError } from "src/utils/logUtils"; + +export async function handleMessageOrPost( + plugin: TelegramSyncPlugin, + msg: TelegramBot.Message, + msgType: "post" | "message" +) { + if (!plugin.botConnected) { + plugin.botConnected = true; + plugin.lastPollingErrors = []; + } + + // if user disconnected and should be connected then reconnect it + if (!plugin.userConnected) await enqueue(plugin, plugin.restartTelegram, "user"); + + const { fileObject, fileType } = getFileObject(msg); + // skip system messages + + if (!msg.text && !fileType) { + displayAndLog(plugin, `Got a system message from Telegram Bot`, 0); + return; + } + let fileInfo = "binary"; + if (fileType && fileObject) + fileInfo = `${fileType} ${ + fileObject instanceof Array ? fileObject[0]?.file_unique_id : fileObject.file_unique_id + }`; + + displayAndLog(plugin, `Got a message from Telegram Bot: ${msg.text || fileInfo}`, 0); + + // Skip processing if the message is a "/start" command + // https://github.com/soberhacker/obsidian-telegram-sync/issues/109 + if (msg.text === "/start") { + return; + } + + // Store topic name if "/topicName " command + if (msg.text?.includes("/topicName")) { + await plugin.settingsTab.storeTopicName(msg); + return; + } + + // Check if message has been sended by allowed users or chats + const telegramUserName = msg.from?.username ?? ""; + const allowedChats = plugin.settings.allowedChats; + + if (!allowedChats.includes(telegramUserName) && !allowedChats.includes(msg.chat.id.toString())) { + const telegramUserNameFull = telegramUserName ? `your username "${telegramUserName}" or` : ""; + plugin.bot?.sendMessage( + msg.chat.id, + `Access denied. Add ${telegramUserNameFull} this chat id "${msg.chat.id}" in the plugin setting "Allowed Chats".`, + { reply_to_message_id: msg.message_id } + ); + return; + } + + try { + await handleMessage(plugin, msg); + msgType == "message" && (await enqueue(ifNewReleaseThenShowChanges, plugin, msg)); + } catch (error) { + await displayAndLogError(plugin, error, "", "", msg, _15sec); + } +} // handle all messages from Telegram export async function handleMessage(plugin: TelegramSyncPlugin, msg: TelegramBot.Message) { @@ -42,19 +105,6 @@ export async function handleMessage(plugin: TelegramSyncPlugin, msg: TelegramBot return; } - // Check if message has been sended by allowed usernames - const telegramUserName = msg.from?.username ?? ""; - const allowedChatFromUsernames = plugin.settings.allowedChatFromUsernames; - - if (!telegramUserName || !allowedChatFromUsernames.includes(telegramUserName)) { - plugin.bot?.sendMessage( - msg.chat.id, - `Access denied. Add your username ${telegramUserName} in the plugin setting "Allowed Chat From Usernames".`, - { reply_to_message_id: msg.message_id } - ); - return; - } - formattedContent = await applyNoteContentTemplate(plugin, plugin.settings.templateFileLocation, msg); const appendAllToTelegramMd = plugin.settings.appendAllToTelegramMd;