Merge branch 'jxxghp:main' into main

This commit is contained in:
Summer⛱ 2023-11-30 00:42:23 +08:00 committed by GitHub
commit 8105dc9c82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 409 additions and 257 deletions

202
README.md
View File

@ -39,11 +39,13 @@ MoviePilot需要配套下载器和媒体服务器配合使用。
docker pull jxxghp/moviepilot:latest
```
- Windows
下载 [MoviePilot.exe](https://github.com/jxxghp/MoviePilot/releases),双击运行后自动生成配置文件目录
下载 [MoviePilot.exe](https://github.com/jxxghp/MoviePilot/releases),双击运行后自动生成配置文件目录访问http://localhost:3000
- 群晖套件
添加套件源https://spk7.imnks.com/
- 本地运行
@ -51,47 +53,73 @@ MoviePilot需要配套下载器和媒体服务器配合使用。
2) 将工程 [MoviePilot-Resources](https://github.com/jxxghp/MoviePilot-Resources) resources目录下的所有文件复制到`app/helper`目录
3) 执行命令:`pip install -r requirements.txt` 安装依赖
4) 执行命令:`python app/main.py` 启动服务
5) 根据前端项目 [MoviePilot-Frontend](https://github.com/jxxghp/MoviePilot-Frontend) 说明,启动前端服务
## 配置
项目的所有配置均通过环境变量进行设置,支持两种配置方式:
- 在Docker环境变量部分或Windows系统环境变量中进行参数配置如未自动显示配置项则需要手动增加对应环境变量。
- 下载 [app.env](https://github.com/jxxghp/MoviePilot/raw/main/config/app.env) 配置文件,修改好配置后放置到配置文件映射路径根目录,配置项可根据说明自主增减。
配置文件映射路径:`/config`,配置项生效优先级:环境变量 > env文件 > 默认值,**部分参数如路径映射、站点认证、权限端口、时区等必须通过环境变量进行配置**。
> ❗号标识的为必填项,其它为可选项,可选项可删除配置变量从而使用默认值。
### 1. **基础设置**
### 1. **环境变量**
- **❗NGINX_PORT** WEB服务端口默认`3000`可自行修改不能与API服务端口冲突(仅支持环境变量配置)
- **❗PORT** API服务端口默认`3001`可自行修改不能与WEB服务端口冲突(仅支持环境变量配置)
- **PUID**:运行程序用户的`uid`,默认`0`(仅支持环境变量配置)
- **PGID**:运行程序用户的`gid`,默认`0`(仅支持环境变量配置)
- **UMASK**:掩码权限,默认`000`,可以考虑设置为`022`(仅支持环境变量配置)
- **PROXY_HOST** 网络代理访问themoviedb或者重启更新需要使用代理访问格式为`http(s)://ip:port``socks5://user:pass@host:port`(仅支持环境变量配置)
- **MOVIEPILOT_AUTO_UPDATE** 重启时自动更新,`true`/`release`/`dev`/`false`,默认`release`需要能正常连接Github **注意:如果出现网络问题可以配置`PROXY_HOST`**(仅支持环境变量配置)
- **❗NGINX_PORT** WEB服务端口默认`3000`可自行修改不能与API服务端口冲突
- **❗PORT** API服务端口默认`3001`可自行修改不能与WEB服务端口冲突
- **PUID**:运行程序用户的`uid`,默认`0`
- **PGID**:运行程序用户的`gid`,默认`0`
- **UMASK**:掩码权限,默认`000`,可以考虑设置为`022`
- **PROXY_HOST** 网络代理访问themoviedb或者重启更新需要使用代理访问格式为`http(s)://ip:port``socks5://user:pass@host:port`
- **MOVIEPILOT_AUTO_UPDATE** 重启时自动更新,`true`/`release`/`dev`/`false`,默认`release`需要能正常连接Github **注意:如果出现网络问题可以配置`PROXY_HOST`**
- **AUTO_UPDATE_RESOURCE**:启动时自动检测和更新资源包(站点索引及认证等),`true`/`false`,默认`true`需要能正常连接Github仅支持Docker
---
- **❗SUPERUSER** 超级管理员用户名,默认`admin`,安装后使用该用户登录后台管理界面
- **❗SUPERUSER_PASSWORD** 超级管理员初始密码,默认`password`,建议修改为复杂密码
- **❗AUTH_SITE** 认证站点(认证通过后才能使用站点相关功能),支持配置多个认证站点,使用`,`分隔,如:`iyuu,hhclub`,会依次执行认证操作,直到有一个站点认证成功。
配置`AUTH_SITE`后,需要根据下表配置对应站点的认证参数,认证资源`v1.0.2`支持`iyuu`/`hhclub`/`audiences`/`hddolby`/`zmpt`/`freefarm`/`hdfans`/`wintersakura`/`leaves`/`1ptba`/`icc2022`/`ptlsp`/`xingtan`/`ptvicomo`/`agsvpt`
| 站点 | 参数 |
|:------------:|:-----------------------------------------------------:|
| iyuu | `IYUU_SIGN`IYUU登录令牌 |
| hhclub | `HHCLUB_USERNAME`:用户名<br/>`HHCLUB_PASSKEY`:密钥 |
| audiences | `AUDIENCES_UID`用户ID<br/>`AUDIENCES_PASSKEY`:密钥 |
| hddolby | `HDDOLBY_ID`用户ID<br/>`HDDOLBY_PASSKEY`:密钥 |
| zmpt | `ZMPT_UID`用户ID<br/>`ZMPT_PASSKEY`:密钥 |
| freefarm | `FREEFARM_UID`用户ID<br/>`FREEFARM_PASSKEY`:密钥 |
| hdfans | `HDFANS_UID`用户ID<br/>`HDFANS_PASSKEY`:密钥 |
| wintersakura | `WINTERSAKURA_UID`用户ID<br/>`WINTERSAKURA_PASSKEY`:密钥 |
| leaves | `LEAVES_UID`用户ID<br/>`LEAVES_PASSKEY`:密钥 |
| 1ptba | `1PTBA_UID`用户ID<br/>`1PTBA_PASSKEY`:密钥 |
| icc2022 | `ICC2022_UID`用户ID<br/>`ICC2022_PASSKEY`:密钥 |
| ptlsp | `PTLSP_UID`用户ID<br/>`PTLSP_PASSKEY`:密钥 |
| xingtan | `XINGTAN_UID`用户ID<br/>`XINGTAN_PASSKEY`:密钥 |
| ptvicomo | `PTVICOMO_UID`用户ID<br/>`PTVICOMO_PASSKEY`:密钥 |
| agsvpt | `AGSVPT_UID`用户ID<br/>`AGSVPT_PASSKEY`:密钥 |
### 2. **app.env配置文件**
下载 [app.env 模板](https://github.com/jxxghp/MoviePilot/raw/main/config/app.env)修改后放配置文件目录下app.env 的所有配置项也可以通过环境变量进行配置。
- **❗SUPERUSER** 超级管理员用户名,默认`admin`,安装后使用该用户登录后台管理界面,**注意:启动一次后再次修改该值不会生效,除非删除数据库文件!**
- **❗SUPERUSER_PASSWORD** 超级管理员初始密码,默认`password`,建议修改为复杂密码,**注意:启动一次后再次修改该值不会生效,除非删除数据库文件!**
- **❗API_TOKEN** API密钥默认`moviepilot`在媒体服务器Webhook、微信回调等地址配置中需要加上`?token=`该值,建议修改为复杂字符串
- **TMDB_API_DOMAIN** TMDB API地址默认`api.themoviedb.org`,也可配置为`api.tmdb.org`或其它中转代理服务地址,能连通即可
- **BIG_MEMORY_MODE** 大内存模式,默认为`false`,开启后会增加缓存数量,占用更多的内存,但响应速度会更快
- **GITHUB_TOKEN** Github token提高自动更新、插件安装等请求Github Api的限流阈值格式ghp_****
---
- **TMDB_API_DOMAIN** TMDB API地址默认`api.themoviedb.org`,也可配置为`api.tmdb.org``tmdb.movie-pilot.org` 或其它中转代理服务地址,能连通即可
- **TMDB_IMAGE_DOMAIN** TMDB图片地址默认`image.tmdb.org`可配置为其它中转代理以加速TMDB图片显示`static-mdb.v.geilijiasu.com`
- **WALLPAPER** 登录首页电影海报,`tmdb`/`bing`,默认`tmdb`
- **RECOGNIZE_SOURCE** 媒体信息识别来源,`themoviedb`/`douban`,默认`themoviedb`,使用`douban`时不支持二级分类
- **SCRAP_SOURCE** 刮削元数据及图片使用的数据源,`themoviedb`/`douban`,默认`themoviedb`
---
- **SCRAP_METADATA** 刮削入库的媒体文件,`true`/`false`,默认`true`
- **SCRAP_SOURCE** 刮削元数据及图片使用的数据源,`themoviedb`/`douban`,默认`themoviedb`
- **SCRAP_FOLLOW_TMDB** 新增已入库媒体是否跟随TMDB信息变化`true`/`false`,默认`true`,为`false`时即使TMDB信息变化了也会仍然按历史记录中已入库的信息进行刮削
---
- **❗TRANSFER_TYPE** 整理转移方式,支持`link`/`copy`/`move`/`softlink`/`rclone_copy`/`rclone_move` **注意:在`link``softlink`转移方式下,转移后的文件会继承源文件的权限掩码,不受`UMASK`影响rclone需要自行映射rclone配置目录到容器中或在容器内完成rclone配置节点名称必须为`MP`**
- **❗OVERWRITE_MODE** 转移覆盖模式,默认为`size`,支持`nerver`/`size`/`always`/`latest`,分别表示`不覆盖同名文件`/`同名文件根据文件大小覆盖(大覆盖小)`/`总是覆盖同名文件`/`仅保留最新版本,删除旧版本文件(包括非同名文件)`
- **❗LIBRARY_PATH** 媒体库目录,多个目录使用`,`分隔
- **LIBRARY_MOVIE_NAME** 电影媒体库目录名称(不是完整路径),默认`电影`
- **LIBRARY_TV_NAME** 电视剧媒体库目录称(不是完整路径),默认`电视剧`
- **LIBRARY_ANIME_NAME** 动漫媒体库目录称(不是完整路径),默认`电视剧/动漫`
- **LIBRARY_CATEGORY** 媒体库二级分类开关,`true`/`false`,默认`false`,开启后会根据配置 [category.yaml](https://github.com/jxxghp/MoviePilot/raw/main/config/category.yaml) 自动在媒体库目录下建立二级目录分类
- **❗TRANSFER_TYPE** 整理转移方式,支持`link`/`copy`/`move`/`softlink`/`rclone_copy`/`rclone_move` **注意:在`link``softlink`转移方式下,转移后的文件会继承源文件的权限掩码,不受`UMASK`影响rclone需要自行映射rclone配置目录到容器中或在容器内完成rclone配置节点名称必须为`MP`**
- **OVERWRITE_MODE** 转移覆盖模式,默认为`size`,支持`nerver`/`size`/`always`/`latest`,分别表示`不覆盖同名文件`/`同名文件根据文件大小覆盖(大覆盖小)`/`总是覆盖同名文件`/`仅保留最新版本,删除旧版本文件(包括非同名文件)`
---
- **❗COOKIECLOUD_HOST** CookieCloud服务器地址格式`http(s)://ip:port`,不配置默认使用内建服务器`https://movie-pilot.org/cookiecloud`
- **❗COOKIECLOUD_KEY** CookieCloud用户KEY
@ -105,8 +133,6 @@ MoviePilot需要配套下载器和媒体服务器配合使用。
- **AUTO_DOWNLOAD_USER** 远程交互搜索时自动择优下载的用户ID消息通知渠道的用户ID多个用户使用,分割,未设置需要选择资源或者回复`0`
---
- **OCR_HOST** OCR识别服务器地址格式`http(s)://ip:port`用于识别站点验证码实现自动登录获取Cookie等不配置默认使用内建服务器`https://movie-pilot.org`,可使用 [这个镜像](https://hub.docker.com/r/jxxghp/moviepilot-ocr) 自行搭建。
- **PLUGIN_MARKET** 插件市场仓库地址,多个地址使用`,`分隔,保留最后的/,默认为官方插件仓库:`https://raw.githubusercontent.com/jxxghp/MoviePilot-Plugins/main/`
- **GITHUB_TOKEN** Github token提高请求api限流阈值 ghp_****(仅支持环境变量配置)
---
- **❗MESSAGER** 消息通知渠道,支持 `telegram`/`wechat`/`slack`/`synologychat`,开启多个渠道时使用`,`分隔。同时还需要配置对应渠道的环境变量,非对应渠道的变量可删除,推荐使用`telegram`
@ -137,7 +163,6 @@ MoviePilot需要配套下载器和媒体服务器配合使用。
- **SYNOLOGYCHAT_WEBHOOK** 在Synology Chat中创建机器人获取机器人`传入URL`
- **SYNOLOGYCHAT_TOKEN** SynologyChat机器人`令牌`
---
- **❗DOWNLOAD_PATH** 下载保存目录,**注意:需要将`moviepilot``下载器`的映射路径保持一致**,否则会导致下载文件无法转移
- **DOWNLOAD_MOVIE_PATH** 电影下载保存目录路径,不设置则下载到`DOWNLOAD_PATH`
@ -145,8 +170,7 @@ MoviePilot需要配套下载器和媒体服务器配合使用。
- **DOWNLOAD_ANIME_PATH** 动漫下载保存目录路径,不设置则下载到`DOWNLOAD_PATH`
- **DOWNLOAD_CATEGORY** 下载二级分类开关,`true`/`false`,默认`false`,开启后会根据配置 [category.yaml](https://github.com/jxxghp/MoviePilot/raw/main/config/category.yaml) 自动在下载目录下建立二级目录分类
- **DOWNLOAD_SUBTITLE** 下载站点字幕,`true`/`false`,默认`true`
- **DOWNLOADER_MONITOR** 下载器监控,`true`/`false`,默认为`true`,开启后下载完成时才会自动整理入库
- **TORRENT_TAG** 下载器种子标签,默认为`MOVIEPILOT`设置后只有MoviePilot添加的下载才会处理留空所有下载器中的任务均会处理
---
- **❗DOWNLOADER** 下载器,支持`qbittorrent`/`transmission`QB版本号要求>= 4.3.9TR版本号要求>= 3.0,同时还需要配置对应渠道的环境变量,非对应渠道的变量可删除,推荐使用`qbittorrent`
- `qbittorrent`设置项:
@ -163,7 +187,8 @@ MoviePilot需要配套下载器和媒体服务器配合使用。
- **TR_HOST** transmission地址格式`ip:port`https需要添加`https://`前缀
- **TR_USER** transmission用户名
- **TR_PASSWORD** transmission密码
- **DOWNLOADER_MONITOR** 下载器监控,`true`/`false`,默认为`true`,开启后下载完成时才会自动整理入库
- **TORRENT_TAG** 下载器种子标签,默认为`MOVIEPILOT`设置后只有MoviePilot添加的下载才会处理留空所有下载器中的任务均会处理
---
- **❗MEDIASERVER** 媒体服务器,支持`emby`/`jellyfin`/`plex`,同时开启多个使用`,`分隔。还需要配置对应媒体服务器的环境变量,非对应媒体服务器的变量可删除,推荐使用`emby`
@ -181,88 +206,55 @@ MoviePilot需要配套下载器和媒体服务器配合使用。
- **PLEX_HOST** Plex服务器地址格式`ip:port`https需要添加`https://`前缀
- **PLEX_TOKEN** Plex网页Url中的`X-Plex-Token`通过浏览器F12->网络从请求URL中获取
- **MEDIASERVER_SYNC_INTERVAL:** 媒体服务器同步间隔(小时),默认`6`,留空则不同步
- **MEDIASERVER_SYNC_BLACKLIST:** 媒体服务器同步黑名单,多个媒体库名称使用,分割
---
- **MOVIE_RENAME_FORMAT** 电影重命名格式基于jinjia2语法
`MOVIE_RENAME_FORMAT`支持的配置项:
### 2. **用户认证**
> `title` 标题
> `original_name` 原文件名
> `original_title` 原语种标题
> `name` 识别名称
> `year` 年份
> `resourceType`:资源类型
> `effect`:特效
> `edition` 版本(资源类型+特效)
> `videoFormat` 分辨率
> `releaseGroup` 制作组/字幕组
> `customization` 自定义占位符
> `videoCodec` 视频编码
> `audioCodec` 音频编码
> `tmdbid` TMDBID
> `imdbid` IMDBID
> `part`:段/节
> `fileExt`:文件扩展名
> `tmdbid`TMDB ID
> `imdbid`IMDB ID
> `customization`:自定义占位符
`MOVIE_RENAME_FORMAT`默认配置格式:
```
{{title}}{% if year %} ({{year}}){% endif %}/{{title}}{% if year %} ({{year}}){% endif %}{% if part %}-{{part}}{% endif %}{% if videoFormat %} - {{videoFormat}}{% endif %}{{fileExt}}
```
`MoviePilot`需要认证后才能使用,配置`AUTH_SITE`后,需要根据下表配置对应站点的认证参数(**仅能通过环境变量配置**
`AUTH_SITE`支持配置多个认证站点,使用`,`分隔,如:`iyuu,hhclub`,会依次执行认证操作,直到有一个站点认证成功。
- **❗AUTH_SITE** 认证站点,认证资源`v1.0.2`支持`iyuu`/`hhclub`/`audiences`/`hddolby`/`zmpt`/`freefarm`/`hdfans`/`wintersakura`/`leaves`/`1ptba`/`icc2022`/`ptlsp`/`xingtan`/`ptvicomo`/`agsvpt`
| 站点 | 参数 |
|:------------:|:-----------------------------------------------------:|
| iyuu | `IYUU_SIGN`IYUU登录令牌 |
| hhclub | `HHCLUB_USERNAME`:用户名<br/>`HHCLUB_PASSKEY`:密钥 |
| audiences | `AUDIENCES_UID`用户ID<br/>`AUDIENCES_PASSKEY`:密钥 |
| hddolby | `HDDOLBY_ID`用户ID<br/>`HDDOLBY_PASSKEY`:密钥 |
| zmpt | `ZMPT_UID`用户ID<br/>`ZMPT_PASSKEY`:密钥 |
| freefarm | `FREEFARM_UID`用户ID<br/>`FREEFARM_PASSKEY`:密钥 |
| hdfans | `HDFANS_UID`用户ID<br/>`HDFANS_PASSKEY`:密钥 |
| wintersakura | `WINTERSAKURA_UID`用户ID<br/>`WINTERSAKURA_PASSKEY`:密钥 |
| leaves | `LEAVES_UID`用户ID<br/>`LEAVES_PASSKEY`:密钥 |
| 1ptba | `1PTBA_UID`用户ID<br/>`1PTBA_PASSKEY`:密钥 |
| icc2022 | `ICC2022_UID`用户ID<br/>`ICC2022_PASSKEY`:密钥 |
| ptlsp | `PTLSP_UID`用户ID<br/>`PTLSP_PASSKEY`:密钥 |
| xingtan | `XINGTAN_UID`用户ID<br/>`XINGTAN_PASSKEY`:密钥 |
| ptvicomo | `PTVICOMO_UID`用户ID<br/>`PTVICOMO_PASSKEY`:密钥 |
| agsvpt | `AGSVPT_UID`用户ID<br/>`AGSVPT_PASSKEY`:密钥 |
### 2. **进阶配置**
- **BIG_MEMORY_MODE** 大内存模式,默认为`false`,开启后会增加缓存数量,占用更多的内存,但响应速度会更快
- **MOVIE_RENAME_FORMAT** 电影重命名格式
`MOVIE_RENAME_FORMAT`支持的配置项:
> `title` 标题
> `original_name` 原文件名
> `original_title` 原语种标题
> `name` 识别名称
> `year` 年份
> `resourceType`:资源类型
> `effect`:特效
> `edition` 版本(资源类型+特效)
> `videoFormat` 分辨率
> `releaseGroup` 制作组/字幕组
> `customization` 自定义占位符
> `videoCodec` 视频编码
> `audioCodec` 音频编码
> `tmdbid` TMDBID
> `imdbid` IMDBID
> `part`:段/节
> `fileExt`:文件扩展名
> `tmdbid`TMDB ID
> `imdbid`IMDB ID
> `customization`:自定义占位符
`MOVIE_RENAME_FORMAT`默认配置格式:
```
{{title}}{% if year %} ({{year}}){% endif %}/{{title}}{% if year %} ({{year}}){% endif %}{% if part %}-{{part}}{% endif %}{% if videoFormat %} - {{videoFormat}}{% endif %}{{fileExt}}
```
- **TV_RENAME_FORMAT** 电视剧重命名格式
`TV_RENAME_FORMAT`额外支持的配置项:
> `season` 季号
> `episode` 集号
> `season_episode` 季集 SxxExx
> `episode_title` 集标题
`TV_RENAME_FORMAT`默认配置格式:
```
{{title}}{% if year %} ({{year}}){% endif %}/Season {{season}}/{{title}} - {{season_episode}}{% if part %}-{{part}}{% endif %}{% if episode %} - 第 {{episode}} 集{% endif %}{{fileExt}}
```
- **TV_RENAME_FORMAT** 电视剧重命名格式基于jinjia2语法
`TV_RENAME_FORMAT`额外支持的配置项:
> `season` 季号
> `episode` 集号
> `season_episode` 季集 SxxExx
> `episode_title` 集标题
`TV_RENAME_FORMAT`默认配置格式:
```
{{title}}{% if year %} ({{year}}){% endif %}/Season {{season}}/{{title}} - {{season_episode}}{% if part %}-{{part}}{% endif %}{% if episode %} - 第 {{episode}} 集{% endif %}{{fileExt}}
```
### 3. **优先级规则**
@ -270,6 +262,10 @@ MoviePilot需要配套下载器和媒体服务器配合使用。
- 符合任一层级规则的资源将被标识选中,匹配成功的层级做为该资源的优先级,排越前面优先级超高
- 不符合过滤规则所有层级规则的资源将不会被选中
### 4. **插件扩展**
- **PLUGIN_MARKET** 插件市场仓库地址仅支持Github仓库`main`分支,多个地址使用`,`分隔,默认为官方插件仓库:`https://github.com/jxxghp/MoviePilot-Plugins` ,通过查看[MoviePilot-Plugins](https://github.com/jxxghp/MoviePilot-Plugins)项目的fork或者查看频道置顶了解更多第三方插件仓库。
## 使用

View File

@ -104,7 +104,7 @@ def stop_downloading(
hashString: str,
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
控制下载任务
暂停下载任务
"""
ret = DownloadChain().set_downloading(hashString, "stop")
return schemas.Response(success=True if ret else False)
@ -115,7 +115,7 @@ def remove_downloading(
hashString: str,
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
控制下载任务
删除下载任务
"""
ret = DownloadChain().remove_downloading(hashString)
return schemas.Response(success=True if ret else False)

View File

@ -62,7 +62,7 @@ def install_plugin(plugin_id: str,
state, msg = PluginHelper().install(pid=plugin_id, repo_url=repo_url)
if not state:
# 安装失败
return schemas.Response(success=False, msg=msg)
return schemas.Response(success=False, message=msg)
# 安装插件
if plugin_id not in install_plugins:
install_plugins.append(plugin_id)
@ -89,11 +89,23 @@ def plugin_form(plugin_id: str,
@router.get("/page/{plugin_id}", summary="获取插件数据页面")
def plugin_page(plugin_id: str, _: schemas.TokenPayload = Depends(verify_token)) -> List[dict]:
"""
根据插件ID获取插件配置信息
根据插件ID获取插件数据页面
"""
return PluginManager().get_plugin_page(plugin_id)
@router.get("/reset/{plugin_id}", summary="重置插件配置", response_model=schemas.Response)
def reset_plugin(plugin_id: str, _: schemas.TokenPayload = Depends(verify_token)) -> List[dict]:
"""
根据插件ID重置插件配置
"""
# 删除配置
PluginManager().delete_plugin_config(plugin_id)
# 重新生效插件
PluginManager().reload_plugin(plugin_id, {})
return schemas.Response(success=True)
@router.get("/{plugin_id}", summary="获取插件配置")
def plugin_config(plugin_id: str, _: schemas.TokenPayload = Depends(verify_token)) -> dict:
"""
@ -106,7 +118,7 @@ def plugin_config(plugin_id: str, _: schemas.TokenPayload = Depends(verify_token
def set_plugin_config(plugin_id: str, conf: dict,
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
根据插件ID获取插件配置信息
更新插件配置
"""
# 保存配置
PluginManager().save_plugin_config(plugin_id, conf)

View File

@ -264,7 +264,7 @@ def delete_subscribe(
async def seerr_subscribe(request: Request, background_tasks: BackgroundTasks,
authorization: str = Header(None)) -> Any:
"""
Jellyseerr/Overseerr订阅
Jellyseerr/Overseerr网络勾子通知订阅
"""
if not authorization or authorization != settings.API_TOKEN:
raise HTTPException(

View File

@ -1,10 +1,10 @@
import json
import time
from datetime import datetime
from typing import Union
from typing import Union, Any
import tailer
from fastapi import APIRouter, HTTPException, Depends
from fastapi import APIRouter, HTTPException, Depends, Response
from fastapi.responses import StreamingResponse
from app import schemas
@ -24,6 +24,19 @@ from version import APP_VERSION
router = APIRouter()
@router.get("/img/{imgurl:path}", summary="图片代理")
def get_img(imgurl: str) -> Any:
"""
通过图片代理使用代理服务器
"""
if not imgurl:
return None
response = RequestUtils(ua=settings.USER_AGENT, proxies=settings.PROXY).get_res(url=imgurl)
if response:
return Response(content=response.content, media_type="image/jpeg")
return None
@router.get("/env", summary="查询系统环境变量", response_model=schemas.Response)
def get_env_setting(_: schemas.TokenPayload = Depends(verify_token)):
"""

View File

@ -283,6 +283,10 @@ class DownloadChain(ChainBase):
if not file_meta.begin_episode \
or file_meta.begin_episode not in episodes:
continue
# 只处理视频格式
if not Path(file).suffix \
or Path(file).suffix not in settings.RMT_MEDIAEXT:
continue
files_to_add.append({
"download_hash": _hash,
"downloader": settings.DOWNLOADER,

View File

@ -1,14 +1,22 @@
from typing import Any
import copy
import json
import re
from typing import Any, Optional, Dict
from app.chain.download import *
from app.chain import ChainBase
from app.chain.download import DownloadChain
from app.chain.media import MediaChain
from app.chain.search import SearchChain
from app.chain.subscribe import SubscribeChain
from app.core.context import MediaInfo
from app.core.config import settings
from app.core.context import MediaInfo, Context
from app.core.event import EventManager
from app.core.meta import MetaBase
from app.helper.torrent import TorrentHelper
from app.log import logger
from app.schemas import Notification
from app.schemas.types import EventType, MessageChannel
from app.schemas.types import EventType, MessageChannel, MediaType
from app.utils.string import StringUtils
# 当前页面
_current_page: int = 0
@ -33,7 +41,6 @@ class MessageChain(ChainBase):
self.subscribechain = SubscribeChain()
self.searchchain = SearchChain()
self.medtachain = MediaChain()
self.torrent = TorrentHelper()
self.eventmanager = EventManager()
self.torrenthelper = TorrentHelper()
@ -353,6 +360,13 @@ class MessageChain(ChainBase):
else:
# 未完成下载
logger.info(f'{_current_media.title_year} 未下载未完整,添加订阅 ...')
if downloads and _current_media.type == MediaType.TV:
# 获取已下载剧集
downloaded = [download.meta_info.begin_episode for download in downloads
if download.meta_info.begin_episode]
note = json.dumps(downloaded)
else:
note = None
# 添加订阅状态为R
self.subscribechain.add(title=_current_media.title,
year=_current_media.year,
@ -362,7 +376,8 @@ class MessageChain(ChainBase):
channel=channel,
userid=userid,
username=username,
state="R")
state="R",
note=note)
def __post_medias_message(self, channel: MessageChannel,
title: str, items: list, userid: str, total: int):

View File

@ -12,6 +12,7 @@ from app.db.site_oper import SiteOper
from app.db.systemconfig_oper import SystemConfigOper
from app.helper.rss import RssHelper
from app.helper.sites import SitesHelper
from app.helper.torrent import TorrentHelper
from app.log import logger
from app.schemas import Notification
from app.schemas.types import SystemConfigKey, MessageChannel, NotificationType
@ -34,6 +35,7 @@ class TorrentsChain(ChainBase, metaclass=Singleton):
self.rsshelper = RssHelper()
self.systemconfig = SystemConfigOper()
self.mediachain = MediaChain()
self.torrenthelper = TorrentHelper()
def remote_refresh(self, channel: MessageChannel, userid: Union[str, int] = None):
"""
@ -143,6 +145,11 @@ class TorrentsChain(ChainBase, metaclass=Singleton):
# 读取缓存
torrents_cache = self.get_torrents()
# 缓存过滤掉无效种子
for _domain, _torrents in torrents_cache.items():
torrents_cache[_domain] = [_torrent for _torrent in _torrents
if not self.torrenthelper.is_invalid(_torrent.torrent_info.enclosure)]
# 所有站点索引
indexers = self.siteshelper.get_indexers()
# 遍历站点缓存资源

View File

@ -1,7 +1,7 @@
import secrets
import sys
from pathlib import Path
from typing import List
from typing import List, Optional
from pydantic import BaseSettings
@ -156,7 +156,7 @@ class Settings(BaseSettings):
# 媒体服务器 emby/jellyfin/plex多个媒体服务器,分割
MEDIASERVER: str = "emby"
# 媒体服务器同步间隔(小时)
MEDIASERVER_SYNC_INTERVAL: int = 6
MEDIASERVER_SYNC_INTERVAL: Optional[int] = 6
# 媒体服务器同步黑名单,多个媒体库名称,分割
MEDIASERVER_SYNC_BLACKLIST: str = None
# EMBY服务器地址IP:PORT
@ -180,7 +180,7 @@ class Settings(BaseSettings):
# CookieCloud端对端加密密码
COOKIECLOUD_PASSWORD: str = None
# CookieCloud同步间隔分钟
COOKIECLOUD_INTERVAL: int = 60 * 24
COOKIECLOUD_INTERVAL: Optional[int] = 60 * 24
# OCR服务器地址
OCR_HOST: str = "https://movie-pilot.org"
# CookieCloud对应的浏览器UA
@ -211,7 +211,7 @@ class Settings(BaseSettings):
# 大内存模式
BIG_MEMORY_MODE: bool = False
# 插件市场仓库地址,多个地址使用,分隔,地址以/结尾
PLUGIN_MARKET: str = "https://raw.githubusercontent.com/jxxghp/MoviePilot-Plugins/main/"
PLUGIN_MARKET: str = "https://github.com/jxxghp/MoviePilot-Plugins"
# Github token提高请求api限流阈值 ghp_****
GITHUB_TOKEN: str = None
# 自动检查和更新站点资源包(站点索引、认证等)

View File

@ -147,6 +147,14 @@ class PluginManager(metaclass=Singleton):
return False
return self.systemconfig.set(self._config_key % pid, conf)
def delete_plugin_config(self, pid: str) -> bool:
"""
删除插件配置
"""
if not self._plugins.get(pid):
return False
return self.systemconfig.delete(self._config_key % pid)
def get_plugin_form(self, pid: str) -> Tuple[List[dict], Dict[str, Any]]:
"""
获取插件表单
@ -288,9 +296,6 @@ class PluginManager(metaclass=Singleton):
# 图标
if plugin.get("icon"):
conf.update({"plugin_icon": plugin.get("icon")})
# 主题色
if plugin.get("color"):
conf.update({"plugin_color": plugin.get("color")})
# 作者
if plugin.get("author"):
conf.update({"plugin_author": plugin.get("author")})
@ -358,9 +363,6 @@ class PluginManager(metaclass=Singleton):
# 图标
if hasattr(plugin, "plugin_icon"):
conf.update({"plugin_icon": plugin.plugin_icon})
# 主题色
if hasattr(plugin, "plugin_color"):
conf.update({"plugin_color": plugin.plugin_color})
# 作者
if hasattr(plugin, "plugin_author"):
conf.update({"plugin_author": plugin.plugin_author})

View File

@ -57,7 +57,14 @@ class DownloadHistoryOper(DbOper):
按fullpath查询下载文件记录
:param fullpath: 数据key
"""
return DownloadFiles.get_by_fullpath(self._db, fullpath)
return DownloadFiles.get_by_fullpath(self._db, fullpath=fullpath, all_files=False)
def get_files_by_fullpath(self, fullpath: str) -> List[DownloadFiles]:
"""
按fullpath查询下载文件记录
:param fullpath: 数据key
"""
return DownloadFiles.get_by_fullpath(self._db, fullpath=fullpath, all_files=True)
def get_files_by_savepath(self, fullpath: str) -> List[DownloadFiles]:
"""
@ -78,7 +85,7 @@ class DownloadHistoryOper(DbOper):
按fullpath查询下载文件记录hash
:param fullpath: 数据key
"""
fileinfo: DownloadFiles = DownloadFiles.get_by_fullpath(self._db, fullpath)
fileinfo: DownloadFiles = DownloadFiles.get_by_fullpath(self._db, fullpath=fullpath, all_files=False)
if fileinfo:
return fileinfo.download_hash
return ""
@ -115,3 +122,13 @@ class DownloadHistoryOper(DbOper):
return DownloadHistory.list_by_user_date(db=self._db,
date=date,
username=username)
def list_by_date(self, date: str, type: str, tmdbid: str, seasons: str = None) -> List[DownloadHistory]:
"""
查询某时间之后的下载历史
"""
return DownloadHistory.list_by_date(db=self._db,
date=date,
type=type,
tmdbid=tmdbid,
seasons=seasons)

View File

@ -123,6 +123,24 @@ class DownloadHistory(Base):
DownloadHistory.id.desc()).all()
return list(result)
@staticmethod
@db_query
def list_by_date(db: Session, date: str, type: str, tmdbid: str, seasons: str = None):
"""
查询某时间之后的下载历史
"""
if seasons:
return db.query(DownloadHistory).filter(DownloadHistory.date > date,
DownloadHistory.type == type,
DownloadHistory.tmdbid == tmdbid,
DownloadHistory.seasons == seasons).order_by(
DownloadHistory.id.desc()).all()
else:
return db.query(DownloadHistory).filter(DownloadHistory.date > date,
DownloadHistory.type == type,
DownloadHistory.tmdbid == tmdbid).order_by(
DownloadHistory.id.desc()).all()
class DownloadFiles(Base):
"""
@ -157,9 +175,13 @@ class DownloadFiles(Base):
@staticmethod
@db_query
def get_by_fullpath(db: Session, fullpath: str):
return db.query(DownloadFiles).filter(DownloadFiles.fullpath == fullpath).order_by(
DownloadFiles.id.desc()).first()
def get_by_fullpath(db: Session, fullpath: str, all_files: bool = False):
if not all_files:
return db.query(DownloadFiles).filter(DownloadFiles.fullpath == fullpath).order_by(
DownloadFiles.id.desc()).first()
else:
return db.query(DownloadFiles).filter(DownloadFiles.fullpath == fullpath).order_by(
DownloadFiles.id.desc()).all()
@staticmethod
@db_query

View File

@ -56,6 +56,20 @@ class SystemConfigOper(DbOper, metaclass=Singleton):
return self.__SYSTEMCONF
return self.__SYSTEMCONF.get(key)
def delete(self, key: Union[str, SystemConfigKey]):
"""
删除系统设置
"""
if isinstance(key, SystemConfigKey):
key = key.value
# 更新内存
self.__SYSTEMCONF.pop(key, None)
# 写入数据库
conf = SystemConfig.get_by_key(self._db, key)
if conf:
conf.delete(self._db, conf.id)
return True
def __del__(self):
if self._db:
self._db.close()

View File

@ -16,6 +16,8 @@ class PluginHelper(metaclass=Singleton):
插件市场管理下载安装插件到本地
"""
_base_url = "https://raw.githubusercontent.com/%s/%s/main/"
@cached(cache=TTLCache(maxsize=10, ttl=1800))
def get_plugins(self, repo_url: str) -> Dict[str, dict]:
"""
@ -24,27 +26,47 @@ class PluginHelper(metaclass=Singleton):
"""
if not repo_url:
return {}
user, repo = self.get_repo_info(repo_url)
if not user or not repo:
return {}
raw_url = self._base_url % (user, repo)
res = RequestUtils(proxies=settings.PROXY, headers=settings.GITHUB_HEADERS,
timeout=10).get_res(f"{repo_url}package.json")
timeout=10).get_res(f"{raw_url}package.json")
if res:
return json.loads(res.text)
return {}
@staticmethod
def install(pid: str, repo_url: str) -> Tuple[bool, str]:
def get_repo_info(repo_url: str) -> Tuple[Optional[str], Optional[str]]:
"""
安装插件
获取Github仓库信息
:param repo_url: Github仓库地址
"""
# 从Github的repo_url获取用户和项目名
if not repo_url:
return None, None
if not repo_url.endswith("/"):
repo_url += "/"
if repo_url.count("/") < 6:
repo_url = f"{repo_url}main/"
try:
user, repo = repo_url.split("/")[-4:-2]
except Exception as e:
return False, f"不支持的插件仓库地址格式:{str(e)}"
if not user or not repo:
return False, "不支持的插件仓库地址格式"
print(str(e))
return None, None
return user, repo
def install(self, pid: str, repo_url: str) -> Tuple[bool, str]:
"""
安装插件
"""
if SystemUtils.is_frozen():
return False, "可执行文件模式下,只能安装本地插件"
# 从Github的repo_url获取用户和项目名
user, repo = self.get_repo_info(repo_url)
if not user or not repo:
return False, "不支持的插件仓库地址格式"
def __get_filelist(_p: str) -> Tuple[Optional[list], Optional[str]]:
"""
获取插件的文件列表

View File

@ -14,13 +14,17 @@ from app.db.systemconfig_oper import SystemConfigOper
from app.log import logger
from app.utils.http import RequestUtils
from app.schemas.types import MediaType, SystemConfigKey
from app.utils.singleton import Singleton
class TorrentHelper:
class TorrentHelper(metaclass=Singleton):
"""
种子帮助类
"""
# 失败的种子:站点链接
_invalid_torrents = []
def __init__(self):
self.system_config = SystemConfigOper()
@ -123,6 +127,8 @@ class TorrentHelper:
elif req.status_code == 429:
return None, None, "", [], "触发站点流控,请稍后重试"
else:
# 把错误的种子记下来,避免重复使用
self.add_invalid(url)
return None, None, "", [], f"下载种子出错,状态码:{req.status_code}"
@staticmethod
@ -276,3 +282,16 @@ class TorrentHelper:
continue
episodes = list(set(episodes).union(set(meta.episode_list)))
return episodes
def is_invalid(self, url: str) -> bool:
"""
判断种子是否是无效种子
"""
return url in self._invalid_torrents
def add_invalid(self, url: str):
"""
添加无效种子
"""
if url not in self._invalid_torrents:
self._invalid_torrents.append(url)

View File

@ -101,6 +101,9 @@ def start_tray():
if not SystemUtils.is_frozen():
return
if not SystemUtils.is_windows():
return
def open_web():
"""
调用浏览器打开前端页面

View File

@ -366,7 +366,7 @@ class Emby(metaclass=Singleton):
season_episodes[season_index] = []
season_episodes[season_index].append(episode_index)
# 返回
return tv_item.get("Id"), season_episodes
return item_id, season_episodes
except Exception as e:
logger.error(f"连接Shows/Id/Episodes出错" + str(e))
return None, None

View File

@ -332,7 +332,7 @@ class Jellyfin(metaclass=Singleton):
if not season_episodes.get(season_index):
season_episodes[season_index] = []
season_episodes[season_index].append(episode_index)
return tv_info.get('Id'), season_episodes
return item_id, season_episodes
except Exception as e:
logger.error(f"连接Shows/Id/Episodes出错" + str(e))
return None, None

View File

@ -14,8 +14,6 @@ class Plugin(BaseModel):
plugin_desc: Optional[str] = None
# 插件图标
plugin_icon: Optional[str] = None
# 主题色
plugin_color: Optional[str] = None
# 插件版本
plugin_version: Optional[str] = None
# 插件作者

View File

@ -16,16 +16,12 @@ class TorrentStatus(Enum):
class EventType(Enum):
# 插件重载
PluginReload = "plugin.reload"
# 插件动作
PluginAction = "plugin.action"
# 执行命令
CommandExcute = "command.excute"
# 站点签到
SiteSignin = "site.signin"
# 站点数据统计
SiteStatistic = "site.statistic"
# 站点删除
SiteDeleted = "site.deleted"
# 豆瓣想看
DoubanSync = "douban.sync"
# Webhook消息
WebhookMessage = "webhook.message"
# 转移完成
@ -44,14 +40,6 @@ class EventType(Enum):
NameRecognize = "name.recognize"
# 名称识别结果
NameRecognizeResult = "name.recognize.result"
# 目录监控同步
DirectorySync = "directory.sync"
# Cloudflare IP优选
CloudFlareSpeedTest = "cloudflare.speedtest"
# 站点自动登录更新Cookie、Ua
SiteLogin = "site.login"
# 网盘删除
NetworkDiskDel = "networkdisk.del"
# 系统配置Key字典

View File

@ -3,9 +3,9 @@
#######################################################################
####################################
# 基础设置 #
# 系统设置 #
####################################
# 【*】API监听地址
# 【*】API监听地址(注意不是前端访问地址)
HOST=0.0.0.0
# 是否调试模式,打开后将输出更多日志
DEBUG=false
@ -15,6 +15,94 @@ DEV=false
SUPERUSER=admin
# 【*】超级管理员初始密码,设置后一但重启将固化到数据库中,修改将无效
SUPERUSER_PASSWORD=password
# 大内存模式,开启后会增加缓存数量,但会占用更多内存
BIG_MEMORY_MODE=false
# 自动检查和更新站点资源包(索引、认证等)
AUTO_UPDATE_RESOURCE=true
####################################
# 消息通知渠道(按需配置) #
####################################
# WeChat企业ID
WECHAT_CORPID=
# WeChat应用Secret
WECHAT_APP_SECRET=
# WeChat应用ID
WECHAT_APP_ID=
# WeChat代理服务器无需代理需保留默认值
WECHAT_PROXY=https://qyapi.weixin.qq.com
# WeChat Token
WECHAT_TOKEN=
# WeChat EncodingAESKey
WECHAT_ENCODING_AESKEY=
# WeChat 管理员
WECHAT_ADMINS=
# Telegram Bot Token
TELEGRAM_TOKEN=
# Telegram Chat ID
TELEGRAM_CHAT_ID=
# Telegram 用户ID使用,分隔
TELEGRAM_USERS=
# Telegram 管理员ID使用,分隔
TELEGRAM_ADMINS=
# Slack Bot User OAuth Token
SLACK_OAUTH_TOKEN=
# Slack App-Level Token
SLACK_APP_TOKEN=
# Slack 频道名称
SLACK_CHANNEL=
# SynologyChat Webhook
SYNOLOGYCHAT_WEBHOOK=
# SynologyChat Token
SYNOLOGYCHAT_TOKEN=
####################################
# 下载器(按需配置) #
####################################
# Qbittorrent地址IP:PORT
QB_HOST=
# Qbittorrent用户名
QB_USER=
# Qbittorrent密码
QB_PASSWORD=
# Qbittorrent分类自动管理
QB_CATEGORY=false
# Qbittorrent按顺序下载
QB_SEQUENTIAL=true
# Qbittorrent忽略队列限制强制继续
QB_FORCE_RESUME=true
# Transmission地址IP:PORT
TR_HOST=
# Transmission用户名
TR_USER=
# Transmission密码
TR_PASSWORD=
####################################
# 媒体服务器(按需配置) #
####################################
# EMBY服务器地址IP:PORT
EMBY_HOST=
# EMBY Api Key
EMBY_API_KEY=
# Jellyfin服务器地址IP:PORT
JELLYFIN_HOST=
# Jellyfin Api Key
JELLYFIN_API_KEY=
# Plex服务器地址IP:PORT
PLEX_HOST=
# Plex Token
PLEX_TOKEN=
####################################
# 基础设置 #
####################################
# 【*】API密钥建议更换复杂字符串有Jellyseerr/Overseerr、媒体服务器Webhook等配置以及部分支持API_TOKEN的API中使用
API_TOKEN=moviepilot
# 登录页面电影海报tmdb/bingtmdb要求能正常连接api.themoviedb.org
@ -25,10 +113,21 @@ TMDB_IMAGE_DOMAIN=image.tmdb.org
TMDB_API_DOMAIN=api.themoviedb.org
# 媒体识别来源 themoviedb/douban使用themoviedb时需要确保能正常连接api.themoviedb.org使用douban时不支持二级分类
RECOGNIZE_SOURCE=themoviedb
# 大内存模式,开启后会增加缓存数量,但会占用更多内存
BIG_MEMORY_MODE=false
# 自动检查和更新站点资源包(索引、认证等)
AUTO_UPDATE_RESOURCE=true
# 【*】消息通知渠道 telegram/wechat/slack多个通知渠道用,分隔,需要在上面配置对应消息通知渠道的参数
MESSAGER=telegram
# 【*】下载器 qbittorrent/transmission仅支持单个下载器做为主下载器使用需要在上面配置对应消下载器的参数
DOWNLOADER=qbittorrent
# 下载器监控开关
DOWNLOADER_MONITOR=true
# 【*】媒体服务器 emby/jellyfin/plex多个媒体服务器,分割
MEDIASERVER=emby
# 媒体服务器同步间隔(小时)
MEDIASERVER_SYNC_INTERVAL=6
# 媒体服务器同步黑名单,多个媒体库名称,分割
MEDIASERVER_SYNC_BLACKLIST=
####################################
# 媒体识别&刮削 #
@ -41,22 +140,24 @@ SCRAP_FOLLOW_TMDB=true
SCRAP_SOURCE=themoviedb
####################################
# 媒体库 #
# 文件整理 & 媒体库 #
####################################
# 【*】转移方式 link/copy/move/softlink/rclone_copy/rclone_move
TRANSFER_TYPE=copy
# 转移覆盖模式,`nerver`/`size`/`always`/`latest`,分别表示`不覆盖同名文件`/`同名文件根据文件大小覆盖(大覆盖小)`/`总是覆盖同名文件`/`仅保留最新版本,删除旧版本文件(包括非同名文件)`
OVERWRITE_MODE=size
# 【*】媒体库目录,多个目录使用,分隔
LIBRARY_PATH=
LIBRARY_PATH=/media
# 电影媒体库目录名,默认电影
LIBRARY_MOVIE_NAME=
LIBRARY_MOVIE_NAME=电影
# 电视剧媒体库目录名,默认电视剧
LIBRARY_TV_NAME=
LIBRARY_TV_NAME=电视剧
# 动漫媒体库目录名,默认电视剧/动漫
LIBRARY_ANIME_NAME=
LIBRARY_ANIME_NAME=电视剧/动漫
# 二级分类,开启后会根据配置 [category.yaml](https://github.com/jxxghp/MoviePilot/raw/main/config/category.yaml) 自动在媒体库目录下建立二级目录分类
LIBRARY_CATEGORY=true
# 电影重命名格式Jinja2语法参考https://jinja.palletsprojects.com/en/3.0.x/templates/
MOVIE_RENAME_FORMAT={{title}}{% if year %} ({{year}}){% endif %}/{{title}}{% if year %} ({{year}}){% endif %}{% if part %}-{{part}}{% endif %}{% if videoFormat %} - {{videoFormat}}{% endif %}{{fileExt}}
# 电视剧重命名格式Jinja2语法参考https://jinja.palletsprojects.com/en/3.0.x/templates/
@ -88,71 +189,9 @@ SUBSCRIBE_SEARCH=false
# 交互搜索自动下载用户ID消息通知渠道的用户ID使用,分割,未设置需要用户手动选择资源或者回复`0`
AUTO_DOWNLOAD_USER=
####################################
# 消息通知 #
####################################
# 【*】消息通知渠道 telegram/wechat/slack多个通知渠道用,分隔
MESSAGER=telegram
# WeChat企业ID
WECHAT_CORPID=
# WeChat应用Secret
WECHAT_APP_SECRET=
# WeChat应用ID
WECHAT_APP_ID=
# WeChat代理服务器无需代理需保留默认值
WECHAT_PROXY=https://qyapi.weixin.qq.com
# WeChat Token
WECHAT_TOKEN=
# WeChat EncodingAESKey
WECHAT_ENCODING_AESKEY=
# WeChat 管理员
WECHAT_ADMINS=
# Telegram Bot Token
TELEGRAM_TOKEN=
# Telegram Chat ID
TELEGRAM_CHAT_ID=
# Telegram 用户ID使用,分隔
TELEGRAM_USERS=
# Telegram 管理员ID使用,分隔
TELEGRAM_ADMINS=
# Slack Bot User OAuth Token
SLACK_OAUTH_TOKEN=
# Slack App-Level Token
SLACK_APP_TOKEN=
# Slack 频道名称
SLACK_CHANNEL=
# SynologyChat Webhook
SYNOLOGYCHAT_WEBHOOK=
# SynologyChat Token
SYNOLOGYCHAT_TOKEN=
####################################
# 下载 #
####################################
# 【*】下载器 qbittorrent/transmission仅支持单个下载器做为主下载器使用非主下载器只要配置了参数仍可在插件等使用
DOWNLOADER=qbittorrent
# 下载器监控开关
DOWNLOADER_MONITOR=true
# Qbittorrent地址IP:PORT
QB_HOST=
# Qbittorrent用户名
QB_USER=
# Qbittorrent密码
QB_PASSWORD=
# Qbittorrent分类自动管理
QB_CATEGORY=false
# Qbittorrent按顺序下载
QB_SEQUENTIAL=true
# Qbittorrent忽略队列限制强制继续
QB_FORCE_RESUME=false
# Transmission地址IP:PORT
TR_HOST=
# Transmission用户名
TR_USER=
# Transmission密码
TR_PASSWORD=
# 种子标签
TORRENT_TAG=MOVIEPILOT
# 【*】下载保存目录,容器内映射路径需要一致,支持不同类型设置不同的下载目录(跨盘)
DOWNLOAD_PATH=/downloads
# 电影下载保存目录(路径),容器内映射路径需要一致
@ -161,38 +200,19 @@ DOWNLOAD_MOVIE_PATH=
DOWNLOAD_TV_PATH=
# 动漫下载保存目录(路径),容器内映射路径需要一致
DOWNLOAD_ANIME_PATH=
# 下载目录二级分类,开启后会根据配置 [category.yaml](https://github.com/jxxghp/MoviePilot/raw/main/config/category.yaml) 自动在下载目录下建立二级目录分类
DOWNLOAD_CATEGORY=false
# 下载站点字幕
# 种子标签
TORRENT_TAG=MOVIEPILOT
# 自动下载站点字幕(如有)
DOWNLOAD_SUBTITLE=true
####################################
# 媒体服务器 #
####################################
# 【*】媒体服务器 emby/jellyfin/plex多个媒体服务器,分割
MEDIASERVER=emby
# 媒体服务器同步间隔(小时)
MEDIASERVER_SYNC_INTERVAL=6
# 媒体服务器同步黑名单,多个媒体库名称,分割
MEDIASERVER_SYNC_BLACKLIST=
# EMBY服务器地址IP:PORT
EMBY_HOST=
# EMBY Api Key
EMBY_API_KEY=
# Jellyfin服务器地址IP:PORT
JELLYFIN_HOST=
# Jellyfin Api Key
JELLYFIN_API_KEY=
# Plex服务器地址IP:PORT
PLEX_HOST=
# Plex Token
PLEX_TOKEN=
####################################
# 第三方服务 #
# 扩展 #
####################################
# OCR服务器地址
OCR_HOST=https://movie-pilot.org
# 插件市场仓库地址,多个地址使用`,`分隔,保留最后的/
PLUGIN_MARKET=https://raw.githubusercontent.com/jxxghp/MoviePilot-Plugins/main/
PLUGIN_MARKET=https://github.com/jxxghp/MoviePilot-Plugins

View File

@ -1 +1 @@
APP_VERSION = 'v1.4.4'
APP_VERSION = 'v1.4.7'