Add OBS widgets for streamers
- Add widget token authentication system - Create leaderboard, current assignment, and progress widgets - Support dark, light, and neon themes - Add widget settings modal for URL generation - Fix avatar loading through backend API proxy 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -134,6 +134,15 @@ from app.schemas.promo_code import (
|
||||
PromoCodeRedemptionUser,
|
||||
)
|
||||
from app.schemas.user import ShopItemPublic
|
||||
from app.schemas.widget import (
|
||||
WidgetTokenCreate,
|
||||
WidgetTokenResponse,
|
||||
WidgetTokenListItem,
|
||||
WidgetLeaderboardEntry,
|
||||
WidgetLeaderboardResponse,
|
||||
WidgetCurrentResponse,
|
||||
WidgetProgressResponse,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# User
|
||||
@@ -260,4 +269,12 @@ __all__ = [
|
||||
"PromoCodeRedeemResponse",
|
||||
"PromoCodeRedemptionResponse",
|
||||
"PromoCodeRedemptionUser",
|
||||
# Widget
|
||||
"WidgetTokenCreate",
|
||||
"WidgetTokenResponse",
|
||||
"WidgetTokenListItem",
|
||||
"WidgetLeaderboardEntry",
|
||||
"WidgetLeaderboardResponse",
|
||||
"WidgetCurrentResponse",
|
||||
"WidgetProgressResponse",
|
||||
]
|
||||
|
||||
79
backend/app/schemas/widget.py
Normal file
79
backend/app/schemas/widget.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from pydantic import BaseModel
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
# === Token schemas ===
|
||||
|
||||
class WidgetTokenCreate(BaseModel):
|
||||
"""Создание токена виджета"""
|
||||
pass # Не требует параметров
|
||||
|
||||
|
||||
class WidgetTokenResponse(BaseModel):
|
||||
"""Ответ с токеном виджета"""
|
||||
id: int
|
||||
token: str
|
||||
created_at: datetime
|
||||
expires_at: datetime | None
|
||||
is_active: bool
|
||||
urls: dict[str, str] # Готовые URL для виджетов
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class WidgetTokenListItem(BaseModel):
|
||||
"""Элемент списка токенов"""
|
||||
id: int
|
||||
token: str
|
||||
created_at: datetime
|
||||
is_active: bool
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# === Widget data schemas ===
|
||||
|
||||
class WidgetLeaderboardEntry(BaseModel):
|
||||
"""Запись в лидерборде виджета"""
|
||||
rank: int
|
||||
nickname: str
|
||||
avatar_url: str | None
|
||||
total_points: int
|
||||
current_streak: int
|
||||
is_current_user: bool # Для подсветки
|
||||
|
||||
|
||||
class WidgetLeaderboardResponse(BaseModel):
|
||||
"""Ответ лидерборда для виджета"""
|
||||
entries: list[WidgetLeaderboardEntry]
|
||||
current_user_rank: int | None
|
||||
total_participants: int
|
||||
marathon_title: str
|
||||
|
||||
|
||||
class WidgetCurrentResponse(BaseModel):
|
||||
"""Текущее задание для виджета"""
|
||||
has_assignment: bool
|
||||
game_title: str | None = None
|
||||
game_cover_url: str | None = None
|
||||
assignment_type: str | None = None # "challenge" | "playthrough"
|
||||
challenge_title: str | None = None
|
||||
challenge_description: str | None = None
|
||||
points: int | None = None
|
||||
difficulty: str | None = None # easy, medium, hard
|
||||
bonus_completed: int | None = None # Для прохождений
|
||||
bonus_total: int | None = None
|
||||
|
||||
|
||||
class WidgetProgressResponse(BaseModel):
|
||||
"""Прогресс участника для виджета"""
|
||||
nickname: str
|
||||
avatar_url: str | None
|
||||
rank: int
|
||||
total_points: int
|
||||
current_streak: int
|
||||
completed_count: int
|
||||
dropped_count: int
|
||||
marathon_title: str
|
||||
Reference in New Issue
Block a user