def daily_task_check(): try: config = get_config_document() n = datetime.now(tz=tz) if config.latest_daily_check: lc = mongo_time_to_local(config.latest_daily_check, tz) if (n - lc) > timedelta(hours=1): if 8 <= n.hour <= 21: logger.debug(f'Performing vacation check task at {n}') config.latest_daily_check = n config.save() daily_task() else: config.latest_daily_check = n config.save() config.reload() if config.latest_monthly_check: lc = mongo_time_to_local(config.latest_monthly_check, tz) if (n - lc) > timedelta(days=1): if n.day == 1: hr_logger.info(f'Performing monthly task at {n}') config.latest_monthly_check = n config.save() monthly_task() else: config.latest_monthly_check = n config.save() except KeyboardInterrupt: return except: logger.exception('Exception occurred while performing daily check')
def daily_task(): now = datetime.now(tz=tz) tbot = None bconfig = get_config() for competitor in Competitor.objects( status=COMPETITOR_STATUS.VACATION): if competitor.vacation_started_at: delta = now - mongo_time_to_local( competitor.vacation_started_at, tz) delta = delta.total_seconds() if competitor.used_vacation_time is not None: delta += competitor.used_vacation_time if timedelta(seconds=delta).days > bconfig.vacation_time: competitor.change_status(competitor.previous_status or COMPETITOR_STATUS.ACTIVE) competitor.save() relevant_user: User = User.objects( associated_with=competitor).first() if relevant_user is not None: if not tbot: tbot = TeleBot(BOT_TOKEN, threaded=False) smwae_check( relevant_user.user_id, get_translation_for('menu_on_vacation_end_msg'), relevant_user, reply_markup=get_menu_keyboard( status=competitor.status)) else: competitor.vacation_started_at = now competitor.used_vacation_time = delta competitor.save() else: logger.error( f"Cannot find vacation_started_at for competitor {competitor.name} (on vacation). Saved current time" ) competitor.vacation_started_at = now competitor.save()
def upload_result(result: Result, at_row=None): try: cfg = get_config() if not cfg.spreadsheet_results_sheet: hr_logger.error( 'Не вдалося надіслати результат матчу в гуглтаблицю - у налаштуваннях відсутня назва листа') logger.error('Cannot insert result into a google sheet - sheet name is missing') return if at_row is None: results = ResultsSheet.get_all_successful_results() if results is None: results = [] at_row = len(results) + 2 if result.result in (RESULT.A_WINS, RESULT.B_WINS): winner = result.player_a.fetch() if result.result == RESULT.A_WINS else result.player_b.fetch() looser = result.player_b.fetch() if result.result == RESULT.A_WINS else result.player_a.fetch() score = result.repr_score() update_data( cfg.spreadsheet_id, f'{cfg.spreadsheet_results_sheet}!A{at_row}:E', values=[ [ mongo_time_to_local(result.date, tz=_k_tz).strftime('%d/%m/%Y'), winner.name, score, looser.name, result.level_change or '-' ] ] ) else: logger.error(f"Wrong method called for result {result.id}. Call upload_canceled_result instead") except: logger.exception('Exception occurred while uploading match result')
def end_vacation(self, message: Message, user: User, bot: TeleBot, competitor: Competitor): if competitor.status != COMPETITOR_STATUS.VACATION: return RET.OK, None, None, None if not competitor.vacation_started_at: logger.error(f"Cannot calculate user's ({user.user_id}) time on vacation - cannot find vacation_started_at") delta = 0 else: tz = timezone('Europe/Kiev') now = datetime.now(tz=tz) delta = now - mongo_time_to_local(competitor.vacation_started_at, tz) delta = delta.total_seconds() if competitor.used_vacation_time is None: competitor.used_vacation_time = delta else: competitor.used_vacation_time += delta competitor.change_status(competitor.previous_status) competitor.save() bot.send_message( message.chat.id, get_translation_for('menu_on_vacation_end_manual_msg'), reply_markup=self.__base_keyboard(status=competitor.status) ) LogsSheet.glog(get_translation_for('gsheet_log_player_finished_vacation').format(competitor.name)) return RET.OK, None, None, None
def check_challenges(): bconfig = get_config() n = datetime.now(tz=tz) tbot = None for competitor in Competitor.objects( status=COMPETITOR_STATUS.CHALLENGE_NEED_RESPONSE): try: if not competitor.latest_challenge_received_at: logger.error( f'Competitor {competitor.name} {competitor.legacy_number} has no latest_challenge_received_at' ) competitor.latest_challenge_received_at = datetime.now( tz=tz) competitor.save() continue cs = mongo_time_to_local( competitor.latest_challenge_received_at, tz) if (n - cs) > timedelta(days=max( 0, bconfig.time_to_accept_challenge - bconfig.accept_challenge_reminder )) and not competitor.challenge_remainder_sent: if tbot is None: tbot = TeleBot(PROJECT_NAME, threaded=False) cuser = User.objects(associated_with=competitor).first() if cuser is None: continue if not smwae_check( cuser.user_id, get_translation_for( 'remainder_challenge_accept_msg').format( bconfig.accept_challenge_reminder), cuser): opponent, opponent_user = get_opponent_and_opponent_user( competitor) if opponent and opponent_user: teardown_challenge( opponent, None, opponent_user, tbot, 'error_bot_blocked_by_opponent_challenge_canceled_msg' ) continue competitor.reload() competitor.challenge_remainder_sent = True competitor.save() elif (n - cs) > timedelta(days=bconfig.time_to_accept_challenge): if tbot is None: tbot = TeleBot(PROJECT_NAME, threaded=False) cuser = User.objects(associated_with=competitor).first() skip_comp = False if cuser is None: skip_comp = True opponent_user: User opponent, opponent_user = get_opponent_and_opponent_user( competitor) prev_level, new_level = None, None level_change = None if opponent and opponent.level > competitor.level: new_level = competitor.level prev_level = opponent.level level_change = f'{prev_level}->{new_level}' ResultsSheet.upload_canceled_result(opponent, competitor, level_change, was_ignored=True) if opponent: config = get_config() if config.group_chat_id: gmsg = get_translation_for( 'group_chat_technical_win_report_msg').format( opponent.name, competitor.name) if level_change: gmsg += '.\n' gmsg += get_translation_for( 'group_chat_players_level_changed').format( level_change) LogsSheet.glog( get_translation_for( 'gsheet_log_player_ignored_challenge_from_player' ).format(competitor.name, opponent.name) + '. ' + get_translation_for( 'group_chat_players_level_changed'). format(level_change)) else: LogsSheet.glog( get_translation_for( 'gsheet_log_player_ignored_challenge_from_player' ).format(competitor.name, opponent.name)) try: tbot.send_message(config.group_chat_id, gmsg, parse_mode='html') except: logger.exception( 'Exception occurred while sending message to group chat' ) res = Result(player_a=opponent, player_a_s=opponent.name, player_b=competitor, player_b_s=competitor.name, result=RESULT.IGNORED, canceled=True, date=datetime.now(tz=tz), level_change=level_change) res.save() competitor.in_challenge_with = None competitor.change_status(competitor.previous_status) competitor.previous_status = None competitor.latest_challenge_received_at = None if prev_level: competitor.level = prev_level competitor.challenges_ignored = ( competitor.challenges_ignored + 1) if competitor.challenges_ignored is not None else 1 competitor.challenges_ignored_total = ( competitor.challenges_ignored_total + 1 ) if competitor.challenges_ignored_total is not None else 1 competitor.losses = competitor.losses + 1 if competitor.losses is not None else 1 competitor.matches = competitor.matches + 1 if competitor.matches is not None else 1 if competitor.challenges_ignored >= bconfig.maximum_challenges_ignored: competitor.change_status(COMPETITOR_STATUS.INACTIVE) LogsSheet.glog( get_translation_for( 'gsheet_log_player_moved_to_inactive').format( competitor.name)) competitor.save() UsersSheet.update_competitor_table_record(competitor) t = get_translation_for( 'challenge_was_ignored_msg').format( competitor.challenges_ignored, bconfig.maximum_challenges_ignored) if not skip_comp: if competitor.status == COMPETITOR_STATUS.INACTIVE: t += '.\n<b>' t += get_translation_for( 'user_was_moved_to_inactive') t += '</b>' elif prev_level: t += '.\n' t += get_translation_for( 'your_level_changed_str').format( new_level, prev_level) smwae_check(cuser.user_id, t, cuser, reply_markup=get_menu_keyboard( status=competitor.status), parse_mode='html') if opponent: opponent.reload() opponent.in_challenge_with = None if opponent.status != COMPETITOR_STATUS.INACTIVE: opponent.change_status(opponent.previous_status) opponent.previous_status = None opponent.latest_challenge_received_at = None opponent.wins = opponent.wins + 1 if opponent.wins is not None else 1 opponent.matches = opponent.matches + 1 if opponent.matches is not None else 1 opponent.level = new_level opponent.save() UsersSheet.update_competitor_table_record(opponent) t = get_translation_for( 'challenge_was_ignored_opponent_msg') if prev_level: t += '\n' t += get_translation_for( 'your_level_changed_str').format( prev_level, new_level) if opponent_user: smwae_check(opponent_user.user_id, t, opponent_user, reply_markup=get_menu_keyboard( status=opponent.status), parse_mode='html') except: logger.exception( f'Exception occurred while checking challenge requests for competitor {competitor.name} {competitor.legacy_number}' ) for competitor in Competitor.objects(status__in=( COMPETITOR_STATUS.CHALLENGE_STARTER, COMPETITOR_STATUS.CHALLENGE_RECEIVER, COMPETITOR_STATUS.CHALLENGE_NEED_RESULTS_CONFIRMATION, COMPETITOR_STATUS.CHALLENGE_NEED_CANCELLATION_CONFIRMATION)): try: if not competitor.challenge_started_at: logger.error( f'Competitor {competitor.name} {competitor.legacy_number} has no challenge_started_at' ) competitor.challenge_started_at = datetime.now(tz=tz) competitor.save() continue cs = mongo_time_to_local(competitor.challenge_started_at, tz) if (n - cs) > timedelta(days=max( 0, bconfig.time_to_play_challenge - bconfig.challenge_play_reminder )) and not competitor.challenge_remainder_sent: if tbot is None: tbot = TeleBot(PROJECT_NAME, threaded=False) cuser = User.objects(associated_with=competitor).first() if cuser is None: continue if not smwae_check( cuser.user_id, get_translation_for('remainder_challenge_play_msg') .format(bconfig.challenge_play_reminder), cuser): opponent, opponent_user = get_opponent_and_opponent_user( competitor) if opponent and opponent_user: teardown_challenge( opponent, None, opponent_user, tbot, 'error_bot_blocked_by_opponent_challenge_canceled_msg' ) continue competitor.reload() competitor.challenge_remainder_sent = True competitor.save() elif (n - cs) > timedelta(days=bconfig.time_to_play_challenge): # TODO pass except: logger.exception( f'Exception occurred while checking challenges in progress (for competitor {competitor.name} {competitor.legacy_number})' )
def synchronize_results(max_delta=None): all_finished_matches = ResultsSheet.get_all_successful_results() all_canceled_matches = ResultsSheet.get_all_canceled_results() stored_results = [] for result in Result.objects(confirmed=True): stored_results.append(result) for sr in stored_results: sr: Result score = sr.repr_score() date = mongo_time_to_local(sr.date, _k_tz).strftime('%d/%m/%Y') if sr.result == RESULT.A_WINS: winner = sr.player_a_s loser = sr.player_b_s elif sr.result == RESULT.B_WINS: winner = sr.player_b_s loser = sr.player_a_s else: logger.error(f'INCONSISTENT RESULT OF A MATCH RESULT: {sr.id} {sr.result} {sr.player_a_s} {sr.player_b_s}') continue found = False for fm in all_finished_matches: if fm[0] == date and \ fm[1] == winner and \ fm[2] == score and \ fm[3] == loser: found = True all_finished_matches.remove(fm) break if not found: if sr.deletion_marker: logger.error(f'Again cannot find result info in gsheet: {sr.id}. Deleting') sr.delete() else: logger.error(f'Cannot find result info in gsheet: {sr.id}. {sr.result} - {sr.date}; {sr.player_a_s} - {sr.player_b_s}; {score} - {date}') sr.deletion_marker = True sr.save() else: sr.deletion_marker = False sr.save() now = datetime.now(tz=_k_tz) tbot = None for new_record in all_finished_matches: try: nr_date = new_record[0] try: nr_date = datetime.strptime(nr_date, '%d/%m/%Y') except ValueError: nr_date = datetime.strptime(nr_date, '%m/%d/%Y') nr_date = _k_tz.localize(nr_date) score = Result.try_to_parse_score(new_record[2]) score_s = None if score is None: score_s = new_record[2] score = [] new_res = Result( player_a_s = new_record[1], player_b_s = new_record[3], scores=score, scores_s=score_s, confirmed=True, level_change=new_record[4] if new_record[4] != '-' else None, date=nr_date, result=RESULT.A_WINS ) new_res.save() cfg = get_config() if cfg.group_chat_id and (nr_date > now or (max_delta and (now - nr_date) < max_delta)): if tbot is None: tbot = TeleBot(BOT_TOKEN, threaded=False) score = new_res.repr_score() gmsg = get_translation_for('group_chat_match_result_msg').format(new_res.player_a_s, new_res.player_b_s, score) if new_res.level_change: gmsg += '.\n' gmsg += get_translation_for('group_chat_players_level_changed').format(new_res.level_change) try: tbot.send_message( cfg.group_chat_id, gmsg, parse_mode='html' ) except: logger.exception('Exception occurred while sending message to group chat') except: logger.exception(f'Exception occurred while checking new_record: {new_record}') # CANCELED CHECKS stored_results = [] for result in Result.objects(canceled=True): stored_results.append(result) for sr in stored_results: sr: Result date = mongo_time_to_local(sr.date, _k_tz).strftime('%d/%m/%Y') alternative_date = mongo_time_to_local(sr.date, _k_tz).strftime('%m/%d/%Y') found = False # logger.warning('----------------------------') # logger.warning(f'{date}, {alternative_date}, {sr.player_a_s}, {sr.player_b_s}') for fm in all_canceled_matches: is_ignored = fm[2].find('игнор') != -1 or fm[2].find('проігнор') != -1 \ or fm[2].find(get_translation_for('gsheet_technical_win_ignored_str')) != -1 is_dismissed = fm[2].find('повторн') != -1 or fm[2].find('відмов') != -1 \ or fm[2].find(get_translation_for('gsheet_technical_win_dismissed_str')) != -1 # logger.warning(f'Is_ignore: {is_ignored} - {sr.result==RESULT.IGNORED}, is_dismissed: {is_dismissed} - {sr.result==RESULT.DISMISSED}') # logger.warning(fm) # logger.warning(f'{fm[0] == date} | {fm[0] == alternative_date} | {fm[3] == sr.player_a_s} | {fm[1] == sr.player_b_s}') # logger.warning(f'{(is_dismissed and sr.result == RESULT.DISMISSED) or (is_ignored and sr.result == RESULT.IGNORED)}') winner = sr.player_a_s loser = sr.player_b_s if fm[0] in (date, alternative_date) and \ fm[3] == winner and \ fm[1] == loser and \ ((is_dismissed and sr.result == RESULT.DISMISSED) or (is_ignored and sr.result == RESULT.IGNORED)): found = True all_canceled_matches.remove(fm) break if not found: if sr.deletion_marker: logger.error(f'Again cannot find result (canceled) info in gsheet: {sr.id}. Deleting') sr.delete() else: logger.error( f'Cannot find result (canceled) info in gsheet: {sr.id}. {sr.result} - {sr.date}; {sr.player_a_s} - {sr.player_b_s}; {date}') sr.deletion_marker = True sr.save() else: sr.deletion_marker = False sr.save() for new_record in all_canceled_matches: try: nr_date = new_record[0] try: nr_date = datetime.strptime(nr_date, '%d/%m/%Y') except ValueError: nr_date = datetime.strptime(nr_date, '%m/%d/%Y') nr_date = _k_tz.localize(nr_date) is_ignored = new_record[2].find('игнор') != -1 or new_record[2].find('проігнор') != -1 #is_dismissed = new_record[2].find('повторн') != -1 or new_record[2].find('відмов') != -1 new_res = Result( player_a_s = new_record[3], player_b_s = new_record[1], canceled=True, level_change=new_record[4], date=nr_date, result=RESULT.IGNORED if is_ignored else RESULT.DISMISSED ) new_res.save() cfg = get_config() if cfg.group_chat_id and (nr_date > now or (max_delta and (now - nr_date) < max_delta)): if tbot is None: tbot = TeleBot(BOT_TOKEN, threaded=False) if is_ignored: gmsg = get_translation_for('gsheet_log_player_ignored_challenge_from_player').format( new_res.player_b_s, new_res.player_a_s ) else: gmsg = get_translation_for('gsheet_log_player_dismissed_challenge_from_player').format( new_res.player_b_s, new_res.player_a_s ) if new_res.level_change: gmsg += '.\n' gmsg += get_translation_for('group_chat_players_level_changed').format(new_res.level_change) try: tbot.send_message( cfg.group_chat_id, gmsg, parse_mode='html' ) except: logger.exception('Exception occurred while sending message to group chat') except: logger.exception(f'Exception occurred while checking new_record: {new_record}')