媒体库模块 改称为 插件

- 媒体库模块改称为插件,更好地反映功能
- 更新相关文档和代码中的所有引用
- 修改变量名以反映插件的概念
- 确保代码一致性和可读性
This commit is contained in:
Cp0204 2024-11-25 00:08:18 +08:00
parent 9c5ade608e
commit c3c4ad6c00
9 changed files with 54 additions and 55 deletions

View File

@ -82,25 +82,25 @@
<div class="row title">
<div class="col">
<h2 style="display: inline-block;">媒体库</h2>
<h2 style="display: inline-block;">插件</h2>
<span class="badge badge-pill badge-light">
<a href="https://github.com/Cp0204/quark-auto-save/wiki/媒体库模块配置" target="_blank" title="媒体库模块配置">?</a>
</span>
</div>
</div>
<div v-for="(server, serverName) in formData.media_servers" :key="serverName" class="task mb-3">
<div v-for="(plugin, pluginName) in formData.plugins" :key="pluginName" class="task mb-3">
<div class="form-group row" style="display:flex; align-items:center">
<div class="col-9" data-toggle="collapse" :data-target="'#collapse_'+serverName" aria-expanded="true" :aria-controls="'collapse_'+serverName">
<div class="col-9" data-toggle="collapse" :data-target="'#collapse_'+pluginName" aria-expanded="true" :aria-controls="'collapse_'+pluginName">
<div class="btn btn-block text-left">
<i class="bi bi-caret-right-fill"></i> <span v-html="`${serverName}`"></span>
<i class="bi bi-caret-right-fill"></i> <span v-html="`${pluginName}`"></span>
</div>
</div>
</div>
<div class="collapse" :id="'collapse_'+serverName" style="padding-left:2em">
<div v-for="(value, key) in server" :key="key" class="form-group row">
<div class="collapse" :id="'collapse_'+pluginName" style="padding-left:2em">
<div v-for="(value, key) in plugin" :key="key" class="form-group row">
<label class="col-sm-2 col-form-label">{{ key }}</label>
<div class="col-sm-10">
<input type="text" v-model="formData.media_servers[serverName][key]" class="form-control">
<input type="text" v-model="formData.plugins[pluginName][key]" class="form-control">
</div>
</div>
</div>
@ -267,7 +267,7 @@
<label class="col-sm-2 col-form-label">插件配置</label>
<div class="col-sm-10">
<!-- <input type="text" name="addition[]" class="form-control" v-model="task.addition" placeholder="可选"> -->
<v-jsoneditor v-model="task.addition" :options="{mode:'tree'}" :plus="false" height="150px"></v-jsoneditor>
<v-jsoneditor v-model="task.addition" :options="{mode:'tree'}" :plus="false" height="200px"></v-jsoneditor>
</div>
</div>
</div>

View File

@ -1,21 +1,21 @@
# 媒体库模块开发指南
# 插件开发指南
本指南介绍如何开发自定义媒体库模块,你可以通过添加新的媒体库模块来扩展项目功能。
本指南介绍如何开发自定义插件,你可以通过添加新的插件来扩展项目功能。
## 基本结构
* 模块位于 `media_servers` 目录下.
* 每个模块是一个 `.py` 文件 (例如 `emby.py`, `plex.py`),文件名小写。
* 每个模块文件包含一个与文件名对应的首字母大写命名类(例如 `emby.py` 中的 `Emby` 类)。
* 插件位于 `media_servers` 目录下.
* 每个插件是一个 `.py` 文件 (例如 `emby.py`, `plex.py`),文件名小写。
* 每个插件文件包含一个与文件名对应的首字母大写命名类(例如 `emby.py` 中的 `Emby` 类)。
## 模块要求
## 插件要求
每个模块类必须包含以下内容:
每个插件类必须包含以下内容:
* **`default_config`**:字典,包含模块所需参数及其默认值。例如:
* **`default_config`**:字典,包含插件所需参数及其默认值。例如:
```python
# 该模块必须配置的键,值可留空
# 该插件必须配置的键,值可留空
default_config = {"url": "", "token": ""}
```
@ -25,11 +25,11 @@
1. 检查 `kwargs` 是否包含所有 `default_config` 中的参数,缺少参数则打印警告。
2. 若参数完整,尝试连接服务器并验证配置,成功则设置 `self.is_active = True`
* **`run(self, task)`**:整个模块入口函数,处理模块逻辑。
* **`run(self, task, **kwargs)`**:整个插件入口函数,处理插件逻辑。
* `task` 是一个字典,包含任务信息。如果需要修改任务参数,返回修改后的 `task` 字典;
* 无修改则不返回或返回 `None`
## 模块示例
## 插件示例
参考 [emby.py](emby.py)
@ -43,7 +43,7 @@
### 最佳实践
requests 部分使用 try-except 块,以防模块请求出错中断整个转存任务。
requests 部分使用 try-except 块,以防插件请求出错中断整个转存任务。
```python
try:
@ -56,7 +56,7 @@ except requests.exceptions.RequestException as e:
return False
```
## 使用自定义模块
## 使用自定义插件
放到 `/media_servers` 目录即可识别,如果你使用 docker 运行:
@ -67,11 +67,11 @@ docker run -d \
# ...
```
如果你有写自定义模块的能力,相信你也知道如何挂载自定义模块,算我啰嗦。🙃
如果你有写自定义插件的能力,相信你也知道如何挂载自定义插件,算我啰嗦。🙃
## 配置文件
`quark_config.json``media_servers` 中配置模块参数:
`quark_config.json``media_servers` 中配置插件参数:
```json
{
@ -84,10 +84,11 @@ docker run -d \
}
```
模块代码正确赋值 `default_config` 时,首次运行会自动补充缺失的键。
插件代码正确赋值 `default_config` 时,首次运行会自动补充缺失的键。
## 🤝 贡献者
| 模块 | 说明 | 贡献者 |
| 插件 | 说明 | 贡献者 |
| ------- | -------------------- | --------------------------------------- |
| plex.py | 自动刷新 Plex 媒体库 | [zhazhayu](https://github.com/zhazhayu) |
| plex.py | 自动刷新 Plex 媒体库 | [zhazhayu](https://github.com/zhazhayu) |
| alist_strm_gen.py | 自动生成strm | [xiaoQQya](https://github.com/xiaoQQya) |

View File

@ -40,7 +40,7 @@ class Alist_strm_gen:
if key in kwargs:
setattr(self, key, kwargs[key])
else:
print(f"{self.__class__.__name__} 模块缺少必要参数: {key}")
print(f"{self.plugin_name} 模块缺少必要参数: {key}")
if self.url and self.token and self.storage_id:
success, result = self.storage_id_to_path(self.storage_id)
if success:

View File

@ -16,11 +16,11 @@ class Emby:
def __init__(self, **kwargs):
self.plugin_name = self.__class__.__name__.lower()
if kwargs:
for key, value in self.default_config.items():
for key, _ in self.default_config.items():
if key in kwargs:
setattr(self, key, kwargs[key])
else:
print(f"{self.__class__.__name__} 模块缺少必要参数: {key}")
print(f"{self.plugin_name} 模块缺少必要参数: {key}")
if self.url and self.token:
if self.get_info():
self.is_active = True

View File

@ -714,13 +714,13 @@ class Quark:
return is_rename_count > 0
def load_media_servers(media_servers_config, media_servers_dir="media_servers"):
media_servers = {}
def load_plugins(plugins_config, plugins_dir="plugins"):
plugins = {}
all_modules = [
f.replace(".py", "") for f in os.listdir(media_servers_dir) if f.endswith(".py")
f.replace(".py", "") for f in os.listdir(plugins_dir) if f.endswith(".py")
]
# 调整模块优先级
priority_path = os.path.join(media_servers_dir, "_priority.json")
priority_path = os.path.join(plugins_dir, "_priority.json")
try:
with open(priority_path, encoding="utf-8") as f:
priority_modules = json.load(f)
@ -730,21 +730,21 @@ def load_media_servers(media_servers_config, media_servers_dir="media_servers"):
] + [module for module in all_modules if module not in priority_modules]
except (FileNotFoundError, json.JSONDecodeError):
priority_modules = []
print(f"🧩 载入媒体库模块")
print(f"🧩 载入插件")
for module_name in all_modules:
try:
module = importlib.import_module(f"{media_servers_dir}.{module_name}")
module = importlib.import_module(f"{plugins_dir}.{module_name}")
ServerClass = getattr(module, module_name.capitalize())
# 检查配置中是否存在该模块的配置
if module_name in media_servers_config:
server_config = media_servers_config[module_name]
media_servers[module_name] = ServerClass(**server_config)
if module_name in plugins_config:
server_config = plugins_config[module_name]
plugins[module_name] = ServerClass(**server_config)
else:
media_servers_config[module_name] = ServerClass().default_config
plugins_config[module_name] = ServerClass().default_config
except (ImportError, AttributeError) as e:
print(f"载入模块 {module_name} 失败: {e}")
print()
return media_servers
return plugins
def verify_account(account):
@ -804,7 +804,7 @@ def do_sign(account):
def do_save(account, tasklist=[]):
media_servers = load_media_servers(CONFIG_DATA.get("media_servers", {}))
plugins = load_plugins(CONFIG_DATA.get("plugins", {}))
print(f"转存账号: {account.nickname}")
# 获取全部保存目录fid
account.update_savepath_fid(tasklist)
@ -835,30 +835,28 @@ def do_save(account, tasklist=[]):
print(f"正则替换: {task['replace']}")
if task.get("enddate"):
print(f"任务截止: {task['enddate']}")
if task.get("media_id"):
print(f"刷媒体库: {task['media_id']}")
if task.get("ignore_extension"):
print(f"忽略后缀: {task['ignore_extension']}")
if task.get("update_subdir"):
print(f"更子目录: {task['update_subdir']}")
print()
is_new = account.do_save_task(task)
is_new_tree = account.do_save_task(task)
is_rename = account.do_rename_task(task)
# 调用媒体库模块
print(f"🧩 调用媒体库模块")
for server_name, media_server in media_servers.items():
if hasattr(media_server, "default_task_config") and not task.get(
# 调用插件
print(f"🧩 调用插件")
for plugin_name, plugin in plugins.items():
if hasattr(plugin, "default_task_config") and not task.get(
"addition", {}
).get(server_name):
).get(plugin_name):
task.setdefault("addition", {})[
server_name
] = media_server.default_task_config
if media_server.is_active and (is_new or is_rename):
task = media_server.run(task, account=account, tree=is_new) or task
plugin_name
] = plugin.default_task_config
if plugin.is_active and (is_new_tree or is_rename):
task = plugin.run(task, account=account, tree=is_new_tree) or task
print()
def reaking_change_update():
def breaking_change_update():
global CONFIG_DATA
# print("Update config v0.3.6.1 to 0.3.7")
if CONFIG_DATA.get("emby"):
@ -900,7 +898,7 @@ def main():
print(f"⚙️ 正从 {config_path} 文件中读取配置")
with open(config_path, "r", encoding="utf-8") as file:
CONFIG_DATA = json.load(file)
reaking_change_update()
breaking_change_update()
cookie_val = CONFIG_DATA.get("cookie")
if not CONFIG_DATA.get("magic_regex"):
CONFIG_DATA["magic_regex"] = MAGIC_REGEX