예제 #1
0
    def _enable_watch(self, summons: Summons) -> NoReturn:

        response = SummonsResponse(summons=summons)
        with self.uowm.start() as uow:
            existing_watch = uow.repostwatch.find_existing_watch(
                summons.requestor, summons.post_id)
            if existing_watch:
                if not existing_watch.enabled:
                    log.info(
                        'Found existing watch that is disabled.  Enabling watch %s',
                        existing_watch.id)
                    existing_watch.enabled = True
                    response.message = WATCH_ENABLED
                    uow.commit()
                    self._send_response(response)
                    return
                else:
                    response.message = WATCH_ALREADY_ENABLED
                    self._send_response(response)
                    return

        repost_watch = RepostWatch(post_id=summons.post_id,
                                   user=summons.requestor,
                                   enabled=True)

        with self.uowm.start() as uow:
            uow.repostwatch.add(repost_watch)
            try:
                uow.commit()
                response.message = WATCH_ENABLED
            except Exception as e:
                log.exception('Failed save repost watch', exc_info=True)
                response.message = 'An error prevented me from creating a watch on this post.  Please try again'

        self._send_response(response)
예제 #2
0
    def _send_private_message(self,
                              user: Redditor,
                              message_body,
                              subject: Text = 'Repost Check',
                              source: Text = None,
                              post_id: Text = None,
                              comment_id: Text = None) -> NoReturn:

        if not user:
            log.error('No user provided to send private message')
            return
        try:
            start_time = perf_counter()
            user.message(subject, message_body)
            self._record_api_event(
                float(round(perf_counter() - start_time, 2)),
                'private_message', self.reddit.reddit.auth.limits['remaining'])
            log.info('Sent PM to %s. ', user.name)
        except Exception as e:
            log.exception('Failed to send PM to %s', user.name, exc_info=True)
            raise

        self._save_private_message(
            BotPrivateMessage(subject=subject,
                              body=message_body,
                              in_response_to_post=post_id,
                              in_response_to_comment=comment_id,
                              triggered_from=source,
                              recipient=user.name))
예제 #3
0
    def _process_comment(self, bot_comment: BotComment):

        reddit_comment = self._get_comment_data(bot_comment.perma_link)

        if not reddit_comment:
            log.error('Failed to locate comment %s', bot_comment.comment_id)
            return

        bot_comment.karma = reddit_comment['ups']
        if bot_comment.karma <= self.config.bot_comment_karma_remove_threshold:
            log.info('Comment %s has karma of %s.  Removing',
                     bot_comment.comment_id, bot_comment.karma)
            if self.notification_svc:
                self.notification_svc.send_notification(
                    f'Removing comment with {bot_comment.karma} karma. https://reddit.com{bot_comment.perma_link}',
                    subject='Removing Downvoted Comment')
            comment = self.reddit.comment(bot_comment.comment_id)
            try:
                comment.delete()
            except Exception as e:
                log.exception('Failed to delete comment %s',
                              bot_comment.comment_id,
                              exc_info=True)
            bot_comment.needs_review = True
            bot_comment.active = False
        elif bot_comment.karma <= self.config.bot_comment_karma_flag_threshold:
            log.info('Comment %s has karma of %s.  Flagging for review',
                     bot_comment.comment_id, bot_comment.karma)
            bot_comment.needs_review = True
 def monitor_for_summons(self, subreddits: str = 'all'):
     """
     Monitors the subreddits set in the config for comments containing the summoning string
     """
     log.info('Starting praw summons monitor for subs %s', subreddits)
     while True:
         try:
             for comment in self.reddit.subreddit(
                     subreddits).stream.comments():
                 if comment is None:
                     continue
                 if self.check_for_summons(comment.body, '\?repost'):
                     if comment.author.name.lower() in [
                             'sneakpeekbot', 'automoderator'
                     ]:
                         continue
                     self._save_summons(comment)
         except ResponseException as e:
             if e.response.status_code == 429:
                 log.error('IP Rate limit hit.  Waiting')
                 time.sleep(60)
                 continue
         except Exception as e:
             if 'code: 429' in str(e):
                 log.error('Too many requests from IP.  Waiting')
                 time.sleep(60)
                 continue
             log.exception('Praw summons thread died', exc_info=True)
예제 #5
0
    def send_mod_mail(self, subreddit_name: Text, subject: Text, body: Text, triggered_from: Text = None) -> NoReturn:
        """
        Send a modmail message
        :rtype: NoReturn
        :param subreddit_name: name of subreddit
        :param subject: Message Subject
        :param body: Message Body
        """
        subreddit = self.reddit.subreddit(subreddit_name)
        if not subreddit:
            log.error('Failed to get Subreddit %s when attempting to send modmail')
            return

        try:
            subreddit.message(subject, body)
            self._save_private_message(
                BotPrivateMessage(
                    subject=subject,
                    body=body,
                    triggered_from=triggered_from,
                    recipient=subreddit_name
                )
            )
        except RedditAPIException:
            log.exception('Problem sending modmail message', exc_info=True)
예제 #6
0
    def _process_comment(self, bot_comment: BotComment):

        reddit_comment = self._get_comment_data(bot_comment.perma_link)

        if not reddit_comment:
            log.error('Failed to locate comment %s', bot_comment.comment_id)
            return

        bot_comment.karma = reddit_comment['ups']
        if bot_comment.karma <= self.config.bot_comment_karma_remove_threshold:
            log.info('Comment %s has karma of %s.  Removing',
                     bot_comment.comment_id, bot_comment.karma)
            comment = self.reddit.comment(bot_comment.comment_id)
            try:
                comment.delete()
            except Exception as e:
                log.exception('Failed to delete comment %s',
                              bot_comment.comment_id,
                              exc_info=True)
            bot_comment.needs_review = True
            bot_comment.active = False
        elif bot_comment.karma <= self.config.bot_comment_karma_flag_threshold:
            log.info('Comment %s has karma of %s.  Flagging for review',
                     bot_comment.comment_id, bot_comment.karma)
            bot_comment.needs_review = True
예제 #7
0
 def _reply_to_comment(self, comment_id: Text, comment_body: Text, subreddit: Text = None) -> Optional[Comment]:
     """
     Post a given reply to a given comment ID
     :rtype: Optional[Comment]
     :param comment_id: ID of comment to reply to
     :param comment_body: Body of the comment to leave in reply
     :return:
     """
     comment = self.reddit.comment(comment_id)
     if not comment:
         log.error('Failed to find comment %s', comment_id)
         return
     try:
         start_time = perf_counter()
         reply_comment = comment.reply(comment_body)
         self._record_api_event(
             float(round(perf_counter() - start_time, 2)),
             'reply_to_comment',
             self.reddit.reddit.auth.limits['remaining']
         )
         self._log_response(reply_comment)
         log.info('Left comment at: https://reddit.com%s', reply_comment.permalink)
         return reply_comment
     except Forbidden:
         log.exception('Forbidden to respond to comment %s', comment_id, exc_info=False)
         # If we get Forbidden there's a chance we don't have hte comment data to get subreddit
         if subreddit:
             self._save_banned_sub(subreddit)
         raise
     except AssertionError:
         log.exception('Problem leaving comment', exc_info=True)
         raise
예제 #8
0
 def _remove_post(self, monitored_sub: MonitoredSub,
                  submission: Submission) -> NoReturn:
     """
     Check if given sub wants posts removed.  Remove is enabled
     @param monitored_sub: Monitored sub
     @param submission: Submission to remove
     """
     if monitored_sub.remove_repost:
         if not monitored_sub.removal_reason:
             log.error(
                 'Sub %s does not have a removal reason set.  Cannot remove',
                 monitored_sub.name)
             return
         try:
             removal_reason_id = self._get_removal_reason_id(
                 monitored_sub.removal_reason, submission.subreddit)
             if not removal_reason_id:
                 log.error('Failed to get Removal Reason ID from reason %s',
                           monitored_sub.removal_reason)
                 return
             submission.mod.remove(reason_id=removal_reason_id)
             log.error(
                 '[%s][%s] - Failed to remove post using reason ID %s.  Likely a bad reasons ID',
                 monitored_sub.name, submission.id,
                 monitored_sub.removal_reason_id)
             submission.mod.remove()
         except Forbidden:
             log.error(
                 'Failed to remove post https://redd.it/%s, no permission',
                 submission.id)
         except Exception as e:
             log.exception('Failed to remove submission https://redd.it/%s',
                           submission.id,
                           exc_info=True)
    def _offer_watch(self, submission: Submission) -> NoReturn:
        """
        Offer to add watch to OC post
        :param search:
        """
        if not self.config.top_post_offer_watch:
            log.debug('Top Post Offer Watch Disabled')
            return

        log.info('Offer watch to %s on post %s', submission.author.name,
                 submission.id)

        with self.uowm.start() as uow:
            existing_response = uow.bot_private_message.get_by_user_source_and_post(
                submission.author.name, 'toppost', submission.id)

        if existing_response:
            log.info('Already sent a message to %s', submission.author.name)
            return

        try:
            self.response_handler.send_private_message(
                submission.author,
                TOP_POST_WATCH_BODY.format(
                    shortlink=f'https://redd.it/{submission.id}'),
                subject=TOP_POST_WATCH_SUBJECT,
                source='toppost',
                post_id=submission.id)
        except APIException as e:
            if e.error_type == 'NOT_WHITELISTED_BY_USER_MESSAGE':
                log.error('Not whitelisted API error')
            else:
                log.exception('Unknown error sending PM to %s',
                              submission.author.name,
                              exc_info=True)
예제 #10
0
    def on_post(self, req: Request, resp: Response, subreddit: Text):
        log.info('Attempting to create monitored sub %s', subreddit)
        try:
            self.reddit.subreddit(subreddit).mod.accept_invite()
        except APIException as e:
            if e.error_type == 'NO_INVITE_FOUND':
                log.error('No open invite to %s', subreddit)
                raise HTTPInternalServerError(
                    f'No available invite for {subreddit}',
                    f'We were unable to find a '
                    f'pending mod invote for r/{subreddit}')
            else:
                log.exception('Problem accepting invite', exc_info=True)
                raise HTTPInternalServerError(
                    f'Unknown error accepting mod invite for r/{subreddit}',
                    f'Unknown error accepting mod invite for r/{subreddit}.  Please contact us'
                )
        except Exception as e:
            log.exception('Failed to accept invite', exc_info=True)
            raise HTTPInternalServerError(
                f'Unknown error accepting mod invite for r/{subreddit}',
                f'Unknown error accepting mod invite for r/{subreddit}.  Please contact us'
            )

        with self.uowm.start() as uow:
            existing = uow.monitored_sub.get_by_sub(subreddit)
            if existing:
                resp.body = json.dumps(existing.to_dict())
                return
            monitored_sub = create_monitored_sub_in_db(subreddit, uow)
            resp.body = json.dumps(monitored_sub.to_dict())
예제 #11
0
 def send_notification(self, msg: Text, **kwargs) -> NoReturn:
     for agent in self.notification_agents:
         log.info('Sending notification to %s', agent.name)
         log.debug(msg)
         try:
             agent.send(msg, **kwargs)
         except Exception as e:
             log.exception('Failed to send notification', exc_info=True)
예제 #12
0
 def _sticky_reply(self, monitored_sub: MonitoredSub,
                   comment: Comment) -> NoReturn:
     if monitored_sub.sticky_comment:
         try:
             comment.mod.distinguish(sticky=True)
             log.info('Made comment %s sticky', comment.id)
         except Forbidden:
             log.error('Failed to sticky comment, no permissions')
         except Exception as e:
             log.exception('Failed to sticky comment', exc_info=True)
예제 #13
0
def notify_watch(self, watches: List[Dict[SearchMatch, RepostWatch]], repost: Post):
    repost_watch_notify(watches, self.reddit, self.response_handler, repost)
    with self.uowm.start() as uow:
        for w in watches:
            w['watch'].last_detection = func.utc_timestamp()
            uow.repostwatch.update(w['watch'])
            try:
                uow.commit()
            except Exception as e:
                log.exception('Failed to save repost watch %s', w['watch'].id, exc_info=True)
예제 #14
0
 def _mark_post_as_comment_left(self, post: Post):
     try:
         with self.uowm.start() as uow:
             post.left_comment = True
             uow.posts.update(post)
             uow.commit()
     except Exception as e:
         log.exception('Failed to mark post %s as checked',
                       post.id,
                       exc_info=True)
예제 #15
0
def generate_img_by_file(path: str) -> Image:

    try:
        img = Image.open(path)
    except (HTTPError, ConnectionError, OSError, DecompressionBombError,
            UnicodeEncodeError) as e:
        log.exception('Failed to convert image %s. Error: %s ', path, str(e))
        raise ImageConversioinException(str(e))

    return img if img else None
    def monitor_for_mentions(self):
        bad_mentions = []
        while True:
            try:
                for comment in self.reddit.inbox.mentions():
                    if comment.created_utc < datetime.utcnow().timestamp(
                    ) - 86400:
                        log.debug('Skipping old mention. Created at %s',
                                  datetime.fromtimestamp(comment.created_utc))
                        continue

                    if comment.author.name.lower() in [
                            'sneakpeekbot', 'automoderator'
                    ]:
                        continue

                    if comment.id in bad_mentions:
                        continue

                    with self.uowm.start() as uow:
                        existing_summons = uow.summons.get_by_comment_id(
                            comment.id)
                        if existing_summons:
                            log.debug('Skipping existing mention %s',
                                      comment.id)
                            continue
                        summons = Summons(
                            post_id=comment.submission.id,
                            comment_id=comment.id,
                            comment_body=comment.body.replace('\\', ''),
                            summons_received_at=datetime.fromtimestamp(
                                comment.created_utc),
                            requestor=comment.author.name,
                            subreddit=comment.subreddit.display_name)
                        uow.summons.add(summons)
                        try:
                            uow.commit()
                        except DataError as e:
                            log.error('SQLAlchemy Data error saving comment')
                            bad_mentions.append(comment.id)
                            continue
            except ResponseException as e:
                if e.response.status_code == 429:
                    log.error('IP Rate limit hit.  Waiting')
                    time.sleep(60)
                    continue
            except AssertionError as e:
                if 'code: 429' in str(e):
                    log.error('Too many requests from IP.  Waiting')
                    time.sleep(60)
                    return
            except Exception as e:
                log.exception('Mention monitor failed', exc_info=True)

            time.sleep(20)
예제 #17
0
def link_repost_check(self, posts, ):
    with self.uowm.start() as uow:
        for post in posts:
            """
            if post.url_hash == '540f1167d27dcca2ea2772443beb5c79':
                continue
            """
            if post.url_hash in self.link_blacklist:
                log.info('Skipping blacklisted URL hash %s', post.url_hash)
                continue

            log.debug('Checking URL for repost: %s', post.url_hash)
            search_results = get_link_reposts(post.url, self.uowm, get_default_link_search_settings(self.config),
                                              post=post)

            if len(search_results.matches) > 10000:
                log.info('Link hash %s shared %s times. Adding to blacklist', post.url_hash, len(search_results.matches))
                self.link_blacklist.append(post.url_hash)
                self.notification_svc.send_notification(f'URL has been shared {len(search_results.matches)} times. Adding to blacklist. \n\n {post.url}')

            search_results = filter_search_results(
                search_results,
                uitl_api=f'{self.config.util_api}/maintenance/removed'
            )
            search_results.search_times.stop_timer('total_search_time')
            log.info('Link Query Time: %s', search_results.search_times.query_time)
            if not search_results.matches:
                log.debug('Not matching linkes for post %s', post.post_id)
                post.checked_repost = True
                uow.posts.update(post)
                uow.commit()
                continue

            log.info('Found %s matching links', len(search_results.matches))
            log.info('Creating Link Repost. Post %s is a repost of %s', post.post_id, search_results.matches[0].post.post_id)
            repost_of = search_results.matches[0].post
            new_repost = LinkRepost(post_id=post.post_id, repost_of=repost_of.post_id, author=post.author, source='ingest', subreddit=post.subreddit)
            repost_of.repost_count += 1
            post.checked_repost = True
            uow.posts.update(post)
            uow.link_repost.add(new_repost)

            try:
                uow.commit()
                self.event_logger.save_event(RepostEvent(event_type='repost_found', status='success',
                                                         repost_of=search_results.matches[0].post.post_id,
                                                         post_type=post.post_type))
            except IntegrityError as e:
                uow.rollback()
                log.exception('Error saving link repost', exc_info=True)
                self.event_logger.save_event(RepostEvent(event_type='repost_found', status='error',
                                                         repost_of=search_results.matches[0].post.post_id,
                                                         post_type=post.post_type))
        self.event_logger.save_event(
            BatchedEvent(event_type='repost_check', status='success', count=len(posts), post_type='link'))
예제 #18
0
 def _report_submission(self, monitored_sub: MonitoredSub,
                        submission: Submission,
                        report_msg: Text) -> NoReturn:
     if not monitored_sub.report_reposts:
         return
     log.info('Reporting post %s on %s', f'https://redd.it/{submission.id}',
              monitored_sub.name)
     try:
         submission.report(report_msg)
     except Exception as e:
         log.exception('Failed to report submission', exc_info=True)
예제 #19
0
 def _create_checked_post(self, post: Post):
     try:
         with self.uowm.start() as uow:
             uow.monitored_sub_checked.add(
                 MonitoredSubChecks(post_id=post.post_id,
                                    subreddit=post.subreddit))
             uow.commit()
     except Exception as e:
         log.exception('Failed to create checked post for submission %s',
                       post.post_id,
                       exc_info=True)
예제 #20
0
def save_image_repost_result(search_results: ImageSearchResults,
                             uowm: UnitOfWorkManager,
                             high_match_check: bool = False,
                             source: Text = 'unknown') -> NoReturn:
    """
    Take a found repost and save to the database
    :param source: What triggered this search
    :rtype: NoReturn
    :param high_match_check: Perform a high match meme check.
    :param search_results: Set of search results
    :param uowm: Unit of Work Manager
    :return:None
    """

    with uowm.start() as uow:
        search_results.checked_post.checked_repost = True

        if not search_results.matches:
            log.debug('Post %s has no matches',
                      search_results.checked_post.post_id)
            uow.posts.update(search_results.checked_post)
            uow.commit()
            return

        # This is used for ingest repost checking.  If a meme template gets created, it intentionally throws a
        # IngestHighMatchMeme exception.  This will cause celery to retry the task so the newly created meme template
        # gets used
        if high_match_check:
            check_for_high_match_meme(
                search_results,
                uowm)  # This intentionally throws if we create a meme template

        log.info('Creating repost. Post %s is a repost of %s',
                 search_results.checked_post.url,
                 search_results.matches[0].post.url)
        new_repost = ImageRepost(
            post_id=search_results.checked_post.post_id,
            repost_of=search_results.matches[0].post.post_id,
            hamming_distance=search_results.matches[0].hamming_distance,
            annoy_distance=search_results.matches[0].annoy_distance,
            author=search_results.checked_post.author,
            search_id=search_results.logged_search.id
            if search_results.logged_search else None,
            subreddit=search_results.checked_post.subreddit,
            source=source)

        uow.image_repost.add(new_repost)
    uow.posts.update(search_results.checked_post)

    try:
        uow.commit()
    except Exception as e:
        log.exception('Failed to save image repost', exc_info=True)
예제 #21
0
 def _lock_comment(self, monitored_sub: MonitoredSub,
                   comment: Comment) -> NoReturn:
     if monitored_sub.lock_response_comment:
         log.info('Attempting to lock comment %s on subreddit %s',
                  comment.id, monitored_sub.name)
         try:
             comment.mod.lock()
             log.info('Locked comment')
         except Forbidden:
             log.error('Failed to lock comment, no permission')
         except Exception as e:
             log.exception('Failed to lock comment', exc_info=True)
예제 #22
0
 def _save_private_message(self, bot_message: BotPrivateMessage) -> NoReturn:
     """
     Save a private message to the database
     :param bot_message: BotMessage obj
     """
     try:
         with self.uowm.start() as uow:
             uow.bot_private_message.add(bot_message)
             uow.commit()
     except Exception as e:
         # TODO - Get specific exc
         log.exception('Failed to save private message to DB', exc_info=True)
예제 #23
0
    def _create_wiki_page(self, subreddit: Subreddit):
        log.info('Creating config wiki page for %s', subreddit.display_name)
        try:
            subreddit.wiki.create(self.config.wiki_config_name,
                                  json.dumps(DEFAULT_CONFIG_VALUES))
        except NotFound:
            log.exception('Failed to create wiki page', exc_info=False)
            raise

        self.notification_svc.send_notification(
            f'Created new config for {subreddit.display_name}',
            subject='Created new config from template')
예제 #24
0
 def _lock_post(self, monitored_sub: MonitoredSub,
                submission: Submission) -> NoReturn:
     if monitored_sub.lock_post:
         try:
             submission.mod.lock()
         except Forbidden:
             log.error(
                 'Failed to lock post https://redd.it/%s, no permission',
                 submission.id)
         except Exception as e:
             log.exception('Failed to lock submission https://redd.it/%s',
                           submission.id,
                           exc_info=True)
예제 #25
0
 def _mark_post_as_oc(self, monitored_sub: MonitoredSub,
                      submission: Submission):
     if monitored_sub.mark_as_oc:
         try:
             submission.mod.set_original_content()
         except Forbidden:
             log.error(
                 'Failed to set post OC https://redd.it/%s, no permission',
                 submission.id)
         except Exception as e:
             log.exception('Failed to set post OC https://redd.it/%s',
                           submission.id,
                           exc_info=True)
예제 #26
0
 def reply_to_private_message(self, message: Message,
                              body: Text) -> NoReturn:
     log.debug('Replying to private message from %s with subject %s',
               message.dest.name, message.subject)
     try:
         message.reply(body)
         self._save_private_message(
             BotPrivateMessage(subject=message.subject,
                               body=body,
                               triggered_from='inbox_reply',
                               recipient=message.dest.name))
     except RedditAPIException:
         log.exception('Problem replying to private message', exc_info=True)
예제 #27
0
 def _save_response(self, response: SummonsResponse):
     with self.uowm.start() as uow:
         summons = uow.summons.get_by_id(response.summons.id)
         if summons:
             summons.comment_reply = response.message
             summons.summons_replied_at = datetime.utcnow()
             summons.comment_reply_id = response.comment_reply_id
             try:
                 uow.commit()
                 log.debug('Committed summons response to database')
             except InternalError:
                 log.exception('Failed to save response to summons',
                               exc_info=True)
예제 #28
0
 def run(self):
     while True:
         try:
             with self.uowm.start() as uow:
                 monitored_subs = uow.monitored_sub.get_all()
                 for sub in monitored_subs:
                     if not sub.active:
                         log.debug('Sub %s is disabled', sub.name)
                         continue
                     self._check_sub(sub)
             log.info('Sleeping until next run')
             time.sleep(60)
         except Exception as e:
             log.exception('Sub monitor service crashed', exc_info=True)
예제 #29
0
 def _delete_mention(self, comment_id: Text) -> NoReturn:
     log.info('Attempting to delete mention %s', comment_id)
     comment = self.reddit.comment(comment_id)
     if not comment:
         log.error('Failed to load comment %s', comment_id)
         return
     try:
         comment.mod.remove()
         log.info('Removed mention %s', comment_id)
     except Exception as e:
         log.exception('Failed to delete comment %s',
                       comment_id,
                       exc_info=True)
         return
    def _log_search(
        self,
        search_results: ImageSearchResults,
        source: str,
        used_current_index: bool,
        used_historical_index: bool,
    ) -> ImageSearchResults:
        image_search = ImageSearch(
            post_id=search_results.checked_post.post_id
            if search_results.checked_post else 'url',
            used_historical_index=used_historical_index,
            used_current_index=used_current_index,
            target_hamming_distance=search_results.target_hamming_distance,
            target_annoy_distance=search_results.search_settings.
            target_annoy_distance,
            same_sub=search_results.search_settings.same_sub,
            max_days_old=search_results.search_settings.max_days_old,
            filter_dead_matches=search_results.search_settings.
            filter_dead_matches,
            only_older_matches=search_results.search_settings.
            only_older_matches,
            meme_filter=search_results.search_settings.meme_filter,
            meme_template_used=search_results.meme_template.id
            if search_results.meme_template else None,
            search_time=search_results.search_times.total_search_time,
            index_search_time=search_results.search_times.index_search_time,
            total_filter_time=search_results.search_times.total_filter_time,
            target_title_match=search_results.search_settings.
            target_title_match,
            matches_found=len(search_results.matches),
            source=source,
            subreddit=search_results.checked_post.subreddit
            if search_results.checked_post else 'url',
            search_results=create_search_result_json(search_results),
            target_image_meme_match=search_results.search_settings.
            target_meme_match_percent,
            target_image_match=search_results.search_settings.
            target_match_percent)

        with self.uowm.start() as uow:
            uow.image_search.add(image_search)
            try:
                uow.commit()
                search_results.logged_search = image_search
            except Exception as e:
                log.exception('Failed to save image search', exc_info=False)

        return search_results