from __future__ import annotations from sanic import response from sqlalchemy import select from datetime import datetime from app.core.models.content_v3 import ContentIndexItem from app.core.logger import make_log async def s_api_v1_content_index(request): rows = (await request.ctx.db_session.execute(select(ContentIndexItem))).scalars().all() items = [{**r.payload, "encrypted_cid": r.encrypted_cid, "sig": r.sig, "_updated_at": (r.updated_at.isoformat() + 'Z') if r.updated_at else None} for r in rows] # ETag by max updated_at + count max_ts = max((it.get("_updated_at") for it in items if it.get("_updated_at")), default="1970-01-01T00:00:00Z") etag = f'W/"{max_ts}.{len(items)}"' inm = request.headers.get('If-None-Match') if inm and inm == etag: resp = response.empty(status=304) resp.headers['ETag'] = etag return resp for it in items: it.pop("_updated_at", None) make_log("content.index", f"items={len(items)} etag={etag}") resp = response.json({"items": items, "schema": "my-network/index@1"}) resp.headers['ETag'] = etag return resp async def s_api_v1_content_delta(request): since = request.args.get('since') if not since: # No since provided → act as full index return await s_api_v1_content_index(request) try: # basic parse _ = datetime.fromisoformat(since.replace('Z', '+00:00')) except Exception: return response.json({"error": "BAD_SINCE"}, status=400) rows = (await request.ctx.db_session.execute(select(ContentIndexItem))).scalars().all() out = [] max_ts = since for r in rows: upd = (r.updated_at.isoformat() + 'Z') if r.updated_at else None if upd and upd > since: out.append({**r.payload, "encrypted_cid": r.encrypted_cid, "sig": r.sig}) if upd > max_ts: max_ts = upd resp = response.json({"items": out, "next_since": max_ts, "schema": "my-network/index@1"}) # Weak ETag for delta response resp.headers['ETag'] = f'W/"{max_ts}.{len(out)}"' return resp