- Detect shorts by duration (SHORTS_MAX_DURATION_SECONDS, default 180)
and expose is_short in feed, video and channel-activity DTOs.
- Feed gains type=all|long|short and anchor; lists show a two-mode
'Обычные | Shorts' filter (no 'Все') persisted in the URL.
- Clicking a short opens /shorts/🆔 a vertical scroll-snap feed with
autoplay for the active slide, context-aware endpoints and infinite
loading.
- Keep the sound choice across swipes, syncing with the player's own
mute control and guarding against the widget's stale isMuted() reads.
102 lines
5.2 KiB
Text
102 lines
5.2 KiB
Text
# =====================================================================
|
||
# MyYouTube — образец .env
|
||
# Скопируй в `.env` и заполни своими значениями.
|
||
# Сам `.env` в git НЕ попадает (в .gitignore) — не коммить его!
|
||
# =====================================================================
|
||
|
||
# ---------- Приложение ----------
|
||
|
||
# Окружение: production | development
|
||
APP_ENV=production
|
||
|
||
# Внешний адрес сервиса. Используется в OAuth-редиректе и для cookie.
|
||
# Локально — http://localhost:8080, в проде — https://твой-домен
|
||
APP_BASE_URL=http://localhost:8080
|
||
|
||
# Порт uvicorn внутри контейнера (наружу проброшен в compose.yml как 8080)
|
||
APP_PORT=8080
|
||
|
||
# Секрет для сессионных cookie. Любая длинная случайная строка, например:
|
||
# python3 -c "import secrets; print(secrets.token_urlsafe(48))"
|
||
APP_SECRET_KEY=CHANGE_ME
|
||
|
||
# Ключ шифрования refresh-токена Google (хранится в БД). Fernet-ключ:
|
||
# python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
||
# Генерируй один раз и не меняй (иначе старый токен не расшифруется).
|
||
TOKEN_ENCRYPTION_KEY=CHANGE_ME
|
||
|
||
# ---------- База данных ----------
|
||
|
||
# Пароль Postgres. Должен совпадать с POSTGRES_PASSWORD у сервиса postgres в compose.yml
|
||
POSTGRES_PASSWORD=CHANGE_ME
|
||
|
||
# URL базы. `postgres` — имя сервиса внутри docker-сети; при запуске без docker замени на localhost
|
||
DATABASE_URL=postgresql+psycopg://youtube_app:CHANGE_ME@postgres:5432/youtube_app
|
||
|
||
# ---------- Google OAuth (YouTube) ----------
|
||
|
||
# Google Cloud Console → APIs & Services → Credentials → Create credentials →
|
||
# OAuth client ID → Application type: Web application
|
||
GOOGLE_CLIENT_ID=
|
||
GOOGLE_CLIENT_SECRET=
|
||
|
||
# Тот же URI добавь в "Authorized redirect URIs" клиента в консоли.
|
||
# Всегда: {APP_BASE_URL}/api/auth/google/callback
|
||
GOOGLE_REDIRECT_URI=http://localhost:8080/api/auth/google/callback
|
||
|
||
# Gmail единственного пользователя, которому разрешён вход (single-user)
|
||
ALLOWED_GOOGLE_EMAIL=
|
||
|
||
# Endpoint'ы Google/YouTube — НЕОБЯЗАТЕЛЬНО (в коде есть дефолты).
|
||
# Раскомментируй, только если нужно их переопределить:
|
||
# GOOGLE_AUTH_URI=https://accounts.google.com/o/oauth2/auth
|
||
# GOOGLE_TOKEN_URI=https://oauth2.googleapis.com/token
|
||
# GOOGLE_USERINFO_URI=https://www.googleapis.com/oauth2/v3/userinfo
|
||
# GOOGLE_REVOKE_URI=https://oauth2.googleapis.com/revoke
|
||
# YOUTUBE_API_BASE_URL=https://www.googleapis.com/youtube/v3
|
||
# YOUTUBE_WATCH_URL_TEMPLATE=https://www.youtube.com/watch?v={video_id}
|
||
|
||
# ---------- MeTube (скачивание) ----------
|
||
|
||
# API-адрес MeTube, куда backend ходит управлять загрузками
|
||
# (POST /add, /delete, GET /history, Socket.IO-события)
|
||
METUBE_API_BASE_URL=http://192.168.8.177:8081
|
||
|
||
# Публичный адрес MeTube, с которого БРАУЗЕР стримит скачанные файлы
|
||
# (/download/...). Если MeTube за reverse-proxy — укажи его внешний URL.
|
||
METUBE_PUBLIC_BASE_URL=http://192.168.8.177:8081
|
||
|
||
# Каталог загрузок внутри контейнера MeTube (как в его настройках)
|
||
METUBE_CONTAINER_DOWNLOAD_DIR=/downloads
|
||
|
||
# Таймаут HTTP-запросов к MeTube/Google, секунды
|
||
METUBE_REQUEST_TIMEOUT_SECONDS=30
|
||
|
||
# ---------- Синхронизация ----------
|
||
|
||
# Интервал планового синка подписок, часов
|
||
SUBSCRIPTIONS_SYNC_INTERVAL_HOURS=6
|
||
|
||
# Авто-синк видео запускается по активности: когда ты делаешь запрос к сервису,
|
||
# а с последнего завершённого синка прошло больше этого числа часов
|
||
VIDEOS_SYNC_IDLE_HOURS=2
|
||
|
||
# Глубина истории канала: максимум последних N видео на канал.
|
||
# Всё, что старше, намеренно не подтягивается.
|
||
VIDEOS_BACKFILL_CAP=200
|
||
|
||
# Остановить перелистывание плейлиста канала, когда подряд встретилось
|
||
# N уже известных видео (дальше — уже синхронизированная история)
|
||
VIDEOS_KNOWN_STOP_THRESHOLD=50
|
||
|
||
# Окно «новых видео», дней. От него зависят бейджи «N новых» у каналов
|
||
# и в сайдбаре категорий, а также фильтр «только новые» по клику на число
|
||
NEW_VIDEOS_WINDOW_DAYS=2
|
||
|
||
# Видео короче или равные этому числу секунд считаются Shorts.
|
||
# Неизвестная длительность (NULL) считается обычным видео.
|
||
SHORTS_MAX_DURATION_SECONDS=180
|
||
|
||
# ---------- Логи ----------
|
||
|
||
LOG_LEVEL=INFO
|