telegram-mirror-bot.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import asyncio, json, traceback
  2. import html.parser
  3. import telegram
  4. from telegram import Bot, Update
  5. from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
  6. from io import StringIO
  7. TOKEN = "..."
  8. TOKEN_TEST = "..."
  9. class IrcBot:
  10. async def connect(self, server, port):
  11. self._reader, self._writer = await asyncio.open_connection(server, port)
  12. self._send("USER tgbridge 0 * :tgbridge")
  13. self._send("NICK tgbridge")
  14. await self._recv()
  15. self._send("CAP REQ :no-history")
  16. await self._recv()
  17. self._send("CAP END")
  18. def _send(self, msg):
  19. msg += "\r\n"
  20. self._writer.write(msg.encode())
  21. async def _recv(self):
  22. message = await self._reader.readline()
  23. message = message.decode()
  24. return message.removesuffix("\r\n")
  25. async def get_message(self):
  26. while True:
  27. line = await self._recv()
  28. print(f"Received line: {line}")
  29. tokens = line.split(" ")
  30. if len(tokens) < 2 or tokens[1] != "PRIVMSG":
  31. continue
  32. assert tokens[0][0] == ":"
  33. username = tokens[0].split("!")[0][1:]
  34. channel = tokens[2]
  35. message = ":".join(line.split(":")[2:])
  36. return (username, channel, message)
  37. class HTMLTextExtractor(html.parser.HTMLParser):
  38. def __init__(self):
  39. super(HTMLTextExtractor, self).__init__()
  40. self.reset()
  41. self.strict = False
  42. self.convert_charrefs= True
  43. self.text = StringIO()
  44. def handle_data(self, d):
  45. self.text.write(d)
  46. def get_text(self):
  47. return self.text.getvalue()
  48. def html_to_text(html):
  49. s = HTMLTextExtractor()
  50. s.feed(html)
  51. return s.get_text()
  52. def append_log(channel, username, message):
  53. with open(f"/srv/http/log/{channel}.txt", "a") as fd:
  54. fd.write(f"<{username}> {message}\n")
  55. with open(f"/srv/http/log/all.txt", "a") as fd:
  56. fd.write(f"{channel} <{username}> {message}\n")
  57. async def main():
  58. irc = IrcBot()
  59. await irc.connect("localhost", 6667)
  60. while True:
  61. nick, channel, message = await irc.get_message()
  62. if message.lower() == "test":
  63. continue
  64. if nick == "testbot":
  65. continue
  66. # Strip all HTML tags
  67. #message = html_to_text(message)
  68. message = message.replace("<", "&lt;")
  69. message = message.replace(">", "&gt;")
  70. # Limit line lengths
  71. message = message[:300]
  72. # Left pad nickname
  73. nick = nick.replace("<", "&lt;")
  74. nick = nick.replace(">", "&gt;")
  75. nick = nick.rjust(12)
  76. # Limit line lengths
  77. message = message[:300]
  78. msg = f"<code>{channel} {nick} |</code> {message}"
  79. append_log(channel, nick, message)
  80. # Keep retrying until the fucker is sent
  81. while True:
  82. try:
  83. async with Bot(TOKEN) as bot:
  84. await bot.send_message("@darkfi_darkirc", msg,
  85. parse_mode="HTML",
  86. disable_notification=True,
  87. disable_web_page_preview=True)
  88. break
  89. #except telegram.error.BadRequest:
  90. # pass
  91. except:
  92. print(channel, msg)
  93. print(traceback.format_exc())
  94. await asyncio.sleep(3)
  95. asyncio.run(main())