vioms2tg.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #!/usr/bin/env python3
  2. # vioms2tg: telegram bot for posting news from VIOMS API
  3. # https://notabug.org/granthin/vioms2tg
  4. # Aliaksandr Hrankin - 2021-2022
  5. # version: 1.0
  6. import asyncio
  7. import sys
  8. import os
  9. from dotenv import load_dotenv
  10. load_dotenv()
  11. from aiogram import Bot, Dispatcher, executor, types, utils
  12. from news_api import News
  13. import config
  14. from telegraph_post import make_telegraph_post
  15. from logger import logging
  16. # Это телеграм бот, который работает с новостными рассылками ВИОМС,
  17. # пересылает их в телеграм канал или пользователю
  18. # На данный момент может получать новости с одного заданного списка рассылки
  19. # через API для мобильного приложения ВИОМС
  20. # Основные настройки в файле config.py
  21. vioms = News(config.VIOMS_CHANNEL_ID)
  22. DELAY = config.CHECK_NEWS_DELAY * 60
  23. is_admin_connected = None
  24. try:
  25. bot = Bot(token=config.BOT_TOKEN)
  26. except utils.exceptions.ValidationError:
  27. logging.error("Ошибка валидации токена")
  28. print("Произошла ошибка валидации токена. Возможно, вам нужно указать \
  29. правильный бот токен в файле .env.\n=== Завершение программы ===")
  30. sys.exit()
  31. dp = Dispatcher(bot)
  32. async def check_admin_connection():
  33. """Проверяет возможность отправки сообщений админу.
  34. Отправляет оповещение о запуске бота"""
  35. global is_admin_connected
  36. try:
  37. await bot.send_message(
  38. config.ADMIN_ID,
  39. "Проверяем связь с админом. Вы будете получать важные сообщения"
  40. )
  41. except:
  42. print('Ошибка отправки сообщения админу. Чтобы получать экстренные сообщения, \
  43. вам необходимо добавить свой айди в переменные окружения. Например, в файл .env. \
  44. А затем перезапустить бота.')
  45. logging.error("Ошибка отправки сообщения админу")
  46. is_admin_connected = False
  47. else:
  48. is_admin_connected = True
  49. async def get_news():
  50. """Асинхронная функция, которая запускается периодически для проверки новостей
  51. и отправки сообщений"""
  52. if is_admin_connected is None:
  53. await check_admin_connection()
  54. result = vioms.check_news()
  55. if 'error' in result:
  56. logging.error(result['error'])
  57. elif result["news_count"]:
  58. news = vioms.get_news_items()[::-1]
  59. for n in news:
  60. try:
  61. post = make_telegraph_post(
  62. n["title"],
  63. n["link"],
  64. n["html"]
  65. )
  66. except Exception as err:
  67. return await bot.send_message(config.ADMIN_ID, f"Произошла ошибка! {err=}, {type(err)=}")
  68. try:
  69. await bot.send_message(config.CHAT_ID, f"{n['title']} 👇\n{post['url']}")
  70. except utils.exceptions.ChatNotFound:
  71. logging.error("Ошибка отправки сообщения в функции get_news")
  72. if is_admin_connected:
  73. await bot.send_message(
  74. config.ADMIN_ID,
  75. "Ошибка отправки сообщения в канал. \
  76. Возможно неправильно указан его айди в файле .env или переменных окружения\nБот отключен")
  77. print("Ошибка отправки сообщения в канал. Возможно неправильно указан \
  78. его айди в файле .env или переменных окружения\n=== Завершение программы ===")
  79. sys.exit()
  80. except KeyError:
  81. logging.error(f"Произошла ошибка при отправке поста в телеграф: {post}")
  82. except Exception as err:
  83. await bot.send_message(config.ADMIN_ID, f"Произошла ошибка! {err=}, {type(err)=}")
  84. else:
  85. pass
  86. def repeat(coro, loop):
  87. asyncio.ensure_future(coro(), loop=loop)
  88. loop.call_later(DELAY, repeat, coro, loop)
  89. @dp.message_handler(commands=['start', 'help'])
  90. async def send_welcome(message: types.Message):
  91. """Обрабатывает команды `/start` и `/help`"""
  92. if message.from_user.id == int(config.ADMIN_ID):
  93. await message.reply("Бот работает. Вы админ")
  94. else:
  95. await message.reply(f"Бот работает.")
  96. # чтобы переслать новость из другой рассылки ВИОМС, нужно послать комманду
  97. # /add_new [channel_id] [post_id]
  98. @dp.message_handler(lambda message: message.text.startswith('/add_new '))
  99. async def send_new_post(message: types.Message):
  100. post_ids = message.text.replace('/add_new ', '').split()
  101. try:
  102. channel_id, post_id = [int(item) for item in post_ids]
  103. except:
  104. return
  105. news_item = vioms.get_post_by_id(channel_id, post_id)
  106. try:
  107. post = make_telegraph_post(
  108. news_item["title"],
  109. news_item["link"],
  110. news_item["html"]
  111. )
  112. except Exception as err:
  113. return await bot.send_message(config.ADMIN_ID, f"Произошла ошибка! {err=}, {type(err)=}")
  114. await bot.send_message(config.CHAT_ID, post['url'])
  115. # дополнительный функционал для взаимодействия с другим моим ботом
  116. # вы можете убрать или закомментировать до строки из равно
  117. @dp.message_handler(content_types=['audio'])
  118. async def resend_audio(message: types.Message):
  119. try:
  120. AGENT_ID = int(os.getenv('AGENT_ID') or 0)
  121. AUDIO_CHAT_ID = int(os.getenv('AUDIO_CHAT_ID') or 0)
  122. except:
  123. await bot.send_message(
  124. config.ADMIN_ID,
  125. "Функция пересылки аудио не работает, потому что \
  126. неправильно определены айди источника и/или цели. Или же бот не добавлен в нужный чат")
  127. return
  128. if message.from_user.id == AGENT_ID:
  129. audio_id = message.audio.file_id
  130. artist = message.audio.performer
  131. title = message.audio.title
  132. try:
  133. await bot.send_audio(
  134. AUDIO_CHAT_ID, audio_id,
  135. f"{artist}\n{title}\nЛекции @newjaipur"
  136. )
  137. except utils.exceptions.ChatNotFound:
  138. await bot.send_message(
  139. config.ADMIN_ID,
  140. "Не удалось отправить аудио. Возможно, бот не добавлен в нужный чат")
  141. # ========================================================================
  142. if __name__ == "__main__":
  143. logging.warning(
  144. f'Начинаем следить за новостями с VIOMS ID {config.VIOMS_CHANNEL_ID} \
  145. каждые {config.CHECK_NEWS_DELAY} минут')
  146. loop = asyncio.get_event_loop()
  147. loop.call_later(DELAY, repeat, get_news, loop)
  148. executor.start_polling(dp, loop=loop)