chore: update doc

This commit is contained in:
Peifan Li
2026-01-04 17:08:53 -05:00
parent 79530dbca2
commit a4eaaa3180
12 changed files with 423 additions and 689 deletions

View File

@@ -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` 覆盖默认值。
## 数据库

View File

@@ -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

View File

@@ -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 }`

View File

@@ -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

View File

@@ -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 repos `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`
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
```

View File

@@ -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

View File

@@ -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.

View File

@@ -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 }`
- 支持: YouTubeBilibiliMissAV 以及所有 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 }`

View File

@@ -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`: 应用配置

View File

@@ -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
```

View File

@@ -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

View File

@@ -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 后端相同的权限执行。
> - 使用修改或删除文件的命令时请务必小心。
> - 请勿复制粘贴来自不可信来源的脚本。
> - 确保您的脚本能够优雅地处理错误。
> - 确保脚本能正确处理错误。