97 lines
3.2 KiB
Python
97 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import re
|
|
from typing import Any
|
|
from urllib.parse import urlencode
|
|
|
|
from .settings import get_settings
|
|
|
|
|
|
def normalize_room(value: str) -> str:
|
|
cleaned = re.sub(r"[^a-z0-9-]+", "-", value.strip().lower())
|
|
return cleaned.strip("-")[:80]
|
|
|
|
|
|
def normalize_lounge_channel(value: str) -> str:
|
|
channel = value.strip()
|
|
if not channel:
|
|
return ""
|
|
return channel if channel.startswith("#") else f"#{channel}"
|
|
|
|
|
|
def create_mirotalk_room_slug(meetup: dict[str, Any]) -> str:
|
|
date_part = re.sub(r"[^0-9]", "", str(meetup.get("date") or "")[:10])
|
|
time_part = re.sub(r"[^0-9]", "", str(meetup.get("time") or "")[:5])
|
|
city_part = normalize_room(str(meetup.get("city") or "online"))
|
|
meetup_id = normalize_room(str(meetup.get("id") or ""))
|
|
return normalize_room("-".join(part for part in ["nomadcna", city_part, date_part, time_part, meetup_id] if part))
|
|
|
|
|
|
def create_lounge_channel(meetup: dict[str, Any]) -> str:
|
|
explicit = normalize_lounge_channel(str(meetup.get("loungeChannel") or ""))
|
|
if explicit:
|
|
return explicit
|
|
room = normalize_room(str(meetup.get("mirotalkRoom") or ""))
|
|
if room:
|
|
return f"#{room}"
|
|
return f"#{create_mirotalk_room_slug(meetup)}"
|
|
|
|
|
|
def build_mirotalk_join_url(meetup: dict[str, Any], display_name: str = "NomadCNA") -> str:
|
|
settings = get_settings()
|
|
meeting_url = str(meetup.get("meetingUrl") or "").strip()
|
|
if meeting_url.startswith(("http://", "https://")):
|
|
return meeting_url
|
|
room = normalize_room(str(meetup.get("mirotalkRoom") or "")) or create_mirotalk_room_slug(meetup)
|
|
name = display_name.strip() or "NomadCNA"
|
|
params = urlencode({"room": room, "name": name})
|
|
return f"{settings.mirotalk_url.rstrip('/')}/join?{params}"
|
|
|
|
|
|
def build_lounge_chat_url(meetup: dict[str, Any]) -> str:
|
|
settings = get_settings()
|
|
channel = create_lounge_channel(meetup).lstrip("#")
|
|
base = settings.lounge_url.rstrip("/")
|
|
return f"{base}/#/chan-{channel}"
|
|
|
|
|
|
def viewer_display_name(user: dict[str, Any] | None) -> str:
|
|
if not user:
|
|
return "NomadCNA"
|
|
name = str(user.get("name") or "").strip()
|
|
if name:
|
|
return name
|
|
email = str(user.get("email") or "").strip()
|
|
return email.split("@")[0] if email else "NomadCNA"
|
|
|
|
|
|
def is_host_user(user: dict[str, Any] | None) -> bool:
|
|
if not user:
|
|
return False
|
|
role = str(user.get("role") or user.get("memberRole") or user.get("siteRole") or "").lower()
|
|
return role in {"admin", "owner", "host", "organizer", "moderator"}
|
|
|
|
|
|
def can_access_meetup(meetup: dict[str, Any], user: dict[str, Any] | None, *, vip: bool) -> bool:
|
|
access = str(meetup.get("accessLevel") or "public").lower()
|
|
if access == "public":
|
|
return True
|
|
if access == "members":
|
|
return bool(user)
|
|
if access == "vip":
|
|
return bool(vip or user and user.get("vip"))
|
|
if access == "hosts":
|
|
return is_host_user(user)
|
|
return False
|
|
|
|
|
|
def access_lock_reason(meetup: dict[str, Any]) -> str:
|
|
access = str(meetup.get("accessLevel") or "public").lower()
|
|
if access == "members":
|
|
return "login_required"
|
|
if access == "vip":
|
|
return "vip_required"
|
|
if access == "hosts":
|
|
return "host_required"
|
|
return "no_access"
|