def getGameDetails(gameID): submission = reddit.submission(url=games[gameID].gameThread) matches = re.findall(r'\[.+\]\(#f/\w+\)\|\d+\|\d+\|\d+\|\d+\|\*\*\d+\*\*', submission.selftext) if matches.__len__() == 2 and checkGameManual( teams[games[gameID].home].name, teams[games[gameID].away].name) is True: g1 = matches[0].split('**') homeScore = g1[1] g2 = matches[1].split('**') awayScore = g2[1] matches = re.findall(r'\s\d:\d\d\|\d', submission.selftext) t1 = matches[0].split("|") quarter = t1[1] if re.search(r'\s0:00', submission.selftext) is not None: quarter = "**F**" if games[gameID].postThread == "": games[gameID].postThread = findPostGame(gameID) if homeScore > awayScore: homeScore = "**" + homeScore + "**" else: awayScore = "**" + awayScore + "**" else: if int(quarter) > 4: quarter = "OT" else: quarter = "Q" + quarter games[gameID].hScore = homeScore games[gameID].aScore = awayScore games[gameID].quarter = quarter else: print(games[gameID].gameThread) manMatches = re.findall( teams[games[gameID].home].name + r'\s|\s' + teams[games[gameID].away].name + r'\s|\s\d+\s|\s\d+\s|\s.+', manualGames) data = None for i in range(manMatches.__len__()): if teams[games[gameID].home].name in manMatches[i]: data = manMatches[i].split(" | ") games[gameID].hScore = data[2] games[gameID].aScore = data[3] games[gameID].quarter = data[4] if "F" in games[gameID].quarter and games[gameID].postThread == "": games[gameID].postThread = findPostGame(gameID)
def main(): import os import time import logging, logging.handlers from pathlib import Path import praw, prawcore from reddit import reddit import db_services from regex_checks import TopicFlags, ExtraFlags, match_control from messages import get_message script_path = Path(__file__).resolve() os.chdir(script_path.parent) logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) #logger.addHandler(logging.StreamHandler()) #logger.disabled = True log_file = script_path.parent / 'log' / script_path.with_suffix( '.log').name if log_file.parent.is_dir(): log_format = '%(asctime)s %(levelname)s %(funcName)s:%(lineno)d | %(message)s' rfh_config = { 'filename': log_file, 'encoding': 'utf-8', 'maxBytes': 5 * 1024 * 1024, # 5 megabytes 'backupCount': 8 } rfh = logging.handlers.RotatingFileHandler(**rfh_config) rfh.setFormatter(logging.Formatter(log_format)) logger.addHandler(rfh) logger.info('Log ({}): {}'.format(logger.name, log_file.absolute())) me = reddit.user.me() sleep_seconds = 30 while True: try: for row in db_services.revisit(): target_id = row['target_id'] reply_id = row['reply_id'] topic_flags = row['topic_flags'] extra_flags = row['extra_flags'] logger.debug( f'Recheck: t1_{reply_id} targeting t3_{target_id}') submission = reddit.submission(target_id) try: submission._fetch() except prawcore.exceptions.NotFound: # This shouldn't happen, even if the submission was deleted. # Avoid processing it in future. logger.warning( 'Skip: recorded submission not found: t3_{}'.format( target_id)) db_services.assign_is_set_0(target_id) continue if not submission.is_self: # This shouldn't happen. logger.warning( 'Note: non-is_self submission: {}-{}'.format( target_id, reply_id)) db_services.assign_is_ignored_1(target_id) continue is_deleted = submission.author is None and submission.selftext == '[deleted]' is_removed = submission.selftext == '[removed]' if is_deleted or is_removed: if is_deleted: logger.info( 'Skip: submission was deleted: {}-{}'.format( target_id, reply_id)) elif is_removed: logger.info( 'Skip: submission was removed: {}-{}'.format( target_id, reply_id)) db_services.assign_is_ignored_1(target_id) continue match_control.check_all(submission.selftext) b = match_control[TopicFlags] y = match_control[ExtraFlags] state_flags_change = (b != topic_flags) or (y != extra_flags) if not state_flags_change: logger.debug('Skip: no change: {}-{}'.format( target_id, reply_id)) continue my_comment = reddit.comment(reply_id) try: my_comment.refresh() except praw.exceptions.PRAWException: # The comment has disappeared. It may have been deleted. logger.warning( f'Warning: missing comment: {target_id}-{reply_id}') db_services.assign_is_set_0(target_id) continue if len(my_comment.replies): logger.info( f'Info: found replies on comment: {target_id}-{reply_id}' ) db_services.assign_is_deletable_0(target_id) message_kwargs = { 'signature': 2, 'pester': True, 'some': bool(y & ExtraFlags.contains_code_block), 'kind': type(submission).__name__, 'redditor': submission.author.name, 'bot_name': me.name, 'reply_id': my_comment.id, 'old_reddit_permalink': 'https://old.reddit.com' + submission.permalink, 'new_reddit_permalink': 'https://new.reddit.com' + submission.permalink } topic_flags_0 = b == 0 if topic_flags_0: # The author has fixed their post. Success! message_kwargs.update({ 'topic_flags': topic_flags, 'passed': True }) message = get_message(**message_kwargs) my_comment.edit(message) logger.info( f'Success: update comment (passing): {target_id}-{reply_id}' ) else: # topic_flags have changed but markdown still not fixed yet. message_kwargs.update({'topic_flags': b, 'passed': False}) message = get_message(**message_kwargs) my_comment.edit(message) logger.info( f'Success: update comment (failing): {target_id}-{reply_id}' ) db_services.assign_topic_flags(b, target_id) db_services.assign_previous_topic_flags(topic_flags, target_id) db_services.assign_extra_flags(y, target_id) time.sleep(sleep_seconds) except (praw.exceptions.PRAWException, prawcore.exceptions.PrawcoreException) as e: if isinstance(e, praw.exceptions.APIException): if e.error_type == 'RATELIMIT': logger.info('Exception: ratelimit exceeded: {}'.format( e.message)) time.sleep(11 * 60) else: logger.warning( 'Exception: unhandled PRAW APIException exception:', exc_info=True) elif isinstance(e, prawcore.exceptions.ResponseException): logger.info('Exception: ResponseException: {}'.format( e.response)) time.sleep(5) elif isinstance(e, prawcore.exceptions.RequestException): logger.info('Exception: RequestException: {}'.format( e.original_exception)) time.sleep(5) else: logger.warning('Exception: unhandled PRAW exception:', exc_info=True) except Exception: logger.error('Exception: unhandled exception:', exc_info=True)
def post(post_id): post = reddit.submission(id=post_id) comments = get_submission_comments(post, 10) return render_template('post.html', post=post, comments=comments)
def process_inbox_item(item): logger.info('[Inbox] Process: inbox item, deletion request (from /u/{}): t4_{}'.format(item.author.name, item.id)) if item.was_comment: logger.info('[Inbox] Skip: ignore non-message item: t1_{}'.format(item.id)) return if time.time() - item.created_utc > ignore_inbox_items_older_than: logger.info('[Inbox] Skip: {0} is older than {1} seconds'.format(type(item).__name__, ignore_inbox_items_older_than)) return delete_match = delete_regexp.match(item.subject) recheck_match = recheck_regexp.match(item.subject) if not (delete_match or recheck_match): logger.info('[Inbox] Skip: no match (subject line): t4_{}'.format(item.id)) return item.mark_read() if delete_match: thing_kind = delete_match.group(1) comment_id = delete_match.group(2) logger.info('[Inbox] Info: deletion request (from /u/{}): "t1_{}"'.format(item.author.name, comment_id)) if thing_kind is not None: if thing_kind != 't1': logger.info(f"[Inbox] Skip: not the kind we're looking for: {thing_kind}_{comment_id}") return target_id = db_services.get_target_id(comment_id) if target_id is None: logger.warning('[Inbox] Warning: could not resolve target_id "{}" from comment: t1_{}'.format(target_id, comment_id)) comment = reddit.comment(comment_id) try: comment.refresh() except praw.exceptions.PRAWException: logger.info('[Inbox] Skip: not found: t1_{}'.format(comment_id)) return by_authority = item.author.name.lower() in trustees if by_authority: comment.delete() if target_id is not None: db_services.assign_is_set_0(target_id) logger.info('[Inbox] Success: force delete: {}-{}'.format(target_id, comment_id)) return if target_id is None: logger.warning('[Inbox] Skip: cannot resolve author_name from null target_id: {}-{}'.format(target_id, comment_id)) return author_name = db_services.get_author_name(target_id) if author_name is None: logger.warning('[Inbox] Skip: could not resolve author_name from target_id: {}-{}'.format(target_id, comment_id)) return if comment.author != me: logger.info('[Inbox] Skip: not owned: {}-{}'.format(target_id, comment_id)) return by_submitter = item.author.name.lower() == author_name.lower() if not by_submitter: logger.info('[Inbox] Skip: delete not permitted: {}-{}'.format(target_id, comment_id)) return if len(comment.replies): logger.info('[Inbox] Skip: has replies: {}-{}'.format(target_id, comment_id)) return if not db_services.is_deletable(comment_id): logger.info('[Inbox] Skip: not deletable: {}-{}'.format(target_id, comment_id)) return comment.delete() db_services.assign_is_set_0(target_id) db_services.assign_is_ignored_1(target_id) logger.info('[Inbox] Success: deleted: {}-{}'.format(target_id, comment_id)) elif recheck_match: logger.info('[Inbox] Process: inbox item, recheck request (from /u/{}): t4_{}'.format(item.author.name, item.id)) by_authority = item.author.name.lower() in trustees if not by_authority: logger.info('[Inbox] Skip: unauthorised: t4_{}'.format(item.id)) return thing_kind = recheck_match.group(1) thing_id = recheck_match.group(2) if thing_kind is None: logger.info('[Inbox] Skip: thing_kind was not specified: {thing_kind}_{thing_id}') return if thing_kind != 't3': logger.info(f"[Inbox] Skip: not the kind we're looking for: {thing_kind}_{thing_id}") return submission = reddit.submission(thing_id) try: submission._fetch() except prawcore.exceptions.NotFound: logger.warning('Skip: submission ID not found: t3_{}'.format(thing_id)) db_services.assign_is_set_0(thing_id) return process_subsmission(submission)
def get_upvote_ratio(self): return reddit.submission(id=self._id).upvote_ratio