ircclient.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #!/usr/bin/env python3
  2. import json
  3. import sys
  4. import time
  5. import shlex
  6. from threading import Thread
  7. from bookworm.constants import IRC_TIME_TO_FIRST_COMMAND, IRC_CHANNEL, REDIS_BOOK_COMMANDS, REDIS_STEP_KEY
  8. from bookworm.logger import log, setup_logger
  9. from bookworm.utils import random_hash
  10. import redis
  11. import irc.client
  12. import jaraco.stream.buffer
  13. class IRCClient(irc.client.SimpleIRCClient):
  14. def __init__(self, target, name):
  15. log.info('startup to %s, as %s', target, name)
  16. irc.client.SimpleIRCClient.__init__(self)
  17. irc.client.ServerConnection.buffer_class = jaraco.stream.buffer.LenientDecodingLineBuffer
  18. self.target = target
  19. self.name = name
  20. self.startup = time.time()
  21. self.r = redis.StrictRedis(host='localhost', port=6379)
  22. self.connect("irc.irchighway.net", 6667, name)
  23. t = Thread(target=self.start)
  24. t.daemon = True
  25. t.start()
  26. def on_welcome(self, connection, event):
  27. if irc.client.is_channel(self.target):
  28. connection.join(self.target)
  29. def wait_for_commands(self):
  30. while True:
  31. log.info('Waiting for message on %s', REDIS_BOOK_COMMANDS)
  32. topic, message = self.r.blpop(REDIS_BOOK_COMMANDS)
  33. log.info('got message: %s', message)
  34. delta = IRC_TIME_TO_FIRST_COMMAND - (time.time() - self.startup)
  35. while delta > 0:
  36. delta = IRC_TIME_TO_FIRST_COMMAND - (time.time() - self.startup)
  37. log.info("I am not ready yet, still %d to go", delta)
  38. time.sleep(max(min(delta, 2), 0))
  39. data = message.decode('utf-8')
  40. log.info('data: %s', data)
  41. command = json.loads(data)
  42. log.info('Command: %s', command)
  43. self.meta = command['meta']
  44. bot = command['bot'].strip()
  45. book = command['book'].strip()
  46. self.job_key = 'book_'+book
  47. self.fetch_queue = command['meta']['fetch_file_queue']
  48. self.r.hset(self.job_key, REDIS_STEP_KEY, 'REQUESTED')
  49. self.connection.privmsg(self.target, f'!{bot} {book}')
  50. def on_pubmsg(self, connection, event):
  51. log.debug('pubmsg %s', event)
  52. def on_privmsg(self, connection, event):
  53. log.info('privmsg %s', event)
  54. def on_ctcp(self, connection, event):
  55. if event.target != self.name:
  56. log.debug('ctcp event: %s', event)
  57. log.debug('ctcp event for someone else')
  58. return
  59. log.info('ctcp event: %s', event)
  60. payload = event.arguments[1]
  61. parts = shlex.split(payload) # quotes
  62. log.info(parts)
  63. command = parts.pop(0)
  64. if command != "SEND":
  65. return
  66. log.info('fname %s', parts[-4])
  67. log.info('peer_address %s', irc.client.ip_numstr_to_quad(parts[-3]))
  68. log.info('Port %s', parts[-2])
  69. log.info('size %s', parts[-1])
  70. filename, peer_address, peer_port, size = parts
  71. peer_address = irc.client.ip_numstr_to_quad(peer_address)
  72. peer_port = int(peer_port)
  73. job_key = 'book_' + filename
  74. data = json.dumps({'ip': peer_address,
  75. 'port': peer_port,
  76. 'size': int(size),
  77. 'filename': filename,
  78. "job_key": job_key,
  79. "meta": self.meta})
  80. log.info('Publishing to %s: %s', self.fetch_queue, data)
  81. self.r.rpush(self.fetch_queue, data)
  82. def on_disconnect(self, connection, event):
  83. sys.exit(0)
  84. def main():
  85. setup_logger()
  86. name = "bookbot" + random_hash()
  87. c = IRCClient(IRC_CHANNEL, name)
  88. c.wait_for_commands()
  89. main()