From a4eaaa3180aab82bee4dc7c94e4258ac0d12d521 Mon Sep 17 00:00:00 2001 From: Peifan Li Date: Sun, 4 Jan 2026 17:08:53 -0500 Subject: [PATCH] chore: update doc --- README-zh.md | 19 +- README.md | 19 +- documents/en/api-endpoints.md | 69 ++++-- documents/en/directory-structure.md | 346 ++++++--------------------- documents/en/docker-guide.md | 14 +- documents/en/getting-started.md | 48 ++-- documents/en/hooks-guide.md | 49 ++-- documents/zh/api-endpoints.md | 81 +++++-- documents/zh/directory-structure.md | 358 +++++++--------------------- documents/zh/docker-guide.md | 12 +- documents/zh/getting-started.md | 48 ++-- documents/zh/hooks-guide.md | 49 ++-- 12 files changed, 423 insertions(+), 689 deletions(-) diff --git a/README-zh.md b/README-zh.md index c2f02d0..fe83cd1 100644 --- a/README-zh.md +++ b/README-zh.md @@ -30,7 +30,7 @@ - **搜索功能**:支持在本地库中搜索视频,或在线搜索 YouTube 视频。 - **收藏夹**:创建自定义收藏夹以整理您的视频。 - **订阅功能**:订阅您喜爱的频道,并在新视频发布时自动下载。 -- **登录保护**:通过密码登录页面保护您的应用。 +- **登录保护**:支持密码登录并可选使用通行密钥 (WebAuthn)。 - **国际化**:支持多种语言,包括英语、中文、西班牙语、法语、德语、日语、韩语、阿拉伯语、葡萄牙语和俄语。 - **分页功能**:支持分页浏览,高效管理大量视频。 - **视频评分**:使用 5 星评级系统为您的视频评分。 @@ -39,9 +39,10 @@ - **视图模式**:在主页上切换收藏夹视图和视频视图。 - **Cookie 管理**:支持上传 `cookies.txt` 以启用年龄限制或会员内容的下载。 - **yt-dlp 配置**: 通过用户界面自定义全局 `yt-dlp` 参数、网络代理及其他高级设置。 -- **访客模式**:启用只读模式,允许查看视频但无法进行修改。非常适合与他人分享您的视频库。 +- **访客用户**:启用只读角色,便于分享但不允许修改。 - **云存储集成**:下载后自动将视频和缩略图上传到云存储(OpenList/Alist)。 - **Cloudflare Tunnel 集成**: 内置 Cloudflare Tunnel 支持,无需端口转发即可轻松将本地 MyTube 实例暴露到互联网。 +- **任务钩子**: 在下载任务的各个阶段(开始、成功、失败、取消)执行自定义 Shell 脚本,以实现集成和自动化。详见 [任务钩子指南](documents/zh/hooks-guide.md)。 ## 目录结构 @@ -89,23 +90,19 @@ ### 前端 (`frontend/.env`) ```env -VITE_API_URL=http://localhost:5551/api -VITE_BACKEND_URL=http://localhost:5551 +VITE_API_URL=/api +VITE_BACKEND_URL= ``` ### 后端 (`backend/.env`) ```env PORT=5551 -UPLOAD_DIR=uploads -VIDEO_DIR=uploads/videos -IMAGE_DIR=uploads/images -SUBTITLES_DIR=uploads/subtitles -DATA_DIR=data -MAX_FILE_SIZE=500000000 ``` -复制前端和后端目录中的 `.env.example` 文件以创建您自己的 `.env` 文件。 +默认数据与上传路径位于 `backend/data` 和 `backend/uploads`(相对于后端工作目录)。 + +将 `backend/.env.example` 复制为 `backend/.env` 并按需调整。前端已提供 `frontend/.env`,可使用 `frontend/.env.local` 覆盖默认值。 ## 数据库 diff --git a/README.md b/README.md index aff3209..f40785e 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Self-hosted downloader and player for YouTube, Bilibili, MissAV, and [yt-dlp sit - **Auto Subtitles**: Automatically download YouTube / Bilibili default language subtitles. - **Search**: Search for videos locally in your library or online via YouTube. - **Collections**: Organize videos into custom collections for easy access. -- **Login Protection**: Secure your application with a password login page. +- **Login Protection**: Secure your application with password login and optional passkeys (WebAuthn). - **Internationalization**: Support for multiple languages including English, Chinese, Spanish, French, German, Japanese, Korean, Arabic, Portuguese, and Russian. - **Pagination**: Efficiently browse large libraries with pagination support. - **Subscriptions**: Manage subscriptions to channels or creators to automatically download new content. @@ -39,9 +39,10 @@ Self-hosted downloader and player for YouTube, Bilibili, MissAV, and [yt-dlp sit - **View Modes**: Toggle between Collection View and Video View on the home page. - **Cookie Management**: Support for uploading `cookies.txt` to enable downloading of age-restricted or premium content. - **yt-dlp Configuration**: Customize global `yt-dlp` arguments, network proxy, and other advanced settings via settings page. -- **Visitor Mode**: Enable read-only mode to allow viewing videos without modification capabilities. Perfect for sharing your library with others. +- **Visitor User**: Enable a read-only role for safe sharing without modification capabilities. - **Cloud Storage Integration**: Automatically upload videos and thumbnails to cloud storage (OpenList/Alist) after download. - **Cloudflare Tunnel Integration**: Built-in Cloudflare Tunnel support to easily expose your local MyTube instance to the internet without port forwarding. +- **Task Hooks**: Execute custom shell scripts at various stages of a download task (start, success, fail, cancel) for integration and automation. See [Task Hooks Guide](documents/en/hooks-guide.md). ## Directory Structure @@ -89,23 +90,19 @@ The application uses environment variables for configuration. ### Frontend (`frontend/.env`) ```env -VITE_API_URL=http://localhost:5551/api -VITE_BACKEND_URL=http://localhost:5551 +VITE_API_URL=/api +VITE_BACKEND_URL= ``` ### Backend (`backend/.env`) ```env PORT=5551 -UPLOAD_DIR=uploads -VIDEO_DIR=uploads/videos -IMAGE_DIR=uploads/images -SUBTITLES_DIR=uploads/subtitles -DATA_DIR=data -MAX_FILE_SIZE=500000000 ``` -Copy the `.env.example` files in both frontend and backend directories to create your own `.env` files. +Data and uploads are stored under `backend/data` and `backend/uploads` by default (relative to the backend working directory). + +Copy `backend/.env.example` to `backend/.env` and adjust as needed. The frontend ships with `frontend/.env`; use `frontend/.env.local` to override defaults. ## Database diff --git a/documents/en/api-endpoints.md b/documents/en/api-endpoints.md index 69fca2d..b19ecb5 100644 --- a/documents/en/api-endpoints.md +++ b/documents/en/api-endpoints.md @@ -1,11 +1,13 @@ # API Endpoints +All API routes are mounted under `/api` unless noted otherwise. + ## Video Download & Search -- `GET /api/search` - Search for videos online (YouTube) +- `GET /api/search` - Search videos online (YouTube) - Query params: `query` (required), `limit` (optional, default: 8), `offset` (optional, default: 1) - `POST /api/download` - Download a video from supported platforms - - Body: `{ url: string, ...options }` + - Body: `{ youtubeUrl: string, ...options }` - Supports: YouTube, Bilibili, MissAV, and all yt-dlp supported sites - `GET /api/check-video-download` - Check if a video has already been downloaded - Query params: `url` (required) @@ -16,8 +18,8 @@ - Query params: `url` (required) - `GET /api/check-playlist` - Check if a URL is a supported playlist - Query params: `url` (required) -- `GET /api/download-status` - Get status of active downloads - - Returns: `{ active: [], queued: [] }` +- `GET /api/download-status` - Get active/queued download status + - Returns: `{ activeDownloads: DownloadInfo[], queuedDownloads: DownloadInfo[] }` ## Video Management @@ -40,7 +42,6 @@ - `GET /api/videos/author-channel-url` - Get author channel URL for a video - Query params: `sourceUrl` (required) - Returns: `{ success: boolean, channelUrl: string | null }` - - Checks database first, then fetches from YouTube/Bilibili API if not found ## Download Management @@ -80,25 +81,54 @@ - `DELETE /api/subscriptions/tasks/:id/delete` - Delete a task record - `DELETE /api/subscriptions/tasks/clear-finished` - Clear all finished tasks -## Settings & System +## Settings & Passwords - `GET /api/settings` - Get application settings - `POST /api/settings` - Update application settings - Body: `{ [key: string]: any }` - Settings object - - Supports: `visitorMode`, `cloudDriveEnabled`, `openListApiUrl`, `openListToken`, `openListPublicUrl`, `cloudDrivePath`, and other settings - `GET /api/settings/cloudflared/status` - Get Cloudflare Tunnel status -- `GET /api/settings/password-enabled` - Check if password protection is enabled -- `POST /api/settings/verify-password` - Verify login password - - Body: `{ password: string }` -- `POST /api/settings/reset-password` - Reset login password - - Body: `{ oldPassword: string, newPassword: string }` - `POST /api/settings/migrate` - Migrate data from JSON to SQLite - `POST /api/settings/delete-legacy` - Delete legacy JSON data files - `POST /api/settings/format-filenames` - Format video filenames according to settings +- `GET /api/settings/password-enabled` - Check if password protection is enabled +- `GET /api/settings/reset-password-cooldown` - Get cooldown time for password reset +- `POST /api/settings/verify-admin-password` - Verify admin password + - Body: `{ password: string }` +- `POST /api/settings/verify-visitor-password` - Verify visitor password + - Body: `{ password: string }` +- `POST /api/settings/verify-password` - Verify login password (deprecated) + - Body: `{ password: string }` +- `POST /api/settings/reset-password` - Reset login password + - Body: `{ oldPassword: string, newPassword: string }` +- `POST /api/settings/logout` - Logout current session + +## Passkey Management + +- `GET /api/settings/passkeys` - Get all registered passkeys +- `GET /api/settings/passkeys/exists` - Check if any passkeys are registered +- `POST /api/settings/passkeys/register` - Start passkey registration +- `POST /api/settings/passkeys/register/verify` - Verify passkey registration +- `POST /api/settings/passkeys/authenticate` - Start passkey authentication +- `POST /api/settings/passkeys/authenticate/verify` - Verify passkey authentication +- `DELETE /api/settings/passkeys` - Remove all passkeys + +## Cookies + - `POST /api/settings/upload-cookies` - Upload cookies.txt for yt-dlp - Multipart form data: `file` (cookies.txt) - `POST /api/settings/delete-cookies` - Delete cookies.txt - `GET /api/settings/check-cookies` - Check if cookies.txt exists + +## Task Hooks + +- `GET /api/settings/hooks/status` - Get status of all hooks +- `POST /api/settings/hooks/:name` - Upload a hook script + - Multipart form data: `file` (script file) + - Params: `name` (hook name, e.g., `task_success`) +- `DELETE /api/settings/hooks/:name` - Delete a hook script + +## Database Backups + - `GET /api/settings/export-database` - Export database as backup file - `POST /api/settings/import-database` - Import database from backup file - Multipart form data: `file` (database backup file) @@ -113,6 +143,15 @@ ## Cloud Storage -- `GET /cloud/videos/:filename` - Proxy endpoint to stream videos from cloud storage (OpenList/Alist) -- `GET /cloud/images/:filename` - Proxy endpoint to serve images from cloud storage (OpenList/Alist) - - Note: These endpoints require cloud storage to be configured in settings +- `GET /api/cloud/signed-url` - Get a signed URL for cloud storage + - Query params: `filename` (required), `type` (optional: `video` or `thumbnail`) +- `POST /api/cloud/sync` - Sync local videos to cloud storage (streams JSON lines) +- `DELETE /api/cloud/thumbnail-cache` - Clear local thumbnail cache +- `GET /api/cloud/thumbnail-cache/:filename` - Serve a cached cloud thumbnail +- `GET /cloud/videos/:filename` - Redirect to signed URL for cloud videos +- `GET /cloud/images/:filename` - Redirect to signed URL (or cached file) for cloud thumbnails + +## System + +- `GET /api/system/version` - Get current and latest version info + - Returns: `{ currentVersion, latestVersion, releaseUrl, hasUpdate }` diff --git a/documents/en/directory-structure.md b/documents/en/directory-structure.md index 6aca19a..8b13799 100644 --- a/documents/en/directory-structure.md +++ b/documents/en/directory-structure.md @@ -2,269 +2,84 @@ ``` mytube/ -├── backend/ # Express.js backend (TypeScript) -│ ├── src/ # Source code -│ │ ├── __tests__/ # Test files -│ │ │ ├── controllers/ # Controller tests -│ │ │ ├── middleware/ # Middleware tests -│ │ │ ├── services/ # Service tests -│ │ │ └── utils/ # Utility tests -│ │ ├── config/ # Configuration files -│ │ │ └── paths.ts # Path configuration -│ │ ├── controllers/ # Route controllers -│ │ │ ├── cleanupController.ts # Cleanup operations +├── backend/ # Express.js backend (TypeScript) +│ ├── src/ # Source code +│ │ ├── __tests__/ # Test files +│ │ ├── config/ # Configuration (paths, etc.) +│ │ ├── controllers/ # Route controllers +│ │ │ ├── cleanupController.ts +│ │ │ ├── cloudStorageController.ts │ │ │ ├── collectionController.ts +│ │ │ ├── cookieController.ts │ │ │ ├── downloadController.ts +│ │ │ ├── hookController.ts +│ │ │ ├── passkeyController.ts +│ │ │ ├── passwordController.ts │ │ │ ├── scanController.ts │ │ │ ├── settingsController.ts │ │ │ ├── subscriptionController.ts +│ │ │ ├── systemController.ts │ │ │ ├── videoController.ts │ │ │ ├── videoDownloadController.ts │ │ │ └── videoMetadataController.ts -│ │ ├── db/ # Database layer -│ │ │ ├── index.ts # Database connection (Drizzle ORM) -│ │ │ ├── migrate.ts # Migration runner -│ │ │ └── schema.ts # Database schema definitions -│ │ ├── errors/ # Custom error classes -│ │ │ └── DownloadErrors.ts -│ │ ├── middleware/ # Express middleware -│ │ │ ├── errorHandler.ts # Error handling middleware -│ │ │ ├── visitorModeMiddleware.ts # Visitor mode (read-only) middleware -│ │ │ └── visitorModeSettingsMiddleware.ts # Visitor mode settings middleware -│ │ ├── routes/ # API route definitions -│ │ │ ├── api.ts # Main API routes -│ │ │ └── settingsRoutes.ts # Settings-specific routes -│ │ ├── scripts/ # Utility scripts -│ │ │ ├── cleanVttFiles.ts -│ │ │ └── rescanSubtitles.ts -│ │ ├── services/ # Business logic services -│ │ │ ├── downloaders/ # Downloader implementations -│ │ │ │ ├── BaseDownloader.ts # Abstract base class -│ │ │ │ ├── BilibiliDownloader.ts -│ │ │ │ ├── MissAVDownloader.ts -│ │ │ │ ├── YtDlpDownloader.ts -│ │ │ │ ├── bilibili/ # Bilibili-specific modules -│ │ │ │ │ ├── bilibiliApi.ts -│ │ │ │ │ ├── bilibiliCollection.ts -│ │ │ │ │ ├── bilibiliCookie.ts -│ │ │ │ │ ├── bilibiliSubtitle.ts -│ │ │ │ │ ├── bilibiliVideo.ts -│ │ │ │ │ └── types.ts -│ │ │ │ └── ytdlp/ # yt-dlp-specific modules -│ │ │ │ ├── types.ts -│ │ │ │ ├── ytdlpChannel.ts -│ │ │ │ ├── ytdlpConfig.ts -│ │ │ │ ├── ytdlpHelpers.ts -│ │ │ │ ├── ytdlpMetadata.ts -│ │ │ │ ├── ytdlpSearch.ts -│ │ │ │ ├── ytdlpSubtitle.ts -│ │ │ │ └── ytdlpVideo.ts -│ │ │ ├── storageService/ # Modular storage service -│ │ │ │ ├── index.ts # Main export file -│ │ │ │ ├── types.ts # Type definitions -│ │ │ │ ├── initialization.ts # Database initialization -│ │ │ │ ├── downloadStatus.ts # Active/queued downloads -│ │ │ │ ├── downloadHistory.ts # Download history -│ │ │ │ ├── videoDownloadTracking.ts # Duplicate prevention -│ │ │ │ ├── settings.ts # Application settings -│ │ │ │ ├── videos.ts # Video CRUD operations -│ │ │ │ ├── collections.ts # Collection operations -│ │ │ │ └── fileHelpers.ts # File system utilities -│ │ │ ├── CloudStorageService.ts -│ │ │ ├── commentService.ts -│ │ │ ├── downloadManager.ts # Download queue management -│ │ │ ├── downloadService.ts -│ │ │ ├── loginAttemptService.ts -│ │ │ ├── metadataService.ts -│ │ │ ├── migrationService.ts -│ │ │ ├── storageService.ts # Legacy compatibility export -│ │ │ ├── subscriptionService.ts -│ │ │ ├── subtitleService.ts -│ │ │ └── thumbnailService.ts -│ │ ├── utils/ # Utility functions -│ │ │ ├── bccToVtt.ts # Subtitle conversion -│ │ │ ├── downloadUtils.ts -│ │ │ ├── helpers.ts -│ │ │ ├── logger.ts -│ │ │ ├── progressTracker.ts -│ │ │ ├── response.ts -│ │ │ └── ytDlpUtils.ts -│ │ ├── server.ts # Main server file -│ │ └── version.ts # Version information -│ ├── bgutil-ytdlp-pot-provider/ # PO Token provider plugin -│ │ ├── plugin/ # Python plugin -│ │ │ └── yt_dlp_plugins/ -│ │ └── server/ # TypeScript server -│ │ └── src/ -│ ├── data/ # Data directory -│ │ ├── mytube.db # SQLite database -│ │ ├── cookies.txt # yt-dlp cookies (optional) -│ │ └── login-attempts.json # Login attempt tracking -│ ├── drizzle/ # Database migrations -│ │ └── meta/ # Migration metadata -│ ├── uploads/ # Uploaded files directory -│ │ ├── videos/ # Downloaded videos -│ │ ├── images/ # Downloaded thumbnails -│ │ └── subtitles/ # Downloaded subtitles -│ ├── dist/ # Compiled JavaScript -│ ├── coverage/ # Test coverage reports -│ ├── Dockerfile # Backend Docker image -│ ├── drizzle.config.ts # Drizzle ORM configuration -│ ├── nodemon.json # Nodemon configuration -│ ├── package.json # Backend dependencies -│ ├── tsconfig.json # TypeScript configuration -│ └── vitest.config.ts # Vitest test configuration -├── frontend/ # React.js frontend (Vite + TypeScript) -│ ├── src/ # Source code -│ │ ├── __tests__/ # Test files -│ │ ├── assets/ # Static assets -│ │ │ └── logo.svg -│ │ ├── components/ # React components -│ │ │ ├── Header/ # Header component group -│ │ │ │ ├── ActionButtons.tsx -│ │ │ │ ├── DownloadsMenu.tsx -│ │ │ │ ├── index.tsx -│ │ │ │ ├── Logo.tsx -│ │ │ │ ├── ManageMenu.tsx -│ │ │ │ ├── MobileMenu.tsx -│ │ │ │ ├── SearchInput.tsx -│ │ │ │ └── types.ts -│ │ │ ├── ManagePage/ # Management page components -│ │ │ │ ├── CollectionsTable.tsx -│ │ │ │ └── VideosTable.tsx -│ │ │ ├── Settings/ # Settings page components -│ │ │ │ ├── AdvancedSettings.tsx -│ │ │ │ ├── CloudDriveSettings.tsx -│ │ │ │ ├── CookieSettings.tsx -│ │ │ │ ├── DatabaseSettings.tsx -│ │ │ │ ├── DownloadSettings.tsx -│ │ │ │ ├── GeneralSettings.tsx -│ │ │ │ ├── SecuritySettings.tsx -│ │ │ │ ├── TagsSettings.tsx -│ │ │ │ ├── VideoDefaultSettings.tsx -│ │ │ │ └── YtDlpSettings.tsx -│ │ │ ├── VideoPlayer/ # Video player components -│ │ │ │ ├── CommentsSection.tsx -│ │ │ │ ├── UpNextSidebar.tsx -│ │ │ │ ├── VideoControls.tsx -│ │ │ │ ├── VideoInfo.tsx -│ │ │ │ └── VideoInfo/ # Video info subcomponents -│ │ │ │ ├── EditableTitle.tsx -│ │ │ │ ├── VideoActionButtons.tsx -│ │ │ │ ├── VideoAuthorInfo.tsx -│ │ │ │ ├── VideoDescription.tsx -│ │ │ │ ├── VideoMetadata.tsx -│ │ │ │ ├── VideoRating.tsx -│ │ │ │ └── VideoTags.tsx -│ │ │ ├── AlertModal.tsx -│ │ │ ├── AnimatedRoutes.tsx -│ │ │ ├── AuthorsList.tsx -│ │ │ ├── BatchDownloadModal.tsx -│ │ │ ├── BilibiliPartsModal.tsx -│ │ │ ├── CollectionCard.tsx -│ │ │ ├── CollectionModal.tsx -│ │ │ ├── Collections.tsx -│ │ │ ├── ConfirmationModal.tsx -│ │ │ ├── DeleteCollectionModal.tsx -│ │ │ ├── Disclaimer.tsx -│ │ │ ├── Footer.tsx -│ │ │ ├── PageTransition.tsx -│ │ │ ├── SubscribeModal.tsx -│ │ │ ├── TagsList.tsx -│ │ │ ├── UploadModal.tsx -│ │ │ └── VideoCard.tsx -│ │ ├── contexts/ # React contexts for state management -│ │ │ ├── AuthContext.tsx -│ │ │ ├── CollectionContext.tsx -│ │ │ ├── DownloadContext.tsx -│ │ │ ├── LanguageContext.tsx -│ │ │ ├── SnackbarContext.tsx -│ │ │ ├── ThemeContext.tsx -│ │ │ └── VideoContext.tsx -│ │ ├── hooks/ # Custom React hooks -│ │ │ ├── useDebounce.ts -│ │ │ ├── useShareVideo.ts -│ │ │ └── useVideoResolution.ts -│ │ ├── pages/ # Page components -│ │ │ ├── AuthorVideos.tsx -│ │ │ ├── CollectionPage.tsx -│ │ │ ├── DownloadPage/ # Download page components -│ │ │ │ ├── ActiveDownloadsTab.tsx -│ │ │ │ ├── CustomTabPanel.tsx -│ │ │ │ ├── HistoryItem.tsx -│ │ │ │ ├── HistoryTab.tsx -│ │ │ │ ├── index.tsx -│ │ │ │ └── QueueTab.tsx -│ │ │ ├── Home.tsx -│ │ │ ├── InstructionPage.tsx -│ │ │ ├── LoginPage.tsx -│ │ │ ├── ManagePage.tsx -│ │ │ ├── SearchPage.tsx -│ │ │ ├── SearchResults.tsx -│ │ │ ├── SettingsPage.tsx -│ │ │ ├── SubscriptionsPage.tsx -│ │ │ └── VideoPlayer.tsx -│ │ ├── utils/ # Utilities and locales -│ │ │ ├── locales/ # Internationalization files -│ │ │ │ ├── ar.ts # Arabic -│ │ │ │ ├── de.ts # German -│ │ │ │ ├── en.ts # English -│ │ │ │ ├── es.ts # Spanish -│ │ │ │ ├── fr.ts # French -│ │ │ │ ├── ja.ts # Japanese -│ │ │ │ ├── ko.ts # Korean -│ │ │ │ ├── pt.ts # Portuguese -│ │ │ │ ├── ru.ts # Russian -│ │ │ │ └── zh.ts # Chinese -│ │ │ ├── consoleManager.ts -│ │ │ ├── constants.ts -│ │ │ ├── formatUtils.ts -│ │ │ ├── recommendations.ts -│ │ │ └── translations.ts -│ │ ├── App.tsx # Main application component -│ │ ├── App.css -│ │ ├── index.css -│ │ ├── main.tsx # Application entry point -│ │ ├── setupTests.ts -│ │ ├── theme.ts # Material-UI theme configuration -│ │ ├── types.ts # TypeScript type definitions -│ │ ├── version.ts # Version information -│ │ └── vite-env.d.ts -│ ├── dist/ # Production build output -│ ├── public/ # Public static files -│ ├── Dockerfile # Frontend Docker image -│ ├── entrypoint.sh # Docker entrypoint script -│ ├── eslint.config.js # ESLint configuration -│ ├── index.html # HTML template -│ ├── nginx.conf # Nginx configuration -│ ├── package.json # Frontend dependencies -│ ├── tsconfig.json # TypeScript configuration +│ │ ├── db/ # Drizzle ORM + SQLite +│ │ ├── errors/ # Custom error classes +│ │ ├── middleware/ # Express middleware +│ │ │ ├── authMiddleware.ts +│ │ │ ├── roleBasedAuthMiddleware.ts +│ │ │ ├── roleBasedSettingsMiddleware.ts +│ │ │ └── errorHandler.ts +│ │ ├── routes/ # Route definitions +│ │ │ ├── api.ts # Main API routes +│ │ │ └── settingsRoutes.ts # Settings-specific routes +│ │ ├── scripts/ # Utility scripts (VTT cleanup, rescans) +│ │ ├── services/ # Business logic +│ │ │ ├── cloudStorage/ # Cloud storage helpers and cache +│ │ │ ├── continuousDownload/ # Subscription task engine +│ │ │ ├── downloaders/ # Platform downloaders (yt-dlp, Bilibili, MissAV) +│ │ │ ├── storageService/ # Modular storage service +│ │ │ └── *.ts # Other services (auth, metadata, etc.) +│ │ ├── utils/ # Shared utilities +│ │ ├── server.ts # Server bootstrap +│ │ └── version.ts # Version info +│ ├── bgutil-ytdlp-pot-provider/ # PO Token provider plugin +│ ├── data/ # Runtime data (db, hooks, backups) +│ ├── drizzle/ # Database migrations +│ ├── uploads/ # Media storage (videos, images, subtitles, cache) +│ ├── scripts/ # Maintenance scripts (reset-password, migrate, verify) +│ ├── Dockerfile +│ ├── drizzle.config.ts +│ ├── nodemon.json +│ ├── package.json +│ ├── tsconfig.json +│ └── vitest.config.ts +├── frontend/ # React frontend (Vite + TypeScript) +│ ├── src/ # Source code +│ │ ├── __tests__/ # Test files +│ │ ├── assets/ # Static assets +│ │ ├── components/ # UI components by feature +│ │ ├── contexts/ # React Context state +│ │ ├── hooks/ # Custom hooks (player, settings, data) +│ │ ├── pages/ # Route pages +│ │ ├── utils/ # API client, helpers, i18n +│ │ ├── App.tsx +│ │ ├── main.tsx +│ │ ├── theme.ts +│ │ └── version.ts +│ ├── public/ # Public assets +│ ├── Dockerfile +│ ├── entrypoint.sh +│ ├── nginx.conf +│ ├── package.json +│ ├── tsconfig.json │ ├── tsconfig.node.json -│ └── vite.config.js # Vite configuration -├── documents/ # Documentation -│ ├── en/ # English documentation -│ │ ├── api-endpoints.md -│ │ ├── directory-structure.md -│ │ ├── docker-guide.md -│ │ └── getting-started.md -│ └── zh/ # Chinese documentation -│ ├── api-endpoints.md -│ ├── directory-structure.md -│ ├── docker-guide.md -│ └── getting-started.md -├── data/ # Root data directory (optional) -│ └── mytube.db -├── build-and-push.sh # Docker build and push script -├── docker-compose.yml # Docker Compose configuration -├── CHANGELOG.md # Changelog -├── CODE_OF_CONDUCT.md # Code of conduct -├── CONTRIBUTING.md # Contributing guidelines -├── LICENSE # MIT License -├── README.md # English README -├── README-zh.md # Chinese README -├── RELEASING.md # Release process guide -├── SECURITY.md # Security policy -└── package.json # Root package.json for running both apps +│ └── vite.config.js +├── documents/ # Documentation (EN/ZH) +├── docker-compose.yml # Compose for standard deployments +├── docker-compose.host-network.yml # Host-network compose for OpenWrt/iStoreOS +├── README.md +├── README-zh.md +└── package.json # Root scripts ``` ## Architecture Overview @@ -273,28 +88,25 @@ mytube/ The backend follows a **layered architecture** pattern: -1. **Routes Layer** (`routes/`): Defines API endpoints and maps them to controllers -2. **Controllers Layer** (`controllers/`): Handles HTTP requests/responses and delegates to services -3. **Services Layer** (`services/`): Contains business logic - - **Downloaders**: Abstract base class pattern for platform-specific downloaders - - **Storage Service**: Modular service split into focused modules - - **Supporting Services**: Download management, subscriptions, metadata, etc. -4. **Database Layer** (`db/`): Drizzle ORM with SQLite for data persistence -5. **Utils Layer** (`utils/`): Shared utility functions +1. **Routes** (`routes/`): Define API endpoints and map them to controllers +2. **Controllers** (`controllers/`): HTTP request/response handling +3. **Services** (`services/`): Business logic (downloaders, storage, cloud, subscriptions) +4. **Database** (`db/`): Drizzle ORM + SQLite +5. **Utilities** (`utils/`): Shared helpers and infrastructure ### Frontend Architecture The frontend follows a **component-based architecture**: 1. **Pages** (`pages/`): Top-level route components -2. **Components** (`components/`): Reusable UI components organized by feature -3. **Contexts** (`contexts/`): React Context API for global state management -4. **Hooks** (`hooks/`): Custom React hooks for reusable logic -5. **Utils** (`utils/`): Helper functions and internationalization +2. **Components** (`components/`): Feature-oriented UI building blocks +3. **Contexts** (`contexts/`): React Context global state +4. **Hooks** (`hooks/`): Reusable logic and data access +5. **Utils** (`utils/`): API client, formatting, and i18n helpers ### Database Schema -The application uses **SQLite** with **Drizzle ORM** for data persistence. Key tables include: +Key tables include: - `videos`: Video metadata and file paths - `collections`: Video collections/playlists diff --git a/documents/en/docker-guide.md b/documents/en/docker-guide.md index 94040f0..3a12f90 100644 --- a/documents/en/docker-guide.md +++ b/documents/en/docker-guide.md @@ -1,6 +1,6 @@ # Docker Deployment Guide for MyTube -This guide provides step-by-step instructions to deploy [MyTube](https://github.com/franklioxygen/MyTube "null") using Docker and Docker Compose. This setup is designed for standard environments (Linux, macOS, Windows) and modifies the original QNAP-specific configurations for general use. +This guide provides step-by-step instructions to deploy [MyTube](https://github.com/franklioxygen/MyTube "null") using Docker and Docker Compose. The repository includes QNAP-oriented compose files; update the volume paths to match your environment or use the sample below. > [!NOTE] > **Multi-Architecture Support:** The official images support both **amd64** (x86_64) and **arm64** (Apple Silicon, Raspberry Pi, etc.) architectures. Docker will automatically pull the correct image for your system. @@ -22,7 +22,7 @@ cd mytube-deploy Create a file named `docker-compose.yml` inside your folder and paste the following content. -**Note:** This version uses standard relative paths (`./data`, `./uploads`) instead of the QNAP-specific paths found in the original repository. +**Note:** This version uses standard relative paths (`./data`, `./uploads`). If you copy the repo’s `docker-compose.yml`, update the volume paths to match your host. ```yaml version: '3.8' @@ -39,8 +39,6 @@ services: - mytube-network environment: - PORT=5551 - # Optional: Set a custom upload directory inside container if needed - # - VIDEO_DIR=/app/uploads/videos volumes: - ./uploads:/app/uploads - ./data:/app/data @@ -217,4 +215,10 @@ If you prefer to build the images yourself (e.g., to modify code), follow these 2. Uncomment `network_mode: host` for both `backend` and `frontend`. 3. Remove (or comment out) the `ports` and `networks` sections for both services. 4. Set `NGINX_BACKEND_URL=http://localhost:5551` in the `frontend` environment variables. - 5. Restart containers: `docker-compose up -d` \ No newline at end of file + 5. Restart containers: `docker-compose up -d` + +Alternatively, the repo includes `docker-compose.host-network.yml` for host-network deployments: + +``` +docker-compose -f docker-compose.host-network.yml up -d +``` diff --git a/documents/en/getting-started.md b/documents/en/getting-started.md index 5ba0518..9cba14d 100644 --- a/documents/en/getting-started.md +++ b/documents/en/getting-started.md @@ -52,23 +52,21 @@ Create a `.env` file in the `backend/` directory: ```env PORT=5551 -UPLOAD_DIR=uploads -VIDEO_DIR=uploads/videos -IMAGE_DIR=uploads/images -SUBTITLES_DIR=uploads/subtitles -DATA_DIR=data -MAX_FILE_SIZE=500000000 ``` +Data and uploads are stored under `backend/data` and `backend/uploads` by default (relative to the backend working directory). + #### Frontend Configuration Create a `.env` file in the `frontend/` directory: ```env -VITE_API_URL=http://localhost:5551/api -VITE_BACKEND_URL=http://localhost:5551 +VITE_API_URL=/api +VITE_BACKEND_URL= ``` +`backend/.env.example` is provided. Copy it to `backend/.env` and adjust as needed. The frontend ships with `frontend/.env`; use `frontend/.env.local` to override defaults. + ### 4. Database Setup The application uses **SQLite** with **Drizzle ORM**. The database will be automatically created and migrated on first startup: @@ -92,7 +90,7 @@ This will start: - **Frontend**: http://localhost:5556 (Vite dev server with hot reload) - **Backend API**: http://localhost:5551 (Express server with nodemon) -### Production Mode +### Production Mode (Local) Build and start in production mode: @@ -100,10 +98,19 @@ Build and start in production mode: # Build frontend npm run build -# Start both services +# Start backend +cd backend npm run start + +# In another terminal, preview the frontend build +cd frontend +npm run preview ``` +For Docker-based production, follow the [Docker Deployment Guide](docker-guide.md). + +`npm run start` at the repo root is a convenience command that runs the backend start script and the frontend dev server together. + ### Individual Services You can also run services individually: @@ -126,9 +133,12 @@ From the root directory: ```bash npm run dev # Start both frontend and backend in development mode -npm run start # Start both frontend and backend in production mode +npm run start # Start backend + frontend dev server (convenience) npm run build # Build the frontend for production npm run install:all # Install dependencies for root, frontend, and backend +npm run test # Run frontend + backend tests +npm run test:frontend # Run frontend tests +npm run test:backend # Run backend tests ``` Backend-specific scripts (from `backend/` directory): @@ -140,6 +150,7 @@ npm run build # Compile TypeScript to JavaScript npm run test # Run tests with Vitest npm run test:coverage # Run tests with coverage report npm run generate # Generate database migrations with Drizzle Kit +npm run reset-password # Reset admin password via script ``` Frontend-specific scripts (from `frontend/` directory): @@ -150,16 +161,18 @@ npm run build # Build for production npm run preview # Preview production build npm run lint # Run ESLint npm run test # Run tests with Vitest +npm run test:coverage # Run tests with coverage report ``` ## First-Time Setup 1. **Access the Application**: Open http://localhost:5556 in your browser -2. **Set Up Password Protection** (Optional): +2. **Set Up Login Protection** (Optional): - Go to Settings → Security - - Enable password protection and set a password + - Enable login and set an admin password + - Optionally register a passkey (WebAuthn) 3. **Configure Download Settings**: @@ -183,12 +196,11 @@ npm run test # Run tests with Vitest - Test the connection to verify settings - Note: When enabled, videos will be automatically uploaded to cloud storage after download, and local files will be deleted -6. **Configure Visitor Mode** (Optional): +6. **Configure Visitor User** (Optional): - - Go to Settings → General Settings - - Enable "Visitor Mode (Read-only)" to allow viewing videos without modification capabilities - - When enabled, all write operations (downloads, deletions, edits) are blocked - - To disable visitor mode, you'll need to enter the website password + - Go to Settings → Security + - Enable "Visitor User" to allow read-only access + - Set a visitor password for the read-only role 7. **Start Downloading**: - Enter a video URL in the download input diff --git a/documents/en/hooks-guide.md b/documents/en/hooks-guide.md index 0be1c89..1039835 100644 --- a/documents/en/hooks-guide.md +++ b/documents/en/hooks-guide.md @@ -1,44 +1,43 @@ # Task Hooks Guide -MyTube allows you to execute custom shell scripts at various stages of a download task's lifecycle. This feature is powerful for integrating MyTube with other systems, performing post-processing on downloaded files, or sending notifications. +MyTube lets you execute custom shell scripts at different stages of a download task. This is useful for post-processing, notifications, or external integrations. -## available Hooks - -You can configure commands for the following events: +## Available Hooks | Hook Name | Trigger Point | Description | | :--- | :--- | :--- | -| **Before Task Start** (`task_before_start`) | Before download begins | Executed immediately before the download process starts. Useful for setup or validation. | -| **Task Success** (`task_success`) | After successful download | Executed after the file is successfully downloaded / merged, but **before** it is uploaded to cloud storage (if enabled) or deleted. This is the ideal place for file processing. | -| **Task Failed** (`task_fail`) | On task failure | Executed if the download fails for any reason. | -| **Task Cancelled** (`task_cancel`) | On task cancellation | Executed when a user manually cancels a running task. | +| **Before Task Start** (`task_before_start`) | Before download begins | Runs right before the download starts. | +| **Task Success** (`task_success`) | After successful download | Runs after download/merge completes but **before** cloud upload (if enabled) or deletion. | +| **Task Failed** (`task_fail`) | On task failure | Runs when a download fails. | +| **Task Cancelled** (`task_cancel`) | On task cancellation | Runs when a user cancels a running task. | + +Hook scripts are stored under `backend/data/hooks` by default. ## Environment Variables -When a hook command is executed, the following environment variables are injected into the shell environment, providing context about the task: - | Variable | Description | Example | | :--- | :--- | :--- | -| `MYTUBE_TASK_ID` | The unique identifier of the task | `335e98f0-15cb-46a4-846d-9d4351368923` | -| `MYTUBE_TASK_TITLE` | The title of the video/task | `Awesome Video Title` | -| `MYTUBE_SOURCE_URL` | The original URL of the video | `https://www.youtube.com/watch?v=...` | -| `MYTUBE_TASK_STATUS` | The current status of the task | `success`, `fail`, `cancelled` | -| `MYTUBE_VIDEO_PATH` | Absolute path to the downloaded video file | `/app/downloads/video.mp4` | -| `MYTUBE_THUMBNAIL_PATH` | Absolute path to the thumbnail file | `/app/downloads/video.jpg` | +| `MYTUBE_TASK_ID` | Unique task ID | `335e98f0-15cb-46a4-846d-9d4351368923` | +| `MYTUBE_TASK_TITLE` | Video/task title | `Awesome Video Title` | +| `MYTUBE_SOURCE_URL` | Original video URL | `https://www.youtube.com/watch?v=...` | +| `MYTUBE_TASK_STATUS` | Current status | `start`, `success`, `fail`, `cancel` | +| `MYTUBE_VIDEO_PATH` | Absolute path to video file | `/app/uploads/videos/video.mp4` | +| `MYTUBE_THUMBNAIL_PATH` | Absolute path to thumbnail | `/app/uploads/images/video.jpg` | | `MYTUBE_ERROR` | Error message (only for `task_fail`) | `Network timeout` | ## Configuration -You can configure hooks in the web interface: 1. Go to **Settings**. -2. Scroll down to **Advanced Settings**. -3. Find the **Task Hooks** section. -4. Upload your `.sh` scripts for the desired events. -5. You can Delete or Re-upload scripts as needed. +2. Open **Advanced Settings**. +3. Find **Task Hooks**. +4. Upload `.sh` scripts for the desired events. +5. Delete or re-upload as needed. + +Hooks are executed with `bash` and are made executable on upload. ## Viewing Logs -Any output from your script (stdout/stderr) will be captured and logged to the MyTube server console. +Any output from your script (stdout/stderr) is captured and logged by the backend. - Standard output (`echo "..."`) is logged as `INFO`. - Standard error (`>&2 echo "..."`) is logged as `WARN`. @@ -69,7 +68,7 @@ curl -d "MyTube Download Failed: $MYTUBE_TASK_TITLE - $MYTUBE_ERROR" https://ntf ``` ### 3. File Post-Processing -Run a python script to process the file. +Run a Python script to process the file. **Hook:** `task_success` ```bash #!/bin/bash @@ -79,7 +78,7 @@ python3 /path/to/process_video.py "$MYTUBE_VIDEO_PATH" ## Security Warning > [!WARNING] -> Hook commands are executed with the same permissions as the MyTube backend server. +> Hook commands run with the same permissions as the MyTube backend. > - Be careful when using commands that modify or delete files. -> - Do not copy-paste scripts from untrusted sources. +> - Do not copy/paste scripts from untrusted sources. > - Ensure your scripts handle errors gracefully. diff --git a/documents/zh/api-endpoints.md b/documents/zh/api-endpoints.md index a290a77..c9fbcdb 100644 --- a/documents/zh/api-endpoints.md +++ b/documents/zh/api-endpoints.md @@ -1,11 +1,14 @@ # API 端点 +除特殊说明外,所有 API 路由均挂载在 `/api` 下。 + ## 视频下载与搜索 + - `GET /api/search` - 在线搜索视频 (YouTube) - 查询参数: `query` (必需), `limit` (可选, 默认: 8), `offset` (可选, 默认: 1) - `POST /api/download` - 从支持的平台下载视频 - - 请求体: `{ url: string, ...options }` - - 支持: YouTube, Bilibili, MissAV 以及所有 yt-dlp 支持的网站 + - 请求体: `{ youtubeUrl: string, ...options }` + - 支持: YouTube、Bilibili、MissAV 以及所有 yt-dlp 支持的网站 - `GET /api/check-video-download` - 检查视频是否已下载 - 查询参数: `url` (必需) - 返回: `{ found: boolean, status: 'exists' | 'deleted', videoId?: string, ... }` @@ -15,10 +18,11 @@ - 查询参数: `url` (必需) - `GET /api/check-playlist` - 检查 URL 是否为受支持的播放列表 - 查询参数: `url` (必需) -- `GET /api/download-status` - 获取活动下载的状态 - - 返回: `{ active: [], queued: [] }` +- `GET /api/download-status` - 获取下载状态 + - 返回: `{ activeDownloads: DownloadInfo[], queuedDownloads: DownloadInfo[] }` ## 视频管理 + - `POST /api/upload` - 上传本地视频文件 - 多部分表单数据: `video` (文件) - 自动生成缩略图 @@ -38,9 +42,9 @@ - `GET /api/videos/author-channel-url` - 获取视频的作者频道 URL - 查询参数: `sourceUrl` (必需) - 返回: `{ success: boolean, channelUrl: string | null }` - - 首先检查数据库,如果未找到则从 YouTube/Bilibili API 获取 ## 下载管理 + - `POST /api/downloads/cancel/:id` - 取消活动下载 - `DELETE /api/downloads/queue/:id` - 从队列中移除下载 - `DELETE /api/downloads/queue` - 清空整个下载队列 @@ -50,6 +54,7 @@ - `DELETE /api/downloads/history` - 清空整个下载历史 ## 收藏夹 + - `GET /api/collections` - 获取所有收藏夹 - `POST /api/collections` - 创建新收藏夹 - 请求体: `{ name: string, videoIds?: string[] }` @@ -58,6 +63,7 @@ - `DELETE /api/collections/:id` - 删除收藏夹 ## 订阅 + - `GET /api/subscriptions` - 获取所有订阅 - `POST /api/subscriptions` - 创建新订阅 - 请求体: `{ authorUrl: string, interval: number, platform?: string }` @@ -70,30 +76,60 @@ - `GET /api/subscriptions/tasks` - 获取所有持续下载任务 - 查询参数: `page` (可选), `limit` (可选) - `POST /api/subscriptions/tasks/playlist` - 创建新的播放列表下载任务 - - Body: `{ url: string, ...options }` + - 请求体: `{ url: string, ...options }` - `DELETE /api/subscriptions/tasks/:id` - 取消持续下载任务 - `DELETE /api/subscriptions/tasks/:id/delete` - 删除任务记录 - `DELETE /api/subscriptions/tasks/clear-finished` - 清除所有已完成的任务 -## 设置与系统 +## 设置与密码 + - `GET /api/settings` - 获取应用设置 - `POST /api/settings` - 更新应用设置 - 请求体: `{ [key: string]: any }` - 设置对象 - - 支持: `visitorMode`, `cloudDriveEnabled`, `openListApiUrl`, `openListToken`, `openListPublicUrl`, `cloudDrivePath` 及其他设置 - `GET /api/settings/cloudflared/status` - 获取 Cloudflare Tunnel 状态 -- `GET /api/settings/password-enabled` - 检查是否启用了密码保护 -- `POST /api/settings/verify-password` - 验证登录密码 - - 请求体: `{ password: string }` -- `POST /api/settings/reset-password` - 重置登录密码 - - 请求体: `{ oldPassword: string, newPassword: string }` - `POST /api/settings/migrate` - 从 JSON 迁移数据到 SQLite - `POST /api/settings/delete-legacy` - 删除旧的 JSON 数据文件 - `POST /api/settings/format-filenames` - 根据设置格式化视频文件名 +- `GET /api/settings/password-enabled` - 检查是否启用了密码保护 +- `GET /api/settings/reset-password-cooldown` - 获取密码重置冷却时间 +- `POST /api/settings/verify-admin-password` - 验证管理员密码 + - 请求体: `{ password: string }` +- `POST /api/settings/verify-visitor-password` - 验证访客密码 + - 请求体: `{ password: string }` +- `POST /api/settings/verify-password` - 验证登录密码 (已废弃) + - 请求体: `{ password: string }` +- `POST /api/settings/reset-password` - 重置登录密码 + - 请求体: `{ oldPassword: string, newPassword: string }` +- `POST /api/settings/logout` - 退出当前会话 + +## 通行密钥管理 + +- `GET /api/settings/passkeys` - 获取所有注册的通行密钥 +- `GET /api/settings/passkeys/exists` - 检查是否已注册任何通行密钥 +- `POST /api/settings/passkeys/register` - 开始通行密钥注册 +- `POST /api/settings/passkeys/register/verify` - 验证通行密钥注册 +- `POST /api/settings/passkeys/authenticate` - 开始通行密钥认证 +- `POST /api/settings/passkeys/authenticate/verify` - 验证通行密钥认证 +- `DELETE /api/settings/passkeys` - 删除所有通行密钥 + +## Cookies + - `POST /api/settings/upload-cookies` - 上传 cookies.txt 以供 yt-dlp 使用 - 多部分表单数据: `file` (cookies.txt) - `POST /api/settings/delete-cookies` - 删除 cookies.txt - `GET /api/settings/check-cookies` - 检查 cookies.txt 是否存在 -- `GET /api/settings/export-database` - 导出数据库作为备份文件 + +## 任务钩子 + +- `GET /api/settings/hooks/status` - 获取所有钩子的状态 +- `POST /api/settings/hooks/:name` - 上传钩子脚本 + - 多部分表单数据: `file` (脚本文件) + - 参数: `name` (钩子名称, 例如 `task_success`) +- `DELETE /api/settings/hooks/:name` - 删除钩子脚本 + +## 数据库备份 + +- `GET /api/settings/export-database` - 导出数据库备份文件 - `POST /api/settings/import-database` - 从备份文件导入数据库 - 多部分表单数据: `file` (数据库备份文件) - `GET /api/settings/last-backup-info` - 获取最后一个数据库备份的信息 @@ -101,10 +137,21 @@ - `POST /api/settings/cleanup-backup-databases` - 清理旧的备份数据库文件 ## 文件管理 + - `POST /api/scan-files` - 扫描上传目录中的现有视频文件 - `POST /api/cleanup-temp-files` - 清理临时下载文件 ## 云存储 -- `GET /cloud/videos/:filename` - 代理端点,用于从云存储(OpenList/Alist)流式传输视频 -- `GET /cloud/images/:filename` - 代理端点,用于从云存储(OpenList/Alist)提供图像 - - 注意:这些端点需要在设置中配置云存储 + +- `GET /api/cloud/signed-url` - 获取云存储签名 URL + - 查询参数: `filename` (必需), `type` (可选: `video` 或 `thumbnail`) +- `POST /api/cloud/sync` - 同步本地视频到云存储 (以 JSON 行流式返回进度) +- `DELETE /api/cloud/thumbnail-cache` - 清空缩略图缓存 +- `GET /api/cloud/thumbnail-cache/:filename` - 访问缓存的云端缩略图 +- `GET /cloud/videos/:filename` - 重定向到云端视频签名 URL +- `GET /cloud/images/:filename` - 重定向到云端缩略图签名 URL(或本地缓存) + +## 系统 + +- `GET /api/system/version` - 获取当前版本与最新版本信息 + - 返回: `{ currentVersion, latestVersion, releaseUrl, hasUpdate }` diff --git a/documents/zh/directory-structure.md b/documents/zh/directory-structure.md index 7b04328..3a3a201 100644 --- a/documents/zh/directory-structure.md +++ b/documents/zh/directory-structure.md @@ -2,305 +2,117 @@ ``` mytube/ -├── backend/ # Express.js 后端 (TypeScript) -│ ├── src/ # 源代码 -│ │ ├── __tests__/ # 测试文件 -│ │ │ ├── controllers/ # 控制器测试 -│ │ │ ├── middleware/ # 中间件测试 -│ │ │ ├── services/ # 服务测试 -│ │ │ └── utils/ # 工具测试 -│ │ ├── config/ # 配置文件 -│ │ │ └── paths.ts # 路径配置 -│ │ ├── controllers/ # 路由控制器 -│ │ │ ├── cleanupController.ts # 清理操作 +├── backend/ # Express.js 后端 (TypeScript) +│ ├── src/ # 源代码 +│ │ ├── __tests__/ # 测试文件 +│ │ ├── config/ # 配置(路径等) +│ │ ├── controllers/ # 路由控制器 +│ │ │ ├── cleanupController.ts +│ │ │ ├── cloudStorageController.ts │ │ │ ├── collectionController.ts +│ │ │ ├── cookieController.ts │ │ │ ├── downloadController.ts +│ │ │ ├── hookController.ts +│ │ │ ├── passkeyController.ts +│ │ │ ├── passwordController.ts │ │ │ ├── scanController.ts │ │ │ ├── settingsController.ts │ │ │ ├── subscriptionController.ts +│ │ │ ├── systemController.ts │ │ │ ├── videoController.ts │ │ │ ├── videoDownloadController.ts │ │ │ └── videoMetadataController.ts -│ │ ├── db/ # 数据库层 -│ │ │ ├── index.ts # 数据库连接 (Drizzle ORM) -│ │ │ ├── migrate.ts # 迁移运行器 -│ │ │ └── schema.ts # 数据库模式定义 -│ │ ├── errors/ # 自定义错误类 -│ │ │ └── DownloadErrors.ts -│ │ ├── middleware/ # Express 中间件 -│ │ │ ├── errorHandler.ts # 错误处理中间件 -│ │ │ ├── visitorModeMiddleware.ts # 访客模式(只读)中间件 -│ │ │ └── visitorModeSettingsMiddleware.ts # 访客模式设置中间件 -│ │ ├── routes/ # API 路由定义 -│ │ │ ├── api.ts # 主 API 路由 -│ │ │ └── settingsRoutes.ts # 设置相关路由 -│ │ ├── scripts/ # 实用脚本 -│ │ │ ├── cleanVttFiles.ts -│ │ │ └── rescanSubtitles.ts -│ │ ├── services/ # 业务逻辑服务 -│ │ │ ├── downloaders/ # 下载器实现 -│ │ │ │ ├── BaseDownloader.ts # 抽象基类 -│ │ │ │ ├── BilibiliDownloader.ts -│ │ │ │ ├── MissAVDownloader.ts -│ │ │ │ ├── YtDlpDownloader.ts -│ │ │ │ ├── bilibili/ # Bilibili 特定模块 -│ │ │ │ │ ├── bilibiliApi.ts -│ │ │ │ │ ├── bilibiliCollection.ts -│ │ │ │ │ ├── bilibiliCookie.ts -│ │ │ │ │ ├── bilibiliSubtitle.ts -│ │ │ │ │ ├── bilibiliVideo.ts -│ │ │ │ │ └── types.ts -│ │ │ │ └── ytdlp/ # yt-dlp 特定模块 -│ │ │ │ ├── types.ts -│ │ │ │ ├── ytdlpChannel.ts -│ │ │ │ ├── ytdlpConfig.ts -│ │ │ │ ├── ytdlpHelpers.ts -│ │ │ │ ├── ytdlpMetadata.ts -│ │ │ │ ├── ytdlpSearch.ts -│ │ │ │ ├── ytdlpSubtitle.ts -│ │ │ │ └── ytdlpVideo.ts -│ │ │ ├── storageService/ # 模块化存储服务 -│ │ │ │ ├── index.ts # 主导出文件 -│ │ │ │ ├── types.ts # 类型定义 -│ │ │ │ ├── initialization.ts # 数据库初始化 -│ │ │ │ ├── downloadStatus.ts # 活动/队列下载 -│ │ │ │ ├── downloadHistory.ts # 下载历史 -│ │ │ │ ├── videoDownloadTracking.ts # 重复下载预防 -│ │ │ │ ├── settings.ts # 应用设置 -│ │ │ │ ├── videos.ts # 视频 CRUD 操作 -│ │ │ │ ├── collections.ts # 收藏夹操作 -│ │ │ │ └── fileHelpers.ts # 文件系统工具 -│ │ │ ├── CloudStorageService.ts -│ │ │ ├── commentService.ts -│ │ │ ├── downloadManager.ts # 下载队列管理 -│ │ │ ├── downloadService.ts -│ │ │ ├── loginAttemptService.ts -│ │ │ ├── metadataService.ts -│ │ │ ├── migrationService.ts -│ │ │ ├── storageService.ts # 向后兼容导出 -│ │ │ ├── subscriptionService.ts -│ │ │ ├── subtitleService.ts -│ │ │ └── thumbnailService.ts -│ │ ├── utils/ # 工具函数 -│ │ │ ├── bccToVtt.ts # 字幕转换 -│ │ │ ├── downloadUtils.ts -│ │ │ ├── helpers.ts -│ │ │ ├── logger.ts -│ │ │ ├── progressTracker.ts -│ │ │ ├── response.ts -│ │ │ └── ytDlpUtils.ts -│ │ ├── server.ts # 主服务器文件 -│ │ └── version.ts # 版本信息 -│ ├── bgutil-ytdlp-pot-provider/ # PO Token 提供者插件 -│ │ ├── plugin/ # Python 插件 -│ │ │ └── yt_dlp_plugins/ -│ │ └── server/ # TypeScript 服务器 -│ │ └── src/ -│ ├── data/ # 数据目录 -│ │ ├── mytube.db # SQLite 数据库 -│ │ ├── cookies.txt # yt-dlp cookies (可选) -│ │ └── login-attempts.json # 登录尝试跟踪 -│ ├── drizzle/ # 数据库迁移 -│ │ └── meta/ # 迁移元数据 -│ ├── uploads/ # 上传文件目录 -│ │ ├── videos/ # 下载的视频 -│ │ ├── images/ # 下载的缩略图 -│ │ └── subtitles/ # 下载的字幕 -│ ├── dist/ # 编译后的 JavaScript -│ ├── coverage/ # 测试覆盖率报告 -│ ├── Dockerfile # 后端 Docker 镜像 -│ ├── drizzle.config.ts # Drizzle ORM 配置 -│ ├── nodemon.json # Nodemon 配置 -│ ├── package.json # 后端依赖 -│ ├── tsconfig.json # TypeScript 配置 -│ └── vitest.config.ts # Vitest 测试配置 -├── frontend/ # React.js 前端 (Vite + TypeScript) -│ ├── src/ # 源代码 -│ │ ├── __tests__/ # 测试文件 -│ │ ├── assets/ # 静态资源 -│ │ │ └── logo.svg -│ │ ├── components/ # React 组件 -│ │ │ ├── Header/ # 头部组件组 -│ │ │ │ ├── ActionButtons.tsx -│ │ │ │ ├── DownloadsMenu.tsx -│ │ │ │ ├── index.tsx -│ │ │ │ ├── Logo.tsx -│ │ │ │ ├── ManageMenu.tsx -│ │ │ │ ├── MobileMenu.tsx -│ │ │ │ ├── SearchInput.tsx -│ │ │ │ └── types.ts -│ │ │ ├── ManagePage/ # 管理页面组件 -│ │ │ │ ├── CollectionsTable.tsx -│ │ │ │ └── VideosTable.tsx -│ │ │ ├── Settings/ # 设置页面组件 -│ │ │ │ ├── AdvancedSettings.tsx -│ │ │ │ ├── CloudDriveSettings.tsx -│ │ │ │ ├── CookieSettings.tsx -│ │ │ │ ├── DatabaseSettings.tsx -│ │ │ │ ├── DownloadSettings.tsx -│ │ │ │ ├── GeneralSettings.tsx -│ │ │ │ ├── SecuritySettings.tsx -│ │ │ │ ├── TagsSettings.tsx -│ │ │ │ ├── VideoDefaultSettings.tsx -│ │ │ │ └── YtDlpSettings.tsx -│ │ │ ├── VideoPlayer/ # 视频播放器组件 -│ │ │ │ ├── CommentsSection.tsx -│ │ │ │ ├── UpNextSidebar.tsx -│ │ │ │ ├── VideoControls.tsx -│ │ │ │ ├── VideoInfo.tsx -│ │ │ │ └── VideoInfo/ # 视频信息子组件 -│ │ │ │ ├── EditableTitle.tsx -│ │ │ │ ├── VideoActionButtons.tsx -│ │ │ │ ├── VideoAuthorInfo.tsx -│ │ │ │ ├── VideoDescription.tsx -│ │ │ │ ├── VideoMetadata.tsx -│ │ │ │ ├── VideoRating.tsx -│ │ │ │ └── VideoTags.tsx -│ │ │ ├── AlertModal.tsx -│ │ │ ├── AnimatedRoutes.tsx -│ │ │ ├── AuthorsList.tsx -│ │ │ ├── BatchDownloadModal.tsx -│ │ │ ├── BilibiliPartsModal.tsx -│ │ │ ├── CollectionCard.tsx -│ │ │ ├── CollectionModal.tsx -│ │ │ ├── Collections.tsx -│ │ │ ├── ConfirmationModal.tsx -│ │ │ ├── DeleteCollectionModal.tsx -│ │ │ ├── Disclaimer.tsx -│ │ │ ├── Footer.tsx -│ │ │ ├── PageTransition.tsx -│ │ │ ├── SubscribeModal.tsx -│ │ │ ├── TagsList.tsx -│ │ │ ├── UploadModal.tsx -│ │ │ └── VideoCard.tsx -│ │ ├── contexts/ # React 上下文用于状态管理 -│ │ │ ├── AuthContext.tsx -│ │ │ ├── CollectionContext.tsx -│ │ │ ├── DownloadContext.tsx -│ │ │ ├── LanguageContext.tsx -│ │ │ ├── SnackbarContext.tsx -│ │ │ ├── ThemeContext.tsx -│ │ │ └── VideoContext.tsx -│ │ ├── hooks/ # 自定义 React hooks -│ │ │ ├── useDebounce.ts -│ │ │ ├── useShareVideo.ts -│ │ │ └── useVideoResolution.ts -│ │ ├── pages/ # 页面组件 -│ │ │ ├── AuthorVideos.tsx -│ │ │ ├── CollectionPage.tsx -│ │ │ ├── DownloadPage/ # 下载页面组件 -│ │ │ │ ├── ActiveDownloadsTab.tsx -│ │ │ │ ├── CustomTabPanel.tsx -│ │ │ │ ├── HistoryItem.tsx -│ │ │ │ ├── HistoryTab.tsx -│ │ │ │ ├── index.tsx -│ │ │ │ └── QueueTab.tsx -│ │ │ ├── Home.tsx -│ │ │ ├── InstructionPage.tsx -│ │ │ ├── LoginPage.tsx -│ │ │ ├── ManagePage.tsx -│ │ │ ├── SearchPage.tsx -│ │ │ ├── SearchResults.tsx -│ │ │ ├── SettingsPage.tsx -│ │ │ ├── SubscriptionsPage.tsx -│ │ │ └── VideoPlayer.tsx -│ │ ├── utils/ # 工具和多语言 -│ │ │ ├── locales/ # 国际化文件 -│ │ │ │ ├── ar.ts # 阿拉伯语 -│ │ │ │ ├── de.ts # 德语 -│ │ │ │ ├── en.ts # 英语 -│ │ │ │ ├── es.ts # 西班牙语 -│ │ │ │ ├── fr.ts # 法语 -│ │ │ │ ├── ja.ts # 日语 -│ │ │ │ ├── ko.ts # 韩语 -│ │ │ │ ├── pt.ts # 葡萄牙语 -│ │ │ │ ├── ru.ts # 俄语 -│ │ │ │ └── zh.ts # 中文 -│ │ │ ├── consoleManager.ts -│ │ │ ├── constants.ts -│ │ │ ├── formatUtils.ts -│ │ │ ├── recommendations.ts -│ │ │ └── translations.ts -│ │ ├── App.tsx # 主应用组件 -│ │ ├── App.css -│ │ ├── index.css -│ │ ├── main.tsx # 应用入口点 -│ │ ├── setupTests.ts -│ │ ├── theme.ts # Material-UI 主题配置 -│ │ ├── types.ts # TypeScript 类型定义 -│ │ ├── version.ts # 版本信息 -│ │ └── vite-env.d.ts -│ ├── dist/ # 生产构建输出 -│ ├── public/ # 公共静态文件 -│ ├── Dockerfile # 前端 Docker 镜像 -│ ├── entrypoint.sh # Docker 入口脚本 -│ ├── eslint.config.js # ESLint 配置 -│ ├── index.html # HTML 模板 -│ ├── nginx.conf # Nginx 配置 -│ ├── package.json # 前端依赖 -│ ├── tsconfig.json # TypeScript 配置 +│ │ ├── db/ # Drizzle ORM + SQLite +│ │ ├── errors/ # 自定义错误类 +│ │ ├── middleware/ # Express 中间件 +│ │ │ ├── authMiddleware.ts +│ │ │ ├── roleBasedAuthMiddleware.ts +│ │ │ ├── roleBasedSettingsMiddleware.ts +│ │ │ └── errorHandler.ts +│ │ ├── routes/ # 路由定义 +│ │ │ ├── api.ts # 主 API 路由 +│ │ │ └── settingsRoutes.ts # 设置相关路由 +│ │ ├── scripts/ # 工具脚本 (VTT 清理、字幕重扫) +│ │ ├── services/ # 业务逻辑 +│ │ │ ├── cloudStorage/ # 云存储相关与缓存 +│ │ │ ├── continuousDownload/ # 订阅任务引擎 +│ │ │ ├── downloaders/ # 平台下载器 (yt-dlp、Bilibili、MissAV) +│ │ │ ├── storageService/ # 模块化存储服务 +│ │ │ └── *.ts # 其他服务 (auth、metadata 等) +│ │ ├── utils/ # 工具函数 +│ │ ├── server.ts # 服务器入口 +│ │ └── version.ts # 版本信息 +│ ├── bgutil-ytdlp-pot-provider/ # PO Token 提供者插件 +│ ├── data/ # 运行数据 (数据库、hooks、备份) +│ ├── drizzle/ # 数据库迁移 +│ ├── uploads/ # 媒体存储 (videos/images/subtitles/cache) +│ ├── scripts/ # 维护脚本 (reset-password、migrate、verify) +│ ├── Dockerfile +│ ├── drizzle.config.ts +│ ├── nodemon.json +│ ├── package.json +│ ├── tsconfig.json +│ └── vitest.config.ts +├── frontend/ # React 前端 (Vite + TypeScript) +│ ├── src/ # 源代码 +│ │ ├── __tests__/ # 测试文件 +│ │ ├── assets/ # 静态资源 +│ │ ├── components/ # 按功能划分的 UI 组件 +│ │ ├── contexts/ # React Context 状态 +│ │ ├── hooks/ # 自定义 hooks (播放器、设置、数据) +│ │ ├── pages/ # 路由页面 +│ │ ├── utils/ # API 客户端、工具、多语言 +│ │ ├── App.tsx +│ │ ├── main.tsx +│ │ ├── theme.ts +│ │ └── version.ts +│ ├── public/ # 公共静态资源 +│ ├── Dockerfile +│ ├── entrypoint.sh +│ ├── nginx.conf +│ ├── package.json +│ ├── tsconfig.json │ ├── tsconfig.node.json -│ └── vite.config.js # Vite 配置 -├── documents/ # 文档 -│ ├── en/ # 英文文档 -│ │ ├── api-endpoints.md -│ │ ├── directory-structure.md -│ │ ├── docker-guide.md -│ │ └── getting-started.md -│ └── zh/ # 中文文档 -│ ├── api-endpoints.md -│ ├── directory-structure.md -│ ├── docker-guide.md -│ └── getting-started.md -├── data/ # 根数据目录 (可选) -│ └── mytube.db -├── build-and-push.sh # Docker 构建和推送脚本 -├── docker-compose.yml # Docker Compose 配置 -├── CHANGELOG.md # 更新日志 -├── CODE_OF_CONDUCT.md # 行为准则 -├── CONTRIBUTING.md # 贡献指南 -├── LICENSE # MIT 许可证 -├── README.md # 英文 README -├── README-zh.md # 中文 README -├── RELEASING.md # 发布流程指南 -├── SECURITY.md # 安全策略 -└── package.json # 运行两个应用的根 package.json +│ └── vite.config.js +├── documents/ # 文档 (EN/ZH) +├── docker-compose.yml # 标准部署 Compose +├── docker-compose.host-network.yml # OpenWrt/iStoreOS 的 host 网络 Compose +├── README.md +├── README-zh.md +└── package.json # 根目录脚本 ``` ## 架构概述 ### 后端架构 -后端遵循**分层架构**模式: +后端遵循 **分层架构**: -1. **路由层** (`routes/`): 定义 API 端点并将其映射到控制器 -2. **控制器层** (`controllers/`): 处理 HTTP 请求/响应并委托给服务 -3. **服务层** (`services/`): 包含业务逻辑 - - **下载器**: 用于平台特定下载器的抽象基类模式 - - **存储服务**: 拆分为专注模块的模块化服务 - - **支持服务**: 下载管理、订阅、元数据等 -4. **数据库层** (`db/`): 使用 Drizzle ORM 和 SQLite 进行数据持久化 -5. **工具层** (`utils/`): 共享工具函数 +1. **Routes** (`routes/`): 定义 API 端点并映射到控制器 +2. **Controllers** (`controllers/`): 处理 HTTP 请求/响应 +3. **Services** (`services/`): 业务逻辑(下载器、存储、云存储、订阅等) +4. **Database** (`db/`): Drizzle ORM + SQLite +5. **Utils** (`utils/`): 通用工具与基础设施 ### 前端架构 -前端遵循**基于组件的架构**: +前端遵循 **组件化架构**: -1. **页面** (`pages/`): 顶级路由组件 -2. **组件** (`components/`): 按功能组织的可重用 UI 组件 -3. **上下文** (`contexts/`): 用于全局状态管理的 React Context API -4. **Hooks** (`hooks/`): 用于可重用逻辑的自定义 React hooks -5. **工具** (`utils/`): 辅助函数和国际化 +1. **Pages** (`pages/`): 顶级路由组件 +2. **Components** (`components/`): 以功能划分的 UI 组件 +3. **Contexts** (`contexts/`): React Context 全局状态 +4. **Hooks** (`hooks/`): 可复用逻辑和数据访问 +5. **Utils** (`utils/`): API、格式化和多语言辅助 ### 数据库模式 -应用程序使用 **SQLite** 和 **Drizzle ORM** 进行数据持久化。关键表包括: +关键表包括: - `videos`: 视频元数据和文件路径 - `collections`: 视频收藏夹/播放列表 -- `collection_videos`: 视频和收藏夹之间的多对多关系 +- `collection_videos`: 视频与收藏夹的多对多关系 - `subscriptions`: 频道/创作者订阅 - `downloads`: 活动下载队列 - `download_history`: 完成的下载历史 -- `video_downloads`: 跟踪已下载的视频以防止重复 -- `settings`: 应用程序配置 +- `video_downloads`: 跟踪已下载视频以防止重复 +- `settings`: 应用配置 diff --git a/documents/zh/docker-guide.md b/documents/zh/docker-guide.md index aa988ef..f5288df 100644 --- a/documents/zh/docker-guide.md +++ b/documents/zh/docker-guide.md @@ -1,6 +1,6 @@ # MyTube Docker 部署指南 -本指南提供了使用 Docker 和 Docker Compose 部署  [MyTube](https://github.com/franklioxygen/MyTube "null")  的详细步骤。此设置适用于标准环境(Linux, macOS, Windows),并针对通用用途修改了原本专用于 QNAP 的配置。 +本指南提供了使用 Docker 和 Docker Compose 部署  [MyTube](https://github.com/franklioxygen/MyTube "null")  的详细步骤。仓库中包含面向 QNAP 的 Compose 文件,请按需调整卷路径,或直接使用下面的通用示例。 > [!NOTE] > **多架构支持:** 官方镜像支持 **amd64** (x86_64) 和 **arm64** (Apple Silicon, Raspberry Pi 等) 架构。Docker 会自动为您的系统拉取正确的镜像。 @@ -21,7 +21,7 @@ cd mytube-deploy 在文件夹中创建一个名为  `docker-compose.yml`  的文件,并粘贴以下内容。 -**注意:** 此版本使用标准的相对路径(`./data`, `./uploads`),而不是原始仓库中特定于 QNAP 的路径。 +**注意:** 此版本使用标准相对路径(`./data`, `./uploads`)。若使用仓库内的 `docker-compose.yml`,请先调整卷路径。 ```yaml version: "3.8" @@ -38,8 +38,6 @@ services: - mytube-network environment: - PORT=5551 - # 可选:如果需要,在容器内设置自定义上传目录 - # - VIDEO_DIR=/app/uploads/videos volumes: - ./uploads:/app/uploads - ./data:/app/data @@ -204,3 +202,9 @@ docker-compose up -d 3. 删除(或注释掉)两个服务的 `ports` 和 `networks` 部分。 4. 在 `frontend` 环境变量中设置 `NGINX_BACKEND_URL=http://localhost:5551`。 5. 重启容器:`docker-compose up -d` + +或者直接使用仓库提供的 `docker-compose.host-network.yml`: + +``` +docker-compose -f docker-compose.host-network.yml up -d +``` diff --git a/documents/zh/getting-started.md b/documents/zh/getting-started.md index d8efa62..b4db6ae 100644 --- a/documents/zh/getting-started.md +++ b/documents/zh/getting-started.md @@ -52,23 +52,21 @@ pipx inject yt-dlp bgutil-ytdlp-pot-provider ```env PORT=5551 -UPLOAD_DIR=uploads -VIDEO_DIR=uploads/videos -IMAGE_DIR=uploads/images -SUBTITLES_DIR=uploads/subtitles -DATA_DIR=data -MAX_FILE_SIZE=500000000 ``` +默认数据与上传路径位于 `backend/data` 和 `backend/uploads`(相对于后端工作目录)。 + #### 前端配置 在 `frontend/` 目录中创建 `.env` 文件: ```env -VITE_API_URL=http://localhost:5551/api -VITE_BACKEND_URL=http://localhost:5551 +VITE_API_URL=/api +VITE_BACKEND_URL= ``` +项目提供 `backend/.env.example`,请复制为 `backend/.env` 并按需调整。前端已提供 `frontend/.env`,如需覆盖默认值请使用 `frontend/.env.local`。 + ### 4. 数据库设置 应用程序使用 **SQLite** 和 **Drizzle ORM**。数据库将在首次启动时自动创建和迁移: @@ -92,7 +90,7 @@ npm run dev - **前端**: http://localhost:5556 (带热重载的 Vite 开发服务器) - **后端 API**: http://localhost:5551 (带 nodemon 的 Express 服务器) -### 生产模式 +### 生产模式 (本地) 构建并以生产模式启动: @@ -100,10 +98,19 @@ npm run dev # 构建前端 npm run build -# 启动两个服务 +# 启动后端 +cd backend npm run start + +# 在另一个终端预览前端构建 +cd frontend +npm run preview ``` +生产环境建议参考 [Docker 部署指南](docker-guide.md)。 + +根目录的 `npm run start` 为便捷命令,会同时运行后端启动脚本和前端开发服务器。 + ### 单独运行服务 您也可以单独运行服务: @@ -126,9 +133,12 @@ npm run preview # 预览生产构建 ```bash npm run dev # 以开发模式启动前端和后端 -npm run start # 以生产模式启动前端和后端 +npm run start # 启动后端 + 前端开发服务器 (便捷) npm run build # 为生产环境构建前端 npm run install:all # 安装根目录、前端和后端的依赖 +npm run test # 运行前后端测试 +npm run test:frontend # 运行前端测试 +npm run test:backend # 运行后端测试 ``` 后端特定脚本 (从 `backend/` 目录): @@ -140,6 +150,7 @@ npm run build # 将 TypeScript 编译为 JavaScript npm run test # 使用 Vitest 运行测试 npm run test:coverage # 运行测试并生成覆盖率报告 npm run generate # 使用 Drizzle Kit 生成数据库迁移 +npm run reset-password # 使用脚本重置管理员密码 ``` 前端特定脚本 (从 `frontend/` 目录): @@ -150,16 +161,18 @@ npm run build # 为生产环境构建 npm run preview # 预览生产构建 npm run lint # 运行 ESLint npm run test # 使用 Vitest 运行测试 +npm run test:coverage # 运行测试并生成覆盖率报告 ``` ## 首次设置 1. **访问应用**: 在浏览器中打开 http://localhost:5556 -2. **设置密码保护** (可选): +2. **设置登录保护** (可选): - 转到设置 → 安全 - - 启用密码保护并设置密码 + - 启用登录并设置管理员密码 + - 可选:注册通行密钥 (WebAuthn) 3. **配置下载设置**: @@ -183,12 +196,11 @@ npm run test # 使用 Vitest 运行测试 - 测试连接以验证设置 - 注意:启用后,视频将在下载后自动上传到云存储,本地文件将被删除 -6. **配置访客模式** (可选): +6. **配置访客用户** (可选): - - 转到设置 → 常规设置 - - 启用"访客模式(只读)"以允许查看视频但无法进行修改 - - 启用后,所有写入操作(下载、删除、编辑)将被阻止 - - 要禁用访客模式,您需要输入网站密码 + - 转到设置 → 安全 + - 启用“访客用户”以获得只读访问 + - 为访客角色设置登录密码 7. **开始下载**: - 在下载输入框中输入视频 URL diff --git a/documents/zh/hooks-guide.md b/documents/zh/hooks-guide.md index ca82d93..14ede6c 100644 --- a/documents/zh/hooks-guide.md +++ b/documents/zh/hooks-guide.md @@ -1,44 +1,43 @@ # 任务钩子使用指南 (Task Hooks Guide) -MyTube允许您在下载任务生命周期的不同阶段执行自定义Shell脚本。此功能对于与其他系统集成、对下载的文件进行后处理或发送通知非常有用。 +MyTube 允许您在下载任务的不同阶段执行自定义 Shell 脚本,用于后处理、通知或外部集成。 ## 可用钩子 (Available Hooks) -您可以为以下事件配置命令: - | 钩子名称 | 触发时机 | 描述 | | :--- | :--- | :--- | -| **任务开始前** (`task_before_start`) | 下载开始前 | 在下载过程开始之前立即执行。适用于设置或验证。 | -| **任务成功** (`task_success`) | 下载成功后 | 在文件成功下载/合并后,但在上传到云存储(如果启用)或删除之前执行。这是文件处理的理想位置。 | -| **任务失败** (`task_fail`) | 任务失败时 | 如果下载因任何原因失败,则执行此钩子。 | -| **任务取消** (`task_cancel`) | 任务取消时 | 当用户手动取消正在运行的任务时执行。 | +| **任务开始前** (`task_before_start`) | 下载开始前 | 在下载开始前立即执行。 | +| **任务成功** (`task_success`) | 下载成功后 | 下载/合并完成后执行,且在云存储上传(若启用)或删除之前执行。 | +| **任务失败** (`task_fail`) | 任务失败时 | 下载失败时执行。 | +| **任务取消** (`task_cancel`) | 任务取消时 | 用户取消正在运行的任务时执行。 | + +默认脚本目录为 `backend/data/hooks`。 ## 环境变量 (Environment Variables) -当钩子命令执行时,以下环境变量将被注入到Shell环境,提供有关任务的上下文: - | 变量 | 描述 | 示例 | | :--- | :--- | :--- | -| `MYTUBE_TASK_ID` | 任务的唯一标识符 | `335e98f0-15cb-46a4-846d-9d4351368923` | -| `MYTUBE_TASK_TITLE` | 视频/任务的标题 | `Awesome Video Title` | -| `MYTUBE_SOURCE_URL` | 视频的原始URL | `https://www.youtube.com/watch?v=...` | -| `MYTUBE_TASK_STATUS` | 任务的当前状态 | `success`, `fail`, `cancelled` | -| `MYTUBE_VIDEO_PATH` | 下载视频文件的绝对路径 | `/app/downloads/video.mp4` | -| `MYTUBE_THUMBNAIL_PATH` | 缩略图文件的绝对路径 | `/app/downloads/video.jpg` | -| `MYTUBE_ERROR` | 错误消息(仅限 `task_fail`) | `Network timeout` | +| `MYTUBE_TASK_ID` | 任务唯一标识 | `335e98f0-15cb-46a4-846d-9d4351368923` | +| `MYTUBE_TASK_TITLE` | 视频/任务标题 | `Awesome Video Title` | +| `MYTUBE_SOURCE_URL` | 视频原始 URL | `https://www.youtube.com/watch?v=...` | +| `MYTUBE_TASK_STATUS` | 当前状态 | `start`, `success`, `fail`, `cancel` | +| `MYTUBE_VIDEO_PATH` | 视频文件绝对路径 | `/app/uploads/videos/video.mp4` | +| `MYTUBE_THUMBNAIL_PATH` | 缩略图绝对路径 | `/app/uploads/images/video.jpg` | +| `MYTUBE_ERROR` | 错误消息(仅 `task_fail`) | `Network timeout` | ## 配置 (Configuration) -您可以在网页界面中配置钩子: -1. 转到 **设置 (Settings)**。 -2. 向下滚动到 **高级设置 (Advanced Settings)**。 -3. 找到 **任务钩子 (Task Hooks)** 部分。 -4. 为特定事件上传您的 `.sh` 脚本。 -5. 您可以根据需要删除或重新上传脚本。 +1. 进入 **设置 (Settings)**。 +2. 打开 **高级设置 (Advanced Settings)**。 +3. 找到 **任务钩子 (Task Hooks)**。 +4. 上传对应事件的 `.sh` 脚本。 +5. 需要时可删除或重新上传。 + +钩子脚本使用 `bash` 执行,上传后会自动赋予可执行权限。 ## 查看日志 (Viewing Logs) -脚本的任何输出 (stdout/stderr) 都将被捕获并记录到 MyTube 服务器控制台。 +脚本输出 (stdout/stderr) 会被后端捕获并记录。 - 标准输出 (`echo "..."`) 记录为 `INFO`。 - 标准错误 (`>&2 echo "..."`) 记录为 `WARN`。 @@ -79,7 +78,7 @@ python3 /path/to/process_video.py "$MYTUBE_VIDEO_PATH" ## 安全警告 (Security Warning) > [!WARNING] -> 钩子命令以与MyTube后端服务器相同的权限执行。 +> 钩子命令以与 MyTube 后端相同的权限执行。 > - 使用修改或删除文件的命令时请务必小心。 > - 请勿复制粘贴来自不可信来源的脚本。 -> - 确保您的脚本能够优雅地处理错误。 +> - 确保脚本能正确处理错误。