ircclient.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #!/usr/bin/env python3
  2. import json
  3. import sys
  4. import time
  5. import shlex
  6. import utils
  7. from threading import Thread
  8. from bookworm.constants import IRC_TIME_TO_FIRST_COMMAND, IRC_CHANNEL, REDIS_BOOK_COMMANDS, REDIS_FETCH_FILE, REDIS_STEP_KEY
  9. from bookworm.logger import log, setup_logger
  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...')
  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. bot = command['bot'].strip()
  44. book = command['book'].strip()
  45. self.r.hset('book_'+book, REDIS_STEP_KEY, 'REQUESTED')
  46. self.connection.privmsg(self.target, f'!{bot} {book}')
  47. def on_pubmsg(self, connection, event):
  48. log.debug('pubmsg %s', event)
  49. def on_privmsg(self, connection, event):
  50. log.info('privmsg %s', event)
  51. def on_ctcp(self, connection, event):
  52. if event.target != self.name:
  53. log.debug('ctcp event: %s', event)
  54. log.debug('ctcp event for someone else')
  55. return
  56. log.info('ctcp event: %s', event)
  57. payload = event.arguments[1]
  58. parts = shlex.split(payload) # quotes
  59. log.info(parts)
  60. command = parts.pop(0)
  61. if command != "SEND":
  62. return
  63. log.info('fname %s', parts[-4])
  64. log.info('peer_address %s', irc.client.ip_numstr_to_quad(parts[-3]))
  65. log.info('Port %s', parts[-2])
  66. log.info('size %s', parts[-1])
  67. filename, peer_address, peer_port, size = parts
  68. peer_address = irc.client.ip_numstr_to_quad(peer_address)
  69. peer_port = int(peer_port)
  70. job_key = 'book_' + filename
  71. data = json.dumps({'ip': peer_address,
  72. 'port': peer_port,
  73. 'size': int(size),
  74. 'filename': filename,
  75. "job_key": job_key})
  76. log.info('Publishing to FETCH_FILE: %s', data)
  77. self.r.rpush(REDIS_FETCH_FILE, data)
  78. def on_disconnect(self, connection, event):
  79. sys.exit(0)
  80. def main():
  81. setup_logger()
  82. name = "bookbot" + utils.random_hash()
  83. c = IRCClient(IRC_CHANNEL, name)
  84. c.wait_for_commands()
  85. main()