telegram-mirror-bot.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import asyncio
  2. import traceback
  3. import html.parser
  4. import irc
  5. import signal
  6. from telegram import Bot
  7. from telegram.constants import MessageLimit
  8. from io import StringIO
  9. TOKEN = "..."
  10. TOKEN_TEST = "..."
  11. MAX_CHANNEL_LENGTH = 10
  12. MAX_NICK_LENGTH = 10
  13. MAX_MESSAGE_LENGTH = MessageLimit.MAX_TEXT_LENGTH - (MAX_CHANNEL_LENGTH + MAX_NICK_LENGTH + 16)
  14. SERVER = "127.0.0.1"
  15. PORT = 6645
  16. CHANNELS = ["#dev","#memes","#philosophy","#markets","#math","#random",]
  17. BOTNICK = "tgbridge"
  18. def signal_handler(sig, frame):
  19. print("Caught termination signal, cleaning up and exiting...")
  20. ircc.disconnect(SERVER, PORT)
  21. print("Shut down successfully")
  22. exit(0)
  23. signal.signal(signal.SIGINT, signal_handler)
  24. signal.signal(signal.SIGTERM, signal_handler)
  25. class HTMLTextExtractor(html.parser.HTMLParser):
  26. def __init__(self):
  27. super(HTMLTextExtractor, self).__init__()
  28. self.reset()
  29. self.strict = False
  30. self.convert_charrefs= True
  31. self.text = StringIO()
  32. def handle_data(self, d):
  33. self.text.write(d)
  34. def get_text(self):
  35. return self.text.getvalue()
  36. def html_to_text(html):
  37. s = HTMLTextExtractor()
  38. s.feed(html)
  39. return s.get_text()
  40. def append_log(channel, username, message):
  41. with open(f"/srv/http/log/{channel}.txt", "a") as fd:
  42. fd.write(f"<{username}> {message}\n")
  43. with open(f"/srv/http/log/all.txt", "a") as fd:
  44. fd.write(f"{channel} <{username}> {message}\n")
  45. ircc = irc.IRC()
  46. ircc.connect(SERVER, PORT, CHANNELS, BOTNICK)
  47. async def main():
  48. while True:
  49. text = ircc.get_response()
  50. if not len(text) > 0:
  51. print("Error: disconnected from server")
  52. exit(-1)
  53. text_list = text.split(' ')
  54. nick = text_list[0].split('!')[0][1:]
  55. if text_list[1] == "PRIVMSG":
  56. channel = text_list[2]
  57. message = ' '.join(text_list[3:])
  58. # remove the prefix
  59. message = message[1:]
  60. # ignore test msgs
  61. if message.lower() == "test" or message.lower() == "echo":
  62. continue
  63. if nick == "testbot":
  64. continue
  65. # Strip all HTML tags
  66. channel = channel.replace("<", "&lt;")
  67. channel = channel.replace(">", "&gt;")
  68. nick = nick.replace("<", "&lt;")
  69. nick = nick.replace(">", "&gt;")
  70. message = message.replace("<", "&lt;")
  71. message = message.replace(">", "&gt;")
  72. # https://www.irchelp.org/protocol/ctcpspec.html
  73. #
  74. # "This is used by losers on IRC to simulate 'role playing' games"
  75. # "Presumably other users on the channel are suitably impressed."
  76. if message.find("ACTION") == 1:
  77. message = nick + message[7:]
  78. nick = "*"
  79. append_log(channel, nick, message)
  80. # Pad and left/right justify channel and nickname
  81. channel = channel[:MAX_CHANNEL_LENGTH].ljust(MAX_CHANNEL_LENGTH)
  82. nick = nick[:MAX_NICK_LENGTH].rjust(MAX_NICK_LENGTH)
  83. # Send messages to Telegram in chunks
  84. while len(message) > 0:
  85. string_to_telegram = f"<code>{channel} {nick} |</code> {message[:MAX_MESSAGE_LENGTH]}"
  86. # Keep retrying until the fucker is sent
  87. while True:
  88. try:
  89. async with Bot(TOKEN) as bot:
  90. await bot.send_message("@darkfi_darkirc", string_to_telegram,
  91. parse_mode="HTML",
  92. disable_notification=True,
  93. disable_web_page_preview=True)
  94. break
  95. #except telegram.error.BadRequest:
  96. # pass
  97. except:
  98. print(channel, string_to_telegram)
  99. print(traceback.format_exc())
  100. await asyncio.sleep(3)
  101. message = message[MAX_MESSAGE_LENGTH:]
  102. asyncio.run(main())