Telegram +
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +1,6 @@
|
|||||||
.fleet
|
.fleet
|
||||||
__pycache__
|
__pycache__
|
||||||
keys*.py
|
keys*.py
|
||||||
vkdel.py
|
vkdel.py
|
||||||
|
tgdel.py
|
||||||
|
*.session
|
101
news-bot.py
101
news-bot.py
@@ -3,17 +3,21 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import urllib.parse
|
import asyncio
|
||||||
import discord
|
import discord
|
||||||
import logging
|
import logging
|
||||||
import colorlog
|
import colorlog
|
||||||
import requests
|
import requests
|
||||||
import html2text
|
import html2text
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
from telethon import events
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
from telethon.sync import TelegramClient
|
||||||
|
from telethon.errors import FloodWaitError
|
||||||
|
|
||||||
import keys
|
import keys
|
||||||
|
|
||||||
|
|
||||||
url_post = "https://linux-gaming.ru/posts.json"
|
url_post = "https://linux-gaming.ru/posts.json"
|
||||||
url_news = "https://linux-gaming.ru/c/news/6.json"
|
url_news = "https://linux-gaming.ru/c/news/6.json"
|
||||||
url_vk_post = "https://api.vk.com/method/wall.post"
|
url_vk_post = "https://api.vk.com/method/wall.post"
|
||||||
@@ -58,6 +62,7 @@ def main():
|
|||||||
check_version(last_changelog, resp_changelog)
|
check_version(last_changelog, resp_changelog)
|
||||||
check_discord_public()
|
check_discord_public()
|
||||||
check_vk_posts()
|
check_vk_posts()
|
||||||
|
check_tg_news()
|
||||||
|
|
||||||
|
|
||||||
def make_soup(resp_changelog):
|
def make_soup(resp_changelog):
|
||||||
@@ -87,6 +92,7 @@ def html_to_text(html_content):
|
|||||||
# Удаление строк, содержащих '* * *'
|
# Удаление строк, содержащих '* * *'
|
||||||
markdown_text = re.sub(r'^.*\* \* \*.*$', '', markdown_text, flags=re.MULTILINE)
|
markdown_text = re.sub(r'^.*\* \* \*.*$', '', markdown_text, flags=re.MULTILINE)
|
||||||
|
|
||||||
|
# Фикс ненумерованных списков
|
||||||
markdown_text = re.sub(r'^.*\* ', '* ', markdown_text, flags=re.MULTILINE)
|
markdown_text = re.sub(r'^.*\* ', '* ', markdown_text, flags=re.MULTILINE)
|
||||||
|
|
||||||
# Убираем переносы строк, кроме строк, начинающихся с *
|
# Убираем переносы строк, кроме строк, начинающихся с *
|
||||||
@@ -111,6 +117,10 @@ def html_to_text(html_content):
|
|||||||
# Удаление избыточных пустых строк после удаления строк
|
# Удаление избыточных пустых строк после удаления строк
|
||||||
markdown_text = re.sub(r'\n\s*\n', '\n', markdown_text)
|
markdown_text = re.sub(r'\n\s*\n', '\n', markdown_text)
|
||||||
|
|
||||||
|
# Замена текстов типа "image1280×474 99.7 KB", "807×454 64.1 KB" на "."
|
||||||
|
markdown_text = re.sub(r'image\d+×\d+\s+\d+(\.\d+)?\s+KB', '.', markdown_text)
|
||||||
|
markdown_text = re.sub(r'\d+×\d+\s+\d+(\.\d+)?\s+KB', '.', markdown_text)
|
||||||
|
|
||||||
# Изменение ссылок без описания
|
# Изменение ссылок без описания
|
||||||
markdown_text = re.sub(r'\[\]\((https:\/\/[^\)]+)\)', r'[.](\1)', markdown_text)
|
markdown_text = re.sub(r'\[\]\((https:\/\/[^\)]+)\)', r'[.](\1)', markdown_text)
|
||||||
markdown_text = re.sub(r'\[\s]\((https:\/\/[^\)]+)\)', r'[.](\1)', markdown_text)
|
markdown_text = re.sub(r'\[\s]\((https:\/\/[^\)]+)\)', r'[.](\1)', markdown_text)
|
||||||
@@ -322,8 +332,8 @@ async def discord_post(post_text, client):
|
|||||||
await channel.send(f"{post_text}")
|
await channel.send(f"{post_text}")
|
||||||
|
|
||||||
|
|
||||||
async def get_discord_messages(client, channel_id):
|
async def get_discord_messages(client_discord, channel_id):
|
||||||
channel = client.get_channel(channel_id)
|
channel = client_discord.get_channel(channel_id)
|
||||||
if not channel:
|
if not channel:
|
||||||
logging.error(f"ID канала Discord {channel_id} не существует")
|
logging.error(f"ID канала Discord {channel_id} не существует")
|
||||||
return []
|
return []
|
||||||
@@ -344,31 +354,31 @@ async def get_discord_messages(client, channel_id):
|
|||||||
def check_discord_public():
|
def check_discord_public():
|
||||||
intents = discord.Intents.default()
|
intents = discord.Intents.default()
|
||||||
intents.messages = True
|
intents.messages = True
|
||||||
client = discord.Client(intents=intents)
|
client_discord = discord.Client(intents=intents)
|
||||||
|
|
||||||
@client.event
|
@client_discord.event
|
||||||
async def on_ready():
|
async def on_ready():
|
||||||
logging.debug(f"Успешный логин в discord {client.user}")
|
logging.debug(f"Успешный логин в discord {client_discord.user}")
|
||||||
channel_id = keys.dicord_channel
|
channel_id = keys.dicord_channel
|
||||||
discord_messages = await get_discord_messages(client, channel_id)
|
discord_messages = await get_discord_messages(client_discord, channel_id)
|
||||||
|
|
||||||
list_titles_and_ids = news()
|
list_titles_and_ids = news()
|
||||||
if list_titles_and_ids:
|
if list_titles_and_ids:
|
||||||
list_for_public = []
|
list_for_public = []
|
||||||
|
|
||||||
for topic_id, topic_title in list_titles_and_ids:
|
for topic_id, topic_title in list_titles_and_ids:
|
||||||
if topic_title not in discord_messages and topic_id > 698:
|
if topic_title not in discord_messages and topic_id > keys.start_topic_id:
|
||||||
list_for_public.append((topic_id, topic_title))
|
list_for_public.append((topic_id, topic_title))
|
||||||
|
|
||||||
if not list_for_public:
|
if not list_for_public:
|
||||||
logging.info(f"Новостей для публикации в дискорд нет")
|
logging.info(f"Новостей для публикации в дискорд нет")
|
||||||
await client.close()
|
await client_discord.close()
|
||||||
else:
|
else:
|
||||||
logging.info(f"Новости для публикации в дискорд: {list_for_public}")
|
logging.info(f"Новости для публикации в дискорд: {list_for_public}")
|
||||||
channel = client.get_channel(channel_id)
|
channel = client_discord.get_channel(channel_id)
|
||||||
if not channel:
|
if not channel:
|
||||||
logging.error(f"ID канала Discord {channel_id} не существует")
|
logging.error(f"ID канала Discord {channel_id} не существует")
|
||||||
await client.close()
|
await client_discord.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
for topic_id, topic_title in reversed(list_for_public):
|
for topic_id, topic_title in reversed(list_for_public):
|
||||||
@@ -378,9 +388,9 @@ def check_discord_public():
|
|||||||
# Разбиваем содержимое на части по 4000 символов
|
# Разбиваем содержимое на части по 4000 символов
|
||||||
for i in range(0, len(content), 2000):
|
for i in range(0, len(content), 2000):
|
||||||
await channel.send(content[i:i+2000])
|
await channel.send(content[i:i+2000])
|
||||||
await client.close()
|
await client_discord.close()
|
||||||
|
|
||||||
client.run(keys.discord_token)
|
client_discord.run(keys.discord_token)
|
||||||
|
|
||||||
|
|
||||||
def vk_post(url, post_text, links=None):
|
def vk_post(url, post_text, links=None):
|
||||||
@@ -460,7 +470,7 @@ def check_vk_posts():
|
|||||||
logging.info(f"Новостей для публикации в ВК нет")
|
logging.info(f"Новостей для публикации в ВК нет")
|
||||||
else:
|
else:
|
||||||
for topic_id, topic_title in reversed(list_for_public):
|
for topic_id, topic_title in reversed(list_for_public):
|
||||||
if topic_id > 698:
|
if topic_id > keys.start_topic_id:
|
||||||
logging.info(f"Новости для публикации в ВК: {list_for_public}")
|
logging.info(f"Новости для публикации в ВК: {list_for_public}")
|
||||||
text_data = news_content(topic_id)
|
text_data = news_content(topic_id)
|
||||||
if text_data:
|
if text_data:
|
||||||
@@ -480,5 +490,66 @@ def check_vk_posts():
|
|||||||
logging.info(f"Новостей для публикации в ВК нет")
|
logging.info(f"Новостей для публикации в ВК нет")
|
||||||
|
|
||||||
|
|
||||||
|
def tg_post(post_text, client_tg):
|
||||||
|
# Отправка сообщения
|
||||||
|
client_tg.send_message(keys.channel_username_tg, post_text)
|
||||||
|
# Завершение сеанса
|
||||||
|
client_tg.disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
async def get_tg_messages(client_tg, channel_username_tg):
|
||||||
|
messages = []
|
||||||
|
async for message in client_tg.iter_messages(channel_username_tg, limit=999):
|
||||||
|
if message.text: # Проверка на NoneType
|
||||||
|
logging.debug(f"Найдены сообщения в Telegram канале {message.text}")
|
||||||
|
messages.append(message.text)
|
||||||
|
return messages
|
||||||
|
|
||||||
|
|
||||||
|
def check_tg_news():
|
||||||
|
session_file = 'LG_news'
|
||||||
|
loop = asyncio.new_event_loop() # Создание нового цикла событий
|
||||||
|
asyncio.set_event_loop(loop) # Установка нового цикла событий
|
||||||
|
|
||||||
|
client_tg = TelegramClient('LG_news', keys.api_id_tg, keys.api_hash_tg)
|
||||||
|
|
||||||
|
@client_tg.on(events.NewMessage(chats=keys.channel_username_tg))
|
||||||
|
async def handler(event):
|
||||||
|
logging.debug(f"Новое сообщение в Telegram: {event.message.message}")
|
||||||
|
|
||||||
|
async def main_tg():
|
||||||
|
await client_tg.start()
|
||||||
|
tg_messages = await get_tg_messages(client_tg, keys.channel_username_tg)
|
||||||
|
list_titles_and_ids = news()
|
||||||
|
if list_titles_and_ids:
|
||||||
|
list_for_public = []
|
||||||
|
|
||||||
|
for topic_id, topic_title in list_titles_and_ids:
|
||||||
|
if all(topic_title not in (msg or '') for msg in tg_messages) and topic_id > keys.start_topic_id:
|
||||||
|
list_for_public.append((topic_id, topic_title))
|
||||||
|
|
||||||
|
if not list_for_public:
|
||||||
|
logging.info(f"Новостей для публикации в Telegram нет")
|
||||||
|
await client_tg.disconnect()
|
||||||
|
else:
|
||||||
|
logging.info(f"Новости для публикации в Telegram: {list_for_public}")
|
||||||
|
for topic_id, topic_title in reversed(list_for_public):
|
||||||
|
text_data = news_content(topic_id)
|
||||||
|
if text_data:
|
||||||
|
content = f"----------------------------------------------------------\n### {topic_title}\t\n" + text_data + "\n"
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
await client_tg.send_message(keys.channel_username_tg, content)
|
||||||
|
break # Сообщение отправлено успешно, выходим из цикла
|
||||||
|
except FloodWaitError as e:
|
||||||
|
logging.warning(f"Flood wait error: нужно подождать {e.seconds} секунд.")
|
||||||
|
await asyncio.sleep(e.seconds) # Ждем указанное время перед повторной попыткой
|
||||||
|
await client_tg.disconnect()
|
||||||
|
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
loop.run_until_complete(main_tg())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
Reference in New Issue
Block a user