From e381dce261279a806eaf09027ff90b5980289231 Mon Sep 17 00:00:00 2001 From: Ching L Date: Thu, 24 Jul 2025 10:35:32 +0800 Subject: [PATCH] feat: Enhance friend match processing to avoid duplicate API calls and improve streak updates --- dota.py | 102 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 21 deletions(-) diff --git a/dota.py b/dota.py index 13a80de..00a9583 100644 --- a/dota.py +++ b/dota.py @@ -256,27 +256,87 @@ def get_friends_recent_matches(): global streak_updates # 使用全局变量存储连胜连败更新 streak_updates = [] - for friend in Friend.filter(active=True): - for match_ in friend.get_recent_matches(): - # 判断玩家是否获胜 - player_won = match_.radiant_win == (match_.player_slot < 128) - - # 总是尝试更新连胜连败(update_streak内部会检查是否重复) - streak_info = friend.update_streak(match_.match_id, player_won) - if streak_info: - streak_updates.append(streak_info) - - # 只有新比赛才创建数据库记录和返回结果 - if not Match.select().where(Match.match_id == match_.match_id).exists(): - logger.info('create match, match info: %s' % match_.__dict__) - match_obj = Match.create( - match_id=match_.match_id, - start_time=datetime.datetime.fromtimestamp(match_.start_time), - duration=match_.duration, - radiant_win=match_.radiant_win, - party_size=match_.party_size, - ) - matches.append(match_obj.serialize_match()) + processed_matches = set() # 记录已处理的比赛ID,避免重复处理开黑比赛 + active_friends = list(Friend.filter(active=True)) + + for friend in active_friends: + try: + recent_matches = friend.get_recent_matches() + for match_ in recent_matches: + # 如果这场比赛已经被处理过(开黑情况下其他朋友已处理),跳过API调用 + if match_.match_id in processed_matches: + # 仍需要为当前朋友更新连胜,但不重复创建比赛记录 + player_won = match_.radiant_win == (match_.player_slot < 128) + streak_info = friend.update_streak(match_.match_id, player_won) + if streak_info: + streak_updates.append(streak_info) + continue + + # 标记此比赛为已处理 + processed_matches.add(match_.match_id) + + # 判断当前朋友是否获胜 + player_won = match_.radiant_win == (match_.player_slot < 128) + + # 更新当前朋友的连胜连败 + streak_info = friend.update_streak(match_.match_id, player_won) + if streak_info: + streak_updates.append(streak_info) + + # 如果是开黑比赛,为其他可能在同一场比赛的朋友也更新连胜 + # 但不需要额外的API调用 + if match_.party_size and match_.party_size > 1: + # 获取比赛详细信息以找出其他朋友 + if not Match.select().where(Match.match_id == match_.match_id).exists(): + # 先创建比赛记录,这样可以获取详细信息 + match_obj = Match.create( + match_id=match_.match_id, + start_time=datetime.datetime.fromtimestamp(match_.start_time), + duration=match_.duration, + radiant_win=match_.radiant_win, + party_size=match_.party_size, + ) + try: + # 获取比赛详细信息 + match_obj.serialize_match() # 这会触发获取详细信息 + + # 解析比赛数据,找出其他朋友 + if match_obj.opendota_response: + match_data = json.loads(match_obj.opendota_response) + player_account_ids = [p['account_id'] for p in match_data['players'] if p['account_id']] + + # 为其他在这场比赛中的朋友更新连胜 + for other_friend in active_friends: + if other_friend != friend and other_friend.steam_id in player_account_ids: + # 找到该朋友在比赛中的信息 + for player in match_data['players']: + if player['account_id'] == other_friend.steam_id: + other_player_won = match_.radiant_win == (player['player_slot'] < 128) + other_streak_info = other_friend.update_streak(match_.match_id, other_player_won) + if other_streak_info: + streak_updates.append(other_streak_info) + break + except Exception as e: + logger.error(f'failed to get match details for {match_.match_id}: {e}') + + matches.append(match_obj.serialize_match()) + + else: + # 单排比赛,正常处理 + if not Match.select().where(Match.match_id == match_.match_id).exists(): + logger.info('create match, match info: %s' % match_.__dict__) + match_obj = Match.create( + match_id=match_.match_id, + start_time=datetime.datetime.fromtimestamp(match_.start_time), + duration=match_.duration, + radiant_win=match_.radiant_win, + party_size=match_.party_size, + ) + matches.append(match_obj.serialize_match()) + + except Exception as e: + logger.error(f'failed to get recent matches for friend {friend.name}: {e}') + continue return matches