nomadweb/backend/app/services/meetup_live.py
eric ff7b721acb feat: NomadCNA community layer, social matching, payments, and ebook
Port meetups, discussions, gigs, dating/chat, VIP pay (ZPay/XorPay), MiroTalk live, digital academy, and ebook reader. Add persistent community_store, git-first deploy docs, and env template for production secrets.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-30 09:38:13 -05:00

69 lines
2.2 KiB
Python

"""Meetup live room URL builders — ported from NomadCNA."""
from __future__ import annotations
import os
import re
from urllib.parse import urlencode
MIROTALK_URL = os.getenv("MIROTALK_URL", "https://mirotalk.nomadro.com")
LOUNGE_URL = os.getenv("LOUNGE_URL", "https://lounge.nomadro.com")
VIP_ROLES = frozenset({"admin", "owner", "host", "organizer", "moderator"})
def normalize_room(value: str) -> str:
slug = re.sub(r"[^a-z0-9]+", "-", (value or "").lower()).strip("-")
return slug[:64] or "nomadro-live"
def create_mirotalk_room_slug(meetup: dict) -> str:
city = normalize_room(meetup.get("city") or "online")
date = (meetup.get("date") or "").replace("-", "")[:8]
time_part = (meetup.get("time") or "0000").replace(":", "")[:4]
mid = normalize_room(meetup.get("id") or "room")
return f"nomadro-{city}-{date}-{time_part}-{mid}"
def create_lounge_channel(meetup: dict) -> str:
if meetup.get("loungeChannel"):
ch = meetup["loungeChannel"].strip()
return ch if ch.startswith("#") else f"#{ch}"
if meetup.get("mirotalkRoom"):
return f"#{normalize_room(meetup['mirotalkRoom'])}"
return f"#{create_mirotalk_room_slug(meetup)}"
def build_mirotalk_join_url(meetup: dict, display_name: str = "nomadro") -> str:
explicit = (meetup.get("meetingUrl") or "").strip()
if explicit.startswith("http"):
return explicit
room = meetup.get("mirotalkRoom") or create_mirotalk_room_slug(meetup)
return f"{MIROTALK_URL.rstrip('/')}/join?{urlencode({'room': room, 'name': display_name})}"
def build_lounge_chat_url(meetup: dict) -> str:
channel = create_lounge_channel(meetup).lstrip("#")
return f"{LOUNGE_URL.rstrip('/')}/#/chan-{channel}"
def can_access_meetup(meetup: dict, user: dict | None, is_vip: bool = False) -> tuple[bool, str]:
level = meetup.get("access_level") or "public"
if level == "public":
return True, ""
if not user:
return False, "login_required"
if level == "members":
return True, ""
if level == "vip":
role = (user.get("role") or "").lower()
if is_vip or role in VIP_ROLES:
return True, ""
return False, "vip_required"
if level == "hosts":
role = (user.get("role") or "").lower()
if role in VIP_ROLES:
return True, ""
return False, "host_required"
return True, ""