def create_daily_stats(context, session): """Create the daily stats entity for today and tomorrow.""" try: today = date.today() tomorrow = today + timedelta(days=1) for stat_date in [today, tomorrow]: statistic = session.query(DailyStatistic).get(stat_date) if statistic is None: statistic = DailyStatistic(stat_date) session.add(statistic) session.commit() except Exception as e: sentry.capture_job_exception(e)
def message_update_job(context, session): """Update all polls that are scheduled for an update.""" try: context.job.enabled = False now = datetime.now() update_count = session.query(Update).filter( Update.next_update <= now).count() while update_count > 0: updates = (session.query(Update).filter( Update.next_update <= now).options(joinedload( Update.poll)).order_by( Update.next_update.asc()).limit(50).all()) for update in updates: try: send_updates(session, context.bot, update.poll, show_warning=True) session.delete(update) session.commit() except ObjectDeletedError: # The update has already been handled somewhere else. # This could be either a job or a person that voted in this very moment session.rollback() except RetryAfter as e: # Schedule an update after the RetryAfter timeout + 1 second buffer update.next_update = now + timedelta( seconds=int(e.retry_after) + 1) try: session.commit() except StaleDataError: # The update has already been handled somewhere else session.rollback() # Update the count again. # Updates can be removed by normal operation as well update_count = (session.query(Update).filter( Update.next_update <= now).count()) except Exception as e: sentry.capture_job_exception(e) finally: context.job.enabled = True
def delete_polls(context, session): """Delete polls from the database and their messages if requested.""" try: context.job.enabled = False # Only delete a few polls at a time to prevent RAM usage spikes polls_to_delete = (session.query(Poll).filter( Poll.delete.isnot(None)).order_by( Poll.updated_at.asc()).limit(20).all()) for poll in polls_to_delete: if poll.delete == PollDeletionMode.DB_ONLY.name: delete_poll(session, context, poll) elif poll.delete == PollDeletionMode.WITH_MESSAGES.name: delete_poll(session, context, poll, True) session.commit() except Exception as e: sentry.capture_job_exception(e) finally: context.job.enabled = True
def send_notifications_for_poll(context, session, poll, message_key): """Send the notifications for a single poll depending on the remaining time.""" locale = poll.locale for notification in poll.notifications: try: # Get the chat and send the notification tg_chat = context.bot.get_chat(notification.chat_id) tg_chat.send_message( i18n.t(message_key, locale=locale, name=poll.name), parse_mode="markdown", reply_to_message_id=notification.poll_message_id, ) except BadRequest as e: if e.message == "Chat not found": session.delete(notification) # Bot was removed from group except Unauthorized: session.delete(notification) except Exception as e: sentry.capture_job_exception(e)