From 72dd038bfb2fc2cd77443263ee7e852914f6ce55 Mon Sep 17 00:00:00 2001 From: Burtasov Date: Wed, 12 Jul 2023 10:40:39 +0100 Subject: [PATCH] chore: add boosty and cashing main results --- .github/FUNDING.yml | 2 +- README.md | 6 +- docs/Template Variables List.md | 10 +- install-plugin.mjs | 2 +- manifest.json | 4 +- src/main.ts | 10 +- src/settings/Settings.ts | 16 ++-- src/settings/donation.ts | 10 +- src/telegram/GramJs/client.ts | 42 ++++++--- src/telegram/GramJs/convertors.ts | 142 ++++++++++++++++++++--------- src/telegram/message/handlers.ts | 12 +-- src/telegram/message/processors.ts | 12 +-- src/telegram/progressBar.ts | 15 ++- src/telegram/tooManyRequests.ts | 18 ++++ src/utils/logUtils.ts | 16 +++- 15 files changed, 212 insertions(+), 105 deletions(-) create mode 100644 src/telegram/tooManyRequests.ts diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index d45f2a4..853bb0f 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1,3 @@ github: soberhacker ko_fi: soberhacker -custom: ["https://www.buymeacoffee.com/soberhacker", "https://www.paypal.com/donate/?hosted_button_id=VYSCUZX8MYGCU", "https://oxapay.com/donate/5855474"] \ No newline at end of file +custom: ["https://www.buymeacoffee.com/soberhacker", "https://www.paypal.com/donate/?hosted_button_id=VYSCUZX8MYGCU", "https://boosty.to/soberhacker/donate"] \ No newline at end of file diff --git a/README.md b/README.md index d33c05a..27c5d58 100644 --- a/README.md +++ b/README.md @@ -79,10 +79,10 @@ Big thanks to everyone who's already been supporting this project - you rock!
If you like this plugin and are considering donating 🌠 to support continued development, use the buttons below.

- - + +    - +
diff --git a/docs/Template Variables List.md b/docs/Template Variables List.md index e003e3b..38a1452 100644 --- a/docs/Template Variables List.md +++ b/docs/Template Variables List.md @@ -2,13 +2,13 @@ ###### Variables: ```ts -{{content}} - forwarded from + file content + message text +{{content}} - forwarded from + file|image + message text {{content:text}} - only message text {{content:firstLine}} - first line of the message text {{content:noFirstLine}} - the message text without the first line {{content:XX}} - XX characters of the message text -{{file}} - file content ![]() -{{file:link}} - link to the file []() +{{file}} - file|image content ![]() +{{file:link}} - link to the file|image []() {{voiceTranscript}} - transcribing voice(video notes!) to text (same limits as for Telegram Premium subscribers) {{voiceTranscript:XX}} - XX symbols of transcribed voices (same limits as for Telegram Premium subscribers) {{chat}} - link to the chat (bot / group / channel) @@ -116,9 +116,9 @@ Integrating these new features might prove challenging and time-consuming, so yo - Donating to enhance my motivation - Contributing to the development (branch "[develop](https://github.com/soberhacker/obsidian-telegram-sync/tree/develop)") -[![Crypto Ð⟠na₮i⟠n](https://img.buymeacoffee.com/button-api/?text=Crypto%20Donation&emoji=🚀&slug=soberhacker&button_colour=5b5757&font_colour=ffffff&font_family=Lato&outline_colour=ffffff&coffee_colour=FFDD00)](https://oxapay.com/donate/5855474) +[![boosty](https://img.buymeacoffee.com/button-api/?text=boosty&emoji=💰&slug=soberhacker&button_colour=f17d1e&font_colour=000000&font_family=Bree&outline_colour=000000&coffee_colour=FFDD00)](https://boosty.to/soberhacker/donate) -[![Buy me a book](https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20book&emoji=📖&slug=soberhacker&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff)](https://www.buymeacoffee.com/soberhacker) +[![Buy me a coffee](https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20coffee&emoji=%E2%98%95&slug=soberhacker&button_colour=5F7FFF&font_colour=ffffff&font_family=Cookie&outline_colour=000000&coffee_colour=FFFFFF)](https://www.buymeacoffee.com/soberhacker) [![Ko-fi Donation](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/soberhacker) diff --git a/install-plugin.mjs b/install-plugin.mjs index 2a4dfb1..ba89a6b 100644 --- a/install-plugin.mjs +++ b/install-plugin.mjs @@ -42,4 +42,4 @@ if (!fs.existsSync(hotReloadFolder)) { }); } -console.log("Plugin installed successfully!"); +console.log(`${new Date().toLocaleTimeString()} Plugin installed successfully!`); diff --git a/manifest.json b/manifest.json index 879307b..9ccd244 100644 --- a/manifest.json +++ b/manifest.json @@ -7,10 +7,10 @@ "author": "soberhacker", "authorUrl": "https://github.com/soberhacker/obsidian-telegram-sync", "fundingUrl": { - "Buy me a book": "https://www.buymeacoffee.com/soberhacker", + "Buy me a coffee": "https://www.buymeacoffee.com/soberhacker", "PayPal": "https://www.paypal.com/donate/?hosted_button_id=VYSCUZX8MYGCU", "Ko-Fi": "https://ko-fi.com/soberhacker", - "Crypto donation": "https://oxapay.com/donate/5855474" + "Boosty": "https://boosty.to/soberhacker/donate" }, "isDesktopOnly": true } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index a510232..fbc81bc 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,7 +4,7 @@ import TelegramBot from "node-telegram-bot-api"; import * as async from "async"; import { handleMessage, ifNewRelaseThenShowChanges } from "./telegram/message/handlers"; import { machineIdSync } from "node-machine-id"; -import { _15sec, displayAndLog } from "./utils/logUtils"; +import { _15sec, _1sec, displayAndLog } from "./utils/logUtils"; import { displayAndLogError } from "./utils/logUtils"; import { appendMessageToTelegramMd } from "./telegram/message/processors"; import * as GramJs from "./telegram/GramJs/client"; @@ -193,13 +193,13 @@ export default class TelegramSyncPlugin extends Plugin { try { // eslint-disable-next-line @typescript-eslint/no-explicit-any - const error_code = (error as any).response.body.error_code; + const errorCode = (error as any).response.body.error_code; - if (error_code === 409) { + if (errorCode === 409) { pollingError = "twoBotInstances"; } - if (error_code === 401) { + if (errorCode === 401) { pollingError = "unAuthorized"; } } catch { @@ -232,7 +232,7 @@ export default class TelegramSyncPlugin extends Plugin { if (this.checkingBotConnection || this.botConnected || !this.bot || !this.bot.isPolling()) return; try { this.checkingBotConnection = true; - await new Promise((resolve) => setTimeout(resolve, intervalInSeconds * 1000)); + await new Promise((resolve) => setTimeout(resolve, intervalInSeconds * _1sec)); this.botUser = await this.bot.getMe(); this.botConnected = true; this.lastPollingErrors = []; diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index b75da6e..ab4594d 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -2,13 +2,14 @@ import TelegramSyncPlugin from "src/main"; import { ButtonComponent, PluginSettingTab, Setting, TextComponent, normalizePath } from "obsidian"; import { FileSuggest } from "./suggesters/FileSuggester"; import { FolderSuggest } from "./suggesters/FolderSuggester"; -import { cryptoDonationButton, paypalButton, buyMeACoffeeButton, kofiButton } from "./donation"; +import { boostyButton, paypalButton, buyMeACoffeeButton, kofiButton } from "./donation"; import TelegramBot from "node-telegram-bot-api"; -import { createProgressBar, updateProgressBar, deleteProgressBar } from "src/telegram/progressBar"; +import { createProgressBar, updateProgressBar, deleteProgressBar, ProgressBarType } from "src/telegram/progressBar"; import * as GramJs from "src/telegram/GramJs/client"; import { BotSettingsModal } from "./BotSettingsModal"; import { UserLogInModal } from "./UserLogInModal"; import { version } from "release-notes.mjs"; +import { _5sec } from "src/utils/logUtils"; export interface TopicName { name: string; @@ -43,6 +44,7 @@ export const DEFAULT_SETTINGS: TelegramSyncSettings = { allowedChatFromUsernames: [""], mainDeviceId: "", pluginVersion: "", + // TODO Check not public appId, apiHash for flood and download speed appId: "17349", // public, ok to be here apiHash: "344583e45741c457fe1862106095a5eb", // public, ok to be here topicNames: [], @@ -93,7 +95,7 @@ export class TelegramSyncSettingTab extends PluginSettingTab { } else if (this.plugin.settings.botToken && this.plugin.botConnected) botStatus.setValue("🤖 connected"); else botStatus.setValue("❌ disconnected"); new Promise((resolve) => { - setTimeout(() => resolve(botStatusConstructor.call(this, botStatus)), 5 * 1000); + setTimeout(() => resolve(botStatusConstructor.call(this, botStatus)), _5sec); }); }; @@ -123,7 +125,7 @@ export class TelegramSyncSettingTab extends PluginSettingTab { }); new Promise((resolve) => { - setTimeout(() => resolve(botSettingsConstructor.call(this, botSettingsButton)), 5 * 1000); + setTimeout(() => resolve(botSettingsConstructor.call(this, botSettingsButton)), _5sec); }); }; const botSettings = new Setting(this.containerEl) @@ -294,8 +296,8 @@ export class TelegramSyncSettingTab extends PluginSettingTab { ); donationDiv.appendChild(donationText); - cryptoDonationButton.style.marginRight = "20px"; - donationDiv.appendChild(cryptoDonationButton); + boostyButton.style.marginRight = "20px"; + donationDiv.appendChild(boostyButton); buyMeACoffeeButton.style.marginRight = "20px"; donationDiv.appendChild(buyMeACoffeeButton); donationDiv.appendChild(createEl("p")); @@ -325,7 +327,7 @@ export class TelegramSyncSettingTab extends PluginSettingTab { } else this.plugin.settings.topicNames.push(newTopicName); await this.plugin.saveSettings(); - const progressBarMessage = await createProgressBar(bot, msg, "stored"); + const progressBarMessage = await createProgressBar(bot, msg, ProgressBarType.stored); // Update the progress bar during the delay let stage = 0; diff --git a/src/settings/donation.ts b/src/settings/donation.ts index 9f8b649..20ee3f5 100644 --- a/src/settings/donation.ts +++ b/src/settings/donation.ts @@ -1,7 +1,7 @@ -export const cryptoDonationLink = "https://oxapay.com/donate/5855474"; -export const cryptoDonationImgLink = - "https://img.buymeacoffee.com/button-api/?text=Crypto%20Donation&emoji=🚀&slug=soberhacker&button_colour=5b5757&font_colour=ffffff&font_family=Lato&outline_colour=ffffff&coffee_colour=FFDD00"; -export const cryptoDonationButton = createDonationButton(cryptoDonationLink, cryptoDonationImgLink, 42); +export const boostyLink = "https://boosty.to/soberhacker/donate"; +export const boostyImgLink = + "https://img.buymeacoffee.com/button-api/?text=boosty&emoji=💰&slug=soberhacker&button_colour=f17d1e&font_colour=000000&font_family=Bree&outline_colour=000000&coffee_colour=FFDD00"; +export const boostyButton = createDonationButton(boostyLink, boostyImgLink, 42); export const paypalLink = "https://www.paypal.com/donate/?hosted_button_id=VYSCUZX8MYGCU"; //export const paypalImgLink = "https://www.paypalobjects.com/webstatic/en_US/i/buttons/PP_logo_h_100x26.png"; @@ -10,7 +10,7 @@ export const paypalButton = createDonationButton(paypalLink, paypalImgLink, 47, export const buyMeACoffeeLink = "https://www.buymeacoffee.com/soberhacker"; export const buyMeACoffeeImgLink = - "https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20book&emoji=📖&slug=soberhacker&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff"; + "https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20coffee&emoji=%E2%98%95&slug=soberhacker&button_colour=5F7FFF&font_colour=ffffff&font_family=Cookie&outline_colour=000000&coffee_colour=FFFFFF"; export const buyMeACoffeeButton = createDonationButton(buyMeACoffeeLink, buyMeACoffeeImgLink, 42); export const kofiLink = "https://ko-fi.com/soberhacker"; diff --git a/src/telegram/GramJs/client.ts b/src/telegram/GramJs/client.ts index aebfafd..d793b98 100644 --- a/src/telegram/GramJs/client.ts +++ b/src/telegram/GramJs/client.ts @@ -6,10 +6,11 @@ import TelegramBot from "node-telegram-bot-api"; import QRCode from "qrcode"; import os from "os"; import { convertBotFileToMessageMedia } from "./convertBotFileToMessageMedia"; -import { createProgressBar, deleteProgressBar, updateProgressBar } from "../progressBar"; -import { getInputPeerUser, getMessage } from "./convertors"; +import { ProgressBarType, createProgressBar, deleteProgressBar, updateProgressBar } from "../progressBar"; +import { getInputPeer, getMessage } from "./convertors"; import { formatDateTime } from "src/utils/dateUtils"; import { LogLevel, Logger } from "telegram/extensions/Logger"; +import { _5sec } from "src/utils/logUtils"; export type SessionType = "bot" | "user"; @@ -184,11 +185,11 @@ export async function downloadMedia( let stage = 0; let message: Api.Message | undefined = undefined; if (_clientUser && botUser && (await isAuthorizedAsUser())) { - const inputPeerUser = await getInputPeerUser(client, _clientUser, botUser, botMsg); - message = await getMessage(client, inputPeerUser, botMsg); + const inputPeer = await getInputPeer(client, _clientUser, botUser, botMsg); + message = await getMessage(client, inputPeer, botMsg); } - const progressBarMessage = await createProgressBar(bot, botMsg, "downloading"); + const progressBarMessage = await createProgressBar(bot, botMsg, ProgressBarType.downloading); return await client .downloadMedia(message || convertBotFileToMessageMedia(fileId || "", fileSize), { progressCallback: async (receivedBytes, totalBytes) => { @@ -213,17 +214,32 @@ export async function downloadMedia( export async function sendReaction(botUser: TelegramBot.User, botMsg: TelegramBot.Message) { if (!client || !(await client.checkAuthorization())) throw NotConnected; if ((await client.isBot()) || !_clientUser) throw NotAuthorizedAsUser; - const inputPeerUser = await getInputPeerUser(client, _clientUser, botUser, botMsg); - const message = await getMessage(client, inputPeerUser, botMsg); + const inputPeer = await getInputPeer(client, _clientUser, botUser, botMsg); + const message = await getMessage(client, inputPeer, botMsg); await client.invoke( new Api.messages.SendReaction({ - peer: inputPeerUser, + peer: inputPeer, msgId: message.id, reaction: [new Api.ReactionEmoji({ emoticon: "👍" })], }) ); } +let sendReactionQueue = Promise.resolve(); + +export const syncSendReaction = async (botUser: TelegramBot.User, botMsg: TelegramBot.Message) => { + let error: Error | undefined; + sendReactionQueue = sendReactionQueue + .then(async () => await sendReaction(botUser, botMsg)) + .catch((e) => { + error = e; + }); + const result = await sendReactionQueue; + if (error) throw error; + return result; +}; + +// TODO check 10 messages parallel transcribing export async function transcribeAudio( botMsg: TelegramBot.Message, botUser?: TelegramBot.User, @@ -246,20 +262,20 @@ export async function transcribeAudio( ); } if (!botUser) return ""; - const inputPeerUser = await getInputPeerUser(client, _clientUser, botUser, botMsg); - const message = await getMessage(client, inputPeerUser, botMsg, mediaId); + const inputPeer = await getInputPeer(client, _clientUser, botUser, botMsg); + const message = await getMessage(client, inputPeer, botMsg, mediaId); let transcribedAudio: Api.messages.TranscribedAudio | undefined; // to avoid endless loop, limited waiting for (let i = 1; i <= limit * 14; i++) { transcribedAudio = await client.invoke( new Api.messages.TranscribeAudio({ - peer: inputPeerUser, + peer: inputPeer, msgId: message.id, }) ); if (transcribedAudio.pending) - await new Promise((resolve) => setTimeout(resolve, 5000)); // 5 sec delay between updates - else if (i == limit * 14) throw new Error("Very long audio. Transcribing audio is limited with 15 min."); + await new Promise((resolve) => setTimeout(resolve, _5sec)); // 5 sec delay between updates + else if (i == limit * 14) throw new Error("Very long audio. Transcribing can't be longer then 15 min lasting."); else break; } if (!transcribedAudio) throw new Error("Can't transcribe the audio"); diff --git a/src/telegram/GramJs/convertors.ts b/src/telegram/GramJs/convertors.ts index 107c4c1..9c3c7a7 100644 --- a/src/telegram/GramJs/convertors.ts +++ b/src/telegram/GramJs/convertors.ts @@ -2,13 +2,45 @@ import TelegramBot from "node-telegram-bot-api"; import { Api, TelegramClient } from "telegram"; import { getFileObject } from "../message/getters"; import { extractMediaId } from "./convertBotFileToMessageMedia"; +import { TotalList } from "telegram/Helpers"; +import { _1h, _1sec, _2h, _2sec } from "src/utils/logUtils"; + +const cantFindTheMessage = "Can't find the message for connected user."; interface MessageCouple { date: number; + creationTime: Date; botMsgId: number; - clientMsgId?: number; + clientMsg: Api.Message; } -export let _listOfMessagesSentTogether: MessageCouple[] = []; + +interface MessagesRequests { + botChatId: number; + msgDate: number; + limit: number; + messages: TotalList; +} + +interface UserCouple { + clientUserId: number; + botUserId: number; + botChatId: number; + clientChat: Api.TypeInputPeer; +} + +let cachedMessageCouples: MessageCouple[] = []; +let cachedMessagesRequests: MessagesRequests[] = []; +const userCouples: UserCouple[] = []; + +// clean every 2 hours message request and couples if needed +setInterval(() => { + if (cachedMessageCouples.length < 5000) return; + const lastMessageCouple = cachedMessageCouples.last(); + if (lastMessageCouple && new Date().getTime() - lastMessageCouple.creationTime.getTime() > _1h) { + cachedMessagesRequests = []; + cachedMessageCouples = []; + } +}, _2h); // eslint-disable-next-line @typescript-eslint/no-explicit-any export function getMediaId(media: any): bigint | undefined { @@ -24,17 +56,25 @@ export function getMediaId(media: any): bigint | undefined { } } -export async function getInputPeerUser( +export async function getInputPeer( client: TelegramClient, clientUser: Api.User, botUser: TelegramBot.User, botMsg: TelegramBot.Message, limit = 10 ): Promise { + let userCouple = userCouples.find( + (usrCouple) => + usrCouple.botChatId == botMsg.chat.id && + usrCouple.botUserId == botUser.id && + usrCouple.clientUserId == clientUser.id.toJSNumber() + ); + if (userCouple) return userCouple.clientChat; + const chatId = botMsg.chat.id == clientUser.id.toJSNumber() ? botUser.id : botMsg.chat.id; const dialogs = await client.getDialogs({ limit }); const dialog = dialogs.find((d) => d.id?.toJSNumber() == chatId); - if (!dialog && limit <= 50) return await getInputPeerUser(client, clientUser, botUser, botMsg, limit + 10); + if (!dialog && limit <= 20) return await getInputPeer(client, clientUser, botUser, botMsg, limit + 10); else if (!dialog || !dialog.inputEntity) { console.log(dialogs); throw new Error( @@ -43,73 +83,89 @@ export async function getInputPeerUser( } ` ); } + userCouple = { + botChatId: botMsg.chat.id, + botUserId: botUser.id, + clientUserId: clientUser.id.toJSNumber(), + clientChat: dialog.inputEntity, + }; + userCouples.push(userCouple); return dialog.inputEntity; } export async function getMessage( client: TelegramClient, - inputPeerUser: Api.TypeInputPeer, + inputPeer: Api.TypeInputPeer, botMsg: TelegramBot.Message, mediaId?: string, limit = 50 ): Promise { - // wait for finishing other message searchs (max 10sec) - for (let i = 1; i < 20; i++) { - if (!_listOfMessagesSentTogether.find((msgCouple) => msgCouple.date == botMsg.date && !msgCouple.clientMsgId)) - break; - await new Promise((resolve) => setTimeout(resolve, 500)); - } - - let messageCouple = _listOfMessagesSentTogether.find((msgCouple) => msgCouple.botMsgId == botMsg.message_id); - if (!messageCouple) { - messageCouple = { - date: botMsg.date, - botMsgId: botMsg.message_id, - clientMsgId: undefined, - }; - _listOfMessagesSentTogether.push(messageCouple); - } else if (messageCouple.clientMsgId) { - const messages = await client.getMessages(inputPeerUser, { ids: messageCouple.clientMsgId }); - return messages[0]; - } + let messageCouple = cachedMessageCouples.find((msgCouple) => msgCouple.botMsgId == botMsg.message_id); try { + if (messageCouple?.clientMsg) return messageCouple.clientMsg; + + const messagesRequests = cachedMessagesRequests.filter( + (rq) => + rq.botChatId == botMsg.chat.id && + rq.msgDate <= botMsg.date && + (rq.messages.last()?.date || botMsg.date - 1) >= botMsg.date + ); + if (!messagesRequests.find((rq) => rq.limit == limit)) { + // wait 1 sec for history updates in Telegram + if (new Date().getTime() - new Date(botMsg.date * 1000).getTime() < _1sec) + await new Promise((resolve) => setTimeout(resolve, _2sec)); + let messages = await client.getMessages(inputPeer, { limit, reverse: true, offsetDate: botMsg.date - 2 }); + // remove bot messages (fromId != undefined) + messages = messages.filter((m) => m.fromId) || []; + messagesRequests.push({ botChatId: botMsg.chat.id, msgDate: botMsg.date, messages, limit }); + cachedMessagesRequests.push(messagesRequests[0]); + } + if (!botMsg.text && !mediaId) { const { fileObject } = getFileObject(botMsg); const fileObjectToUse = fileObject instanceof Array ? fileObject.pop() : fileObject; mediaId = extractMediaId(fileObjectToUse.file_id); } - const skipMsgs = _listOfMessagesSentTogether.filter((msgCouple) => msgCouple.date == botMsg.date); - // if other dates have already proccessed, clean unnecessary - if (!_listOfMessagesSentTogether.find((msgCouple) => !msgCouple.clientMsgId && msgCouple.date != botMsg.date)) - _listOfMessagesSentTogether = skipMsgs; - const skipMsgIds = skipMsgs - .filter((msgCouple) => msgCouple.botMsgId != botMsg.message_id) - .map((msgCouple) => msgCouple.clientMsgId); - let messages = await client.getMessages(inputPeerUser, { limit, reverse: true, offsetDate: botMsg.date - 1 }); - const total = messages.total || limit; - messages = messages.filter((msg) => !skipMsgIds.contains(msg.id)); - const clientMsg = messages.find( + const skipMsgIds = cachedMessageCouples + .filter( + (msgCouple) => + (msgCouple.date == botMsg.date || msgCouple.date + 1 == botMsg.date) && + msgCouple.botMsgId != botMsg.message_id + ) + .map((msgCouple) => msgCouple.clientMsg && msgCouple.clientMsg.id); + + const messages = messagesRequests + .map((rq) => rq.messages) + .reduce((accumulator, msgs) => accumulator.concat(msgs)); + const unprocessedMessages = messages.filter((msg) => !skipMsgIds.contains(msg.id)); + const clientMsg = unprocessedMessages.find( (m) => - m.date == botMsg.date && + (m.date == botMsg.date || m.date + 1 /*different rounding for some reason*/ == botMsg.date) && (m.message || "") == (botMsg.text || botMsg.caption || "") && ((mediaId && m.media && mediaId == getMediaId(m.media)?.toString()) || !(mediaId && m.media)) ); if ( !clientMsg && - limit <= 200 && - total > limit && + limit < 200 && messages.length > 0 && botMsg.date >= (messages.last()?.date || botMsg.date + 1) ) - return await getMessage(client, inputPeerUser, botMsg, mediaId, limit + 50); + return await getMessage(client, inputPeer, botMsg, mediaId, limit + 150); else if (!clientMsg) { - console.log(messages); - throw new Error("Can't find the message for connected user"); + console.log(`${cantFindTheMessage}\n\n botMsg=\n${botMsg}\n\nmessagesRequest=\n${messagesRequests}`); + throw new Error(cantFindTheMessage); } - messageCouple.clientMsgId = clientMsg.id; + // TODO throw error if clientMsg.id already exists + messageCouple = { + date: botMsg.date, + creationTime: new Date(), + botMsgId: botMsg.message_id, + clientMsg: clientMsg, + }; + cachedMessageCouples.push(messageCouple); return clientMsg; } catch (e) { - _listOfMessagesSentTogether.remove(messageCouple); + if (messageCouple) cachedMessageCouples.remove(messageCouple); throw e; } } diff --git a/src/telegram/message/handlers.ts b/src/telegram/message/handlers.ts index 88c0d81..fb39287 100644 --- a/src/telegram/message/handlers.ts +++ b/src/telegram/message/handlers.ts @@ -2,13 +2,13 @@ import TelegramSyncPlugin from "../../main"; import TelegramBot from "node-telegram-bot-api"; import { createFolderIfNotExist, getUniqueFilePath } from "src/utils/fsUtils"; import * as release from "../../../release-notes.mjs"; -import { buyMeACoffeeLink, cryptoDonationLink, kofiLink, paypalLink } from "../../settings/donation"; +import { buyMeACoffeeLink, boostyLink, kofiLink, paypalLink } from "../../settings/donation"; import { SendMessageOptions } from "node-telegram-bot-api"; import path from "path"; import * as GramJs from "../GramJs/client"; import { extension } from "mime-types"; import { applyNoteContentTemplate, finalizeMessageProcessing } from "./processors"; -import { createProgressBar, deleteProgressBar, updateProgressBar } from "../progressBar"; +import { ProgressBarType, createProgressBar, deleteProgressBar, updateProgressBar } from "../progressBar"; import { getFileObject } from "./getters"; // handle all messages from Telegram @@ -106,7 +106,7 @@ export async function handleFiles(plugin: TelegramSyncPlugin, msg: TelegramBot.M return; } - const progressBarMessage = await createProgressBar(plugin.bot, msg, "downloading"); + const progressBarMessage = await createProgressBar(plugin.bot, msg, ProgressBarType.downloading); const totalBytes = fileObjectToUse.file_size; let receivedBytes = 0; @@ -207,11 +207,11 @@ export async function ifNewRelaseThenShowChanges(plugin: TelegramSyncPlugin, msg reply_markup: { inline_keyboard: [ [ - { text: "🚀 Ð⟠na₮e crypto", url: cryptoDonationLink }, - { text: "📖 Buy me a book", url: buyMeACoffeeLink }, + { text: "⚡ Boosty", url: boostyLink }, + { text: "☕ Buy me a coffee", url: buyMeACoffeeLink }, ], [ - { text: "☕ Ko-fi Donation", url: kofiLink }, + { text: "💰 Ko-fi Donation", url: kofiLink }, { text: "💳 PayPal Donation", url: paypalLink }, ], ], diff --git a/src/telegram/message/processors.ts b/src/telegram/message/processors.ts index 8547060..21fa509 100644 --- a/src/telegram/message/processors.ts +++ b/src/telegram/message/processors.ts @@ -4,8 +4,8 @@ import { getChatLink, getForwardFromLink, getReplyMessageId, getTopicLink, getUr import { createFolderIfNotExist } from "src/utils/fsUtils"; import { TFile, normalizePath } from "obsidian"; import { formatDateTime } from "../../utils/dateUtils"; -import { _5sec, displayAndLog, displayAndLogError } from "src/utils/logUtils"; -import { createProgressBar, deleteProgressBar, updateProgressBar } from "../progressBar"; +import { _15sec, _1h, _5sec, displayAndLog, displayAndLogError } from "src/utils/logUtils"; +import { ProgressBarType, createProgressBar, deleteProgressBar, updateProgressBar } from "../progressBar"; import { convertMessageTextToMarkdown, escapeRegExp } from "./convertToMarkdown"; import * as GramJs from "../GramJs/client"; @@ -20,11 +20,11 @@ export async function finalizeMessageProcessing(plugin: TelegramSyncPlugin, msg: const currentTime = new Date(); const messageTime = new Date(msg.date * 1000); const timeDifference = currentTime.getTime() - messageTime.getTime(); - const hoursDifference = timeDifference / (1000 * 60 * 60); + const hoursDifference = timeDifference / _1h; if (plugin.settings.deleteMessagesFromTelegram && hoursDifference <= 48) { // Send the initial progress bar - const progressBarMessage = await createProgressBar(plugin.bot, msg, "deleting"); + const progressBarMessage = await createProgressBar(plugin.bot, msg, ProgressBarType.deleting); // Update the progress bar during the delay let stage = 0; @@ -40,7 +40,7 @@ export async function finalizeMessageProcessing(plugin: TelegramSyncPlugin, msg: let error = ""; try { if (plugin.userConnected && plugin.botUser) { - await GramJs.sendReaction(plugin.botUser, msg); + await GramJs.syncSendReaction(plugin.botUser, msg); needReply = false; } } catch (e) { @@ -161,7 +161,7 @@ export async function applyNoteContentTemplate( if (!height || Number.isInteger(parseFloat(height))) { linkPreview = ``; } else { - displayAndLog(plugin, `Template variable {{url1:preview${height}}} isn't supported!`, 15 * 1000); + displayAndLog(plugin, `Template variable {{url1:preview${height}}} isn't supported!`, _15sec); } } return linkPreview; diff --git a/src/telegram/progressBar.ts b/src/telegram/progressBar.ts index a929a51..83195a5 100644 --- a/src/telegram/progressBar.ts +++ b/src/telegram/progressBar.ts @@ -1,13 +1,21 @@ import TelegramBot from "node-telegram-bot-api"; +import { checkIfTooManyRequests, isTooManyRequests } from "./tooManyRequests"; + +export enum ProgressBarType { + downloading = "downloading", + deleting = "deleting", + stored = "stored", +} export async function createProgressBar( bot: TelegramBot, msg: TelegramBot.Message, - action: string + action: ProgressBarType ): Promise { return await bot.sendMessage(msg.chat.id, action, { reply_to_message_id: msg.message_id, reply_markup: { inline_keyboard: createProgressBarKeyboard(0).inline_keyboard }, + disable_notification: true, }); } @@ -21,7 +29,7 @@ export async function updateProgressBar( previousStage: number ): Promise { const stage = Math.ceil((current / total) * 10); - if (previousStage == stage) return stage; + if (previousStage == stage || isTooManyRequests) return stage; try { await bot.editMessageReplyMarkup( { @@ -30,7 +38,8 @@ export async function updateProgressBar( { chat_id: msg.chat.id, message_id: progressBarMessage.message_id } ); } catch (e) { - console.log(e); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (!checkIfTooManyRequests(e)) console.log(e); } return stage; } diff --git a/src/telegram/tooManyRequests.ts b/src/telegram/tooManyRequests.ts new file mode 100644 index 0000000..8b9badd --- /dev/null +++ b/src/telegram/tooManyRequests.ts @@ -0,0 +1,18 @@ +import { _5sec } from "src/utils/logUtils"; + +export let isTooManyRequests = false; +// reset isTooManyRequests +setInterval(() => { + isTooManyRequests = false; +}, _5sec); + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function checkIfTooManyRequests(error: any): boolean { + try { + const errorCode = error.response.body.error_code; + isTooManyRequests = errorCode == 429; + return isTooManyRequests; + } catch { + return false; + } +} diff --git a/src/utils/logUtils.ts b/src/utils/logUtils.ts index 2757df1..1a7a6f2 100644 --- a/src/utils/logUtils.ts +++ b/src/utils/logUtils.ts @@ -2,11 +2,17 @@ import TelegramBot from "node-telegram-bot-api"; import { Notice } from "obsidian"; import TelegramSyncPlugin from "src/main"; -export const _5sec = 5 * 1000; -export const _15sec = 15 * 1000; -export const _5min = 5 * 60 * 1000; -export const _30min = 30 * 60 * 1000; -export const doNotHide = 24 * 60 * 60 * 1000; +export const _1sec = 1000; +export const _2sec = 2 * _1sec; +export const _5sec = 5 * _1sec; +export const _15sec = 15 * _1sec; +export const _1min = 60 * _1sec; +export const _2min = 2 * _1min; +export const _5min = 5 * _1min; +export const _30min = 30 * _1min; +export const _1h = 60 * _1min; +export const _2h = 2 * _1h; +export const doNotHide = 24 * _1h; // Show notification and log message into console. export function displayAndLog(plugin: TelegramSyncPlugin, message: string, timeout?: number) {