telegram-mirror-bot.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. continue
  52. text_list = text.split(' ')
  53. nick = text_list[0].split('!')[0][1:]
  54. if text_list[1] == "PRIVMSG":
  55. channel = text_list[2]
  56. message = ' '.join(text_list[3:])
  57. # remove the prefix
  58. message = message[1:]
  59. # ignore test msgs
  60. if message.lower() == "test" or message.lower() == "echo":
  61. continue
  62. if nick == "testbot":
  63. continue
  64. # Strip all HTML tags
  65. channel = channel.replace("<", "&lt;")
  66. channel = channel.replace(">", "&gt;")
  67. nick = nick.replace("<", "&lt;")
  68. nick = nick.replace(">", "&gt;")
  69. message = message.replace("<", "&lt;")
  70. message = message.replace(">", "&gt;")
  71. # https://www.irchelp.org/protocol/ctcpspec.html
  72. #
  73. # "This is used by losers on IRC to simulate 'role playing' games"
  74. # "Presumably other users on the channel are suitably impressed."
  75. if message.find("ACTION") == 1:
  76. message = nick + message[7:]
  77. nick = "*"
  78. append_log(channel, nick, message)
  79. # Pad and left/right justify channel and nickname
  80. channel = channel[:MAX_CHANNEL_LENGTH].ljust(MAX_CHANNEL_LENGTH)
  81. nick = nick[:MAX_NICK_LENGTH].rjust(MAX_NICK_LENGTH)
  82. # Send messages to Telegram in chunks
  83. while len(message) > 0:
  84. string_to_telegram = f"<code>{channel} {nick} |</code> {message[:MAX_MESSAGE_LENGTH]}"
  85. # Keep retrying until the fucker is sent
  86. while True:
  87. try:
  88. async with Bot(TOKEN) as bot:
  89. await bot.send_message("@darkfi_darkirc", string_to_telegram,
  90. parse_mode="HTML",
  91. disable_notification=True,
  92. disable_web_page_preview=True)
  93. break
  94. #except telegram.error.BadRequest:
  95. # pass
  96. except:
  97. print(channel, string_to_telegram)
  98. print(traceback.format_exc())
  99. await asyncio.sleep(3)
  100. message = message[MAX_MESSAGE_LENGTH:]
  101. asyncio.run(main())