jirorian/src/jirorian/r2.py
randogoth be93d74d68 Implement all modules
- store: SQLite whitelist + per-pubkey daily rate limiting
- auth: NIP-98 kind:27235 event verification via pynostr
- r2: boto3 presigned PUT URL generation for Cloudflare R2
- nostr: websocket relay subscription for kind:5392 registration events
- main: FastAPI app with NIP-96 info endpoint and upload request endpoint

Also moves package to src/ layout (required by uv_build) and pins
Python to 3.12 for coincurve wheel availability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 17:33:40 +03:00

48 lines
1.4 KiB
Python

import os
import uuid
import boto3
from botocore.config import Config
ALLOWED_CONTENT_TYPES: dict[str, str] = {
"image/jpeg": "jpg",
"image/png": "png",
"image/webp": "webp",
"image/gif": "gif",
}
MAX_FILE_SIZE = int(os.environ.get("JIRORIAN_MAX_FILE_SIZE", str(10 * 1024 * 1024)))
PRESIGNED_URL_TTL = int(os.environ.get("JIRORIAN_PRESIGNED_TTL", "300"))
_client = None
def _get_client():
global _client
if _client is None:
_client = boto3.client(
"s3",
endpoint_url=os.environ["R2_ENDPOINT"],
aws_access_key_id=os.environ["R2_ACCESS_KEY_ID"],
aws_secret_access_key=os.environ["R2_SECRET_ACCESS_KEY"],
region_name="auto",
config=Config(signature_version="s3v4"),
)
return _client
def generate_presigned_upload(app: str, pubkey: str, content_type: str) -> tuple[str, str]:
"""Return (presigned PUT URL, public CDN URL) for a new upload."""
ext = ALLOWED_CONTENT_TYPES[content_type]
key = f"{app}/{pubkey}/{uuid.uuid4()}.{ext}"
bucket = os.environ["R2_BUCKET_NAME"]
cdn_base = os.environ["R2_CDN_URL"].rstrip("/")
upload_url = _get_client().generate_presigned_url(
"put_object",
Params={"Bucket": bucket, "Key": key, "ContentType": content_type},
ExpiresIn=PRESIGNED_URL_TTL,
HttpMethod="PUT",
)
return upload_url, f"{cdn_base}/{key}"