From 77c8a87e165aca077e7626537fd8c6be4923fe71 Mon Sep 17 00:00:00 2001 From: vrubel Date: Mon, 22 Jun 2026 15:19:39 +0000 Subject: [PATCH] fix: stop burning request limit on finished tournaments + reset stale result counts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit check_all_subscriptions: always call update_round even for the final round. Previously, last_round_done was never updated past the second-to-last round (because pairings aren't calculated for the last round). This kept quick_rd > last_round_done forever on finished tournaments, triggering a full fetch (~22 HTTP requests) every 5 minutes — causing 26k+ daily requests to chess-results.com against a 2000-request daily limit. rescan_existing_tournaments: when correcting player_sno, also reset last_results_count to 0. Stale counts from a wrong player (from the FIDE ID parsing bug) could be higher than the real player's count, permanently suppressing result notifications for the correct player. DB patched directly: last_results_count reset to 0 for subs 40 (Vrubel) and 47 (Aslanbekov) so they re-learn correct scores on next fetch. Co-Authored-By: Claude Sonnet 4.6 --- bots/tracker.py | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/bots/tracker.py b/bots/tracker.py index 14bb0a0..e652493 100644 --- a/bots/tracker.py +++ b/bots/tracker.py @@ -825,7 +825,10 @@ async def rescan_existing_tournaments(context): continue # tournament deleted or unreachable new_fids = set(new_data['players'].keys()) - # Correct player_sno for subscriptions whose SNo drifted from the cache + # Correct player_sno for subscriptions whose SNo drifted from the cache. + # Also reset last_results_count so the bot re-learns points for the + # correct player (stale counts from the old wrong player could be higher + # than the real player's count, suppressing result notifications forever). tnr_url_frag = f'tnr{tnr}.aspx' for fid in new_fids: if fid not in fide_to_users: @@ -833,7 +836,7 @@ async def rescan_existing_tournaments(context): correct_sno = new_data['players'][fid]['sno'] conn = _get_conn() conn.execute( - 'UPDATE subscriptions SET player_sno = ? ' + 'UPDATE subscriptions SET player_sno = ?, last_results_count = 0 ' 'WHERE fide_id = ? AND tournament_url LIKE ? ' 'AND player_sno != ? AND active = 1', (correct_sno, fid, f'%{tnr_url_frag}%', correct_sno)) @@ -922,24 +925,29 @@ async def check_all_subscriptions(context): pass update_result(sub['id'], results_count, points) - # Round fully completed → calculate next round pairings + # Round fully completed → calculate next round pairings (if not the last round) current_rd = tournament.get('current_round', 0) - if current_rd > sub['last_round_done'] and current_rd < tournament.get('num_rounds', 0): - try: - result = calculate_next_round(tournament) - fmt = format_pairings(result, tournament.get('name', ''), sub['lang'], - sub['player_name'], sub['player_sno']) - chunks = _render_chunks(fmt) - for chunk in chunks: - try: - await context.bot.send_message( - sub['user_id'], chunk, - parse_mode=ParseMode.MARKDOWN_V2, - disable_web_page_preview=True) - except Exception: - break - except Exception: - pass + if current_rd > sub['last_round_done']: + if current_rd < tournament.get('num_rounds', 0): + try: + result = calculate_next_round(tournament) + fmt = format_pairings(result, tournament.get('name', ''), sub['lang'], + sub['player_name'], sub['player_sno']) + chunks = _render_chunks(fmt) + for chunk in chunks: + try: + await context.bot.send_message( + sub['user_id'], chunk, + parse_mode=ParseMode.MARKDOWN_V2, + disable_web_page_preview=True) + except Exception: + break + except Exception: + pass + # Always advance last_round_done — even for the final round. + # Without this, the quick-check condition (quick_rd > last_round_done) + # stays True forever on finished tournaments, causing a full fetch + # (~22 HTTP requests) every 5 minutes. update_round(sub['id'], current_rd)