fix: preserve countdown dates and restore ids
ci / gitleaks (push) Successful in 7s
ci / docker (push) Successful in 3m19s

This commit is contained in:
2026-09-09 11:45:26 +08:00
parent 010bfd3653
commit e163f6f368
2 changed files with 100 additions and 10 deletions
+23 -10
View File
@@ -5,7 +5,7 @@ import json
import re
from datetime import UTC, date, datetime, time, timedelta
from pathlib import Path
from uuid import UUID
from uuid import UUID, uuid5
from zoneinfo import ZoneInfo
from fastapi import APIRouter, Depends, File, HTTPException, Query, Response, UploadFile
@@ -461,6 +461,9 @@ async def edit_countdown(countdown_id: UUID, payload: CountdownUpdate, user: Use
"lunar_day": values.get("lunar_day", row.lunar_day),
"ignore_year": values.get("ignore_year", row.ignore_year),
}
calendar_fields_changed = bool(
{"event_date", "calendar_mode", "lunar_month", "lunar_day"} & values.keys()
)
if combined["calendar_mode"] == "solar":
if combined["lunar_month"] is not None or combined["lunar_day"] is not None:
if "calendar_mode" not in values:
@@ -469,12 +472,17 @@ async def edit_countdown(countdown_id: UUID, payload: CountdownUpdate, user: Use
else:
if combined["lunar_month"] is None or combined["lunar_day"] is None:
raise HTTPException(422, "农历倒数日需要月份和日期")
converted = lunar_to_solar_safe(
combined["event_date"].year, combined["lunar_month"], combined["lunar_day"]
)
if converted is None:
raise HTTPException(422, "所选年份不存在该农历日期")
combined["event_date"] = converted
if calendar_fields_changed:
if "event_date" in values:
lunar_year = combined["event_date"].year
else:
lunar_year, _, _ = solar_to_lunar_parts(row.event_date)
converted = lunar_to_solar_safe(
lunar_year, combined["lunar_month"], combined["lunar_day"]
)
if converted is None:
raise HTTPException(422, "所选年份不存在该农历日期")
combined["event_date"] = converted
values.update(combined)
for key, value in values.items():
setattr(row, key, value)
@@ -982,13 +990,17 @@ async def restore_json(payload: dict, mode: str = Query("merge", pattern="^(merg
)
db.add(row)
existing_countdown_ids = set((await db.scalars(select(Countdown.id).where(Countdown.user_id == user.id))).all())
occupied_countdown_ids = dict((await db.execute(select(Countdown.id, Countdown.user_id))).all())
has_pinned_countdown = bool(await db.scalar(select(Countdown.id).where(Countdown.user_id == user.id, Countdown.pinned.is_(True))))
for raw in payload.get("countdowns", []):
try:
source_id = UUID(raw["id"])
except (KeyError, TypeError, ValueError) as exc:
raise HTTPException(422, "无效的倒数日备份 ID") from exc
if mode == "merge" and source_id in existing_countdown_ids:
row_id = source_id
while row_id in occupied_countdown_ids and occupied_countdown_ids[row_id] != user.id:
row_id = uuid5(user.id, str(row_id))
if mode == "merge" and row_id in existing_countdown_ids:
continue
try:
item = CountdownInput(
@@ -1009,7 +1021,7 @@ async def restore_json(payload: dict, mode: str = Query("merge", pattern="^(merg
except (KeyError, TypeError, ValueError) as exc:
raise HTTPException(422, "无效的倒数日备份数据") from exc
row = Countdown(
id=source_id,
id=row_id,
user_id=user.id,
**item.model_dump(),
archived_at=datetime.fromisoformat(raw["archived_at"]) if raw.get("archived_at") else None,
@@ -1020,7 +1032,8 @@ async def restore_json(payload: dict, mode: str = Query("merge", pattern="^(merg
row.pinned = False
has_pinned_countdown = has_pinned_countdown or row.pinned
db.add(row)
existing_countdown_ids.add(source_id)
existing_countdown_ids.add(row_id)
occupied_countdown_ids[row_id] = user.id
audit(db, user.id, "restore", "backup", count=restored, mode=mode)
await db.commit()
return {"restored": restored, "mode": mode}