增强TBD事件清理功能 v3.9
All checks were successful
continuous-integration/drone/push Build is passing

- 自动删除已结束但仍包含TBD的事件
- 智能删除与确认比赛同时间段的TBD vs TBD占位符
- 改进事件分组逻辑,使用30分钟时间窗口

修复了9月11-12日日历中残留的TBD事件问题

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ching L 2025-09-12 11:48:11 +08:00
parent 253277620c
commit e72661f4cd
3 changed files with 67 additions and 25 deletions

View File

@ -1,5 +1,18 @@
# Changelog
## v3.9 - 2025-09-12 - 增强TBD事件清理功能
- **自动删除已结束的TBD事件**
- 检查事件的结束时间如果已过且仍包含TBD则自动删除
- 避免日历中保留已过期但未更新的TBD占位符
- 例如:删除已结束的 "BB vs TBD"、"Tidebd vs TBD" 等事件
- **智能删除TBD vs TBD占位符**
- 当同一时间段30分钟窗口存在确认的比赛时自动删除TBD vs TBD事件
- 解决了TBD vs TBD与确认比赛重复的问题
- 例如9月11日的多个TBD vs TBD事件被正确清理
- **改进的事件分组逻辑**
- 按30分钟时间窗口分组事件更准确地识别同时间的比赛
- 优化了TBD事件与确认比赛的匹配算法
## v3.8 - 2025-09-08 - 修复重复比分显示问题
- **修复标题中重复比分的问题**
- 修复了在更新比赛比分时可能出现重复比分的bug如 "0-2 0-1"
@ -143,6 +156,7 @@
| v3.6 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| v3.7 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| v3.8 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| v3.9 | ✓ | ✓ | ✓ | ✓ | ✓+ | ✓ |
## 使用建议

View File

@ -1,6 +1,6 @@
# Dota 2 Calendar Sync v3.8
# Dota 2 Calendar Sync v3.9
自动从 Liquipedia 获取 Dota 2 Tier 1 比赛信息并同步到 Google Calendar支持自动更新比赛结果、时间变更、智能管理TBD占位事件和自动清理重复比赛。
自动从 Liquipedia 获取 Dota 2 Tier 1 比赛信息并同步到 Google Calendar支持自动更新比赛结果、时间变更、智能管理TBD占位事件、自动清理过期和重复比赛。
## 功能
@ -11,6 +11,7 @@
- **检测并更新比赛时间变更**(赛程调整时自动同步)
- **智能管理TBD占位事件**(自动更新队伍信息,删除过期和被取代的事件)
- **自动清理重复比赛**(优先保留已完成的比赛记录)
- **增强的TBD事件清理**删除已结束但仍包含TBD的事件删除与确认比赛同时间的TBD占位符
- 避免重复添加已存在的比赛
- 支持 dry-run 模式进行测试
@ -87,6 +88,8 @@ python sync_dota2_matches.py --dry-run
- **改进的TBD匹配**1小时时间窗口匹配更好处理赛程调整
- **重复比赛清理**:自动检测并删除同队伍的重复事件
- **TBD事件自动删除**当队伍确定后自动删除对应的TBD占位符
- **增强的过期事件清理**自动删除已结束但仍包含TBD的事件
- **智能TBD vs TBD处理**删除与确认比赛在同一时间段的TBD vs TBD占位符
2. **日历事件管理**
- 自动设置比赛时长(根据 Bo 格式估算)

View File

@ -998,10 +998,18 @@ class Dota2CalendarSync:
if event_id in updated_tbd_events:
continue
# Get event time
# Get event time and end time
event_start = event['start'].get('dateTime', event['start'].get('date'))
event_dt = datetime.fromisoformat(event_start.replace('Z', '+00:00'))
# Get event end time for checking if match has ended
event_end = event.get('end', {}).get('dateTime', event.get('end', {}).get('date'))
if event_end:
event_end_dt = datetime.fromisoformat(event_end.replace('Z', '+00:00'))
else:
# If no end time, assume 3 hours duration
event_end_dt = event_dt + timedelta(hours=3)
# Use 30-minute window for "same time"
time_key = (event_dt.year, event_dt.month, event_dt.day,
event_dt.hour, event_dt.minute // 30)
@ -1013,14 +1021,14 @@ class Dota2CalendarSync:
if 'vs TBD' in summary or 'TBD vs' in summary:
events_by_time[time_key]['tbd'].append(event)
# Also check if it's expired (for TBD vs TBD only)
if 'TBD vs TBD' in summary and event_dt < now - timedelta(hours=2):
# Delete if match has ended (end time has passed) and still contains TBD
if event_end_dt < now:
if self.delete_calendar_event(event_id):
print(f"🗑️ Deleted expired TBD event: {summary} ({event_dt.strftime('%Y-%m-%d %H:%M UTC')})")
print(f"🗑️ Deleted ended TBD event: {summary} (ended at {event_end_dt.strftime('%Y-%m-%d %H:%M UTC')})")
deleted_tbd_count += 1
time.sleep(0.2)
else:
print(f"✗ Failed to delete TBD event: {summary}")
print(f"✗ Failed to delete ended TBD event: {summary}")
error_count += 1
continue # Don't process this event further
@ -1040,7 +1048,24 @@ class Dota2CalendarSync:
for tbd_event in events['tbd']:
tbd_summary = tbd_event.get('summary', '')
# Extract team from TBD event
# Check if this is a complete TBD vs TBD event
if 'TBD vs TBD' in tbd_summary:
# Delete TBD vs TBD when there's any confirmed match at the same time
# Since TBD vs TBD is a placeholder, any confirmed match supersedes it
if events['confirmed']:
confirmed_event = events['confirmed'][0] # Use first confirmed match for logging
confirmed_summary = confirmed_event.get('summary', '')
if self.delete_calendar_event(tbd_event['id']):
print(f"🗑️ Deleted TBD vs TBD event at same time as confirmed match")
print(f" TBD event: {tbd_summary}")
print(f" Confirmed match: {confirmed_summary}")
deleted_tbd_count += 1
time.sleep(0.2)
else:
print(f"✗ Failed to delete TBD vs TBD event: {tbd_summary}")
error_count += 1
else:
# For partial TBD events (one team is known), check for team match
team_match = re.search(r'(\w+)\s+vs\s+TBD|TBD\s+vs\s+(\w+)', tbd_summary)
if team_match:
team_in_tbd = team_match.group(1) or team_match.group(2)