diff --git a/xiaomusic/config.py b/xiaomusic/config.py
index 0b4374c..bcda511 100644
--- a/xiaomusic/config.py
+++ b/xiaomusic/config.py
@@ -4,6 +4,7 @@ import argparse
import json
import os
from dataclasses import dataclass
+from typing import get_type_hints
from xiaomusic.utils import validate_proxy
@@ -58,7 +59,7 @@ class Config:
port: int = int(os.getenv("XIAOMUSIC_PORT", "8090"))
proxy: str | None = os.getenv("XIAOMUSIC_PROXY", None)
search_prefix: str = os.getenv(
- "XIAOMUSIC_SEARCH", "ytsearch:"
+ "XIAOMUSIC_SEARCH", "bilisearch:"
) # "bilisearch:" or "ytsearch:"
ffmpeg_location: str = os.getenv("XIAOMUSIC_FFMPEG_LOCATION", "./ffmpeg/bin")
active_cmd: str = os.getenv(
@@ -137,3 +138,34 @@ class Config:
if value is not None and key in cls.__dataclass_fields__:
result[key] = value
return result
+
+ def update_config(self, data):
+ # 获取类型提示
+ type_hints = get_type_hints(self)
+
+ for k, v in data.items():
+ if v and k in type_hints:
+ # 获取字段的类型
+ expected_type = type_hints[k]
+
+ # 根据期望的类型进行转换
+ if isinstance(v, expected_type):
+ # 如果v已经是正确的类型,则直接赋值
+ setattr(self, k, v)
+ else:
+ # 尝试转换类型
+ try:
+ # 特殊情况处理(例如对布尔值的转换)
+ if expected_type is bool:
+ converted_value = False
+ if v and v.lower() == "true":
+ converted_value = True
+ else:
+ # 使用期望类型的构造函数进行转换
+ converted_value = expected_type(v)
+ except (ValueError, TypeError) as e:
+ print(f"Error converting {v} to {expected_type}: {e}")
+ continue
+
+ # 设置转换后的值
+ setattr(self, k, converted_value)
diff --git a/xiaomusic/httpserver.py b/xiaomusic/httpserver.py
index 9dbc24d..3503f9f 100644
--- a/xiaomusic/httpserver.py
+++ b/xiaomusic/httpserver.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
import os
+from dataclasses import asdict
from threading import Thread
from flask import Flask, request, send_file, send_from_directory
@@ -10,6 +11,7 @@ from xiaomusic import (
__version__,
)
from xiaomusic.utils import (
+ deepcopy_data_no_sensitive_info,
downloadfile,
)
@@ -98,19 +100,11 @@ async def do_cmd():
@auth.login_required
async def getsetting():
config = xiaomusic.getconfig()
-
+ data = asdict(config)
alldevices = await xiaomusic.call_main_thread_function(xiaomusic.getalldevices)
- log.info(alldevices)
- data = {
- "mi_did": config.mi_did,
- "mi_did_list": alldevices["did_list"],
- "mi_hardware": config.hardware,
- "mi_hardware_list": alldevices["hardware_list"],
- "xiaomusic_search": config.search_prefix,
- "xiaomusic_proxy": config.proxy,
- "xiaomusic_music_list_url": config.music_list_url,
- "xiaomusic_music_list_json": config.music_list_json,
- }
+ log.info(f"getsetting alldevices: {alldevices}")
+ data["mi_did_list"] = alldevices["did_list"]
+ data["mi_hardware_list"] = alldevices["hardware_list"]
return data
@@ -118,7 +112,8 @@ async def getsetting():
@auth.login_required
async def savesetting():
data = request.get_json()
- log.info(data)
+ debug_data = deepcopy_data_no_sensitive_info(data)
+ log.info(f"saveconfig: {debug_data}")
await xiaomusic.saveconfig(data)
return "save success"
diff --git a/xiaomusic/static/setting.html b/xiaomusic/static/setting.html
index a77ec8e..e07676a 100644
--- a/xiaomusic/static/setting.html
+++ b/xiaomusic/static/setting.html
@@ -14,22 +14,103 @@
)
-
+
+
+
+
+
+
+
+
-
-
-
-
diff --git a/xiaomusic/static/setting.js b/xiaomusic/static/setting.js
index 14d4f8b..e0e5692 100644
--- a/xiaomusic/static/setting.js
+++ b/xiaomusic/static/setting.js
@@ -5,6 +5,17 @@ $(function(){
$("#version").text(`${data.version}`);
});
+ // 遍历所有的select元素,默认选中只有1个选项的
+ const autoSelectOne = () => {
+ $('select').each(function() {
+ // 如果select元素仅有一个option子元素
+ if ($(this).children('option').length === 1) {
+ // 选中这个option
+ $(this).find('option').prop('selected', true);
+ }
+ });
+ };
+
const updateSelectOptions = (selectId, optionsList, selectedOption) => {
const select = $(selectId);
select.empty();
@@ -42,51 +53,37 @@ $(function(){
// 拉取现有配置
$.get("/getsetting", function(data, status) {
console.log(data, status);
-
updateSelectOptions("#mi_did", data.mi_did_list, data.mi_did);
- updateSelectOptions("#mi_hardware", data.mi_hardware_list, data.mi_hardware);
+ updateSelectOptions("#hardware", data.mi_hardware_list, data.hardware);
// 初始化联动
- linkSelects('#mi_did', data.mi_did_list, '#mi_hardware', data.mi_hardware_list);
+ linkSelects('#mi_did', data.mi_did_list, '#hardware', data.mi_hardware_list);
- if (data.xiaomusic_search != "") {
- $("#xiaomusic_search").val(data.xiaomusic_search);
+ // 初始化显示
+ for (const key in data) {
+ if (data.hasOwnProperty(key) && data[key] != "") {
+ const $element = $("#" + key);
+ if ($element.length) {
+ $element.val(data[key]);
+ }
+ }
}
- if (data.xiaomusic_proxy != "") {
- $("#xiaomusic_proxy").val(data.xiaomusic_proxy);
- }
-
- if (data.xiaomusic_music_list_url != "") {
- $("#xiaomusic_music_list_url").val(data.xiaomusic_music_list_url);
- }
-
- if (data.xiaomusic_music_list_json != "") {
- $("#xiaomusic_music_list_json").val(data.xiaomusic_music_list_json);
- }
+ autoSelectOne();
});
$("#save").on("click", () => {
- var mi_did = $("#mi_did").val();
- var mi_hardware = $("#mi_hardware").val();
- var xiaomusic_search = $("#xiaomusic_search").val();
- var xiaomusic_proxy = $("#xiaomusic_proxy").val();
- var xiaomusic_music_list_url = $("#xiaomusic_music_list_url").val();
- var xiaomusic_music_list_json = $("#xiaomusic_music_list_json").val();
- console.log("mi_did", mi_did);
- console.log("mi_hardware", mi_hardware);
- console.log("xiaomusic_search", xiaomusic_search);
- console.log("xiaomusic_proxy", xiaomusic_proxy);
- console.log("xiaomusic_music_list_url", xiaomusic_music_list_url);
- console.log("xiaomusic_music_list_json", xiaomusic_music_list_json);
- var data = {
- mi_did: mi_did,
- mi_hardware: mi_hardware,
- xiaomusic_search: xiaomusic_search,
- xiaomusic_proxy: xiaomusic_proxy,
- xiaomusic_music_list_url: xiaomusic_music_list_url,
- xiaomusic_music_list_json: xiaomusic_music_list_json,
- };
+ var setting = $('#setting');
+ var inputs = setting.find('input, select, textarea');
+ var data = {};
+ inputs.each(function() {
+ var id = this.id;
+ if (id) {
+ data[id] = $(this).val();
+ }
+ });
+ console.log(data)
+
$.ajax({
type: "POST",
url: "/savesetting",
@@ -102,10 +99,10 @@ $(function(){
});
$("#get_music_list").on("click", () => {
- var xiaomusic_music_list_url = $("#xiaomusic_music_list_url").val();
- console.log("xiaomusic_music_list_url", xiaomusic_music_list_url);
+ var music_list_url = $("#music_list_url").val();
+ console.log("music_list_url", music_list_url);
var data = {
- url: xiaomusic_music_list_url,
+ url: music_list_url,
};
$.ajax({
type: "POST",
@@ -114,7 +111,7 @@ $(function(){
data: JSON.stringify(data),
success: (res) => {
if (res.ret == "OK") {
- $("#xiaomusic_music_list_json").val(res.content);
+ $("#music_list_json").val(res.content);
} else {
console.log(res);
alert(res.ret);
diff --git a/xiaomusic/utils.py b/xiaomusic/utils.py
index 556a085..2a21057 100644
--- a/xiaomusic/utils.py
+++ b/xiaomusic/utils.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
from __future__ import annotations
+import copy
import difflib
import os
import random
@@ -240,3 +241,30 @@ def get_local_music_duration(filename):
def get_random(length):
return "".join(random.sample(string.ascii_letters + string.digits, length))
+
+
+# 深拷贝把敏感数据设置位*
+def deepcopy_data_no_sensitive_info(data, fields_to_anonymize=None):
+ if fields_to_anonymize is None:
+ fields_to_anonymize = [
+ "account",
+ "password",
+ "httpauth_username",
+ "httpauth_password",
+ ]
+
+ copy_data = copy.deepcopy(data)
+
+ # 检查copy_data是否是字典或具有属性的对象
+ if isinstance(copy_data, dict):
+ # 对字典进行处理
+ for field in fields_to_anonymize:
+ if field in copy_data:
+ copy_data[field] = "******"
+ else:
+ # 对对象进行处理
+ for field in fields_to_anonymize:
+ if hasattr(copy_data, field):
+ setattr(copy_data, field, "******")
+
+ return copy_data
diff --git a/xiaomusic/xiaomusic.py b/xiaomusic/xiaomusic.py
index d2861cc..5402ef7 100644
--- a/xiaomusic/xiaomusic.py
+++ b/xiaomusic/xiaomusic.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python3
import asyncio
-import copy
import json
import logging
import os
@@ -31,6 +30,7 @@ from xiaomusic.const import (
from xiaomusic.httpserver import StartHTTPServer
from xiaomusic.utils import (
custom_sort_key,
+ deepcopy_data_no_sensitive_info,
find_best_match,
fuzzyfinder,
get_local_music_duration,
@@ -61,20 +61,6 @@ class XiaoMusic:
self.new_record_event = asyncio.Event()
self.queue = queue.Queue()
- self.music_path = config.music_path
- self.conf_path = config.conf_path
- if not self.conf_path:
- self.conf_path = config.music_path
-
- self.hostname = config.hostname
- self.port = config.port
- self.proxy = config.proxy
- self.search_prefix = config.search_prefix
- self.ffmpeg_location = config.ffmpeg_location
- self.active_cmd = config.active_cmd.split(",")
- self.exclude_dirs = set(config.exclude_dirs.split(","))
- self.music_path_depth = config.music_path_depth
-
# 下载对象
self.download_proc = None
# 单曲循环,全部循环
@@ -93,6 +79,9 @@ class XiaoMusic:
# 关机定时器
self._stop_timer = None
+ # 初始化配置
+ self.init_config()
+
# 初始化日志
self.setup_logger()
@@ -105,6 +94,24 @@ class XiaoMusic:
# 启动时初始化获取声音
self.set_last_record("get_volume#")
+ debug_config = deepcopy_data_no_sensitive_info(self.config)
+ self.log.info(f"Startup OK. {debug_config}")
+
+ def init_config(self):
+ self.music_path = self.config.music_path
+ self.conf_path = self.config.conf_path
+ if not self.conf_path:
+ self.conf_path = self.config.music_path
+
+ self.hostname = self.config.hostname
+ self.port = self.config.port
+ self.proxy = self.config.proxy
+ self.search_prefix = self.config.search_prefix
+ self.ffmpeg_location = self.config.ffmpeg_location
+ self.active_cmd = self.config.active_cmd.split(",")
+ self.exclude_dirs = set(self.config.exclude_dirs.split(","))
+ self.music_path_depth = self.config.music_path_depth
+
def setup_logger(self):
log_format = f"%(asctime)s [{__version__}] [%(levelname)s] %(message)s"
date_format = "[%X]"
@@ -127,12 +134,6 @@ class XiaoMusic:
self.log = logging.getLogger("xiaomusic")
self.log.addHandler(handler)
self.log.setLevel(logging.DEBUG if self.config.verbose else logging.INFO)
- debug_config = copy.deepcopy(self.config)
- debug_config.account = "******"
- debug_config.password = "******"
- debug_config.httpauth_username = "******"
- debug_config.httpauth_password = "******"
- self.log.info(debug_config)
async def poll_latest_ask(self):
async with ClientSession() as session:
@@ -982,19 +983,23 @@ class XiaoMusic:
await self.call_main_thread_function(self.reinit)
def update_config_from_setting(self, data):
- self.config.mi_did = data.get("mi_did")
+ # 兼容旧配置:一段时间后清理这里的旧代码
self.config.hardware = data.get("mi_hardware")
self.config.search_prefix = data.get("xiaomusic_search")
self.config.proxy = data.get("xiaomusic_proxy")
self.config.music_list_url = data.get("xiaomusic_music_list_url")
self.config.music_list_json = data.get("xiaomusic_music_list_json")
- self.search_prefix = self.config.search_prefix
- self.proxy = self.config.proxy
- self.log.debug("update_config_from_setting ok. data:%s", data)
+ # 自动赋值相同字段的配置
+ self.config.update_config(data)
+
+ self.init_config()
+ debug_config = deepcopy_data_no_sensitive_info(self.config)
+ self.log.info("update_config_from_setting ok. data:%s", debug_config)
# 重新初始化
async def reinit(self, **kwargs):
+ self.setup_logger()
await self.init_all_data(self.session)
self._gen_all_music_list()
self.log.info("reinit success")