From 03e16333b49663a43b7087b39992260eed6383cd Mon Sep 17 00:00:00 2001 From: DUB1401 Date: Wed, 28 Jun 2023 12:40:47 +0300 Subject: [PATCH] Add: Telegram channels support --- MessageEditor.py | 11 +++- README.md | 8 +-- Settings.json | 2 +- Source/Callback.py | 34 +++++++++---- Source/DUBLIB.py | 123 --------------------------------------------- vtp.py | 8 +-- 6 files changed, 43 insertions(+), 143 deletions(-) delete mode 100644 Source/DUBLIB.py diff --git a/MessageEditor.py b/MessageEditor.py index 292dd2b..0122c12 100644 --- a/MessageEditor.py +++ b/MessageEditor.py @@ -1,5 +1,12 @@ -# Обрабатывает полученные из ВКонтакте посты пользовательским скриптом перед отправкой в Telegram. -# Примечание: Если вернуть None, пост будет проигнорирован. +#==========================================================================================# +# >>>>> ПРИМЕЧАНИЕ <<<<< # +#==========================================================================================# +# При использовании MarkdownV2 следующие символы, не участвующие в разметке, должны быть экранированы: +# _ * [ ] ( ) ~ ` > # + - = | { } . ! →→→ \_ \* \[ \] \( \) \~ \` \> \# \+ \- \= \| \{ \} \. \! +# В тексте поста экранирование происходит автоматически до обработки пользовательским скриптом. +#==========================================================================================# + +# Обрабатывает полученные из ВКонтакте посты пользовательским скриптом перед отправкой в Telegram. Если вернуть None, пост будет проигнорирован. def MessageEditor(Post: str) -> str | None: #==========================================================================================# diff --git a/README.md b/README.md index 9b20881..4e8a45c 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # VK-Telegram-Poster -**VK-Telegram Poster** – это инструмент автопостинга записей из сообщества ВКонтакте в группу Telegram с возможностью настройки пользовательского скрипта обработки постов. Для отправки сообщений используется буфер ожидания, что позволяет автопостеру корректно работать с включённым медленным режимом группы Telegram (чтобы игнорировать медленный режим, бот должен иметь права администратора). +**VK-Telegram Poster** – это инструмент автопостинга записей из сообщества ВКонтакте в каналы и группы Telegram с возможностью настройки пользовательского скрипта обработки постов. Для отправки сообщений используется буфер ожидания, что позволяет автопостеру корректно работать с включённым медленным режимом группы (чтобы игнорировать медленный режим или отправлять сообщения в канал, бот должен иметь права администратора). ## Порядок установки и использования -1. Установить Python версии не старше 3.10. Если основная версия Python вашего сервера старше, указать целевую платформу путём редактирования первой строчки в файле _vtp.py_ (_#!/usr/bin/python_ → _#!/usr/bin/python3.x_). +1. Установить Python версии не ниже 3.10. Если основная версия Python вашего сервера старше, указать целевую платформу путём редактирования первой строчки в файле _vtp.py_ (_#!/usr/bin/python_ → _#!/usr/bin/python3.x_). 2. В среду исполнения установить следующие пакеты вручную или при помощи файла _requirements.txt_: [pyTelegramBotAPI](https://github.com/eternnoir/pyTelegramBotAPI), [fastapi](https://github.com/tiangolo/fastapi), [uvicorn](https://github.com/encode/uvicorn). ``` pip install pyTelegramBotAPI @@ -22,9 +22,9 @@ pip install uvicorn Сюда необходимо занести токен бота Telegram (можно узнать у [@BotFather](https://t.me/BotFather)). ___ ```JSON -"group-id": "" +"target-id": "" ``` -Сюда необходимо занести ID группы Telegram (можно получить, переслав сообщение из группы боту [Chat ID Bot](https://t.me/chat_id_echo_bot)). +Сюда необходимо занести ID группы или канала Telegram (можно получить у [Chat ID Bot](https://t.me/chat_id_echo_bot)). ___ ```JSON "source": "vk-group-wall" diff --git a/Settings.json b/Settings.json index ec581be..ffcc759 100644 --- a/Settings.json +++ b/Settings.json @@ -1,8 +1,8 @@ { "token": "", - "group-id": "", "source": "vk-group-wall", "parse-mode": null, + "target-id": "", "clean-tags": true, "disable-web-page-preview": true, "blacklist": [], diff --git a/Source/Callback.py b/Source/Callback.py index 524b7bc..9fa1aea 100644 --- a/Source/Callback.py +++ b/Source/Callback.py @@ -1,9 +1,9 @@ -from Source.DUBLIB import RemoveRegexSubstring from MessageEditor import MessageEditor from threading import Thread from time import sleep import telebot +import re class Callback: @@ -26,14 +26,26 @@ class Callback: # >>>>> МЕТОДЫ <<<<< # #==========================================================================================# + # Очищает сообщение от упоминаний в тегах ВКонтакте. + def __CleanTags(self, Post: str) -> str: + # Поиск всех совпадений. + RegexSubstrings = re.findall("#\w+@\w+", Post) + + # Удаление каждой подстроки. + for RegexSubstring in RegexSubstrings: + Post = Post.replace("@" + RegexSubstring.split('@')[1], "") + print(Post) + return Post + # Экранирует символы при использовании MarkdownV2 разметки. def __EscapeCharacters(self, Post: str) -> str: - Post = Post.replace('.', "\.") - Post = Post.replace('#', "\#") - Post = Post.replace('!', "\!") - Post = Post.replace('-', "\-") - Post = Post.replace('(', "\(") - Post = Post.replace(')', "\)") + # Список экранируемых символов. _ * [ ] ( ) ~ ` > # + - = | { } . ! + CharactersList = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'] + + # Экранировать каждый символ из списка. + for Character in CharactersList: + Post = Post.replace(Character, "\\" + Character) + return Post # Обрабатывает очередь сообщений. @@ -47,7 +59,7 @@ def __SenderThread(self): try: # Попытка отправить сообщение. - self.__TelegramBot.send_message(self.__Settings["group-id"], self.__MessagesBufer[0], parse_mode = self.__Settings["parse-mode"], disable_web_page_preview = self.__Settings["disable-web-page-preview"]) + self.__TelegramBot.send_message(self.__Settings["target-id"], self.__MessagesBufer[0], parse_mode = self.__Settings["parse-mode"], disable_web_page_preview = self.__Settings["disable-web-page-preview"]) except telebot.apihelper.ApiTelegramException as ExceptionData: # Описание исключения. @@ -57,6 +69,10 @@ def __SenderThread(self): if "Too Many Requests" in Description: sleep(int(Description.split()[-1]) + 1) + # Иначе удалить первое сообщение в очереди отправки. + else: + self.__MessagesBufer.pop(0) + else: # Удаление первого сообщения в очереди отправки. self.__MessagesBufer.pop(0) @@ -79,7 +95,7 @@ def __SendMessage(self, Post: str): # Если включена очистка тегов. if self.__Settings["clean-tags"] == True: - Post = RemoveRegexSubstring("@\w+", Post) + Post = self.__CleanTags(Post) # Для каждого запрещённого слова проверить соответствие словам поста. for ForbiddenWord in self.__Settings["blacklist"]: diff --git a/Source/DUBLIB.py b/Source/DUBLIB.py deleted file mode 100644 index 04e6e23..0000000 --- a/Source/DUBLIB.py +++ /dev/null @@ -1,123 +0,0 @@ -import sys -import os -import re - -#==========================================================================================# -# >>>>> КЛАССЫ <<<<< # -#==========================================================================================# - -# Вывод в консоль цветного текста. -class ColoredPrinter: - - # Конструктор. - def __init__(self): - # Базовые цвета. - self.BLACK = "0" - self.RED = "1" - self.GREEN = "2" - self.YELLOW = "3" - self.BLUE = "4" - self.PURPLE = "5" - self.CYAN = "6" - self.WHITE = "7" - # Переключатель: возвращать ли стандартные настройки после каждого вывода. - self.ResetStylesAfterPrint = True - # Переключатель: переход на новую строку после вывода. - self.NewLineAfterPrint = False - - # Вывод в консоль. - def Print(self, Text: str, TextColor: str, BackgroundColor: str = ""): - # Если передан цвет для фота, то создать соответствующий модификатор. - if BackgroundColor != "": - BackgroundColor = "\033[4" + BackgroundColor + "m" - # Генерация модификатора цвета текста. - TextColor = "\033[3" + TextColor + "m" - # Создание результирующей строки со стилями: цветового модификатора, модификатора фона, текста. - StyledText = TextColor + BackgroundColor + Text - # Если указано, добавить модификатор сброса стилей после вывода. - if self.ResetStylesAfterPrint == True: - StyledText = StyledText + "\033[0m" - # Вывод в консоль и установка параметра перехода на норвую строку. - if self.NewLineAfterPrint == True: - print(StyledText, end = "") - else: - print(StyledText) - -#==========================================================================================# -# >>>>> ФУНКЦИИ <<<<< # -#==========================================================================================# - -# Проверяет, имеются ли кирилические символы в строке. -def CheckForCyrillicPresence(Text: str) -> bool: - # Русский алфавит в нижнем регистре. - Alphabet = set("абвгдеёжзийклмнопрстуфхцчшщъыьэюя") - # Состояние: содержит ли строка кирилические символы. - TextContainsCyrillicCharacters = not Alphabet.isdisjoint(Text.lower()) - - return TextContainsCyrillicCharacters - -# Очищает консоль. -def Cls(): - os.system("cls" if os.name == "nt" else "clear") - -# Объединяет словари без перезаписи. -def MergeDictionaries(DictionaryOne: dict, DictionaryTwo: dict) -> dict: - - # Скопировать значения отсутствующих в оригинале ключей. - for Key in DictionaryTwo.keys(): - if Key not in DictionaryOne.keys(): - DictionaryOne[Key] = DictionaryTwo[Key] - - return DictionaryOne - -# Удаляет теги HTML из строки. -def RemoveHTML(TextHTML: str) -> str: - # Регулярное выражение фильтрации тегов HTML. - TagsHTML = re.compile('<.*?>|&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});') - # Удаление найденных по регулярному выражению тегов. - CleanText = re.sub(TagsHTML, '', str(TextHTML)) - - return str(CleanText) - -# Удаляет из строки подряд идущие повторяющиеся символы. -def RemoveRecurringCharacters(String: str, Character: str) -> str: - - # Пока в строке находятся повторы указанного символа, удалять их. - while Character + Character in String: - String = String.replace(Character + Character, Character) - - return String - -# Удаляет из строки все вхождения подстрок, совпадающие с регулярным выражением. -def RemoveRegexSubstring(Regex: str, String: str) -> str: - # Поиск всех совпадений. - RegexSubstrings = re.findall(Regex, String) - - # Удаление каждой подстроки. - for RegexSubstring in RegexSubstrings: - String = String.replace(RegexSubstring, "") - - return String - -# Переименовывает ключ в словаре, сохраняя исходный порядок. -def RenameDictKey(Dictionary: dict, OldKey: str, NewKey: str) -> dict: - # Результат выполнения. - Result = dict() - - # Перебор элементов словаря по списку ключей. - for Key in Dictionary.keys(): - - # Если нашли нужный ключ, то переместить значение по новому ключу в результат, иначе просто копировать. - if Key == OldKey: - Result[NewKey] = Dictionary[OldKey] - else: - Result[Key] = Dictionary[Key] - - return Result - -# Выключает ПК: работает на Windows и Linux. -def Shutdown(): - if sys.platform == "linux" or sys.platform == "linux2": - os.system("sudo shutdown now") - elif sys.platform == "win32": - os.system("shutdown /s") \ No newline at end of file diff --git a/vtp.py b/vtp.py index 63b5ce7..b65fde0 100644 --- a/vtp.py +++ b/vtp.py @@ -24,7 +24,7 @@ #==========================================================================================# # Версия скрипта. -Version = "0.2.0" +Version = "0.2.1" # Текст копирайта. Copyright = "Copyright © DUB1401. 2022-2023." # Обработчик запросов FastAPI. @@ -32,7 +32,7 @@ # Глобальные настройки. Settings = { "token": "", - "group-id": "", + "target-id": "", "source": "vk-group-wall", "clean-tags": True, "parse-mode": None, @@ -54,8 +54,8 @@ raise Exception("Incorrect Telegram bot's token.") # Проверка корректности заданного пароля. - if type(Settings["group-id"]) != str or len(Settings["group-id"]) == 0: - raise Exception("Incorrect group ID.") + if type(Settings["target-id"]) != str or len(Settings["target-id"]) == 0: + raise Exception("Incorrect group or channel ID.") # Установка информирующего сообщения в случае отсутствия кода подтверждения сервера. if type(Settings["confirmation-code"]) != str or len(Settings["confirmation-code"]) == 0: