Support activity_id (hash) in /activities/{ref} URL

- Accept both numeric index and activity_id hash
- Look up activity by ID from database when hash provided
- Refactor ui_activity_detail to support both lookup methods

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gilesb
2026-01-10 18:37:53 +00:00
parent e4cbbb1fbc
commit a5619208cf

View File

@@ -606,6 +606,17 @@ async def ui_activity_detail(activity_index: int, request: Request):
return HTMLResponse(base_html("Activity Not Found", content, username))
activity = activities[activity_index]
return await _render_activity_detail(activity, request)
async def ui_activity_detail_by_data(activity: dict, request: Request):
"""Activity detail page taking activity data directly."""
return await _render_activity_detail(activity, request)
async def _render_activity_detail(activity: dict, request: Request):
"""Core activity detail rendering logic."""
username = get_user_from_cookie(request)
activity_type = activity.get("activity_type", "")
activity_id = activity.get("activity_id", "")
actor_id = activity.get("actor_id", "")
@@ -2501,16 +2512,36 @@ async def get_activities(request: Request, page: int = 1, limit: int = 20):
}
@app.get("/activities/{activity_index}")
async def get_activity_detail(activity_index: int, request: Request):
"""Get single activity. HTML for browsers (default), JSON only if explicitly requested."""
activities = await load_activities()
@app.get("/activities/{activity_ref}")
async def get_activity_detail(activity_ref: str, request: Request):
"""Get single activity by index or activity_id. HTML for browsers (default), JSON only if explicitly requested."""
# Check if JSON explicitly requested
accept = request.headers.get("accept", "")
wants_json = ("application/json" in accept or "application/activity+json" in accept) and "text/html" not in accept
if activity_index < 0 or activity_index >= len(activities):
activity = None
activity_index = None
# Check if it's a numeric index or an activity_id (hash)
if activity_ref.isdigit():
# Numeric index (legacy)
activity_index = int(activity_ref)
activities = await load_activities()
if 0 <= activity_index < len(activities):
activity = activities[activity_index]
else:
# Activity ID (hash) - look up directly
activity = await db.get_activity(activity_ref)
if activity:
# Find index for UI rendering
activities = await load_activities()
for i, a in enumerate(activities):
if a.get("activity_id") == activity_ref:
activity_index = i
break
if not activity:
if wants_json:
raise HTTPException(404, "Activity not found")
content = '''
@@ -2520,13 +2551,15 @@ async def get_activity_detail(activity_index: int, request: Request):
'''
return HTMLResponse(base_html("Activity Not Found", content, get_user_from_cookie(request)))
activity = activities[activity_index]
if wants_json:
return activity
# Default to HTML for browsers
return await ui_activity_detail(activity_index, request)
if activity_index is not None:
return await ui_activity_detail(activity_index, request)
else:
# Render activity directly if no index found
return await ui_activity_detail_by_data(activity, request)
@app.get("/activity/{activity_index}")