update update

This commit is contained in:
gpatruno
2026-04-28 21:06:26 +02:00
parent 7b2135bfed
commit b4254c9e06
28 changed files with 2032 additions and 547 deletions
+125
View File
@@ -0,0 +1,125 @@
import json
from typing import Any, Dict, List, Optional
import requests
def _read_json(path: str, default):
try:
with open(path, "r", encoding="utf-8") as f:
v = json.load(f)
return v if v is not None else default
except Exception:
return default
def twitch_client_id(config_path: str = "config/config.json") -> str:
cfg = _read_json(config_path, default={})
if isinstance(cfg, dict):
v = cfg.get("twitch_client_id") or cfg.get("twitch_clientId") or cfg.get("twitchClientId")
if isinstance(v, str):
return v.strip()
return ""
def _normalize_bearer(raw: str) -> str:
raw = (raw or "").strip()
if raw.lower().startswith("oauth:"):
raw = raw.split(":", 1)[1].strip()
return raw
def bearer_token_for_pseudo(pseudo: str, users_path: str = "config/user.json") -> str:
users = _read_json(users_path, default=[])
if not isinstance(users, list):
users = []
wanted = (pseudo or "").strip().lstrip("@").lower()
for u in users:
if not isinstance(u, dict):
continue
p = (u.get("tw_acc_pseudo") or "").strip().lower()
if p == wanted:
tok = _normalize_bearer(u.get("tw_acc_token") or "")
if not tok:
raise ValueError("Token OAuth manquant")
return tok
raise ValueError("Utilisateur (pseudo) non trouvé")
def _helix_headers(*, client_id: str, bearer: str) -> Dict[str, str]:
if not client_id:
raise ValueError("Client-ID Twitch manquant (config/config.json:twitch_client_id)")
if not bearer:
raise ValueError("Token OAuth manquant")
return {"Client-ID": client_id, "Authorization": f"Bearer {bearer}"}
def get_user_id_by_login(*, client_id: str, bearer: str, login: str, timeout_s: int = 10) -> str:
login = (login or "").strip().lstrip("@")
if not login:
raise ValueError("Nom de chaîne requis")
r = requests.get(
"https://api.twitch.tv/helix/users",
headers=_helix_headers(client_id=client_id, bearer=bearer),
params={"login": login},
timeout=timeout_s,
)
payload: Optional[Dict[str, Any]]
try:
payload = r.json()
except Exception:
payload = None
if r.status_code >= 400:
msg = ""
if isinstance(payload, dict):
msg = payload.get("message") or payload.get("error") or ""
raise RuntimeError(f"Erreur Twitch /helix/users ({r.status_code}) {msg}".strip())
data = payload.get("data") if isinstance(payload, dict) else None
if not isinstance(data, list) or not data:
raise ValueError("Chaîne Twitch introuvable (login)")
uid = (data[0] or {}).get("id")
if not uid:
raise RuntimeError("Réponse Twitch invalide: id manquant")
return str(uid)
def create_clip(
*,
client_id: str,
bearer: str,
broadcaster_id: str,
has_delay: bool = False,
timeout_s: int = 15,
) -> Dict[str, str]:
r = requests.post(
"https://api.twitch.tv/helix/clips",
headers=_helix_headers(client_id=client_id, bearer=bearer),
params={"broadcaster_id": str(broadcaster_id), "has_delay": "true" if has_delay else "false"},
timeout=timeout_s,
)
payload: Optional[Dict[str, Any]]
try:
payload = r.json()
except Exception:
payload = None
if r.status_code >= 400:
msg = ""
if isinstance(payload, dict):
msg = payload.get("message") or payload.get("error") or ""
hint = ""
if r.status_code in (401, 403):
hint = " (scope requis: clips:edit)"
raise RuntimeError(f"Erreur Twitch /helix/clips ({r.status_code}) {msg}{hint}".strip())
data = payload.get("data") if isinstance(payload, dict) else None
if not isinstance(data, list) or not data:
raise RuntimeError("Réponse Twitch invalide: data manquant")
clip = data[0] or {}
clip_id = clip.get("id")
edit_url = clip.get("edit_url")
if not clip_id:
raise RuntimeError("Réponse Twitch invalide: clip id manquant")
return {"id": str(clip_id), "edit_url": str(edit_url or ""), "url": f"https://clips.twitch.tv/{clip_id}"}