feat: Enhance friend match processing to avoid duplicate API calls and improve streak updates
All checks were successful
continuous-integration/drone Build is passing
continuous-integration/drone/push Build is passing

This commit is contained in:
Ching L 2025-07-24 10:35:32 +08:00
parent 895737927a
commit e381dce261

98
dota.py
View File

@ -256,27 +256,87 @@ def get_friends_recent_matches():
global streak_updates # 使用全局变量存储连胜连败更新 global streak_updates # 使用全局变量存储连胜连败更新
streak_updates = [] streak_updates = []
for friend in Friend.filter(active=True): processed_matches = set() # 记录已处理的比赛ID避免重复处理开黑比赛
for match_ in friend.get_recent_matches(): active_friends = list(Friend.filter(active=True))
# 判断玩家是否获胜
player_won = match_.radiant_win == (match_.player_slot < 128)
# 总是尝试更新连胜连败update_streak内部会检查是否重复 for friend in active_friends:
streak_info = friend.update_streak(match_.match_id, player_won) try:
if streak_info: recent_matches = friend.get_recent_matches()
streak_updates.append(streak_info) 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
# 只有新比赛才创建数据库记录和返回结果 # 标记此比赛为已处理
if not Match.select().where(Match.match_id == match_.match_id).exists(): processed_matches.add(match_.match_id)
logger.info('create match, match info: %s' % match_.__dict__)
match_obj = Match.create( # 判断当前朋友是否获胜
match_id=match_.match_id, player_won = match_.radiant_win == (match_.player_slot < 128)
start_time=datetime.datetime.fromtimestamp(match_.start_time),
duration=match_.duration, # 更新当前朋友的连胜连败
radiant_win=match_.radiant_win, streak_info = friend.update_streak(match_.match_id, player_won)
party_size=match_.party_size, if streak_info:
) streak_updates.append(streak_info)
matches.append(match_obj.serialize_match())
# 如果是开黑比赛,为其他可能在同一场比赛的朋友也更新连胜
# 但不需要额外的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 return matches