Skip to content

Commit

Permalink
#78 支持配置自定义网络歌单
Browse files Browse the repository at this point in the history
  • Loading branch information
hanxi committed Jun 25, 2024
1 parent 80c6d29 commit b2a3cda
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 35 deletions.
2 changes: 2 additions & 0 deletions xiaomusic/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class Config:
)
httpauth_username: str = os.getenv("XIAOMUSIC_HTTPAUTH_USERNAME", "admin")
httpauth_password: str = os.getenv("XIAOMUSIC_HTTPAUTH_PASSWORD", "admin")
music_list_url: str = os.getenv("XIAOMUSIC_MUSIC_LIST_URL", "")
music_list_json: str = os.getenv("XIAOMUSIC_MUSIC_LIST_JSON", "")

def __post_init__(self) -> None:
if self.proxy:
Expand Down
17 changes: 17 additions & 0 deletions xiaomusic/httpserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
from xiaomusic.config import (
KEY_WORD_DICT,
)
from xiaomusic.utils import (
downloadfile,
)

app = Flask(__name__)
auth = HTTPBasicAuth()
Expand Down Expand Up @@ -109,6 +112,8 @@ async def getsetting():
"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,
}
return data

Expand Down Expand Up @@ -143,6 +148,18 @@ def delmusic():
return "success"


@app.route("/downloadjson", methods=["POST"])
@auth.login_required
def downloadjson():
data = request.get_json()
log.info(data)
ret, content = downloadfile(data["url"])
return {
"ret": ret,
"content": content,
}


def static_path_handler(filename):
log.debug(filename)
log.debug(static_path)
Expand Down
5 changes: 5 additions & 0 deletions xiaomusic/static/setting.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ <h2>小爱音箱设置面板<span id="version">(版本未知)</span></h2>
</select>
<label for="xiaomusic_proxy">XIAOMUSIC_PROXY(ytsearch需要):</label>
<input id="xiaomusic_proxy" type="text" placeholder="http://192.168.2.5:8080"></input>
<label for="xiaomusic_music_list_url">歌单地址:</label>
<input id="xiaomusic_music_list_url" type="text" value="https://gist.githubusercontent.com/hanxi/dda82d964a28f8110f8fba81c3ff8314/raw/example.json"></input>
<label for="xiaomusic_music_list_json">歌单内容:</label>
<textarea id="xiaomusic_music_list_json" type="text"></textarea>
</div>
<hr>
<button onclick="location.href='/';">返回首页</button>
<button id="get_music_list">获取歌单</button>
<button id="save">保存</button>

<footer>
Expand Down
40 changes: 40 additions & 0 deletions xiaomusic/static/setting.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,36 @@ $(function(){
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);
}
});

$("#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,
};
$.ajax({
type: "POST",
Expand All @@ -70,4 +84,30 @@ $(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 data = {
url: xiaomusic_music_list_url,
};
$.ajax({
type: "POST",
url: "/downloadjson",
contentType: "application/json",
data: JSON.stringify(data),
success: (res) => {
if (res.ret == "OK") {
$("#xiaomusic_music_list_json").val(res.content);
} else {
console.log(res);
alert(res.ret);
}
},
error: (res) => {
console.log(res);
alert(res);
}
});
});
});
6 changes: 6 additions & 0 deletions xiaomusic/static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,9 @@ footer {
text-align: center;
padding: 10px 0;
}

textarea{
margin: 10px;
width: 300px;
height: 200px;
}
48 changes: 48 additions & 0 deletions xiaomusic/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
import difflib
import os
import re
import tempfile
from collections.abc import AsyncIterator
from http.cookies import SimpleCookie
from urllib.parse import urlparse

import aiohttp
import mutagen
import requests
from requests.utils import cookiejar_from_dict


Expand Down Expand Up @@ -144,3 +148,47 @@ def fallback_func(root, depth, *args, **kwargs):
except KeyError:
yield from main_func(root, depth, *args, **kwargs)
return


def downloadfile(url):
try:
response = requests.get(url, timeout=5) # 增加超时以避免长时间挂起
response.raise_for_status() # 如果响应不是200,引发HTTPError异常
return ("OK", response.text)
except requests.exceptions.HTTPError as errh:
return (f"HTTP Error: {errh}", "")
except requests.exceptions.ConnectionError as errc:
return (f"Error Connecting: {errc}", "")
except requests.exceptions.Timeout as errt:
return (f"Timeout Error: {errt}", "")
except requests.exceptions.RequestException as err:
return (f"Oops: Something Else, {err}", "")
return ("Unknow Error", "")


async def get_web_music_duration(url, start=0, end=500):
headers = {"Range": f"bytes={start}-{end}"}
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers) as response:
array_buffer = await response.read()
with tempfile.NamedTemporaryFile() as tmp:
tmp.write(array_buffer)
try:
m = mutagen.File(tmp)
except Exception:
headers = {"Range": f"bytes={0}-{1000}"}
async with session.get(url, headers=headers) as response:
array_buffer = await response.read()
with tempfile.NamedTemporaryFile() as tmp2:
tmp2.write(array_buffer)
m = mutagen.File(tmp2)
return m.info.length


# 获取文件播放时长
def get_local_music_duration(filename):
# 获取音频文件对象
audio = mutagen.File(filename)
# 获取播放时长
duration = audio.info.length
return duration
Loading

0 comments on commit b2a3cda

Please sign in to comment.