Compare commits

..

No commits in common. "cdbd2882f3660c496aa902f7630b0e05997542b5" and "becaef7f19839a0b16f8f68d34aebd8aff4cb0e3" have entirely different histories.

4 changed files with 102 additions and 153 deletions

View File

@ -179,18 +179,12 @@ def run_script_now():
) )
def generate_output(): def generate_output():
# 设置环境变量
process_env = os.environ.copy()
process_env["PYTHONIOENCODING"] = "utf-8"
process = subprocess.Popen( process = subprocess.Popen(
command, command,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, stderr=subprocess.STDOUT,
universal_newlines=True, universal_newlines=True,
encoding="utf-8",
errors="replace",
bufsize=1, bufsize=1,
env=process_env,
) )
try: try:
for line in iter(process.stdout.readline, ""): for line in iter(process.stdout.readline, ""):

View File

@ -82,24 +82,19 @@
<div class="row title"> <div class="row title">
<div class="col"> <div class="col">
<h2>媒体库</h2> <h2>Emby</h2>
</div> </div>
</div> </div>
<div v-for="(server, serverName) in formData.media_servers" :key="serverName" class="task mb-3"> <div class="form-group row">
<div class="form-group row" style="display:flex; align-items:center"> <label class="col-sm-2 col-form-label">Emby URL</label>
<div class="col-9" data-toggle="collapse" :data-target="'#collapse_'+serverName" aria-expanded="true" :aria-controls="'collapse_'+serverName"> <div class="col-sm-10">
<div class="btn btn-block text-left"> <input type="text" v-model="formData.emby.url" class="form-control" placeholder="可选">
<i class="bi bi-caret-right-fill"></i> <span v-html="`${serverName}`"></span>
</div>
</div>
</div> </div>
<div class="collapse" :id="'collapse_'+serverName" style="padding-left:2em"> </div>
<div v-for="(value, key) in server" :key="key" class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label">{{ key }}</label> <label class="col-sm-2 col-form-label">Emby API Key</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="text" v-model="formData.media_servers[serverName][key]" class="form-control" :placeholder="key === 'url' ? 'URL' : 'API Key/Token'"> <input type="text" v-model="formData.emby.apikey" class="form-control" placeholder="可选">
</div>
</div>
</div> </div>
</div> </div>
@ -261,9 +256,9 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label">媒体库ID</label> <label class="col-sm-2 col-form-label">Emby ID</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="number" name="media_id[]" class="form-control" v-model="task.media_id" placeholder="可选"> <input type="number" name="emby_id[]" class="form-control" v-model="task.emby_id" placeholder="可选">
</div> </div>
</div> </div>
</div> </div>
@ -370,7 +365,10 @@
formData: { formData: {
cookie: [], cookie: [],
push_config: {}, push_config: {},
media_servers: {}, emby: {
url: "",
apikey: ""
},
tasklist: [], tasklist: [],
magic_regex: {} magic_regex: {}
}, },
@ -381,7 +379,7 @@
pattern: "", pattern: "",
replace: "", replace: "",
enddate: "", enddate: "",
media_id: "", emby_id: "",
ignore_extension: false, ignore_extension: false,
runweek: [1, 2, 3, 4, 5, 6, 7] runweek: [1, 2, 3, 4, 5, 6, 7]
}, },

View File

@ -1,83 +0,0 @@
import requests
class Emby:
default_config = {"url": "", "apikey": ""}
def __init__(self, **kwargs):
self.is_active = False
if kwargs:
for key, value in self.default_config.items():
if key in kwargs:
setattr(self, key, kwargs[key])
else:
print(f"{self.__class__.__name__} 模块缺少必要参数: {key}")
if self.url and self.apikey:
if self.get_info():
self.is_active = True
def get_info(self):
url = f"{self.url}/emby/System/Info"
headers = {"X-Emby-Token": self.apikey}
querystring = {}
response = requests.request("GET", url, headers=headers, params=querystring)
if "application/json" in response.headers["Content-Type"]:
response = response.json()
print(
f"Emby媒体库: {response.get('ServerName','')} v{response.get('Version','')}"
)
return True
else:
print(f"Emby媒体库: 连接失败❌ {response.text}")
return False
def refresh(self, emby_id):
if emby_id:
url = f"{self.url}/emby/Items/{emby_id}/Refresh"
headers = {"X-Emby-Token": self.apikey}
querystring = {
"Recursive": "true",
"MetadataRefreshMode": "FullRefresh",
"ImageRefreshMode": "FullRefresh",
"ReplaceAllMetadata": "false",
"ReplaceAllImages": "false",
}
response = requests.request(
"POST", url, headers=headers, params=querystring
)
if response.text == "":
print(f"🎞 刷新Emby媒体库成功✅")
return True
else:
print(f"🎞 刷新Emby媒体库{response.text}")
return False
def search(self, media_name):
if media_name:
url = f"{self.url}/emby/Items"
headers = {"X-Emby-Token": self.apikey}
querystring = {
"IncludeItemTypes": "Series",
"StartIndex": 0,
"SortBy": "SortName",
"SortOrder": "Ascending",
"ImageTypeLimit": 0,
"Recursive": "true",
"SearchTerm": media_name,
"Limit": 10,
"IncludeSearchTypes": "false",
}
response = requests.request("GET", url, headers=headers, params=querystring)
if "application/json" in response.headers["Content-Type"]:
response = response.json()
if response.get("Items"):
for item in response["Items"]:
if item["IsFolder"]:
print(
f"🎞 《{item['Name']}》匹配到Emby媒体库ID{item['Id']}"
)
return item["Id"]
else:
print(f"🎞 搜索Emby媒体库{response.text}")
return False

View File

@ -1,6 +1,6 @@
# !/usr/bin/env python3 # !/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Modify: 2024-11-13 # Modify: 2024-04-03
# Repo: https://github.com/Cp0204/quark_auto_save # Repo: https://github.com/Cp0204/quark_auto_save
# ConfigFile: quark_config.json # ConfigFile: quark_config.json
""" """
@ -14,7 +14,6 @@ import json
import time import time
import random import random
import requests import requests
import importlib
from datetime import datetime from datetime import datetime
# 兼容青龙 # 兼容青龙
@ -687,24 +686,79 @@ class Quark:
return is_rename_count > 0 return is_rename_count > 0
def load_media_servers(media_servers_config, media_servers_dir="media_servers"): class Emby:
media_servers = {} def __init__(self, emby_url, emby_apikey):
available_modules = [ self.is_active = False
f.replace(".py", "") for f in os.listdir(media_servers_dir) if f.endswith(".py") if emby_url and emby_apikey:
] self.emby_url = emby_url
for module_name in available_modules: self.emby_apikey = emby_apikey
try: if self.get_info():
module = importlib.import_module(f"{media_servers_dir}.{module_name}") self.is_active = True
ServerClass = getattr(module, module_name.capitalize())
# 检查配置中是否存在该模块的配置 def get_info(self):
if module_name in media_servers_config: url = f"{self.emby_url}/emby/System/Info"
server_config = media_servers_config[module_name] headers = {"X-Emby-Token": self.emby_apikey}
media_servers[module_name] = ServerClass(**server_config) querystring = {}
response = requests.request("GET", url, headers=headers, params=querystring)
if "application/json" in response.headers["Content-Type"]:
response = response.json()
print(
f"Emby媒体库: {response.get('ServerName','')} v{response.get('Version','')}"
)
return True
else:
print(f"Emby媒体库: 连接失败❌ {response.text}")
return False
def refresh(self, emby_id):
if emby_id:
url = f"{self.emby_url}/emby/Items/{emby_id}/Refresh"
headers = {"X-Emby-Token": self.emby_apikey}
querystring = {
"Recursive": "true",
"MetadataRefreshMode": "FullRefresh",
"ImageRefreshMode": "FullRefresh",
"ReplaceAllMetadata": "false",
"ReplaceAllImages": "false",
}
response = requests.request(
"POST", url, headers=headers, params=querystring
)
if response.text == "":
print(f"🎞 刷新Emby媒体库成功✅")
return True
else: else:
media_servers_config[module_name] = ServerClass().default_config print(f"🎞 刷新Emby媒体库{response.text}")
except (ImportError, AttributeError): return False
print(f"加载模块 {module_name} 失败")
return media_servers def search(self, media_name):
if media_name:
url = f"{self.emby_url}/emby/Items"
headers = {"X-Emby-Token": self.emby_apikey}
querystring = {
"IncludeItemTypes": "Series",
"StartIndex": 0,
"SortBy": "SortName",
"SortOrder": "Ascending",
"ImageTypeLimit": 0,
"Recursive": "true",
"SearchTerm": media_name,
"Limit": 10,
"IncludeSearchTypes": "false",
}
response = requests.request("GET", url, headers=headers, params=querystring)
if "application/json" in response.headers["Content-Type"]:
response = response.json()
if response.get("Items"):
for item in response["Items"]:
if item["IsFolder"]:
print(
f"🎞 《{item['Name']}》匹配到Emby媒体库ID{item['Id']}"
)
return item["Id"]
else:
print(f"🎞 搜索Emby媒体库{response.text}")
return False
def verify_account(account): def verify_account(account):
@ -764,7 +818,10 @@ def do_sign(account):
def do_save(account, tasklist=[]): def do_save(account, tasklist=[]):
media_servers = load_media_servers(CONFIG_DATA.get("media_servers", {})) emby = Emby(
CONFIG_DATA.get("emby", {}).get("url", ""),
CONFIG_DATA.get("emby", {}).get("apikey", ""),
)
print(f"转存账号: {account.nickname}") print(f"转存账号: {account.nickname}")
# 获取全部保存目录fid # 获取全部保存目录fid
account.update_savepath_fid(tasklist) account.update_savepath_fid(tasklist)
@ -805,33 +862,17 @@ def do_save(account, tasklist=[]):
is_new = account.do_save_task(task) is_new = account.do_save_task(task)
is_rename = account.do_rename_task(task) is_rename = account.do_rename_task(task)
# 刷新媒体库 # 刷新媒体库
for server_name, media_server in media_servers.items(): if emby.is_active and (is_new or is_rename) and task.get("emby_id") != "0":
if ( if task.get("emby_id"):
media_server.is_active emby.refresh(task["emby_id"])
and (is_new or is_rename) else:
and task.get("media_id") != "0" match_emby_id = emby.search(task["taskname"])
): if match_emby_id:
if task.get("media_id"): task["emby_id"] = match_emby_id
media_server.refresh(task["media_id"]) emby.refresh(match_emby_id)
else:
match_media_id = media_server.search(task["taskname"])
if match_media_id:
task["media_id"] = match_media_id
media_server.refresh(match_media_id)
print() print()
def reaking_change_update():
global CONFIG_DATA
# print("Update config v0.3.6.1 to 0.3.7")
if CONFIG_DATA.get("emby"):
CONFIG_DATA.setdefault("media_servers", {})["emby"] = CONFIG_DATA["emby"]
del CONFIG_DATA["emby"]
for task in CONFIG_DATA.get("tasklist", {}):
task["media_id"] = task.get("emby_id", "")
del task["emby_id"]
def main(): def main():
global CONFIG_DATA global CONFIG_DATA
start_time = datetime.now() start_time = datetime.now()
@ -859,7 +900,6 @@ def main():
print(f"⚙️ 正从 {config_path} 文件中读取配置") print(f"⚙️ 正从 {config_path} 文件中读取配置")
with open(config_path, "r", encoding="utf-8") as file: with open(config_path, "r", encoding="utf-8") as file:
CONFIG_DATA = json.load(file) CONFIG_DATA = json.load(file)
reaking_change_update()
cookie_val = CONFIG_DATA.get("cookie") cookie_val = CONFIG_DATA.get("cookie")
if not CONFIG_DATA.get("magic_regex"): if not CONFIG_DATA.get("magic_regex"):
CONFIG_DATA["magic_regex"] = MAGIC_REGEX CONFIG_DATA["magic_regex"] = MAGIC_REGEX