Verify integration points: OC webhook events (order.processed/new member), Cloudron user payload

This commit is contained in:
inference-bot committed 2026-09-04 17:10:41 -06:00
1 parent 451fb561bc
commit 7b84025e60
2 files changed
+28 -10

No files matched your search

+23 -8
View File
@@ -48,24 +48,34 @@ def cloudron_headers() -> dict:
async def cloudron_create_user(email: str, name: str) -> str:
"""Create (or return existing) Cloudron user, assigned to the chat app."""
"""Create (or return existing) Cloudron user, assigned to the chat app.
Verified user shape (from live API):
{id, username, email, fallbackEmail, displayName, role, active, groupIds}
Roles: "owner", "admin", "user".
"""
async with httpx.AsyncClient() as client:
# Check if user exists
r = await client.get(
f"{CLOUDRON_API}/api/v1/users",
headers=cloudron_headers(),
params={"email": email},
)
r.raise_for_status()
users = r.json().get("users", [])
if users:
return users[0]["id"]
for u in r.json().get("users", []):
if u.get("email") == email:
return u["id"]
# Create user
# Create user (role "user" = regular member)
r = await client.post(
f"{CLOUDRON_API}/api/v1/users",
headers=cloudron_headers(),
json={"email": email, "displayName": name, "role": "user"},
json={
"username": email.split("@")[0],
"email": email,
"displayName": name,
"role": "user",
"active": True,
},
)
r.raise_for_status()
return r.json()["id"]
@@ -143,7 +153,12 @@ async def opencollective_webhook(request: Request):
logger.info("Open Collective event: %s for %s", event_type, email)
if event_type in ("collective.member.created", "collective.transaction.created"):
# Open Collective webhook events (verified):
# - "order.processed" → fires on EVERY payment (incl. monthly recurring)
# - "new member" → fires on FIRST contribution only
# - payload has "firstPayment" boolean to distinguish new vs recurring
# - "collective.transaction.created" is DEPRECATED (being removed)
if event_type in ("order.processed", "new.member", "collective.member.created"):
# New or renewed member → ensure active
tier = (data.get("tier") or {}).get("slug", DEFAULT_TIER)
budget = TIER_BUDGETS.get(tier, TIER_BUDGETS[DEFAULT_TIER])