heystreamer/app/routers/auth.py
Bashy 6ad661c220 Initial commit — BashyOverlay v1
Twitch stream event platform with OBS browser source overlay.

Features:
- Twitch OAuth login (streamer + mod access)
- EventSub WebSocket for subs, gift subs, bits, channel points, follows, raids
- Chat commands via tmi.js in the overlay
- Gap audio — tone plays on new chat message after silence, volume/pitch scale with gap length
- Self-hosted media library (upload sounds and videos)
- Action configuration — map any event to sound, video, or alert
- Per-action cooldowns, test button, enable/disable toggle
- Multiple actions per event (all matching actions fire)
- Activity log dashboard with EventSub connection status
- Layout editor — iframe-based WYSIWYG with drag handles, live style preview
- Custom CSS and custom JS injection into overlay
- Custom DOM events (bashyoverlay:sub, bashyoverlay:raid, etc.) for custom JS hooks
- deploy.sh — one-shot setup and launch script

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-22 23:48:35 +03:00

75 lines
2.4 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from sqlmodel import Session, select
from app.auth import TWITCH_AUTH_URL, exchange_code, get_twitch_user, get_current_user
from app.database import get_session
from app.models import Settings, User
from app.templates import templates
router = APIRouter(prefix="/auth")
@router.get("/login", response_class=HTMLResponse)
async def login_page(request: Request, user=Depends(get_current_user)):
if user:
return RedirectResponse(url="/")
return templates.TemplateResponse("login.html", {"request": request})
@router.get("/twitch")
async def twitch_redirect():
return RedirectResponse(url=TWITCH_AUTH_URL)
@router.get("/callback")
async def twitch_callback(request: Request, code: str, session: Session = Depends(get_session)):
try:
tokens = await exchange_code(code)
twitch_user = await get_twitch_user(tokens["access_token"])
except Exception:
raise HTTPException(status_code=400, detail="OAuth failed")
user = session.exec(select(User).where(User.twitch_id == twitch_user["id"])).first()
is_first = user is None
if not user:
user = User(
twitch_id=twitch_user["id"],
twitch_login=twitch_user["login"],
twitch_display_name=twitch_user["display_name"],
broadcaster_id=twitch_user["id"],
access_token=tokens["access_token"],
refresh_token=tokens.get("refresh_token", ""),
is_admin=True,
)
else:
user.access_token = tokens["access_token"]
user.refresh_token = tokens.get("refresh_token", user.refresh_token)
user.twitch_display_name = twitch_user["display_name"]
session.add(user)
if is_first:
settings = session.exec(select(Settings)).first()
if not settings:
settings = Settings()
settings.twitch_channel = twitch_user["login"]
session.add(settings)
session.commit()
session.refresh(user)
request.session["user_id"] = user.id
if is_first:
from app.main import start_eventsub
import asyncio
asyncio.create_task(start_eventsub())
return RedirectResponse(url="/", status_code=303)
@router.get("/logout")
async def logout(request: Request):
request.session.clear()
return RedirectResponse(url="/auth/login")