73 lines
2.8 KiB
Python
73 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
from typing import Any
|
|
|
|
import requests
|
|
from fastapi import HTTPException
|
|
|
|
from app.services.harborforge_config import get_discord_wakeup_config
|
|
|
|
DISCORD_API_BASE = "https://discord.com/api/v10"
|
|
WAKEUP_CATEGORY_NAME = "HarborForge Wakeup"
|
|
|
|
|
|
def _headers(bot_token: str) -> dict[str, str]:
|
|
return {
|
|
"Authorization": f"Bot {bot_token}",
|
|
"Content-Type": "application/json",
|
|
}
|
|
|
|
|
|
def _ensure_category(guild_id: str, bot_token: str) -> str | None:
|
|
resp = requests.get(f"{DISCORD_API_BASE}/guilds/{guild_id}/channels", headers=_headers(bot_token), timeout=15)
|
|
if not resp.ok:
|
|
raise HTTPException(status_code=502, detail=f"Discord list channels failed: {resp.text}")
|
|
for ch in resp.json():
|
|
if ch.get("type") == 4 and ch.get("name") == WAKEUP_CATEGORY_NAME:
|
|
return ch.get("id")
|
|
payload = {"name": WAKEUP_CATEGORY_NAME, "type": 4}
|
|
created = requests.post(f"{DISCORD_API_BASE}/guilds/{guild_id}/channels", headers=_headers(bot_token), json=payload, timeout=15)
|
|
if not created.ok:
|
|
raise HTTPException(status_code=502, detail=f"Discord create category failed: {created.text}")
|
|
return created.json().get("id")
|
|
|
|
|
|
def create_private_wakeup_channel(discord_user_id: str, title: str, message: str) -> dict[str, Any]:
|
|
cfg = get_discord_wakeup_config()
|
|
guild_id = cfg.get("guild_id")
|
|
bot_token = cfg.get("bot_token")
|
|
if not guild_id or not bot_token:
|
|
raise HTTPException(status_code=400, detail="Discord wakeup config is incomplete")
|
|
|
|
category_id = _ensure_category(guild_id, bot_token)
|
|
channel_name = f"wake-{discord_user_id[-6:]}-{int(datetime.now(timezone.utc).timestamp())}"
|
|
payload = {
|
|
"name": channel_name,
|
|
"type": 0,
|
|
"parent_id": category_id,
|
|
"permission_overwrites": [
|
|
{"id": guild_id, "type": 0, "deny": "1024"},
|
|
{"id": discord_user_id, "type": 1, "allow": "1024"},
|
|
],
|
|
"topic": title,
|
|
}
|
|
created = requests.post(f"{DISCORD_API_BASE}/guilds/{guild_id}/channels", headers=_headers(bot_token), json=payload, timeout=15)
|
|
if not created.ok:
|
|
raise HTTPException(status_code=502, detail=f"Discord create channel failed: {created.text}")
|
|
channel = created.json()
|
|
sent = requests.post(
|
|
f"{DISCORD_API_BASE}/channels/{channel['id']}/messages",
|
|
headers=_headers(bot_token),
|
|
json={"content": message},
|
|
timeout=15,
|
|
)
|
|
if not sent.ok:
|
|
raise HTTPException(status_code=502, detail=f"Discord send message failed: {sent.text}")
|
|
return {
|
|
"guild_id": guild_id,
|
|
"channel_id": channel.get("id"),
|
|
"channel_name": channel.get("name"),
|
|
"message_id": sent.json().get("id"),
|
|
}
|