bot.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #!/usr/bin/env python3.7
  2. import logging
  3. import queue
  4. import shlex
  5. import subprocess
  6. import sys
  7. import readline
  8. import os
  9. from threading import Thread
  10. from ircclient import IRCClient, MODE_SEARCH, MODE_BOOK
  11. logging.basicConfig(level=logging.DEBUG)
  12. log = logging.getLogger(__name__)
  13. log.setLevel(logging.DEBUG)
  14. histfile = os.path.join(os.path.expanduser("~"), ".book_history")
  15. def usage():
  16. print("USAGE:")
  17. print("\t SEARCH <BOOK>")
  18. print("\t BOOK <BOT COMMAND>")
  19. def get_books_from_list(filename):
  20. f = open(filename, "r")
  21. ret = []
  22. for line in f.readlines():
  23. line = line.lower().strip()
  24. if not line.startswith('!') or not any(_type in line for _type in ['epub', 'mobi']):
  25. continue
  26. ret.append(line)
  27. log.info("Book matches: %s", line)
  28. ret = list(set(ret)) # dedup
  29. return ret
  30. def mode_from_files(files):
  31. for f in files:
  32. f = f.lower()
  33. if 'searchbot' in f or 'searchook' in f.lower():
  34. return MODE_SEARCH
  35. return MODE_BOOK
  36. def handle_files(files):
  37. log.info("Unarchived files %s", files)
  38. out = []
  39. mode = mode_from_files(files)
  40. if mode == MODE_SEARCH:
  41. for f in files:
  42. if "searchbot" not in f.lower() and "searchook" not in f.lower():
  43. continue
  44. out.extend(get_books_from_list(f))
  45. return
  46. for f in files:
  47. if f.lower().endswith(".epub"):
  48. log.info("EPUB %s", f)
  49. new_fname = f.replace("epub", "mobi")
  50. p = subprocess.Popen(["ebook-convert", f, new_fname], stdout=subprocess.DEVNULL)
  51. # TODO log to file?
  52. p.wait()
  53. out.append(new_fname)
  54. out.append(f)
  55. # TODO make paths absolute?
  56. for filename in out:
  57. log.info(filename)
  58. def handle_results(q):
  59. while True:
  60. item = q.get()
  61. log.info("Got a result! %s", item)
  62. if item['type'] == 'status':
  63. print(item['key'], item['status'])
  64. elif item['type'] == 'files':
  65. handle_files(item['files'])
  66. def main():
  67. q = queue.Queue()
  68. rq = queue.Queue()
  69. workers = []
  70. worker = IRCClient(command_queue=q, results_queue=rq)
  71. worker.start()
  72. workers.append(worker)
  73. results_t = Thread(target=handle_results, args=(rq,))
  74. results_t.daemon = True
  75. results_t.start()
  76. while True:
  77. line = input('> ').strip().lower()
  78. try:
  79. split = shlex.split(line)
  80. except Exception as e:
  81. print(e)
  82. continue
  83. if len(split) == 0:
  84. continue
  85. if split[0].lower() not in [MODE_SEARCH, MODE_BOOK]:
  86. usage()
  87. continue
  88. if not any([ not worker.busy for worker in workers]):
  89. print("Spawning a new worker as all are busy...")
  90. worker = IRCClient(command_queue=q, results_queue=rq)
  91. worker.start()
  92. workers.append(worker)
  93. mode = split[0]
  94. query = " ".join(split[1:])
  95. data = {'query': query, 'mode': mode}
  96. q.put(data)
  97. print("Command acknowledged")
  98. results_t.join()
  99. for worker in workers:
  100. worker.join()
  101. if __name__ == "__main__":
  102. try:
  103. readline.read_history_file(histfile)
  104. # default history len is -1 (infinite), which may grow unruly
  105. readline.set_history_length(10000)
  106. except FileNotFoundError:
  107. pass
  108. try:
  109. main()
  110. except KeyboardInterrupt:
  111. print("\nBye")
  112. except EOFError:
  113. print("\nBye")
  114. readline.write_history_file(histfile)