Example #1
0
def process_edit_request(r, message):
    """ Processes an edit request if found in check_messages(). Simply reconstructs
	an updated VerseBot comments based on the user's revised verse quotations,
	and replaces the outdated comment with the updated one. Additionally, the bot
	sends the user a message letting them know that the edit has been completed
	successfully.
	NOTE: Users can only edit a VerseBot comment if they authored the parent
	comment of VerseBot's reply. """

    try:
        comment_url = message.body[1:message.body.find('}')]
        comment = r.get_submission(comment_url)
    except:
        message.reply(
            'An error occurred while processing your request. Please make sure that you do not modify the subject line of your message to VerseBot.'
        )
        comment = False
    if message.author == comment.author and comment:
        verses_to_find = regex.find_bracketed_text(message.body)
        lookup_list = list()
        if len(verses_to_find) != 0:
            for ver in verses_to_find:
                next_ver = regex.find_verses(ver)
                lookup_list.append(str(next_ver))
            if len(lookup_list) != 0:
                for reply in comment.comments[0].replies:
                    if str(reply.author) == get_bot_username():
                        try:
                            print(
                                str(comment.author) +
                                ' has requested a comment edit...')
                            link = reply.permalink[24:comment.permalink.
                                                   find('/', 24)]
                            verse_object = Verse(lookup_list, message,
                                                 comment_url, link)
                            edited_comment = '*^This ^comment ^has ^been ^edited ^by ^' + str(
                                comment.author
                            ) + '.* \n\n' + verse_object.get_comment()
                            remove_invalid_statistics(reply.body, link)
                            reply.edit(edited_comment)
                            database.update_db_stats(verse_object)
                            verse_object.clear_verses()
                            message.mark_as_read()
                            message.reply(
                                '[Your triggered VerseBot response](' +
                                comment_url +
                                ') has been successfully edited to reflect your updated quotations.'
                            )
                            break
                        except:
                            print(
                                'Comment edit failed. Will try again later...')
                            verse_object.clear_verses()
                lookup_list[:] = []
            else:
                message.mark_as_read()
    else:
        message.mark_as_read()
Example #2
0
    def respond_to_edit_request(self, message):
        """ Responds to an edit request. The bot will parse the body of the message, looking for verse
        quotations. These will replace the quotations that were placed in the original response to the
        user. Once the comment has been successfully edited, the bot then sends a message to the user
        letting them know that their verse quotations have been updated. """

        try:
            comment_url = message.body[1:message.body.find("}")]
            comment = self.r.get_submission(comment_url)
        except:
            try:
                message.reply("An error occurred while processing your edit request. "
                    "Please make sure that you do not modify the subject line of your message to %s."
                    % REDDIT_USERNAME)
            except requests.exceptions.ConnectionError:
                pass
            return

        if message.author == comment.author and comment:
            verses = find_verses(message.body)
            if verses is not None:
                for reply in comment.comments[0].replies:
                    if str(reply.author) == REDDIT_USERNAME:
                        try:
                            self.log.info("%s has requested a comment edit..." % comment.author)
                            link = reply.permalink[24:comment.permalink.find("/", 24)]
                            response = Response(message, self.parser, comment_url)
                            for verse in verses:
                                book_name = books.get_book(verse[0])
                                if book_name is not None:
                                    v = Verse(book_name,  # Book
                                        verse[1],  # Chapter
                                        verse[3],  # Translation
                                        message.author,  # User
                                        link,  # Subreddit
                                        verse[2])  # Verse
                                    if not response.is_duplicate_verse(v):
                                        response.add_verse(v)
                            if len(response.verse_list) != 0:
                                message_response = ("*^This ^comment ^has ^been ^edited ^by ^%s.*\n\n" % message.author)
                                message_response += response.construct_message()
                                if message_response is not None:
                                    self.log.info("Editing %s's comment with updated verse quotations..." % message.author)
                                    database.remove_invalid_statistics(reply.body, link)
                                    reply.edit(message_response)
                                    database.update_db_stats(response.verse_list)
                                    try:
                                        message.reply("[Your triggered %s response](%s) has been successfully edited to reflect"
                                            " your updated quotations." % (REDDIT_USERNAME, comment_url))
                                    except requests.exceptions.ConnectionError:
                                        pass
                                    break
                        except:
                            raise
                            self.log.warning("Comment edit failed. Will try again later...")
                            break
Example #3
0
    def respond_to_username_mention(self, msg):
        """ Responds to a username mention. This could either contain one or
        more valid Bible verse quotation requests, or it could simply be a
        username mention without any valid Bible verses. If there are valid
        Bible verses, VerseBot generates a response that contains the text
        from these quotations. Otherwise, the message is forwarded to the
        VerseBot admin for review.

        :param msg: The message that contains the username mention
        """
        verses = find_verses(msg.body)
        if verses is not None:
            response = Response(msg, self.parser)
            for verse in verses:
                book_name = books.get_book(verse[0])
                if book_name is not None:
                    v = Verse(
                        book_name,  # Book
                        verse[1],  # Chapter
                        verse[3],  # Translation
                        msg.author,  # User
                        msg.subreddit.display_name,  # Subreddit
                        verse[2])  # Verse
                    if not response.is_duplicate_verse(v):
                        response.add_verse(v)
            if len(response.verse_list) != 0:
                message_response = response.construct_message()
                if message_response is not None:
                    self.log.info("Replying to %s with verse quotations..." %
                                  msg.author)
                    try:
                        msg.reply(message_response)
                        database.update_db_stats(response.verse_list)
                        database.increment_comment_count()
                    except praw.errors.Forbidden:
                        # This message is unreachable.
                        pass
                    except praw.errors.APIException as err:
                        if err.error_type in ("TOO_OLD", "DELETED_LINK",
                                              "DELETED_COMMENT"):
                            self.log.warning("An error occurred while replying"
                                             " with error_type %s." %
                                             err.error_type)
        else:
            self.log.info("No verses found in this message. "
                          "Forwarding to /u/%s..." % VERSEBOT_ADMIN)
            try:
                self.r.send_message(
                    VERSEBOT_ADMIN, "Forwarded VerseBot Message",
                    "%s\n\n[[Link to Original Message](%s)]" %
                    (msg.body, msg.permalink))
            except requests.ConnectionError:
                pass
Example #4
0
    def respond_to_username_mention(self, msg):
        """ Responds to a username mention. This could either contain one or
        more valid Bible verse quotation requests, or it could simply be a
        username mention without any valid Bible verses. If there are valid
        Bible verses, VerseBot generates a response that contains the text
        from these quotations. Otherwise, the message is forwarded to the
        VerseBot admin for review.

        :param msg: The message that contains the username mention
        """
        verses = find_verses(msg.body)
        if verses is not None:
            response = Response(msg, self.parser)
            for verse in verses:
                book_name = books.get_book(verse[0])
                if book_name is not None:
                    v = Verse(book_name,                   # Book
                              verse[1],                    # Chapter
                              verse[3],                    # Translation
                              msg.author,                  # User
                              msg.subreddit.display_name,  # Subreddit
                              verse[2])                    # Verse
                    if not response.is_duplicate_verse(v):
                        response.add_verse(v)
            if len(response.verse_list) != 0:
                message_response = response.construct_message()
                if message_response is not None:
                    self.log.info("Replying to %s with verse quotations..."
                                  % msg.author)
                    try:
                        msg.reply(message_response)
                        database.update_db_stats(response.verse_list)
                        database.increment_comment_count()
                    except praw.errors.Forbidden:
                        # This message is unreachable.
                        pass
                    except praw.errors.APIException as err:
                        if err.error_type in ("TOO_OLD", "DELETED_LINK",
                                              "DELETED_COMMENT"):
                            self.log.warning("An error occurred while replying"
                                             " with error_type %s."
                                             % err.error_type)
        else:
            self.log.info("No verses found in this message. "
                          "Forwarding to /u/%s..." % VERSEBOT_ADMIN)
            try:
                self.r.send_message(VERSEBOT_ADMIN,
                                    "Forwarded VerseBot Message",
                                    "%s\n\n[[Link to Original Message](%s)]"
                                    % (msg.body, msg.permalink))
            except requests.ConnectionError:
                pass
    async def send_verses_response(self, msg, websocket):
        user = msg['user']
        channel = msg['channel']
        body = msg['text']

        match = re.search(r'["“].*"', body)

        if match is not None:
            reference = self.search(match.group(0))
            if reference is None:
                pass
            else:
                body = '[' + reference + ']'

        verses = find_verses(body)
        await self.send_verses(body, verses, user, channel, websocket)
Example #6
0
    def respond_to_edit_request(self, msg):
        """ Responds to an edit request. The bot will parse the body of the
        message, looking for verse quotations. These will replace the
        quotations that were placed in the original response to the user.
        Once the comment has been successfully edited, the bot then sends a
        message to the user letting them know that their verse quotations
        have been updated.

        :param msg: The message that contains the edit request
        """
        try:
            comment_url = re.search("\{(.*?)\}", msg.body).group(1)
            comment = self.r.get_submission(comment_url)
        except:
            try:
                msg.reply("An error occurred while processing your edit "
                          "request. Please make sure that you do not modify "
                          "the subject line of your message to %s." %
                          REDDIT_USERNAME)
            except requests.ConnectionError:
                pass
            return

        if msg.author == comment.author and comment:
            verses = find_verses(msg.body)
            if verses is not None:
                for reply in comment.comments[0].replies:
                    if str(reply.author) == REDDIT_USERNAME:
                        try:
                            self.log.info(
                                "%s has requested a comment edit..." %
                                comment.author)
                            sub = re.search("/r/(.*?)/", comment_url).group(1)
                            response = Response(msg, self.parser, comment_url)
                            for verse in verses:
                                book_name = books.get_book(verse[0])
                                if book_name is not None:
                                    v = Verse(
                                        book_name,  # Book
                                        verse[1],  # Chapter
                                        verse[3],  # Translation
                                        msg.author,  # User
                                        sub,  # Subreddit
                                        verse[2])  # Verse
                                    if not response.is_duplicate_verse(v):
                                        response.add_verse(v)
                            if len(response.verse_list) != 0:
                                msg_response = ("*^This ^comment ^has ^been "
                                                "^edited ^by ^%s.*\n\n" %
                                                msg.author)
                                msg_response += response.construct_message()
                                if msg_response is not None:
                                    self.log.info(
                                        "Editing %s's comment with "
                                        "updated verse quotations..." %
                                        msg.author)
                                    database.remove_invalid_stats(
                                        reply.body, sub)
                                    reply.edit(msg_response)
                                    database.update_db_stats(
                                        response.verse_list)
                                    try:
                                        msg.reply(
                                            "[Your triggered %s "
                                            "response](%s) has been "
                                            "successfully edited to "
                                            "reflect your updated "
                                            "quotations." %
                                            (REDDIT_USERNAME, comment_url))
                                    except requests.ConnectionError:
                                        pass
                                    break
                        except:
                            self.log.warning("Comment edit failed. "
                                             "Will try again later...")
Example #7
0
def main():
	""" The main program for VerseBot. Starts a loop that infinitely retrieves, scans, processes, and replies
	to comments. """
	
	print('Starting up VerseBot...')

	# Connects to reddit via PRAW.
	try:
		r = praw.Reddit(user_agent = ('VerseBot by /u/mgrieger. Github: https://github.com/matthieugrieger/versebot'))
		r.login(config.get_bot_username(), config.get_bot_password())
		print('Connected to reddit!')
	except:
		print('Connection to reddit failed. Either reddit is down at the moment or something in the config is incorrect.')
		exit()

	print('Connecting to database...')
	database.connect()
	print('Cleaning database...')
	database.clean_comment_id_database()

	print('Retrieving supported translations...')
	find_supported_translations()

	lookup_list = list()
	comment_ids_this_session = set()
	
	#check_message_timer = datetime.datetime.utcnow()
	
	print('Beginning to scan comments...')
	while True:
		comments = praw.helpers.comment_stream(r, 'all', limit=None)
		for comment in comments:
			# This if statement allows for messages to be checked every 2 minutes (or so). Ideally this would be
			# done with another timed thread, but Reddit objects in PRAW (which check_messages() takes as
			# an argument) are not thread-safe.
			#if (datetime.datetime.utcnow() - check_message_timer).seconds >= 120:
			#	print('Checking messages...')
			#	check_messages(r)
			#	check_message_timer = datetime.datetime.utcnow()
			if comment.author != config.get_bot_username() and not database.check_comment_id(comment.id) and comment.id not in comment_ids_this_session:
				comment_ids_this_session.add(comment.id)
				verses_to_find = regex.find_bracketed_text(comment.body)
				if len(verses_to_find) != 0:
					for ver in verses_to_find:
						next_ver = regex.find_verses(ver)
						lookup_list.append(str(next_ver))

					if len(lookup_list) != 0:
						verse_object = Verse(lookup_list, comment)
						next_comment = verse_object.get_comment()
						if next_comment != False:
							try:
								comment.reply(next_comment)
							except requests.exceptions.HTTPError, err:
								# If true, this means the bot is banned.
								if str(err) == '403 Client Error: Forbidden':
									print('Banned from subreddit. Cannot reply.')
									next_comment = False
							except praw.errors.APIException, err:
								if err.error_type in ('TOO_OLD','DELETED_LINK', 'DELETED_COMMENT'):
									next_comment = False
								else:
									raise
					else:
						next_comment = False

					if next_comment != False:
						print('Inserting new comment id to database...')
						database.add_comment_id(comment.id)
						print('Updating statistics...')
						database.update_db_stats(verse_object)

						lookup_list[:] = []
					else:
						try:
							comment_ids_this_session.remove(comment.id)
						except KeyError:
							pass
						lookup_list[:] = []
					verse_object.clear_verses()
Example #8
0
 def test_verse_regex(self):
     self.assertTrue(regex.find_verses("Testing testing! [genesis 5:3-5 (nrsv)]") != None)
     self.assertTrue(regex.find_verses("[genesis (nrsv)") == None)
Example #9
0
 def test_verse_regex(self):
     self.assertTrue(regex.find_verses(
         "Testing testing! [genesis 5:3-5 (nrsv)]") is not None)
     self.assertTrue(regex.find_verses("[genesis (nrsv)") is None)
Example #10
0
def main():
    """ The main program for VerseBot. Starts a loop that infinitely retrieves, scans, processes, and replies
	to comments. """

    print('Starting up VerseBot...')

    # Connects to reddit via PRAW.
    try:
        r = praw.Reddit(user_agent=(
            'VerseBot by /u/mgrieger. Github: https://github.com/matthieugrieger/versebot'
        ))
        r.login(config.get_bot_username(), config.get_bot_password())
        print('Connected to reddit!')
    except:
        print(
            'Connection to reddit failed. Either reddit is down at the moment or something in the config is incorrect.'
        )
        exit()

    print('Connecting to database...')
    database.connect()
    print('Cleaning database...')
    database.clean_comment_id_database()

    print('Retrieving supported translations...')
    find_supported_translations()

    lookup_list = list()
    comment_ids_this_session = set()

    #check_message_timer = datetime.datetime.utcnow()

    print('Beginning to scan comments...')
    while True:
        comments = praw.helpers.comment_stream(r, 'all', limit=None)
        for comment in comments:
            # This if statement allows for messages to be checked every 2 minutes (or so). Ideally this would be
            # done with another timed thread, but Reddit objects in PRAW (which check_messages() takes as
            # an argument) are not thread-safe.
            #if (datetime.datetime.utcnow() - check_message_timer).seconds >= 120:
            #	print('Checking messages...')
            #	check_messages(r)
            #	check_message_timer = datetime.datetime.utcnow()
            if comment.author != config.get_bot_username(
            ) and not database.check_comment_id(
                    comment.id) and comment.id not in comment_ids_this_session:
                comment_ids_this_session.add(comment.id)
                verses_to_find = regex.find_bracketed_text(comment.body)
                if len(verses_to_find) != 0:
                    for ver in verses_to_find:
                        next_ver = regex.find_verses(ver)
                        lookup_list.append(str(next_ver))

                    if len(lookup_list) != 0:
                        verse_object = Verse(lookup_list, comment)
                        next_comment = verse_object.get_comment()
                        if next_comment != False:
                            try:
                                comment.reply(next_comment)
                            except requests.exceptions.HTTPError, err:
                                # If true, this means the bot is banned.
                                if str(err) == '403 Client Error: Forbidden':
                                    print(
                                        'Banned from subreddit. Cannot reply.')
                                    next_comment = False
                            except praw.errors.APIException, err:
                                if err.error_type in ('TOO_OLD',
                                                      'DELETED_LINK',
                                                      'DELETED_COMMENT'):
                                    next_comment = False
                                else:
                                    raise
                    else:
                        next_comment = False

                    if next_comment != False:
                        print('Inserting new comment id to database...')
                        database.add_comment_id(comment.id)
                        print('Updating statistics...')
                        database.update_db_stats(verse_object)

                        lookup_list[:] = []
                    else:
                        try:
                            comment_ids_this_session.remove(comment.id)
                        except KeyError:
                            pass
                        lookup_list[:] = []
                    verse_object.clear_verses()
Example #11
0
    def respond_to_edit_request(self, message):
        """ Responds to an edit request. The bot will parse the body of the message, looking for verse
        quotations. These will replace the quotations that were placed in the original response to the
        user. Once the comment has been successfully edited, the bot then sends a message to the user
        letting them know that their verse quotations have been updated. """

        try:
            comment_url = message.body[1:message.body.find("}")]
            comment = self.r.get_submission(comment_url)
        except:
            try:
                message.reply(
                    "An error occurred while processing your edit request. "
                    "Please make sure that you do not modify the subject line of your message to %s."
                    % REDDIT_USERNAME)
            except requests.exceptions.ConnectionError:
                pass
            return

        if message.author == comment.author and comment:
            verses = find_verses(message.body)
            if verses is not None:
                for reply in comment.comments[0].replies:
                    if str(reply.author) == REDDIT_USERNAME:
                        try:
                            self.log.info(
                                "%s has requested a comment edit..." %
                                comment.author)
                            link = reply.permalink[24:comment.permalink.
                                                   find("/", 24)]
                            response = Response(message, self.parser,
                                                comment_url)
                            for verse in verses:
                                book_name = books.get_book(verse[0])
                                if book_name is not None:
                                    v = Verse(
                                        book_name,  # Book
                                        verse[1],  # Chapter
                                        verse[3],  # Translation
                                        message.author,  # User
                                        link,  # Subreddit
                                        verse[2])  # Verse
                                    if not response.is_duplicate_verse(v):
                                        response.add_verse(v)
                            if len(response.verse_list) != 0:
                                message_response = (
                                    "*^This ^comment ^has ^been ^edited ^by ^%s.*\n\n"
                                    % message.author)
                                message_response += response.construct_message(
                                )
                                if message_response is not None:
                                    self.log.info(
                                        "Editing %s's comment with updated verse quotations..."
                                        % message.author)
                                    database.remove_invalid_statistics(
                                        reply.body, link)
                                    reply.edit(message_response)
                                    database.update_db_stats(
                                        response.verse_list)
                                    try:
                                        message.reply(
                                            "[Your triggered %s response](%s) has been successfully edited to reflect"
                                            " your updated quotations." %
                                            (REDDIT_USERNAME, comment_url))
                                    except requests.exceptions.ConnectionError:
                                        pass
                                    break
                        except:
                            raise
                            self.log.warning(
                                "Comment edit failed. Will try again later...")
                            break
Example #12
0
    def respond_to_edit_request(self, msg):
        """ Responds to an edit request. The bot will parse the body of the
        message, looking for verse quotations. These will replace the
        quotations that were placed in the original response to the user.
        Once the comment has been successfully edited, the bot then sends a
        message to the user letting them know that their verse quotations
        have been updated.

        :param msg: The message that contains the edit request
        """
        try:
            comment_url = re.search("\{(.*?)\}", msg.body).group(1)
            comment = self.r.get_submission(comment_url)
        except:
            try:
                msg.reply("An error occurred while processing your edit "
                          "request. Please make sure that you do not modify "
                          "the subject line of your message to %s."
                          % REDDIT_USERNAME)
            except requests.ConnectionError:
                pass
            return

        if msg.author == comment.author and comment:
            verses = find_verses(msg.body)
            if verses is not None:
                for reply in comment.comments[0].replies:
                    if str(reply.author) == REDDIT_USERNAME:
                        try:
                            self.log.info("%s has requested a comment edit..."
                                          % comment.author)
                            sub = re.search("/r/(.*?)/", comment_url).group(1)
                            response = Response(msg, self.parser, comment_url)
                            for verse in verses:
                                book_name = books.get_book(verse[0])
                                if book_name is not None:
                                    v = Verse(book_name,      # Book
                                              verse[1],       # Chapter
                                              verse[3],       # Translation
                                              msg.author,     # User
                                              sub,            # Subreddit
                                              verse[2])       # Verse
                                    if not response.is_duplicate_verse(v):
                                        response.add_verse(v)
                            if len(response.verse_list) != 0:
                                msg_response = ("*^This ^comment ^has ^been "
                                                "^edited ^by ^%s.*\n\n"
                                                % msg.author)
                                msg_response += response.construct_message()
                                if msg_response is not None:
                                    self.log.info("Editing %s's comment with "
                                                  "updated verse quotations..."
                                                  % msg.author)
                                    database.remove_invalid_stats(reply.body,
                                                                  sub)
                                    reply.edit(msg_response)
                                    database.update_db_stats(
                                        response.verse_list)
                                    try:
                                        msg.reply("[Your triggered %s "
                                                  "response](%s) has been "
                                                  "successfully edited to "
                                                  "reflect your updated "
                                                  "quotations."
                                                  % (REDDIT_USERNAME,
                                                     comment_url))
                                    except requests.ConnectionError:
                                        pass
                                    break
                        except:
                            self.log.warning("Comment edit failed. "
                                             "Will try again later...")