PrawStreamManager.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import logging
  2. import praw
  3. import os
  4. import signal
  5. import time
  6. from prawcore.exceptions import ServerError, RequestException
  7. from . import WelcomeBot, ModerationHelper, WikiLinker
  8. SUBREDDIT_NAME = 'Piracy'
  9. logger = logging.getLogger('main')
  10. class PrawStreamManager:
  11. def __init__(self):
  12. self.time_last_reloaded_streams = time.time()
  13. self.reload_streams_frequency_secs = 4 * 3600
  14. # watch for SIGTERM signals (docker stop / docker compose down) to exit gracefully
  15. self.kill_now = False
  16. signal.signal(signal.SIGINT, self.exit_gracefully)
  17. signal.signal(signal.SIGTERM, self.exit_gracefully)
  18. logger.info('-- Bot starting')
  19. self.reddit = self._init_reddit()
  20. self.subreddit = self.reddit.subreddit(SUBREDDIT_NAME)
  21. self.new_user_handler = WelcomeBot.WelcomeBot(self.reddit)
  22. self.remover = ModerationHelper.SubmissionRemover(self.reddit)
  23. self.nuker = ModerationHelper.Nuker(self.reddit)
  24. self.wiki_linker = WikiLinker.Linker(self.reddit)
  25. logger.info('-- Loaded handlers')
  26. def monitor_streams(self):
  27. comment_stream = self.subreddit.stream.comments(skip_existing=True, pause_after=-1)
  28. submission_stream = self.subreddit.stream.submissions(skip_existing=True, pause_after=-1)
  29. inbox_stream = self.reddit.inbox.stream(pause_after=-1)
  30. logger.info('-- Initializing streams')
  31. while True:
  32. if self._is_time_to_reload():
  33. logger.info('Reloading streams')
  34. return True
  35. elif self.kill_now:
  36. logger.info('Responding to SIGTERM signal')
  37. return False
  38. try:
  39. for submission in submission_stream:
  40. if submission is None:
  41. break
  42. if submission.author is None:
  43. continue
  44. self.new_user_handler.handle_submission(submission)
  45. for comment in comment_stream:
  46. if comment is None:
  47. break
  48. if comment.author is None:
  49. continue
  50. self.new_user_handler.handle_comment(comment)
  51. self.wiki_linker.handle_comment(comment)
  52. self.remover.handle_comment(comment)
  53. self.nuker.handle_comment(comment)
  54. for message in inbox_stream:
  55. if message is None:
  56. break
  57. if message.author is None:
  58. continue
  59. self.new_user_handler.handle_message(message)
  60. message.mark_read()
  61. except ServerError as e:
  62. logger.exception(e)
  63. time.sleep(45)
  64. return True
  65. except RequestException as e:
  66. logger.exception(e)
  67. time.sleep(25)
  68. return True
  69. except Exception as e:
  70. logger.error("Undefined exception occurred")
  71. logger.exception(e)
  72. return False
  73. def _is_time_to_reload(self):
  74. if time.time() - self.time_last_reloaded_streams > self.reload_streams_frequency_secs:
  75. self.time_last_reloaded_streams = time.time()
  76. return True
  77. return False
  78. def exit_gracefully(self, *args):
  79. self.kill_now = True
  80. def _init_reddit(self):
  81. return praw.Reddit(
  82. username=os.environ['BOT_USERNAME'],
  83. password=os.environ['BOT_PASSWORD'],
  84. client_id=os.environ['CLIENT_ID'],
  85. client_secret=os.environ['CLIENT_SECRET'],
  86. user_agent=os.environ['USER_AGENT'],
  87. )