def __init__(self): # list consisting of submissions that already proccessed but not emailed self.processed = [] self.subreddits = settings.SUBREDDITS self.keywords = settings.KEYWORDS self.exclude = settings.EXCLUDE self.e = EmailHandler()
from bot import Bot from emailhandler import EmailHandler Bot.validate() EmailHandler.register() bot = Bot() bot.run()
class Bot: def __init__(self): # list consisting of submissions that already proccessed but not emailed self.processed = [] self.subreddits = settings.SUBREDDITS self.keywords = settings.KEYWORDS self.exclude = settings.EXCLUDE self.e = EmailHandler() @staticmethod def validate(): try: if not bool(re.search('@gmail.com', settings.SENDER_EMAIL)): raise error.BotInvalidSenderEmail if not bool(re.search('@', settings.RECEPIENT_EMAIL)): raise error.BotInvalidRecepientEmail for subreddit in settings.SUBREDDITS: if str(subreddit) not in settings.KEYWORDS: raise error.BotInvalidKeywords( 'Missing subreddit in keywords') if type(settings.SLEEP) != int: raise error.BotInvalidSleep if type(settings.KEYWORDS) != dict: raise error.BotInvalidKeywords( 'Invalid keywords data structure') if type(settings.EXCLUDE) != dict: raise error.BotInvalidExclude for subreddit, keywords_dict in settings.KEYWORDS.items(): if type(subreddit) != str or type(keywords_dict) != dict: raise error.BotInvalidKeywords( 'Invalid keywords data structure') for attribute, keyword in keywords_dict.items(): if type(attribute) != str or type(keyword) != list: raise error.BotInvalidKeywords( 'Invalid keywords data structure') for subreddit, keywords_dict in settings.EXCLUDE.items(): if type(subreddit) != str or type(keywords_dict) != dict: raise error.BotInvalidExclude( 'Invalid exclude data structure') for attribute, keyword in keywords_dict.items(): if type(attribute) != str or type(keyword) != list: raise error.BotInvalidExclude( 'Invalid exclude data structure') except AttributeError: print('Missing configuration, please check your settings') sys.exit() def log_match(self, subreddit, submission): print( str(datetime.datetime.now()) + " Match found in " + subreddit + " subreddit, adding result to mail ") print((str(datetime.datetime.now()) + ' title : ' + submission.title)) print((str(datetime.datetime.now()) + ' url : ' + submission.url)) def has_keyword(self, subreddit, submission): # get a dict of attributes and its keywords for current subreddit dict_of_keywords = self.keywords[subreddit] for attribute, keywords in dict_of_keywords.items(): submission_attribute_value = getattr(submission, attribute).lower() for keyword in keywords: # each of submission attribute will be caselowered if keyword in submission_attribute_value \ and not self.has_exclude(subreddit, submission) == True \ and submission.id not in self.processed: try: keywords = "{'" + attribute + "': ['" + keyword + "']}" self.e.add_header(keywords=keywords, subreddit=subreddit, exclude=str(self.exclude[subreddit])) except KeyError: keywords = "{'" + attribute + "': ['" + keyword + "']}" self.e.add_header(keywords=keywords, subreddit=subreddit) return True return False def has_exclude(self, subreddit, submission): try: dict_of_keywords = self.exclude[subreddit] except KeyError: return False for attribute, keywords in dict_of_keywords.items(): submission_attribute_value = getattr(submission, attribute).lower() if any(keyword in submission_attribute_value for keyword in keywords) == True: return True return False def process(self, connection): r = connection for subreddit in self.subreddits: subreddit_str = subreddit # the subreddit string subreddit = r.get_subreddit(subreddit) # this is an object try: # connection error submissions = subreddit.get_hot(limit=50) except: print("Error has occured " + str(sys.exc_info()[0])) break for submission in submissions: has_keyword = self.has_keyword(subreddit=subreddit_str, submission=submission) if submission.id not in self.processed and has_keyword: self.log_match(subreddit=subreddit_str, submission=submission) self.e.add_result(submission=submission) self.processed.append(submission.id) time.sleep(2) # sleep between each subreddits if not self.e.content: print( str(datetime.datetime.now()) + " No match found, waiting for next run at " + str(datetime.datetime.now() + datetime.timedelta(seconds=settings.SLEEP))) else: print( str(datetime.datetime.now()) + ' Sending results to ' + settings.RECEPIENT_EMAIL) self.e.send() print( str(datetime.datetime.now()) + ' Waiting for next run at ' + str(datetime.datetime.now() + datetime.timedelta(seconds=settings.SLEEP))) def run(self): while True: try: # connection error r = praw.Reddit(user_agent=settings.USER_AGENT) except: print("Error has occured " + str(sys.exc_info()[0])) break print(str(datetime.datetime.now()) + ' Starting bot') self.process(connection=r) time.sleep(settings.SLEEP) # sleep between each run
def load_config(): """ Load handlers and other appropriate state. Returns a dict of handler identifier -> EmailHandler object """ # globals shared among all handlers global target_class global target global default_interval scp = ConfigParser.SafeConfigParser() # bail on a bad read logger.info("Loading config.") if (scp.read(os.path.expanduser(config_file)) == []): print "Failed to read config file at %s." % config_file sys.exit(1) handlers = {} target = scp.get(global_section, "recipient") target_class = "MAIL" if scp.has_option(global_section, "class"): target_class = scp.get(global_section, "class") if scp.has_option(global_section, "interval"): default_interval = scp.getint(global_section, "interval") # loop through each account for section in scp.sections(): if section == global_section: continue # zephyr is for globals logger.info("Parsing section %s." % section) kwargs = {} kwargs['server'] = server = scp.get(section, "server") use_gssapi = False kwargs['username'] = username = scp.get(section, "username") if scp.has_option(section, 'use_gssapi') and scp.getboolean(section, 'use_gssapi'): kwargs['use_gssapi'] = use_gssapi = True kwargs['username'] = kwargs['password'] = None else: if scp.has_option(section, "password"): password = scp.get(section, "password") else: password = getpass.getpass("Password for server %s, username %s: " % (server, username)) kwargs['password'] = password # determine whether to use ssl; defaults to yes if scp.has_option(section, "ssl") and not scp.getboolean(section, "ssl"): ssl = False default_port = 143 else: ssl = True default_port = 993 kwargs['use_ssl'] = ssl if scp.has_option(section, "port"): port = scp.getint("port") else: port = default_port kwargs['port'] = port if scp.has_option(section, "interval"): interval = scp.getint(section, "interval") else: interval = default_interval interval = max(interval, 10) # don't want to be constantly checking. if scp.has_option(section, "regex"): is_regex = scp.get(section, "regex") else: is_regex = False if scp.has_option(section, "include"): include = scp.get(section, "include") if is_regex: include_re = include else: include_re = clude_to_re(include) else: include_re = "^.*$" if scp.has_option(section, "exclude"): exclude = scp.get(section, "exclude") if is_regex: exclude_re = exclude else: exclude_re = clude_to_re(exclude) else: exclude_re = "^$" kwargs['include'] = include_re kwargs['exclude'] = exclude_re logger.debug("Constructing handler for section %s: server %s, username %s, ssl %s, port %d, interval %d, is_regex %s, include_re %s, exclude_re %s, use_gssapi %s." % (section, server, username, ssl, port, interval, is_regex, include_re, exclude_re, use_gssapi)) handlers[section] = EmailHandler(**kwargs) handlers[section].interval = interval return handlers