mirror of
https://github.com/hanxi/xiaomusic.git
synced 2025-12-06 14:52:50 +08:00
Compare commits
295 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
417a5c924a | ||
|
|
d4bc1c49ea | ||
|
|
51ef9e08fe | ||
|
|
285203a342 | ||
|
|
af6077693e | ||
|
|
40ac67cce0 | ||
|
|
96d03c5c29 | ||
|
|
82aa453e50 | ||
|
|
1718211619 | ||
|
|
09310675fc | ||
|
|
ca711bbdb8 | ||
|
|
fb44f88df2 | ||
|
|
e5b32b2831 | ||
|
|
19ddbb7ca9 | ||
|
|
3e82d7acdc | ||
|
|
3921c70c86 | ||
|
|
aea9333e57 | ||
|
|
7043ca31cf | ||
|
|
963d86de7c | ||
|
|
d6b0e974b7 | ||
|
|
8a8340a159 | ||
|
|
20d3c9fce9 | ||
|
|
729549a7a9 | ||
|
|
d28614177c | ||
|
|
db53517784 | ||
|
|
186e9c1417 | ||
|
|
7498016d61 | ||
|
|
7114ea2e6e | ||
|
|
e8ca1f8678 | ||
|
|
2275bc2600 | ||
|
|
45a94f4bfe | ||
|
|
5cb2c84715 | ||
|
|
a3bf8d8aaa | ||
|
|
0a88b7be26 | ||
|
|
05da3e8fc4 | ||
|
|
560ea1aeca | ||
|
|
5ef1f2d940 | ||
|
|
e01fcdcecd | ||
|
|
8ff04dd0f6 | ||
|
|
4a7b5ac2b0 | ||
|
|
ac74ef3c15 | ||
|
|
8913057c27 | ||
|
|
a75030a73c | ||
|
|
e2e74f9459 | ||
|
|
09febb66dc | ||
|
|
ad0db8c9a9 | ||
|
|
90b0fecd3b | ||
|
|
a8f88e8bfc | ||
|
|
d8035f0713 | ||
|
|
76c1a8952f | ||
|
|
d8a66ca152 | ||
|
|
dd77176035 | ||
|
|
6d7d90d642 | ||
|
|
514bf9b8b2 | ||
|
|
cd5869ff84 | ||
|
|
ee6f4ee4e4 | ||
|
|
0189a00155 | ||
|
|
e3d60d3f2e | ||
|
|
27fecd788b | ||
|
|
e9b1d94fb3 | ||
|
|
043a9303a5 | ||
|
|
aa698667c9 | ||
|
|
700e17854c | ||
|
|
40258c9fa1 | ||
|
|
eb59bf0db5 | ||
|
|
a9df78af97 | ||
|
|
901506a32d | ||
|
|
0ddbe58fbd | ||
|
|
350d82184f | ||
|
|
5b8054abd9 | ||
|
|
c5c691b653 | ||
|
|
7a44c8587c | ||
|
|
5092ffc91a | ||
|
|
2da12e12d5 | ||
|
|
5aff72dbb6 | ||
|
|
043f452e71 | ||
|
|
5cedf8a907 | ||
|
|
ae77c7232e | ||
|
|
d559413d46 | ||
|
|
8b185d8768 | ||
|
|
202105a11f | ||
|
|
7da80594e3 | ||
|
|
a032a1d50a | ||
|
|
be62d8abc8 | ||
|
|
aaf9f4b6a7 | ||
|
|
bb5d82097e | ||
|
|
d6ba656641 | ||
|
|
742cae0543 | ||
|
|
a4ab1af160 | ||
|
|
86f158532a | ||
|
|
9ea7935cfb | ||
|
|
20c7e14076 | ||
|
|
e10f5b89b6 | ||
|
|
cb0bae5ae7 | ||
|
|
6a583119d0 | ||
|
|
9349070e8b | ||
|
|
01d99dc699 | ||
|
|
f4d9a6c1fd | ||
|
|
1919bc84d9 | ||
|
|
4c1761468f | ||
|
|
c75230a67d | ||
|
|
ee7ffa55cb | ||
|
|
45bbc8af42 | ||
|
|
ab8bf8fa62 | ||
|
|
493cad080e | ||
|
|
eaa159c5cb | ||
|
|
96e3b8c2ff | ||
|
|
794e8dcd06 | ||
|
|
f2675e4340 | ||
|
|
e5059840fb | ||
|
|
f3e57789fa | ||
|
|
c151b826f7 | ||
|
|
1b3ed3b35a | ||
|
|
77a37a9438 | ||
|
|
f22de9f906 | ||
|
|
090e8c3f4c | ||
|
|
aef51fb65d | ||
|
|
a5a3a2dc62 | ||
|
|
ce9adcee7f | ||
|
|
485a42a9a0 | ||
|
|
3754970c84 | ||
|
|
924fbc208b | ||
|
|
c1a2ee4577 | ||
|
|
e84ee5de1e | ||
|
|
0414830539 | ||
|
|
385f23842d | ||
|
|
1deceaa5a5 | ||
|
|
b8f1157e27 | ||
|
|
06558c24b7 | ||
|
|
6bd399b654 | ||
|
|
228d89f1f8 | ||
|
|
e97639302f | ||
|
|
7f4e51be08 | ||
|
|
cdab5fc92d | ||
|
|
6efe498f2a | ||
|
|
0f3f2e47f5 | ||
|
|
3b720b7367 | ||
|
|
9a3e513b6c | ||
|
|
5a8e5dfa82 | ||
|
|
70d9ad93cb | ||
|
|
87b3411f5e | ||
|
|
5c88c79ac6 | ||
|
|
5df91e7a59 | ||
|
|
71e9c15b5d | ||
|
|
c151144a5a | ||
|
|
82a3373e72 | ||
|
|
29ef5f238f | ||
|
|
1809a2ab54 | ||
|
|
3b1684f553 | ||
|
|
d088374333 | ||
|
|
80da6bd1e6 | ||
|
|
619bb9c853 | ||
|
|
5add7b7a5c | ||
|
|
f61f14e16c | ||
|
|
125421db22 | ||
|
|
98b73f72df | ||
|
|
e68bc3b937 | ||
|
|
ab447a4633 | ||
|
|
23d321a722 | ||
|
|
20945954b1 | ||
|
|
d6c2078917 | ||
|
|
a5b8dc639c | ||
|
|
84751e0d68 | ||
|
|
e759658481 | ||
|
|
d83100588f | ||
|
|
83d0e02eb4 | ||
|
|
20f1f33b6c | ||
|
|
fbb5d26c28 | ||
|
|
2c21778675 | ||
|
|
959acd8fb7 | ||
|
|
148c5b7621 | ||
|
|
d7a2afba48 | ||
|
|
559ed23214 | ||
|
|
1d1e63df8a | ||
|
|
27e9d92a0a | ||
|
|
69573f3fa4 | ||
|
|
edafd79140 | ||
|
|
7c45d93fea | ||
|
|
f19a7e1080 | ||
|
|
5e0ae07978 | ||
|
|
116a05ce4b | ||
|
|
d6fdee5905 | ||
|
|
af25300917 | ||
|
|
f18b2f49bf | ||
|
|
db1e4e6fc4 | ||
|
|
dc49f63a37 | ||
|
|
6837841872 | ||
|
|
637347ae0c | ||
|
|
ff968c4db4 | ||
|
|
ca547e0d81 | ||
|
|
f0931c447b | ||
|
|
d098b5eb60 | ||
|
|
09111e849d | ||
|
|
49a76dee60 | ||
|
|
637672473e | ||
|
|
e4e1d13b69 | ||
|
|
7736f8c5b4 | ||
|
|
29db69b52f | ||
|
|
37fe51771b | ||
|
|
77ece713dc | ||
|
|
4436cc3a15 | ||
|
|
c875350112 | ||
|
|
d6df2f6bfe | ||
|
|
03e3312218 | ||
|
|
5d7451c3f2 | ||
|
|
551dfa0c7f | ||
|
|
3cc35e8f97 | ||
|
|
01c68ba64e | ||
|
|
61d167d347 | ||
|
|
9393e9f1ca | ||
|
|
c08ef030e9 | ||
|
|
bad13f01f4 | ||
|
|
049e1a2c38 | ||
|
|
a9fb829563 | ||
|
|
e66f731301 | ||
|
|
538ac1d485 | ||
|
|
88fbc503e7 | ||
|
|
1dc3ccbc16 | ||
|
|
df007d8e1b | ||
|
|
0876551795 | ||
|
|
51acb3ac8e | ||
|
|
786af1c79e | ||
|
|
7fba78e44b | ||
|
|
9434cf3216 | ||
|
|
f71ab25407 | ||
|
|
a634813c21 | ||
|
|
17279aaae0 | ||
|
|
4a234e8829 | ||
|
|
805b3c41c8 | ||
|
|
7a154fd847 | ||
|
|
3cdc836e9e | ||
|
|
d232627796 | ||
|
|
579820e606 | ||
|
|
a24a5166f9 | ||
|
|
ad67894244 | ||
|
|
725d4c4ab3 | ||
|
|
6a0310fe05 | ||
|
|
463fd9dd38 | ||
|
|
34fe19abd1 | ||
|
|
3365f082f7 | ||
|
|
13361c57b8 | ||
|
|
2a22b00d53 | ||
|
|
925b52d979 | ||
|
|
468efb63fb | ||
|
|
38aae7eca3 | ||
|
|
44df1134a8 | ||
|
|
243c1673db | ||
|
|
82eab4810c | ||
|
|
e0a59b5729 | ||
|
|
ad3bad85db | ||
|
|
743d85de32 | ||
|
|
8bd32f878f | ||
|
|
eccb52c197 | ||
|
|
603d60d8b8 | ||
|
|
3ef04f4159 | ||
|
|
7888ee7938 | ||
|
|
b2a3cda7b5 | ||
|
|
80c6d29079 | ||
|
|
0b020deaef | ||
|
|
74c8bea756 | ||
|
|
af10d6261f | ||
|
|
a178278576 | ||
|
|
474fea8434 | ||
|
|
d271f7b0f7 | ||
|
|
7e2af515ed | ||
|
|
2d403ff18c | ||
|
|
f08244a990 | ||
|
|
4869e5cf80 | ||
|
|
b887504f9f | ||
|
|
ad43a4f732 | ||
|
|
8699938b61 | ||
|
|
40bd099153 | ||
|
|
750923d5ca | ||
|
|
6d99b30e2d | ||
|
|
a155f16560 | ||
|
|
d4aa045487 | ||
|
|
8080dd9822 | ||
|
|
2eab8d8113 | ||
|
|
b51e56718a | ||
|
|
088d448e10 | ||
|
|
4a89b4bce5 | ||
|
|
b351b4bcd4 | ||
|
|
b2edaf48e4 | ||
|
|
33e02cee82 | ||
|
|
91a8c9eb50 | ||
|
|
50da8a0554 | ||
|
|
42b5978d89 | ||
|
|
bf29fc67b4 | ||
|
|
dbc68d6b56 | ||
|
|
5dabf66e7c | ||
|
|
d6e4478eb6 | ||
|
|
23ef4719ba | ||
|
|
d799a85ab9 | ||
|
|
4ad6bcc636 | ||
|
|
d2473ec7e8 |
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
github: [hanxi]
|
||||
custom: ['https://afdian.com/a/imhanxi']
|
||||
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
@@ -2,7 +2,8 @@ name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches:
|
||||
- "*"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
@@ -25,6 +26,12 @@ jobs:
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: true
|
||||
tags: ${{ secrets.DOCKERHUB_USERNAME }}/xiaomusic:${{ github.ref_name }}
|
||||
- name: Docker Hub Description
|
||||
uses: peter-evans/dockerhub-description@v4
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
repository: hanxi/xiaomusic
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -61,6 +61,6 @@ jobs:
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v6,linux/arm/v7
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: true
|
||||
tags: ${{ secrets.DOCKERHUB_USERNAME }}/xiaomusic:${{ github.ref_name }}, ${{ secrets.DOCKERHUB_USERNAME }}/xiaomusic:latest, ${{ secrets.DOCKERHUB_USERNAME }}/xiaomusic:stable
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -164,3 +164,4 @@ cython_debug/
|
||||
ffmpeg
|
||||
music
|
||||
test.sh
|
||||
conf
|
||||
|
||||
8
.pre-commit-config.yaml
Normal file
8
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
repos:
|
||||
- hooks:
|
||||
- id: commitizen
|
||||
- id: commitizen-branch
|
||||
stages:
|
||||
- push
|
||||
repo: https://github.com/commitizen-tools/commitizen
|
||||
rev: v3.27.0
|
||||
484
CHANGELOG.md
Normal file
484
CHANGELOG.md
Normal file
@@ -0,0 +1,484 @@
|
||||
## v0.3.10 (2024-07-19)
|
||||
|
||||
### Feat
|
||||
|
||||
- 支持软连接的接口直接用os.walk即可
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复软连接目录不能播放的问题
|
||||
- 修复自定义语音口令设置不生效的问题
|
||||
|
||||
## v0.3.9 (2024-07-17)
|
||||
|
||||
### Feat
|
||||
|
||||
- #119 音乐目录支持软连接
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复日志下载报错问题
|
||||
- 兼容旧的setting.json文件中conf_path为空的情况
|
||||
- 修复设置页面可能打不开的问题
|
||||
|
||||
## v0.3.8 (2024-07-16)
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复播放url接口问题
|
||||
|
||||
## v0.3.7 (2024-07-16)
|
||||
|
||||
### Feat
|
||||
|
||||
- 播放链接按钮对应给个默认的链接用于测试
|
||||
- Uvicorn 的日志信息合并到 xiaomusic 日志里显示
|
||||
|
||||
## v0.3.6 (2024-07-15)
|
||||
|
||||
### Fix
|
||||
|
||||
- #126 修复pip安装时主页打不开的问题
|
||||
|
||||
## v0.3.5 (2024-07-15)
|
||||
|
||||
### Fix
|
||||
|
||||
- #116 播放失败自动切下首歌
|
||||
|
||||
## v0.3.4 (2024-07-15)
|
||||
|
||||
### Fix
|
||||
|
||||
- #125 修复本地英文歌曲匹大小写字母配不到的问题
|
||||
|
||||
## v0.3.3 (2024-07-15)
|
||||
|
||||
### Fix
|
||||
|
||||
- 尝试修复播放卡顿问题 see #124
|
||||
|
||||
## v0.3.2 (2024-07-15)
|
||||
|
||||
### Fix
|
||||
|
||||
- #122 pip安装方式下,static目录找不到报错
|
||||
- 版本更新时更新页面缓存
|
||||
|
||||
## v0.3.1 (2024-07-15)
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复主页选择设备不生效的问题 see #120
|
||||
|
||||
## v0.3.0 (2024-07-14)
|
||||
|
||||
### Feat
|
||||
|
||||
- 建议音乐目录和配置目录分开不同目录
|
||||
- 优化后台网络设置,同时支持ipv4和ipv6
|
||||
- 使用fastapi替换flask,解决多线程问题
|
||||
- #106 网页上显示音箱当前状态(播放中or空闲中)以及当前的播放模式
|
||||
- 优化首页加载慢的问题
|
||||
- 优化设置页面布局,方便配置必须项
|
||||
- 优化配置界面,支持配置分组
|
||||
- 支持多设备分开播放 see #65
|
||||
|
||||
### Fix
|
||||
|
||||
- #114 修复部分 mp3 文件长度识别错误
|
||||
- 删除 armv6 的支持
|
||||
- 修复编译问题
|
||||
- 修复音乐路径设置后找不到音乐的问题
|
||||
- 修复启动报错的问题
|
||||
- 修复CI警告问题
|
||||
|
||||
## v0.2.0 (2024-07-09)
|
||||
|
||||
### Feat
|
||||
|
||||
- 触屏版可以不用设置 XIAOMUSIC_USE_MUSIC_API
|
||||
- 升级依赖库
|
||||
- 唤醒口令配置支持配语音词,简化自定义口令配置 see #105
|
||||
|
||||
## v0.1.101 (2024-07-07)
|
||||
|
||||
### Fix
|
||||
|
||||
- #81 修复播放列表时,当前歌曲不在列表没有更换歌曲的问题
|
||||
- #110 修复配置加载问题
|
||||
|
||||
## v0.1.100 (2024-07-07)
|
||||
|
||||
### Fix
|
||||
|
||||
- 日志代码写错
|
||||
|
||||
## v0.1.99 (2024-07-07)
|
||||
|
||||
### Fix
|
||||
|
||||
- #81 修复播放列表没有继续播放上次播放的歌曲,并把随机播放,全部循环,单曲循环状态落地
|
||||
|
||||
## v0.1.98 (2024-07-07)
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复多设备获取不到对话记录的问题 see #65
|
||||
- #93 修复目录深度设置后导致目录下的歌曲无法加到播放列表里的问题
|
||||
|
||||
## v0.1.97 (2024-07-06)
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复网页控制台设置页面保存报错
|
||||
|
||||
## v0.1.96 (2024-07-06)
|
||||
|
||||
### Feat
|
||||
|
||||
- 使用commitizen管理版本号
|
||||
- 页面版本号链接到CHANGELOG页面
|
||||
- 规范版本管理
|
||||
|
||||
## v0.1.95 (2024-07-06)
|
||||
|
||||
## v0.1.94 (2024-07-06)
|
||||
|
||||
### Feat
|
||||
|
||||
- 优化多设备接口执行效果,尽量做到同时执行
|
||||
|
||||
### Fix
|
||||
|
||||
- 新增参数配置强制打断小爱说话
|
||||
- 修复多设备获取对话记录的问题
|
||||
- 修复windows下路径分隔符被视为转移符导致音箱无法播放音乐的问题
|
||||
- 修复播放链接报错
|
||||
- 修复配置页面默认配置被置空的问题
|
||||
|
||||
## v0.1.93 (2024-07-05)
|
||||
|
||||
### Feat
|
||||
|
||||
- 访问账号密码默认为空
|
||||
- 支持下载的目录与本地音乐目录分开 see #98
|
||||
- 新增m4a文件格式支持
|
||||
- 设置页面支持配置多设备
|
||||
- 默认用空的后台账号和密码
|
||||
- 支持多个设备同时播放 see #65
|
||||
- 新增自定义口令功能 #105
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复设置页面没成功初始化设置问题
|
||||
- 修复镜像缺少文件问题
|
||||
- 尝试解决插件路径问题
|
||||
- 设置页面日志路径写错了
|
||||
- 修复口令导致异常关闭的问题
|
||||
|
||||
## v0.1.92 (2024-07-04)
|
||||
|
||||
### Feat
|
||||
|
||||
- 启动参数新增 --port 配置监听端口
|
||||
- 外网访问端口可独立配置
|
||||
- 优化设置页面,新增更多配置项
|
||||
- 首次保存设置后不需要重启容器
|
||||
|
||||
### Fix
|
||||
|
||||
- 日志文件配置的环境变量写错了
|
||||
|
||||
## v0.1.91 (2024-07-03)
|
||||
|
||||
### Fix
|
||||
|
||||
- 尝试解决触屏版不能播放的问题
|
||||
|
||||
## v0.1.90 (2024-07-02)
|
||||
|
||||
### Feat
|
||||
|
||||
- 优化触屏版播放页面显示歌曲
|
||||
|
||||
## v0.1.89 (2024-07-02)
|
||||
|
||||
### Feat
|
||||
|
||||
- 尝试解决触屏版无法播放的问题
|
||||
|
||||
### Fix
|
||||
|
||||
- 播放歌曲写成固定的了
|
||||
- 播放歌曲时被其他指令打断后没有继续播放
|
||||
|
||||
## v0.1.88 (2024-07-02)
|
||||
|
||||
### Feat
|
||||
|
||||
- 日志里不要输出敏感信息
|
||||
- 优化下载 ffmpeg 脚本,尝试解决 armv7 环境问题
|
||||
- 优化日志输出信息
|
||||
- 尝试解决触屏版无法播放的问题
|
||||
|
||||
### Fix
|
||||
|
||||
- 是否下载中判断错误导致播放无法自动重新开始播放
|
||||
- 升级yt-dlp到2024.07.01
|
||||
- 修复部分型号关机失败的问题
|
||||
|
||||
## v0.1.87 (2024-07-01)
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复XIAOMUSIC_USE_MUSIC_API=true时播放不了的问题
|
||||
|
||||
## v0.1.86 (2024-07-01)
|
||||
|
||||
### Feat
|
||||
|
||||
- 优化 ffmpeg 安装脚本
|
||||
- 新增调试工具用来调试 player_play_music 接口
|
||||
- 升级依赖库 MiService
|
||||
|
||||
### Fix
|
||||
|
||||
- 尝试修复 armv7 的 ffmpeg 问题
|
||||
- 尝试修复关机失败的问题
|
||||
- 修复口令不能播放的问题
|
||||
|
||||
## v0.1.85 (2024-06-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- 版本号链接到github的release页面,方便查看版本更新日志
|
||||
|
||||
### Fix
|
||||
|
||||
- 修复电台删除后没有从电台列表中删除的问题
|
||||
|
||||
## v0.1.84 (2024-06-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- config.json 支持更多配置选项
|
||||
- 新增 XIAOMUSIC_STOP_TTS_MSG 配置关机提示音
|
||||
|
||||
## v0.1.83 (2024-06-30)
|
||||
|
||||
## v0.1.82 (2024-06-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- 优化指令匹配规则
|
||||
|
||||
## v0.1.81 (2024-06-30)
|
||||
|
||||
## v0.1.80 (2024-06-30)
|
||||
|
||||
### Fix
|
||||
|
||||
- #91 修复下载歌曲报错
|
||||
|
||||
## v0.1.79 (2024-06-29)
|
||||
|
||||
## v0.1.77 (2024-06-29)
|
||||
|
||||
### Fix
|
||||
|
||||
- #52 支持配置模糊匹配本地歌曲
|
||||
|
||||
## v0.1.76 (2024-06-28)
|
||||
|
||||
## v0.1.75 (2024-06-28)
|
||||
|
||||
## v0.1.74 (2024-06-28)
|
||||
|
||||
## v0.1.73 (2024-06-28)
|
||||
|
||||
## v0.1.72 (2024-06-28)
|
||||
|
||||
## v0.1.71 (2024-06-28)
|
||||
|
||||
### Fix
|
||||
|
||||
- #83
|
||||
|
||||
## v0.1.70 (2024-06-27)
|
||||
|
||||
## v0.1.69 (2024-06-26)
|
||||
|
||||
## v0.1.67 (2024-06-26)
|
||||
|
||||
## v0.1.66 (2024-06-26)
|
||||
|
||||
## v0.1.65 (2024-06-26)
|
||||
|
||||
## v0.1.64 (2024-06-26)
|
||||
|
||||
## v0.1.62 (2024-06-25)
|
||||
|
||||
## v0.1.61 (2024-06-25)
|
||||
|
||||
## v0.1.60 (2024-06-25)
|
||||
|
||||
## v0.1.58 (2024-06-25)
|
||||
|
||||
### Fix
|
||||
|
||||
- 登陆失败不阻塞启动
|
||||
|
||||
## v0.1.57 (2024-06-24)
|
||||
|
||||
## v0.1.56 (2024-06-24)
|
||||
|
||||
## v0.1.55 (2024-06-23)
|
||||
|
||||
### Fix
|
||||
|
||||
- #47 支持配置基础的BaseAuth登录
|
||||
|
||||
## v0.1.54 (2024-06-23)
|
||||
|
||||
### Fix
|
||||
|
||||
- #76 新增XIAOMUSIC_MUSIC_PATH_DEPTH配置生成播放列表的目录深度,默认10
|
||||
- #74 配置目录可以和下载目录分开配置, 新增XIAOMUSIC_CONF_PATH用来设置配置目录,不配置时使用下载目录
|
||||
|
||||
## v0.1.53 (2024-06-23)
|
||||
|
||||
## v0.1.52 (2024-06-21)
|
||||
|
||||
## v0.1.51 (2024-06-20)
|
||||
|
||||
## v0.1.49 (2024-06-20)
|
||||
|
||||
## v0.1.48 (2024-06-16)
|
||||
|
||||
## v0.1.47 (2024-06-16)
|
||||
|
||||
## v0.1.46 (2024-06-15)
|
||||
|
||||
## v0.1.45 (2024-06-15)
|
||||
|
||||
## v0.1.44 (2024-06-14)
|
||||
|
||||
## v0.1.43 (2024-06-14)
|
||||
|
||||
## v0.1.41 (2024-06-14)
|
||||
|
||||
## v0.1.40 (2024-06-12)
|
||||
|
||||
## v0.1.39 (2024-06-12)
|
||||
|
||||
## v0.1.38 (2024-06-12)
|
||||
|
||||
### Fix
|
||||
|
||||
- #70 下一首歌曲不存在时从播放列表中删除并继续找下一首
|
||||
|
||||
## v0.1.37 (2024-06-04)
|
||||
|
||||
## v0.1.36 (2024-05-30)
|
||||
|
||||
## v0.1.35 (2024-05-30)
|
||||
|
||||
### Fix
|
||||
|
||||
- #67 没配置did时也允许启动 http 服务
|
||||
|
||||
## v0.1.34 (2024-05-19)
|
||||
|
||||
## v0.1.33 (2024-05-19)
|
||||
|
||||
### Fix
|
||||
|
||||
- #50 新增配置页面
|
||||
- #62
|
||||
|
||||
## v0.1.32 (2024-05-17)
|
||||
|
||||
## v0.1.31 (2024-05-16)
|
||||
|
||||
## v0.1.30 (2024-05-16)
|
||||
|
||||
### Fix
|
||||
|
||||
- 控制台显示版本号 #59
|
||||
|
||||
## v0.1.29 (2024-05-16)
|
||||
|
||||
### Fix
|
||||
|
||||
- #57 #55
|
||||
|
||||
## v0.1.28 (2024-05-16)
|
||||
|
||||
## v0.1.27 (2024-05-16)
|
||||
|
||||
## v0.1.26 (2024-05-08)
|
||||
|
||||
## v0.1.25 (2024-05-06)
|
||||
|
||||
## v0.1.24 (2024-04-30)
|
||||
|
||||
## v0.1.23 (2024-04-30)
|
||||
|
||||
## v0.1.22 (2024-04-30)
|
||||
|
||||
## v0.1.21 (2024-04-08)
|
||||
|
||||
## v0.1.20 (2024-04-08)
|
||||
|
||||
## v0.1.19 (2024-04-04)
|
||||
|
||||
## v0.1.18 (2024-02-24)
|
||||
|
||||
## v0.1.16 (2024-02-24)
|
||||
|
||||
## v0.1.15 (2024-02-03)
|
||||
|
||||
## v0.1.14 (2024-02-03)
|
||||
|
||||
## v0.1.13 (2024-02-02)
|
||||
|
||||
## v0.1.12 (2024-01-30)
|
||||
|
||||
### Fix
|
||||
|
||||
- set volume failed
|
||||
|
||||
## v0.1.11 (2024-01-29)
|
||||
|
||||
## v0.1.10 (2024-01-29)
|
||||
|
||||
## v0.1.9 (2024-01-28)
|
||||
|
||||
### Fix
|
||||
|
||||
- arg1 漏修改
|
||||
|
||||
## v0.1.8 (2024-01-28)
|
||||
|
||||
### Fix
|
||||
|
||||
- http server listen host
|
||||
|
||||
## v0.1.7 (2024-01-28)
|
||||
|
||||
## v0.1.6 (2024-01-28)
|
||||
|
||||
## v0.1.5 (2024-01-27)
|
||||
|
||||
## v0.1.4 (2024-01-27)
|
||||
|
||||
### Fix
|
||||
|
||||
- error when play next
|
||||
|
||||
## v0.1.3 (2023-10-15)
|
||||
|
||||
## v0.1.2 (2023-10-15)
|
||||
|
||||
## v0.1.1 (2023-10-14)
|
||||
@@ -1,21 +1,23 @@
|
||||
FROM python:3.10 AS builder
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN python3 -m venv .venv && .venv/bin/pip install --no-cache-dir -r requirements.txt
|
||||
RUN python3 -m venv .venv && .venv/bin/pip install --upgrade pip && .venv/bin/pip install --no-cache-dir -r requirements.txt
|
||||
COPY install_dependencies.sh .
|
||||
RUN bash install_dependencies.sh
|
||||
|
||||
FROM python:3.10-slim
|
||||
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/.venv /app/.venv
|
||||
COPY --from=builder /app/ffmpeg /app/ffmpeg
|
||||
COPY xiaomusic/ ./xiaomusic/
|
||||
COPY plugins/ ./plugins/
|
||||
COPY xiaomusic.py .
|
||||
ENV XDG_CONFIG_HOME=/config
|
||||
ENV XIAOMUSIC_HOSTNAME=192.168.2.5
|
||||
ENV XIAOMUSIC_PORT=8090
|
||||
VOLUME /config
|
||||
VOLUME /app/conf
|
||||
VOLUME /app/music
|
||||
EXPOSE 8090
|
||||
ENV PATH=/app/.venv/bin:$PATH
|
||||
ENTRYPOINT [".venv/bin/python3","xiaomusic.py"]
|
||||
|
||||
199
README.md
199
README.md
@@ -1,6 +1,19 @@
|
||||
# xiaomusic
|
||||
[](https://github.com/hanxi/xiaomusic)
|
||||
[](https://hub.docker.com/r/hanxi/xiaomusic)
|
||||
[](https://hub.docker.com/r/hanxi/xiaomusic)
|
||||
[](https://pypi.org/project/xiaomusic/)
|
||||
[](https://pypi.org/project/xiaomusic/)
|
||||
[](https://pypi.org/project/xiaomusic/)
|
||||
[](https://github.com/hanxi/xiaomusic/releases)
|
||||
|
||||
使用小爱/红米音箱播放音乐,音乐使用 yt-dlp 下载。
|
||||
|
||||
|
||||
使用小爱音箱播放音乐,音乐使用 yt-dlp 下载。
|
||||
|
||||
<https://github.com/hanxi/xiaomusic>
|
||||
|
||||
> 初次安装遇到问题请查阅 <https://github.com/hanxi/xiaomusic/issues/99> 上是否已经有解决办法。
|
||||
|
||||
## 最简配置运行
|
||||
|
||||
@@ -16,12 +29,77 @@ services:
|
||||
- 8090:8090
|
||||
volumes:
|
||||
- ./music:/app/music
|
||||
environment:
|
||||
MI_USER: '小米账号'
|
||||
MI_PASS: '小米密码'
|
||||
XIAOMUSIC_HOSTNAME: 'docker 主机 ip'
|
||||
- ./conf:/app/conf
|
||||
```
|
||||
启动成功后,在 web 页面可以配置 MI_DID, MI_HARDWARE, XIAOMUSIC_SEARCH, XIAOMUSIC_PROXY 参数。
|
||||
|
||||
对应的 docker 启动命令如下:
|
||||
|
||||
```yaml
|
||||
docker run -p 8090:8090 \
|
||||
-v ./music:/app/music \
|
||||
-v ./conf:/app/conf
|
||||
hanxi/xiaomusic
|
||||
```
|
||||
|
||||
其中 conf 目录为配置文件存放目录,music 目录为音乐存放目录,建议分开配置为不同的目录。
|
||||
|
||||
启动成功后,在 web 页面可以配置其他参数,带有 `*` 号的配置是必须要配置的,其他的用不上时不用修改。初次配置时需要在页面上输入小米账号和密码保存后才能获取到设备列表。
|
||||
|
||||
### ✨✨✨ 修改默认8090端口映射 ✨✨✨
|
||||
|
||||
如果需要修改 8090 端口为其他端口,比如 5678,需要这样配,3个数字都需要是 5678 。见 <https://github.com/hanxi/xiaomusic/issues/19>
|
||||
|
||||
```yaml
|
||||
services:
|
||||
xiaomusic:
|
||||
image: hanxi/xiaomusic
|
||||
container_name: xiaomusic
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 5678:5678
|
||||
volumes:
|
||||
- ./music:/app/music
|
||||
environment:
|
||||
XIAOMUSIC_PORT: 5678
|
||||
```
|
||||
|
||||
遇到问题可以去 web 设置页面底部点击【下载日志文件】按钮,然后搜索一下日志文件内容确保里面没有账号密码信息后(有就删除这些敏感信息),然后在提 issues 反馈问题时把下载的日志文件带上。
|
||||
|
||||
> 目前除了 XIAOMUSIC_PORT 只能在启动前配置,其他参数都可以在 web 网页里配置。
|
||||
|
||||
## pip 方式安装运行
|
||||
|
||||
```shell
|
||||
> pip install -U xiaomusic
|
||||
> xiaomusic --help
|
||||
__ __ _ __ __ _
|
||||
\ \/ / (_) __ _ ___ | \/ | _ _ ___ (_) ___
|
||||
\ / | | / _` | / _ \ | |\/| | | | | | / __| | | / __|
|
||||
/ \ | | | (_| | | (_) | | | | | | |_| | \__ \ | | | (__
|
||||
/_/\_\ |_| \__,_| \___/ |_| |_| \__,_| |___/ |_| \___|
|
||||
XiaoMusic v0.1.92 by: github.com/hanxi
|
||||
|
||||
usage: xiaomusic [-h] [--port PORT] [--hardware HARDWARE] [--account ACCOUNT]
|
||||
[--password PASSWORD] [--cookie COOKIE] [--verbose]
|
||||
[--config CONFIG] [--ffmpeg_location FFMPEG_LOCATION]
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
--port PORT 监听端口
|
||||
--hardware HARDWARE 小爱音箱型号
|
||||
--account ACCOUNT xiaomi account
|
||||
--password PASSWORD xiaomi password
|
||||
--cookie COOKIE xiaomi cookie
|
||||
--verbose show info
|
||||
--config CONFIG config file path
|
||||
--ffmpeg_location FFMPEG_LOCATION
|
||||
ffmpeg bin path
|
||||
> xiaomusic --config config.json
|
||||
```
|
||||
|
||||
其中 `config.json` 文件可以参考 `config-example.json` 文件配置。见 <https://github.com/hanxi/xiaomusic/issues/94>
|
||||
|
||||
不修改默认端口 8090 的情况下,只需要执行 `xiaomusic` 即可启动。
|
||||
|
||||
## 开发环境运行
|
||||
|
||||
@@ -42,6 +120,8 @@ export XIAOMUSIC_SEARCH='bilisearch:'
|
||||
pdm run xiaomusic.py
|
||||
````
|
||||
|
||||
如果是开发前端界面,可以通过 <http://localhost:8090/docs> 查看有什么接口。
|
||||
|
||||
### 支持口令
|
||||
|
||||
- **播放歌曲**
|
||||
@@ -57,26 +137,45 @@ pdm run xiaomusic.py
|
||||
|
||||
> 隐藏玩法: 对小爱同学说播放歌曲小猪佩奇的故事,会播放小猪佩奇的故事。
|
||||
|
||||
## 已测试设备
|
||||
## 已测试支持的设备
|
||||
|
||||
| 型号 | 名称 |
|
||||
| ---- | ---------------------------------------------------------------------------------------------- |
|
||||
| L06A | [小爱音箱](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.l06a) |
|
||||
| L07A | [Redmi小爱音箱 Play](https://home.mi.com/webapp/content/baike/product/index.html?model=xiaomi.wifispeaker.l7a) |
|
||||
| S12/S12A/MDZ-25-DA | [小米AI音箱](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.s12) |
|
||||
| LX5A | [小爱音箱 万能遥控版](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.lx5a) |
|
||||
| LX05 | [小爱音箱Play(2019款)](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.lx05) |
|
||||
| L16A | [Xiaomi Sound](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.l16a) |
|
||||
| L17A | [Xiaomi Sound Pro](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.l17a) |
|
||||
| LX06 | [小爱音箱Pro](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.lx06) |
|
||||
| LX01 | [小爱音箱mini](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.lx01) |
|
||||
| L05B | [小爱音箱Play](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.l05b) |
|
||||
| L05C | [小米小爱音箱Play 增强版](https://home.mi.com/baike/index.html#/detail?model=xiaomi.wifispeaker.l05c) |
|
||||
| LX04 X10A X08A | 已经支持的触屏版 |
|
||||
|
||||
型号与产品名称对照可以在这里查询 <https://home.miot-spec.com/s/xiaomi.wifispeaker>
|
||||
|
||||
> 如果你的设备支持播放,请反馈给我添加到支持列表里,谢谢。
|
||||
> 目前应该所有设备类型都已经支持播放,有问题随时反馈。
|
||||
> 其他触屏版不能播放可以设置 XIAOMUSIC_USE_MUSIC_API 为 true 试试。
|
||||
|
||||
```txt
|
||||
"L07A": ("5-1", "5-5"), # Redmi小爱音箱Play(l7a)
|
||||
````
|
||||
## 支持音乐格式
|
||||
|
||||
- mp3
|
||||
- flac
|
||||
- wav
|
||||
- ape
|
||||
- ogg
|
||||
- m4a
|
||||
|
||||
> 本地音乐会搜索 mp3 和 flac 格式的文件,下载的歌曲是 mp3 格式的。
|
||||
|
||||
## 其他参数
|
||||
|
||||
- XIAOMUSIC_ACTIVE_CMD 环境变量,配置成'play,random_play',在非播放状态下,只有这两个指令(播放歌曲和随机播放)可以触发,触发后,xiaomusic进入playing状态,其他指令则可以正常触发。
|
||||
> 本地音乐会搜索目录下上面格式的文件,下载的歌曲是 mp3 格式的。
|
||||
> 已知 L05B L05C 不支持 flac 格式。
|
||||
|
||||
## 在 Docker 里使用
|
||||
|
||||
```shell
|
||||
docker run -e MI_USER=<your-xiaomi-account> \
|
||||
docker run -e MI_USER='your-xiaomi-account' \
|
||||
-e MI_PASS='your-xiaomi-password' \
|
||||
-e MI_DID='your-xiaomi-speaker-mid' \
|
||||
-e MI_HARDWARE='L07A' \
|
||||
@@ -162,6 +261,26 @@ services:
|
||||
XIAOMUSIC_HOSTNAME: '192.168.2.5'
|
||||
```
|
||||
|
||||
如果想让 setting.json 文件不存储到 music 目录,可以这样配,下面的示例会把 setting.json 文件放到容器的 /app/conf 目录且映射到本地的 ./conf 目录:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
xiaomusic:
|
||||
image: hanxi/xiaomusic
|
||||
container_name: xiaomusic
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- 8090:8090
|
||||
volumes:
|
||||
- ./music:/app/music
|
||||
- ./conf:/app/conf
|
||||
environment:
|
||||
MI_USER: '小米账号'
|
||||
MI_PASS: '小米密码'
|
||||
XIAOMUSIC_HOSTNAME: 'docker 主机 ip'
|
||||
XIAOMUSIC_CONF_PATH: '/app/conf'
|
||||
```
|
||||
|
||||
|
||||
## 简易的控制面板
|
||||
|
||||
@@ -169,11 +288,14 @@ services:
|
||||
|
||||
- ip 是 XIAOMUSIC_HOSTNAME 设置的
|
||||
- 8090 是默认端口
|
||||
- 新功能
|
||||
- 支持功能
|
||||
- 显示正在播放的歌曲
|
||||
- 模糊搜索本地歌曲
|
||||
- 播放列表
|
||||
- 删除歌曲
|
||||
- 设置页面
|
||||
|
||||
- 配置网络歌单
|
||||
- 日志文件下载
|
||||
|
||||
采用新的设置页面之后,必须在启动前配置的环境变量只剩下:
|
||||
- MI_USER
|
||||
@@ -186,11 +308,42 @@ services:
|
||||
- XIAOMUSIC_SEARCH
|
||||
- XIAOMUSIC_PROXY
|
||||
|
||||
## 网络歌单功能
|
||||
|
||||
可以配置一个 json 格式的歌单,支持电台和歌曲,也可以直接用别人分享的链接,同时配备了 m3u 文件格式转换工具,可以很方便的把 m3u 电台文件转换成网络歌单格式的 json 文件,具体用法见 <https://github.com/hanxi/xiaomusic/issues/78>
|
||||
|
||||
> 欢迎有想法的朋友们制作更多的歌单转换工具。
|
||||
|
||||
## 更多其他可选配置
|
||||
|
||||
- XIAOMUSIC_ACTIVE_CMD 环境变量,用于唤醒口令,配置成'play,random_play',在非播放状态下,只有这两个指令(播放歌曲和随机播放)可以触发,触发后,xiaomusic进入playing状态,其他指令则可以正常触发。具体见 <https://github.com/hanxi/xiaomusic/pull/43>
|
||||
- XIAOMUSIC_EXCLUDE_DIRS 配置歌曲目录里需要忽略的目录
|
||||
- XIAOMUSIC_MUSIC_PATH_DEPTH 配置歌曲目录搜索深度,具体见 <https://github.com/hanxi/xiaomusic/issues/76>
|
||||
- XIAOMUSIC_DISABLE_HTTPAUTH 配置成 false 表示开启密码访问web控制台,具体见 <https://github.com/hanxi/xiaomusic/issues/47>
|
||||
- XIAOMUSIC_HTTPAUTH_USERNAME 配置 web 控制台用户
|
||||
- XIAOMUSIC_HTTPAUTH_PASSWORD 配置 web 控制台密码
|
||||
- XIAOMUSIC_CONF_PATH 用来存放配置文件的目录,记得把目录映射到主机,默认为 `/app/config` ,具体见 <https://github.com/hanxi/xiaomusic/issues/74>
|
||||
- XIAOMUSIC_DISABLE_DOWNLOAD 设为 true 时关闭下载功能,见 <https://github.com/hanxi/xiaomusic/issues/82>
|
||||
- XIAOMUSIC_USE_MUSIC_API 设为 true 时使用 player_play_music 接口播放音乐,用于兼容不能播放的型号,如果发现需要设置这个选项的时候请告知我加一下设备型号,方便以后不用设置。 见 <https://github.com/hanxi/xiaomusic/issues/30>
|
||||
- XIAOMUSIC_KEYWORDS_PLAY 用来播放歌曲的口令前缀,默认是 "播放歌曲,放歌曲" ,可以用英文逗号分割配置多个
|
||||
- XIAOMUSIC_KEYWORDS_STOP 用来关机的口令,默认是 "关机,暂停,停止" ,可以用英文逗号分割配置多个。
|
||||
- XIAOMUSIC_KEYWORDS_PLAYLOCAL 用来播放本地歌曲的口令前缀,本地找不到时不会下载歌曲,默认是 "播放本地歌曲,本地播放歌曲" ,可以用英文逗号分割配置多个。
|
||||
- XIAOMUSIC_ENABLE_FUZZY_MATCH 设为 true 时开启模糊匹配(默认),设为 false 时关闭模糊匹配,支持模糊匹配歌名和歌单名。 具体见 <https://github.com/hanxi/xiaomusic/issues/52>
|
||||
- XIAOMUSIC_FUZZY_MATCH_CUTOFF 设置模糊搜索匹配的最低相似度阈值(默认0.6,可以配0到1直接的小数),越小越模糊,越大越精准。具体见 <https://github.com/hanxi/xiaomusic/issues/52>
|
||||
- XIAOMUSIC_PUBLIC_PORT 用于设置外网端口,当使用反向代理时可以设置为外网端口,XIAOMUSIC_HOSTNAME 设为外网IP或者域名即可。
|
||||
- XIAOMUSIC_DOWNLOAD_PATH 变量可以配置下载目录,默认为空,表示使用 music 目录为下载目录。设置这个目录必须是 music 的子目录,否则刷新列表后会找不到歌曲。具体见 <https://github.com/hanxi/xiaomusic/issues/98>
|
||||
|
||||
## 高级篇
|
||||
|
||||
- 自定义口令功能 <https://github.com/hanxi/xiaomusic/issues/105>
|
||||
- [ ] 缺少一篇教程 [如何写自定义插件](https://github.com/hanxi/xiaomusic/issues/105)
|
||||
|
||||
## 讨论区
|
||||
|
||||
- [点击链接加入QQ频道【xiaomusic】](https://pd.qq.com/s/e2jybz0ss)
|
||||
- [点击链接加入群聊【xiaomusic】 604526973](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=13St5PLVcTxYlWTAs_iAawazjtdD1l-a&authKey=dJWEpaT2fDBDpdUUOWj%2FLt6NS1ePBfShDfz7a6seNURi05VvVnAGQzXF%2FM%2F5HgIm&noverify=0&group_code=604526973)
|
||||
- https://github.com/hanxi/xiaomusic/issues
|
||||
- <https://github.com/hanxi/xiaomusic/issues>
|
||||
- [微信群二维码](https://github.com/hanxi/xiaomusic/issues/86)
|
||||
|
||||
## 感谢
|
||||
|
||||
@@ -202,7 +355,15 @@ services:
|
||||
- [NAS部署教程](https://post.m.smzdm.com/p/avpe7n99/)
|
||||
- [群晖部署教程](https://post.m.smzdm.com/p/a7px7dol/)
|
||||
- [QNAS部署教程](https://post.smzdm.com/p/a5xz5x63/)
|
||||
- 所有帮忙调试和测试的朋友
|
||||
- 所有反馈问题和建议的朋友
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#hanxi/xiaomusic&Date)
|
||||
|
||||
## 赞赏
|
||||
|
||||
- 爱发电 <https://afdian.net/a/imhanxi>
|
||||
- 点个 Star ⭐
|
||||
- 谢谢 ❤️
|
||||
|
||||
81
config-example.json
Normal file
81
config-example.json
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"account": "",
|
||||
"password": "",
|
||||
"mi_did": "",
|
||||
"cookie": "",
|
||||
"verbose": false,
|
||||
"music_path": "music",
|
||||
"download_path": "",
|
||||
"conf_path": null,
|
||||
"hostname": "192.168.2.5",
|
||||
"port": 8090,
|
||||
"public_port": 0,
|
||||
"proxy": null,
|
||||
"search_prefix": "bilisearch:",
|
||||
"ffmpeg_location": "./ffmpeg/bin",
|
||||
"active_cmd": "play,set_random_play,playlocal,play_music_list,stop",
|
||||
"exclude_dirs": "@eaDir",
|
||||
"music_path_depth": 10,
|
||||
"disable_httpauth": true,
|
||||
"httpauth_username": "",
|
||||
"httpauth_password": "",
|
||||
"music_list_url": "",
|
||||
"music_list_json": "",
|
||||
"disable_download": false,
|
||||
"key_word_dict": {
|
||||
"播放歌曲": "play",
|
||||
"播放本地歌曲": "playlocal",
|
||||
"关机": "stop",
|
||||
"下一首": "play_next",
|
||||
"单曲循环": "set_play_type_one",
|
||||
"全部循环": "set_play_type_all",
|
||||
"随机播放": "set_random_play",
|
||||
"分钟后关机": "stop_after_minute",
|
||||
"播放列表": "play_music_list",
|
||||
"刷新列表": "gen_music_list",
|
||||
"本地播放歌曲": "playlocal",
|
||||
"放歌曲": "play",
|
||||
"暂停": "stop",
|
||||
"停止": "stop",
|
||||
"停止播放": "stop",
|
||||
"测试自定义口令": "exec#code1(\"hello\")",
|
||||
"测试链接": "exec#httpget(\"https://github.com/hanxi/xiaomusic\")"
|
||||
},
|
||||
"key_match_order": [
|
||||
"分钟后关机",
|
||||
"播放歌曲",
|
||||
"下一首",
|
||||
"单曲循环",
|
||||
"全部循环",
|
||||
"随机播放",
|
||||
"关机",
|
||||
"刷新列表",
|
||||
"播放列表",
|
||||
"播放本地歌曲",
|
||||
"本地播放歌曲",
|
||||
"放歌曲",
|
||||
"暂停",
|
||||
"停止",
|
||||
"停止播放",
|
||||
"测试自定义口令",
|
||||
"测试链接"
|
||||
],
|
||||
"use_music_api": false,
|
||||
"use_music_audio_id": "1582971365183456177",
|
||||
"use_music_id": "355454500",
|
||||
"log_file": "/tmp/xiaomusic.txt",
|
||||
"fuzzy_match_cutoff": 0.6,
|
||||
"enable_fuzzy_match": true,
|
||||
"stop_tts_msg": "收到,再见",
|
||||
"enable_config_example": true,
|
||||
"keywords_playlocal": "播放本地歌曲,本地播放歌曲",
|
||||
"keywords_play": "播放歌曲,放歌曲",
|
||||
"keywords_stop": "关机,暂停,停止,停止播放",
|
||||
"user_key_word_dict": {
|
||||
"测试自定义口令": "exec#code1(\"hello\")",
|
||||
"测试链接": "exec#httpget(\"https://github.com/hanxi/xiaomusic\")"
|
||||
},
|
||||
"enable_force_stop": false,
|
||||
"devices": {},
|
||||
"group_list": ""
|
||||
}
|
||||
@@ -4,14 +4,47 @@
|
||||
# https://github.com/yt-dlp/yt-dlp#dependencies
|
||||
|
||||
# 判断系统架构
|
||||
arch=$(arch)
|
||||
arch=$(uname -m)
|
||||
|
||||
pkg=ffmpeg-master-latest-linuxarm64-gpl
|
||||
if [[ "${arch}" == "x86_64" ]]; then
|
||||
pkg=ffmpeg-master-latest-linux64-gpl
|
||||
fi
|
||||
# 输出架构信息
|
||||
echo "当前系统架构是:$arch"
|
||||
|
||||
#export ALL_PROXY=http://192.168.2.5:8080
|
||||
wget https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/$pkg.tar.xz
|
||||
tar -xvJf $pkg.tar.xz
|
||||
mv $pkg ffmpeg
|
||||
install_from_github() {
|
||||
pkg=$1
|
||||
wget https://github.com/yt-dlp/FFmpeg-Builds/releases/download/latest/$pkg.tar.xz
|
||||
tar -xvJf $pkg.tar.xz
|
||||
mkdir -p ffmpeg/bin
|
||||
mv $pkg/bin/ffmpeg ffmpeg/bin/
|
||||
mv $pkg/bin/ffprobe ffmpeg/bin/
|
||||
}
|
||||
|
||||
install_from_ffmpeg() {
|
||||
pkg=$1
|
||||
wget https://johnvansickle.com/ffmpeg/builds/$pkg.tar.xz
|
||||
mkdir -p $pkg
|
||||
tar -xvJf $pkg.tar.xz -C $pkg
|
||||
mkdir -p ffmpeg/bin
|
||||
mv $pkg/*/ffmpeg ffmpeg/bin/
|
||||
mv $pkg/*/ffprobe ffmpeg/bin/
|
||||
}
|
||||
|
||||
# 基于架构执行不同的操作
|
||||
case "$arch" in
|
||||
x86_64)
|
||||
echo "64位 x86 架构"
|
||||
install_from_github ffmpeg-master-latest-linux64-gpl
|
||||
#install_from_ffmpeg ffmpeg-git-amd64-static
|
||||
;;
|
||||
arm64 | aarch64)
|
||||
echo "64位 ARM 架构"
|
||||
install_from_github ffmpeg-master-latest-linuxarm64-gpl
|
||||
#install_from_ffmpeg ffmpeg-git-arm64-static
|
||||
;;
|
||||
armv7l)
|
||||
echo "armv7l 架构"
|
||||
install_from_ffmpeg ffmpeg-git-armhf-static
|
||||
;;
|
||||
*)
|
||||
echo "未知架构 $arch"
|
||||
;;
|
||||
esac
|
||||
|
||||
9
newpatch.sh
Executable file
9
newpatch.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
./update-static-version.py
|
||||
git add xiaomusic/static
|
||||
git commit -m 'build: update static version'
|
||||
|
||||
cz bump --check-consistency --increment patch
|
||||
|
||||
git push -u origin main --tags
|
||||
@@ -1,37 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
./update-static-version.py
|
||||
git add xiaomusic/static
|
||||
git commit -m 'build: update static version'
|
||||
|
||||
version_file=./pyproject.toml
|
||||
init_file=./xiaomusic/__init__.py
|
||||
# 获取当前版本号
|
||||
current_version=$(grep -oE "version = \"[0-9]+\.[0-9]+\.[0-9]+\"" $version_file | cut -d'"' -f2)
|
||||
echo "当前版本号: "$current_version
|
||||
cz bump --check-consistency
|
||||
|
||||
# 将版本号分割成三部分
|
||||
major=$(echo $current_version | cut -d'.' -f1)
|
||||
minor=$(echo $current_version | cut -d'.' -f2)
|
||||
patch=$(echo $current_version | cut -d'.' -f3)
|
||||
|
||||
echo "major: $major"
|
||||
echo "minor: $minor"
|
||||
echo "patch: $patch"
|
||||
|
||||
# 将补丁号加1
|
||||
patch=$((patch + 1))
|
||||
|
||||
# 生成新版本号
|
||||
new_version="$major.$minor.$patch"
|
||||
|
||||
# 将新版本号写入文件
|
||||
sed -i "s/version.*/version = \"$new_version\"/g" $version_file
|
||||
sed -i "s/__version__.*/__version__ = \"$new_version\"/g" $init_file
|
||||
|
||||
echo "新版本号:$new_version"
|
||||
|
||||
git diff
|
||||
git add $version_file
|
||||
git add $init_file
|
||||
git commit -m "new version v$new_version"
|
||||
git tag v$new_version
|
||||
git push -u origin main --tags
|
||||
|
||||
824
pdm.lock
generated
824
pdm.lock
generated
@@ -2,10 +2,10 @@
|
||||
# It is not intended for manual editing.
|
||||
|
||||
[metadata]
|
||||
groups = ["default", "lint"]
|
||||
groups = ["default", "lint", "dev"]
|
||||
strategy = ["cross_platform"]
|
||||
lock_version = "4.4.1"
|
||||
content_hash = "sha256:fa83f8134ccb4a432304dead5fe1303899418558634abaa0824e8d9fdfb1f490"
|
||||
lock_version = "4.4.2"
|
||||
content_hash = "sha256:fe8f356d82d38641f48975833c27c352829a895c3c3293c36e0e010a3202966e"
|
||||
|
||||
[[package]]
|
||||
name = "aiohttp"
|
||||
@@ -83,16 +83,39 @@ files = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asgiref"
|
||||
version = "3.7.2"
|
||||
requires_python = ">=3.7"
|
||||
summary = "ASGI specs, helper code, and adapters"
|
||||
name = "annotated-types"
|
||||
version = "0.7.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Reusable constraint types to use with typing.Annotated"
|
||||
files = [
|
||||
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
|
||||
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.4.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "High level compatibility layer for multiple asynchronous event loop implementations"
|
||||
dependencies = [
|
||||
"typing-extensions>=4; python_version < \"3.11\"",
|
||||
"exceptiongroup>=1.0.2; python_version < \"3.11\"",
|
||||
"idna>=2.8",
|
||||
"sniffio>=1.1",
|
||||
"typing-extensions>=4.1; python_version < \"3.11\"",
|
||||
]
|
||||
files = [
|
||||
{file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"},
|
||||
{file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
|
||||
{file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"},
|
||||
{file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argcomplete"
|
||||
version = "3.3.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Bash tab completion for argparse"
|
||||
files = [
|
||||
{file = "argcomplete-3.3.0-py3-none-any.whl", hash = "sha256:c168c3723482c031df3c207d4ba8fa702717ccb9fc0bfe4117166c1f537b4a54"},
|
||||
{file = "argcomplete-3.3.0.tar.gz", hash = "sha256:fd03ff4a5b9e6580569d34b273f741e85cd9e072f3feeeee3eba4891c70eda62"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -115,16 +138,6 @@ files = [
|
||||
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blinker"
|
||||
version = "1.7.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Fast, simple object-to-object and broadcast signaling"
|
||||
files = [
|
||||
{file = "blinker-1.7.0-py3-none-any.whl", hash = "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9"},
|
||||
{file = "blinker-1.7.0.tar.gz", hash = "sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "1.1.0"
|
||||
@@ -340,35 +353,106 @@ files = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flask"
|
||||
version = "3.0.3"
|
||||
name = "commitizen"
|
||||
version = "3.27.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A simple framework for building complex web applications."
|
||||
summary = "Python commitizen client tool"
|
||||
dependencies = [
|
||||
"Jinja2>=3.1.2",
|
||||
"Werkzeug>=3.0.0",
|
||||
"blinker>=1.6.2",
|
||||
"click>=8.1.3",
|
||||
"itsdangerous>=2.1.2",
|
||||
"argcomplete<3.4,>=1.12.1",
|
||||
"charset-normalizer<4,>=2.1.0",
|
||||
"colorama<0.5.0,>=0.4.1",
|
||||
"decli<0.7.0,>=0.6.0",
|
||||
"importlib-metadata<8,>=4.13",
|
||||
"jinja2>=2.10.3",
|
||||
"packaging>=19",
|
||||
"pyyaml>=3.08",
|
||||
"questionary<3.0,>=2.0",
|
||||
"termcolor<3,>=1.1",
|
||||
"tomlkit<1.0.0,>=0.5.3",
|
||||
]
|
||||
files = [
|
||||
{file = "flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3"},
|
||||
{file = "flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"},
|
||||
{file = "commitizen-3.27.0-py3-none-any.whl", hash = "sha256:11948fa563d5ad5464baf09eaacff3cf8cbade1ca029ed9c4978f2227f033130"},
|
||||
{file = "commitizen-3.27.0.tar.gz", hash = "sha256:5874d0c7e8e1be3b75b1b0a2269cffe3dd5c843b860d84b0bdbb9ea86e3474b8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flask"
|
||||
version = "3.0.3"
|
||||
extras = ["async"]
|
||||
name = "decli"
|
||||
version = "0.6.2"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Minimal, easy-to-use, declarative cli tool"
|
||||
files = [
|
||||
{file = "decli-0.6.2-py3-none-any.whl", hash = "sha256:2fc84106ce9a8f523ed501ca543bdb7e416c064917c12a59ebdc7f311a97b7ed"},
|
||||
{file = "decli-0.6.2.tar.gz", hash = "sha256:36f71eb55fd0093895efb4f416ec32b7f6e00147dda448e3365cf73ceab42d6f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dnspython"
|
||||
version = "2.6.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A simple framework for building complex web applications."
|
||||
summary = "DNS toolkit"
|
||||
files = [
|
||||
{file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"},
|
||||
{file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "email-validator"
|
||||
version = "2.2.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A robust email address syntax and deliverability validation library."
|
||||
dependencies = [
|
||||
"asgiref>=3.2",
|
||||
"flask==3.0.3",
|
||||
"dnspython>=2.0.0",
|
||||
"idna>=2.0.0",
|
||||
]
|
||||
files = [
|
||||
{file = "flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3"},
|
||||
{file = "flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"},
|
||||
{file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"},
|
||||
{file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.2.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Backport of PEP 654 (exception groups)"
|
||||
files = [
|
||||
{file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"},
|
||||
{file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastapi"
|
||||
version = "0.111.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
|
||||
dependencies = [
|
||||
"email-validator>=2.0.0",
|
||||
"fastapi-cli>=0.0.2",
|
||||
"httpx>=0.23.0",
|
||||
"jinja2>=2.11.2",
|
||||
"orjson>=3.2.1",
|
||||
"pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4",
|
||||
"python-multipart>=0.0.7",
|
||||
"starlette<0.38.0,>=0.37.2",
|
||||
"typing-extensions>=4.8.0",
|
||||
"ujson!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,>=4.0.1",
|
||||
"uvicorn[standard]>=0.12.0",
|
||||
]
|
||||
files = [
|
||||
{file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"},
|
||||
{file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastapi-cli"
|
||||
version = "0.0.4"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Run and manage FastAPI apps from the command line with FastAPI CLI. 🚀"
|
||||
dependencies = [
|
||||
"typer>=0.12.3",
|
||||
]
|
||||
files = [
|
||||
{file = "fastapi_cli-0.0.4-py3-none-any.whl", hash = "sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809"},
|
||||
{file = "fastapi_cli-0.0.4.tar.gz", hash = "sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -410,6 +494,77 @@ files = [
|
||||
{file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.14.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
|
||||
files = [
|
||||
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
|
||||
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.5"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A minimal low-level HTTP client."
|
||||
dependencies = [
|
||||
"certifi",
|
||||
"h11<0.15,>=0.13",
|
||||
]
|
||||
files = [
|
||||
{file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"},
|
||||
{file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httptools"
|
||||
version = "0.6.1"
|
||||
requires_python = ">=3.8.0"
|
||||
summary = "A collection of framework independent HTTP protocol utils."
|
||||
files = [
|
||||
{file = "httptools-0.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f"},
|
||||
{file = "httptools-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563"},
|
||||
{file = "httptools-0.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58"},
|
||||
{file = "httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185"},
|
||||
{file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142"},
|
||||
{file = "httptools-0.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658"},
|
||||
{file = "httptools-0.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b"},
|
||||
{file = "httptools-0.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1"},
|
||||
{file = "httptools-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0"},
|
||||
{file = "httptools-0.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc"},
|
||||
{file = "httptools-0.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2"},
|
||||
{file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837"},
|
||||
{file = "httptools-0.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d"},
|
||||
{file = "httptools-0.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3"},
|
||||
{file = "httptools-0.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0"},
|
||||
{file = "httptools-0.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2"},
|
||||
{file = "httptools-0.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90"},
|
||||
{file = "httptools-0.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503"},
|
||||
{file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84"},
|
||||
{file = "httptools-0.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb"},
|
||||
{file = "httptools-0.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949"},
|
||||
{file = "httptools-0.6.1.tar.gz", hash = "sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.27.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "The next generation HTTP client."
|
||||
dependencies = [
|
||||
"anyio",
|
||||
"certifi",
|
||||
"httpcore==1.*",
|
||||
"idna",
|
||||
"sniffio",
|
||||
]
|
||||
files = [
|
||||
{file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"},
|
||||
{file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.4"
|
||||
@@ -421,13 +576,16 @@ files = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itsdangerous"
|
||||
version = "2.1.2"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Safely pass data to untrusted environments and back."
|
||||
name = "importlib-metadata"
|
||||
version = "7.2.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Read metadata from Python packages"
|
||||
dependencies = [
|
||||
"zipp>=0.5",
|
||||
]
|
||||
files = [
|
||||
{file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
|
||||
{file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"},
|
||||
{file = "importlib_metadata-7.2.1-py3-none-any.whl", hash = "sha256:ffef94b0b66046dd8ea2d619b701fe978d9264d38f3998bc4c27ec3b146a87c8"},
|
||||
{file = "importlib_metadata-7.2.1.tar.gz", hash = "sha256:509ecb2ab77071db5137c655e24ceb3eee66e7bbc6574165d0d114d9fc4bbe68"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -507,7 +665,7 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "miservice-fork"
|
||||
version = "2.5.0"
|
||||
version = "2.7.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "XiaoMi Cloud Service fork from https://github.com/Yonsm/MiService"
|
||||
dependencies = [
|
||||
@@ -516,8 +674,8 @@ dependencies = [
|
||||
"rich",
|
||||
]
|
||||
files = [
|
||||
{file = "miservice_fork-2.5.0-py3-none-any.whl", hash = "sha256:97b6360ea53c34fe035ac9d94e8705f305b8fa7fc2b44a7aea182449a76cb622"},
|
||||
{file = "miservice_fork-2.5.0.tar.gz", hash = "sha256:8ca2d370d5b32f7e330add38aa1912d734aefa7880f16cef9eac110a5a3029e2"},
|
||||
{file = "miservice_fork-2.7.0-py3-none-any.whl", hash = "sha256:8e2c91ebe1fc4b3c63b01cbf1818e5d5833d024fd3a8311970d649ad2d49d6e6"},
|
||||
{file = "miservice_fork-2.7.0.tar.gz", hash = "sha256:8e87ef6d89adceaf3f7a98242cdae1c9135498d77f2c743ec3871d2e42bcbab8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -569,6 +727,68 @@ files = [
|
||||
{file = "mutagen-1.47.0.tar.gz", hash = "sha256:719fadef0a978c31b4cf3c956261b3c58b6948b32023078a2117b1de09f0fc99"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "orjson"
|
||||
version = "3.10.6"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
|
||||
files = [
|
||||
{file = "orjson-3.10.6-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7"},
|
||||
{file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365"},
|
||||
{file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eadc8fd310edb4bdbd333374f2c8fec6794bbbae99b592f448d8214a5e4050c0"},
|
||||
{file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:61272a5aec2b2661f4fa2b37c907ce9701e821b2c1285d5c3ab0207ebd358d38"},
|
||||
{file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57985ee7e91d6214c837936dc1608f40f330a6b88bb13f5a57ce5257807da143"},
|
||||
{file = "orjson-3.10.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:633a3b31d9d7c9f02d49c4ab4d0a86065c4a6f6adc297d63d272e043472acab5"},
|
||||
{file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1c680b269d33ec444afe2bdc647c9eb73166fa47a16d9a75ee56a374f4a45f43"},
|
||||
{file = "orjson-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f759503a97a6ace19e55461395ab0d618b5a117e8d0fbb20e70cfd68a47327f2"},
|
||||
{file = "orjson-3.10.6-cp310-none-win32.whl", hash = "sha256:95a0cce17f969fb5391762e5719575217bd10ac5a189d1979442ee54456393f3"},
|
||||
{file = "orjson-3.10.6-cp310-none-win_amd64.whl", hash = "sha256:df25d9271270ba2133cc88ee83c318372bdc0f2cd6f32e7a450809a111efc45c"},
|
||||
{file = "orjson-3.10.6-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b1ec490e10d2a77c345def52599311849fc063ae0e67cf4f84528073152bb2ba"},
|
||||
{file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d43d3feb8f19d07e9f01e5b9be4f28801cf7c60d0fa0d279951b18fae1932b"},
|
||||
{file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3045267e98fe749408eee1593a142e02357c5c99be0802185ef2170086a863"},
|
||||
{file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c27bc6a28ae95923350ab382c57113abd38f3928af3c80be6f2ba7eb8d8db0b0"},
|
||||
{file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d27456491ca79532d11e507cadca37fb8c9324a3976294f68fb1eff2dc6ced5a"},
|
||||
{file = "orjson-3.10.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05ac3d3916023745aa3b3b388e91b9166be1ca02b7c7e41045da6d12985685f0"},
|
||||
{file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1335d4ef59ab85cab66fe73fd7a4e881c298ee7f63ede918b7faa1b27cbe5212"},
|
||||
{file = "orjson-3.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4bbc6d0af24c1575edc79994c20e1b29e6fb3c6a570371306db0993ecf144dc5"},
|
||||
{file = "orjson-3.10.6-cp311-none-win32.whl", hash = "sha256:450e39ab1f7694465060a0550b3f6d328d20297bf2e06aa947b97c21e5241fbd"},
|
||||
{file = "orjson-3.10.6-cp311-none-win_amd64.whl", hash = "sha256:227df19441372610b20e05bdb906e1742ec2ad7a66ac8350dcfd29a63014a83b"},
|
||||
{file = "orjson-3.10.6-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:ea2977b21f8d5d9b758bb3f344a75e55ca78e3ff85595d248eee813ae23ecdfb"},
|
||||
{file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6f3d167d13a16ed263b52dbfedff52c962bfd3d270b46b7518365bcc2121eed"},
|
||||
{file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f710f346e4c44a4e8bdf23daa974faede58f83334289df80bc9cd12fe82573c7"},
|
||||
{file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7275664f84e027dcb1ad5200b8b18373e9c669b2a9ec33d410c40f5ccf4b257e"},
|
||||
{file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0943e4c701196b23c240b3d10ed8ecd674f03089198cf503105b474a4f77f21f"},
|
||||
{file = "orjson-3.10.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:446dee5a491b5bc7d8f825d80d9637e7af43f86a331207b9c9610e2f93fee22a"},
|
||||
{file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:64c81456d2a050d380786413786b057983892db105516639cb5d3ee3c7fd5148"},
|
||||
{file = "orjson-3.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34"},
|
||||
{file = "orjson-3.10.6-cp312-none-win32.whl", hash = "sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5"},
|
||||
{file = "orjson-3.10.6-cp312-none-win_amd64.whl", hash = "sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc"},
|
||||
{file = "orjson-3.10.6.tar.gz", hash = "sha256:e54b63d0a7c6c54a5f5f726bc93a2078111ef060fec4ecbf34c5db800ca3b3a7"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "24.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Core utilities for Python packages"
|
||||
files = [
|
||||
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
||||
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prompt-toolkit"
|
||||
version = "3.0.36"
|
||||
requires_python = ">=3.6.2"
|
||||
summary = "Library for building powerful interactive command lines in Python"
|
||||
dependencies = [
|
||||
"wcwidth",
|
||||
]
|
||||
files = [
|
||||
{file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"},
|
||||
{file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.21"
|
||||
@@ -608,6 +828,98 @@ files = [
|
||||
{file = "pycryptodomex-3.19.0.tar.gz", hash = "sha256:af83a554b3f077564229865c45af0791be008ac6469ef0098152139e6bd4b5b6"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.8.2"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Data validation using Python type hints"
|
||||
dependencies = [
|
||||
"annotated-types>=0.4.0",
|
||||
"pydantic-core==2.20.1",
|
||||
"typing-extensions>=4.12.2; python_version >= \"3.13\"",
|
||||
"typing-extensions>=4.6.1; python_version < \"3.13\"",
|
||||
]
|
||||
files = [
|
||||
{file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"},
|
||||
{file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.20.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Core functionality for Pydantic validation and serialization"
|
||||
dependencies = [
|
||||
"typing-extensions!=4.7.0,>=4.6.0",
|
||||
]
|
||||
files = [
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"},
|
||||
{file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"},
|
||||
{file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"},
|
||||
{file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"},
|
||||
{file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"},
|
||||
{file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"},
|
||||
{file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"},
|
||||
{file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"},
|
||||
{file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"},
|
||||
{file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"},
|
||||
{file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"},
|
||||
{file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"},
|
||||
{file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"},
|
||||
{file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"},
|
||||
{file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"},
|
||||
{file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"},
|
||||
{file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"},
|
||||
{file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"},
|
||||
{file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"},
|
||||
{file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"},
|
||||
{file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"},
|
||||
{file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"},
|
||||
{file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"},
|
||||
{file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"},
|
||||
{file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"},
|
||||
{file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"},
|
||||
{file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"},
|
||||
{file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"},
|
||||
{file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"},
|
||||
{file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygments"
|
||||
version = "2.16.1"
|
||||
@@ -618,10 +930,75 @@ files = [
|
||||
{file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.0.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Read key-value pairs from a .env file and set them as environment variables"
|
||||
files = [
|
||||
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
|
||||
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-multipart"
|
||||
version = "0.0.9"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A streaming multipart parser for Python"
|
||||
files = [
|
||||
{file = "python_multipart-0.0.9-py3-none-any.whl", hash = "sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215"},
|
||||
{file = "python_multipart-0.0.9.tar.gz", hash = "sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.1"
|
||||
requires_python = ">=3.6"
|
||||
summary = "YAML parser and emitter for Python"
|
||||
files = [
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
|
||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "questionary"
|
||||
version = "2.0.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Python library to build pretty command line user prompts ⭐️"
|
||||
dependencies = [
|
||||
"prompt-toolkit<=3.0.36,>=2.0",
|
||||
]
|
||||
files = [
|
||||
{file = "questionary-2.0.1-py3-none-any.whl", hash = "sha256:8ab9a01d0b91b68444dff7f6652c1e754105533f083cbe27597c8110ecc230a2"},
|
||||
{file = "questionary-2.0.1.tar.gz", hash = "sha256:bcce898bf3dbb446ff62830c86c5c6fb9a22a54146f0f5597d3da43b10d8fc8b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.31.0"
|
||||
requires_python = ">=3.7"
|
||||
version = "2.32.3"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Python HTTP for Humans."
|
||||
dependencies = [
|
||||
"certifi>=2017.4.17",
|
||||
@@ -630,8 +1007,8 @@ dependencies = [
|
||||
"urllib3<3,>=1.21.1",
|
||||
]
|
||||
files = [
|
||||
{file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
|
||||
{file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
|
||||
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -650,37 +1027,173 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.4.8"
|
||||
version = "0.5.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
files = [
|
||||
{file = "ruff-0.4.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7663a6d78f6adb0eab270fa9cf1ff2d28618ca3a652b60f2a234d92b9ec89066"},
|
||||
{file = "ruff-0.4.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eeceb78da8afb6de0ddada93112869852d04f1cd0f6b80fe464fd4e35c330913"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aad360893e92486662ef3be0a339c5ca3c1b109e0134fcd37d534d4be9fb8de3"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:284c2e3f3396fb05f5f803c9fffb53ebbe09a3ebe7dda2929ed8d73ded736deb"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7354f921e3fbe04d2a62d46707e569f9315e1a613307f7311a935743c51a764"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:72584676164e15a68a15778fd1b17c28a519e7a0622161eb2debdcdabdc71883"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9678d5c9b43315f323af2233a04d747409d1e3aa6789620083a82d1066a35199"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704977a658131651a22b5ebeb28b717ef42ac6ee3b11e91dc87b633b5d83142b"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05f8d6f0c3cce5026cecd83b7a143dcad503045857bc49662f736437380ad45"},
|
||||
{file = "ruff-0.4.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6ea874950daca5697309d976c9afba830d3bf0ed66887481d6bca1673fc5b66a"},
|
||||
{file = "ruff-0.4.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fc95aac2943ddf360376be9aa3107c8cf9640083940a8c5bd824be692d2216dc"},
|
||||
{file = "ruff-0.4.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:384154a1c3f4bf537bac69f33720957ee49ac8d484bfc91720cc94172026ceed"},
|
||||
{file = "ruff-0.4.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e9d5ce97cacc99878aa0d084c626a15cd21e6b3d53fd6f9112b7fc485918e1fa"},
|
||||
{file = "ruff-0.4.8-py3-none-win32.whl", hash = "sha256:6d795d7639212c2dfd01991259460101c22aabf420d9b943f153ab9d9706e6a9"},
|
||||
{file = "ruff-0.4.8-py3-none-win_amd64.whl", hash = "sha256:e14a3a095d07560a9d6769a72f781d73259655919d9b396c650fc98a8157555d"},
|
||||
{file = "ruff-0.4.8-py3-none-win_arm64.whl", hash = "sha256:14019a06dbe29b608f6b7cbcec300e3170a8d86efaddb7b23405cb7f7dcaf780"},
|
||||
{file = "ruff-0.4.8.tar.gz", hash = "sha256:16d717b1d57b2e2fd68bd0bf80fb43931b79d05a7131aa477d66fc40fbd86268"},
|
||||
{file = "ruff-0.5.1-py3-none-linux_armv6l.whl", hash = "sha256:6ecf968fcf94d942d42b700af18ede94b07521bd188aaf2cd7bc898dd8cb63b6"},
|
||||
{file = "ruff-0.5.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:204fb0a472f00f2e6280a7c8c7c066e11e20e23a37557d63045bf27a616ba61c"},
|
||||
{file = "ruff-0.5.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d235968460e8758d1e1297e1de59a38d94102f60cafb4d5382033c324404ee9d"},
|
||||
{file = "ruff-0.5.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38beace10b8d5f9b6bdc91619310af6d63dd2019f3fb2d17a2da26360d7962fa"},
|
||||
{file = "ruff-0.5.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e478d2f09cf06add143cf8c4540ef77b6599191e0c50ed976582f06e588c994"},
|
||||
{file = "ruff-0.5.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0368d765eec8247b8550251c49ebb20554cc4e812f383ff9f5bf0d5d94190b0"},
|
||||
{file = "ruff-0.5.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3a9a9a1b582e37669b0138b7c1d9d60b9edac880b80eb2baba6d0e566bdeca4d"},
|
||||
{file = "ruff-0.5.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bdd9f723e16003623423affabcc0a807a66552ee6a29f90eddad87a40c750b78"},
|
||||
{file = "ruff-0.5.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be9fd62c1e99539da05fcdc1e90d20f74aec1b7a1613463ed77870057cd6bd96"},
|
||||
{file = "ruff-0.5.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e216fc75a80ea1fbd96af94a6233d90190d5b65cc3d5dfacf2bd48c3e067d3e1"},
|
||||
{file = "ruff-0.5.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c4c2112e9883a40967827d5c24803525145e7dab315497fae149764979ac7929"},
|
||||
{file = "ruff-0.5.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dfaf11c8a116394da3b65cd4b36de30d8552fa45b8119b9ef5ca6638ab964fa3"},
|
||||
{file = "ruff-0.5.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d7ceb9b2fe700ee09a0c6b192c5ef03c56eb82a0514218d8ff700f6ade004108"},
|
||||
{file = "ruff-0.5.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:bac6288e82f6296f82ed5285f597713acb2a6ae26618ffc6b429c597b392535c"},
|
||||
{file = "ruff-0.5.1-py3-none-win32.whl", hash = "sha256:5c441d9c24ec09e1cb190a04535c5379b36b73c4bc20aa180c54812c27d1cca4"},
|
||||
{file = "ruff-0.5.1-py3-none-win_amd64.whl", hash = "sha256:b1789bf2cd3d1b5a7d38397cac1398ddf3ad7f73f4de01b1e913e2abc7dfc51d"},
|
||||
{file = "ruff-0.5.1-py3-none-win_arm64.whl", hash = "sha256:2875b7596a740cbbd492f32d24be73e545a4ce0a3daf51e4f4e609962bfd3cd2"},
|
||||
{file = "ruff-0.5.1.tar.gz", hash = "sha256:3164488aebd89b1745b47fd00604fb4358d774465f20d1fcd907f9c0fc1b0655"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellingham"
|
||||
version = "1.5.4"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Tool to Detect Surrounding Shell"
|
||||
files = [
|
||||
{file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
|
||||
{file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sniffio"
|
||||
version = "1.3.1"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Sniff out which async library your code is running under"
|
||||
files = [
|
||||
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
|
||||
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "starlette"
|
||||
version = "0.37.2"
|
||||
requires_python = ">=3.8"
|
||||
summary = "The little ASGI library that shines."
|
||||
dependencies = [
|
||||
"anyio<5,>=3.4.0",
|
||||
]
|
||||
files = [
|
||||
{file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"},
|
||||
{file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "2.4.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "ANSI color formatting for output in terminal"
|
||||
files = [
|
||||
{file = "termcolor-2.4.0-py3-none-any.whl", hash = "sha256:9297c0df9c99445c2412e832e882a7884038a25617c60cea2ad69488d4040d63"},
|
||||
{file = "termcolor-2.4.0.tar.gz", hash = "sha256:aab9e56047c8ac41ed798fa36d892a37aca6b3e9159f3e0c24bc64a9b3ac7b7a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomlkit"
|
||||
version = "0.12.5"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Style preserving TOML library"
|
||||
files = [
|
||||
{file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"},
|
||||
{file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typer"
|
||||
version = "0.12.3"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Typer, build great CLIs. Easy to code. Based on Python type hints."
|
||||
dependencies = [
|
||||
"click>=8.0.0",
|
||||
"rich>=10.11.0",
|
||||
"shellingham>=1.3.0",
|
||||
"typing-extensions>=3.7.4.3",
|
||||
]
|
||||
files = [
|
||||
{file = "typer-0.12.3-py3-none-any.whl", hash = "sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914"},
|
||||
{file = "typer-0.12.3.tar.gz", hash = "sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.9.0"
|
||||
version = "4.12.2"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
files = [
|
||||
{file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"},
|
||||
{file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"},
|
||||
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
|
||||
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ujson"
|
||||
version = "5.10.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Ultra fast JSON encoder and decoder for Python"
|
||||
files = [
|
||||
{file = "ujson-5.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-win32.whl", hash = "sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518"},
|
||||
{file = "ujson-5.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-win32.whl", hash = "sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f"},
|
||||
{file = "ujson-5.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-win32.whl", hash = "sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e"},
|
||||
{file = "ujson-5.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-win32.whl", hash = "sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165"},
|
||||
{file = "ujson-5.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539"},
|
||||
{file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64"},
|
||||
{file = "ujson-5.10.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3"},
|
||||
{file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a"},
|
||||
{file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746"},
|
||||
{file = "ujson-5.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88"},
|
||||
{file = "ujson-5.10.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b"},
|
||||
{file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337"},
|
||||
{file = "ujson-5.10.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1"},
|
||||
{file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753"},
|
||||
{file = "ujson-5.10.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6"},
|
||||
{file = "ujson-5.10.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5"},
|
||||
{file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4"},
|
||||
{file = "ujson-5.10.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8"},
|
||||
{file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b"},
|
||||
{file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804"},
|
||||
{file = "ujson-5.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e"},
|
||||
{file = "ujson-5.10.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7"},
|
||||
{file = "ujson-5.10.0.tar.gz", hash = "sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -694,13 +1207,137 @@ files = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "waitress"
|
||||
version = "3.0.0"
|
||||
requires_python = ">=3.8.0"
|
||||
summary = "Waitress WSGI server"
|
||||
name = "uvicorn"
|
||||
version = "0.30.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "The lightning-fast ASGI server."
|
||||
dependencies = [
|
||||
"click>=7.0",
|
||||
"h11>=0.8",
|
||||
"typing-extensions>=4.0; python_version < \"3.11\"",
|
||||
]
|
||||
files = [
|
||||
{file = "waitress-3.0.0-py3-none-any.whl", hash = "sha256:2a06f242f4ba0cc563444ca3d1998959447477363a2d7e9b8b4d75d35cfd1669"},
|
||||
{file = "waitress-3.0.0.tar.gz", hash = "sha256:005da479b04134cdd9dd602d1ee7c49d79de0537610d653674cc6cbde222b8a1"},
|
||||
{file = "uvicorn-0.30.1-py3-none-any.whl", hash = "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81"},
|
||||
{file = "uvicorn-0.30.1.tar.gz", hash = "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uvicorn"
|
||||
version = "0.30.1"
|
||||
extras = ["standard"]
|
||||
requires_python = ">=3.8"
|
||||
summary = "The lightning-fast ASGI server."
|
||||
dependencies = [
|
||||
"colorama>=0.4; sys_platform == \"win32\"",
|
||||
"httptools>=0.5.0",
|
||||
"python-dotenv>=0.13",
|
||||
"pyyaml>=5.1",
|
||||
"uvicorn==0.30.1",
|
||||
"uvloop!=0.15.0,!=0.15.1,>=0.14.0; (sys_platform != \"cygwin\" and sys_platform != \"win32\") and platform_python_implementation != \"PyPy\"",
|
||||
"watchfiles>=0.13",
|
||||
"websockets>=10.4",
|
||||
]
|
||||
files = [
|
||||
{file = "uvicorn-0.30.1-py3-none-any.whl", hash = "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81"},
|
||||
{file = "uvicorn-0.30.1.tar.gz", hash = "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uvloop"
|
||||
version = "0.19.0"
|
||||
requires_python = ">=3.8.0"
|
||||
summary = "Fast implementation of asyncio event loop on top of libuv"
|
||||
files = [
|
||||
{file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e"},
|
||||
{file = "uvloop-0.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428"},
|
||||
{file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8"},
|
||||
{file = "uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849"},
|
||||
{file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957"},
|
||||
{file = "uvloop-0.19.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd"},
|
||||
{file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef"},
|
||||
{file = "uvloop-0.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2"},
|
||||
{file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1"},
|
||||
{file = "uvloop-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24"},
|
||||
{file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533"},
|
||||
{file = "uvloop-0.19.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12"},
|
||||
{file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650"},
|
||||
{file = "uvloop-0.19.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec"},
|
||||
{file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc"},
|
||||
{file = "uvloop-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6"},
|
||||
{file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593"},
|
||||
{file = "uvloop-0.19.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3"},
|
||||
{file = "uvloop-0.19.0.tar.gz", hash = "sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "watchfiles"
|
||||
version = "0.22.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Simple, modern and high performance file watching and code reload in python."
|
||||
dependencies = [
|
||||
"anyio>=3.0.0",
|
||||
]
|
||||
files = [
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39"},
|
||||
{file = "watchfiles-0.22.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848"},
|
||||
{file = "watchfiles-0.22.0-cp310-none-win32.whl", hash = "sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797"},
|
||||
{file = "watchfiles-0.22.0-cp310-none-win_amd64.whl", hash = "sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d"},
|
||||
{file = "watchfiles-0.22.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c"},
|
||||
{file = "watchfiles-0.22.0-cp311-none-win32.whl", hash = "sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67"},
|
||||
{file = "watchfiles-0.22.0-cp311-none-win_amd64.whl", hash = "sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1"},
|
||||
{file = "watchfiles-0.22.0-cp311-none-win_arm64.whl", hash = "sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b"},
|
||||
{file = "watchfiles-0.22.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35"},
|
||||
{file = "watchfiles-0.22.0-cp312-none-win32.whl", hash = "sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e"},
|
||||
{file = "watchfiles-0.22.0-cp312-none-win_amd64.whl", hash = "sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e"},
|
||||
{file = "watchfiles-0.22.0-cp312-none-win_arm64.whl", hash = "sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea"},
|
||||
{file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68"},
|
||||
{file = "watchfiles-0.22.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c"},
|
||||
{file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab"},
|
||||
{file = "watchfiles-0.22.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2"},
|
||||
{file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2"},
|
||||
{file = "watchfiles-0.22.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6"},
|
||||
{file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795"},
|
||||
{file = "watchfiles-0.22.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71"},
|
||||
{file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed"},
|
||||
{file = "watchfiles-0.22.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc"},
|
||||
{file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31"},
|
||||
{file = "watchfiles-0.22.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2"},
|
||||
{file = "watchfiles-0.22.0.tar.gz", hash = "sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wcwidth"
|
||||
version = "0.2.13"
|
||||
summary = "Measures the displayed width of unicode strings in a terminal"
|
||||
files = [
|
||||
{file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
|
||||
{file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -761,19 +1398,6 @@ files = [
|
||||
{file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "werkzeug"
|
||||
version = "3.0.1"
|
||||
requires_python = ">=3.8"
|
||||
summary = "The comprehensive WSGI web application library."
|
||||
dependencies = [
|
||||
"MarkupSafe>=2.1.1",
|
||||
]
|
||||
files = [
|
||||
{file = "werkzeug-3.0.1-py3-none-any.whl", hash = "sha256:90a285dc0e42ad56b34e696398b8122ee4c681833fb35b8334a095d82c56da10"},
|
||||
{file = "werkzeug-3.0.1.tar.gz", hash = "sha256:507e811ecea72b18a404947aded4b3390e1db8f826b494d76550ef45bb3b1dcc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yarl"
|
||||
version = "1.9.2"
|
||||
@@ -819,7 +1443,7 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "yt-dlp"
|
||||
version = "2024.5.16.232713.dev0"
|
||||
version = "2024.7.9"
|
||||
requires_python = ">=3.8"
|
||||
summary = "A feature-rich command-line audio/video downloader"
|
||||
dependencies = [
|
||||
@@ -828,11 +1452,21 @@ dependencies = [
|
||||
"certifi",
|
||||
"mutagen",
|
||||
"pycryptodomex",
|
||||
"requests<3,>=2.31.0",
|
||||
"requests<3,>=2.32.2",
|
||||
"urllib3<3,>=1.26.17",
|
||||
"websockets>=12.0",
|
||||
]
|
||||
files = [
|
||||
{file = "yt_dlp-2024.5.16.232713.dev0-py3-none-any.whl", hash = "sha256:42d3c27ab77583ff67ee2ddc94e376ea2a76a561ed8b1836ee04fd1cd23ad88c"},
|
||||
{file = "yt_dlp-2024.5.16.232713.dev0.tar.gz", hash = "sha256:d431187fa703c9f52225080ae56471272679e44d9363f97b7b3187d37a5e6480"},
|
||||
{file = "yt_dlp-2024.7.9-py3-none-any.whl", hash = "sha256:b50a595abde523b5cc84d788f97e69c642503bd673ba740f709ebf65b5ec6592"},
|
||||
{file = "yt_dlp-2024.7.9.tar.gz", hash = "sha256:e19f00f9e55e90bca1c94bcaf809aa33e51634be9f0de2df84a72d3206934f94"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.19.2"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
files = [
|
||||
{file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"},
|
||||
{file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"},
|
||||
]
|
||||
|
||||
0
plugins/__init__.py
Normal file
0
plugins/__init__.py
Normal file
4
plugins/code1.py
Normal file
4
plugins/code1.py
Normal file
@@ -0,0 +1,4 @@
|
||||
async def code1(arg1):
|
||||
global log, xiaomusic
|
||||
log.info(f"code1:{arg1}")
|
||||
await xiaomusic.do_tts("你好,我是自定义的测试口令")
|
||||
10
plugins/httpget.py
Normal file
10
plugins/httpget.py
Normal file
@@ -0,0 +1,10 @@
|
||||
import requests
|
||||
|
||||
|
||||
def httpget(url):
|
||||
global log
|
||||
|
||||
# 发起请求
|
||||
response = requests.get(url, timeout=5) # 增加超时以避免长时间挂起
|
||||
response.raise_for_status() # 如果响应不是200,引发HTTPError异常
|
||||
log.info(f"httpget url:{url} response:{response.text}")
|
||||
@@ -1,24 +1,29 @@
|
||||
[project]
|
||||
name = "xiaomusic"
|
||||
version = "0.1.48"
|
||||
version = "0.3.10"
|
||||
description = "Play Music with xiaomi AI speaker"
|
||||
authors = [
|
||||
{name = "涵曦", email = "im.hanxi@gmail.com"},
|
||||
{name = "涵曦", email = "im.hanxi@gmail.com"},
|
||||
]
|
||||
dependencies = [
|
||||
"rich>=13.6.0",
|
||||
"requests>=2.31.0",
|
||||
"aiohttp>=3.8.6",
|
||||
"miservice-fork>=2.5.0",
|
||||
"miservice-fork>=2.7.0",
|
||||
"mutagen>=1.47.0",
|
||||
"yt-dlp>=2024.04.09",
|
||||
"flask[async]>=3.0.1",
|
||||
"waitress>=3.0.0",
|
||||
"yt-dlp>=2024.07.01",
|
||||
"uvicorn>=0.30.1",
|
||||
"fastapi>=0.111.0",
|
||||
"starlette>=0.37.2",
|
||||
]
|
||||
requires-python = ">=3.10"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/hanxi/xiaomusic"
|
||||
|
||||
[project.scripts]
|
||||
xiaomusic = "xiaomusic.cli:main"
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
||||
@@ -28,25 +33,42 @@ build-backend = "pdm.backend"
|
||||
lint = [
|
||||
"ruff>=0.4.8",
|
||||
]
|
||||
[tool.ruff]
|
||||
select = [
|
||||
"B", # flake8-bugbear
|
||||
"C4", # flake8-comprehensions
|
||||
"E", # pycodestyle - Error
|
||||
"F", # Pyflakes
|
||||
"I", # isort
|
||||
"W", # pycodestyle - Warning
|
||||
"UP", # pyupgrade
|
||||
dev = [
|
||||
"commitizen>=3.27.0",
|
||||
]
|
||||
ignore = [
|
||||
"E501", # line-too-long
|
||||
"W191", # tab-indentation
|
||||
[tool.ruff]
|
||||
lint.select = [
|
||||
"B", # flake8-bugbear
|
||||
"C4", # flake8-comprehensions
|
||||
"E", # pycodestyle - Error
|
||||
"F", # Pyflakes
|
||||
"I", # isort
|
||||
"W", # pycodestyle - Warning
|
||||
"UP", # pyupgrade
|
||||
]
|
||||
lint.ignore = [
|
||||
"E501", # line-too-long
|
||||
"W191", # tab-indentation
|
||||
]
|
||||
include = ["**/*.py", "**/*.pyi", "**/pyproject.toml"]
|
||||
|
||||
[tool.ruff.pydocstyle]
|
||||
[tool.ruff.lint.pydocstyle]
|
||||
convention = "google"
|
||||
|
||||
[tool.ruff.lint.flake8-bugbear]
|
||||
extend-immutable-calls = ["fastapi.Depends", "fastapi.params.Depends", "fastapi.Query", "fastapi.params.Query"]
|
||||
|
||||
[tool.pdm.scripts]
|
||||
lint = "ruff check ."
|
||||
fmt = "ruff format ."
|
||||
|
||||
[tool.commitizen]
|
||||
name = "cz_conventional_commits"
|
||||
tag_format = "v$version"
|
||||
version_scheme = "pep440"
|
||||
version_provider = "pep621"
|
||||
update_changelog_on_bump = true
|
||||
major_version_zero = true
|
||||
version_files = [
|
||||
"xiaomusic/__init__.py",
|
||||
]
|
||||
|
||||
377
requirements.txt
377
requirements.txt
@@ -51,18 +51,18 @@ aiohttp==3.9.5 \
|
||||
aiosignal==1.3.1 \
|
||||
--hash=sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc \
|
||||
--hash=sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17
|
||||
asgiref==3.7.2 \
|
||||
--hash=sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e \
|
||||
--hash=sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed
|
||||
annotated-types==0.7.0 \
|
||||
--hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \
|
||||
--hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89
|
||||
anyio==4.4.0 \
|
||||
--hash=sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94 \
|
||||
--hash=sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7
|
||||
async-timeout==4.0.3; python_version < "3.11" \
|
||||
--hash=sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f \
|
||||
--hash=sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028
|
||||
attrs==23.1.0 \
|
||||
--hash=sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 \
|
||||
--hash=sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015
|
||||
blinker==1.7.0 \
|
||||
--hash=sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9 \
|
||||
--hash=sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182
|
||||
brotli==1.1.0; implementation_name == "cpython" \
|
||||
--hash=sha256:0c6244521dda65ea562d5a69b9a26120769b7a9fb3db2fe9545935ed6735b128 \
|
||||
--hash=sha256:19c116e796420b0cee3da1ccec3b764ed2952ccfcc298b55a10e5610ad7885f9 \
|
||||
@@ -217,12 +217,24 @@ charset-normalizer==3.3.0 \
|
||||
click==8.1.7 \
|
||||
--hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \
|
||||
--hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de
|
||||
colorama==0.4.6; platform_system == "Windows" \
|
||||
colorama==0.4.6; platform_system == "Windows" or sys_platform == "win32" \
|
||||
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
|
||||
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
|
||||
flask==3.0.3 \
|
||||
--hash=sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3 \
|
||||
--hash=sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842
|
||||
dnspython==2.6.1 \
|
||||
--hash=sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50 \
|
||||
--hash=sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc
|
||||
email-validator==2.2.0 \
|
||||
--hash=sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631 \
|
||||
--hash=sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7
|
||||
exceptiongroup==1.2.1; python_version < "3.11" \
|
||||
--hash=sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad \
|
||||
--hash=sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16
|
||||
fastapi==0.111.0 \
|
||||
--hash=sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0 \
|
||||
--hash=sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7
|
||||
fastapi-cli==0.0.4 \
|
||||
--hash=sha256:a2552f3a7ae64058cdbb530be6fa6dbfc975dc165e4fa66d224c3d396e25e809 \
|
||||
--hash=sha256:e2e9ffaffc1f7767f488d6da34b6f5a377751c996f397902eb6abb99a67bde32
|
||||
frozenlist==1.4.0 \
|
||||
--hash=sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01 \
|
||||
--hash=sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251 \
|
||||
@@ -255,13 +267,42 @@ frozenlist==1.4.0 \
|
||||
--hash=sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb \
|
||||
--hash=sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963 \
|
||||
--hash=sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f
|
||||
h11==0.14.0 \
|
||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||
--hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761
|
||||
httpcore==1.0.5 \
|
||||
--hash=sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61 \
|
||||
--hash=sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5
|
||||
httptools==0.6.1 \
|
||||
--hash=sha256:00d5d4b68a717765b1fabfd9ca755bd12bf44105eeb806c03d1962acd9b8e563 \
|
||||
--hash=sha256:0ac5a0ae3d9f4fe004318d64b8a854edd85ab76cffbf7ef5e32920faef62f142 \
|
||||
--hash=sha256:1ed99a373e327f0107cb513b61820102ee4f3675656a37a50083eda05dc9541b \
|
||||
--hash=sha256:3f30d3ce413088a98b9db71c60a6ada2001a08945cb42dd65a9a9fe228627658 \
|
||||
--hash=sha256:48ed8129cd9a0d62cf4d1575fcf90fb37e3ff7d5654d3a5814eb3d55f36478c2 \
|
||||
--hash=sha256:4f0f8271c0a4db459f9dc807acd0eadd4839934a4b9b892f6f160e94da309837 \
|
||||
--hash=sha256:5cceac09f164bcba55c0500a18fe3c47df29b62353198e4f37bbcc5d591172c3 \
|
||||
--hash=sha256:639dc4f381a870c9ec860ce5c45921db50205a37cc3334e756269736ff0aac58 \
|
||||
--hash=sha256:6a4f5ccead6d18ec072ac0b84420e95d27c1cdf5c9f1bc8fbd8daf86bd94f43d \
|
||||
--hash=sha256:6f58e335a1402fb5a650e271e8c2d03cfa7cea46ae124649346d17bd30d59c90 \
|
||||
--hash=sha256:75c8022dca7935cba14741a42744eee13ba05db00b27a4b940f0d646bd4d56d0 \
|
||||
--hash=sha256:7a7ea483c1a4485c71cb5f38be9db078f8b0e8b4c4dc0210f531cdd2ddac1ef1 \
|
||||
--hash=sha256:7d9ceb2c957320def533671fc9c715a80c47025139c8d1f3797477decbc6edd2 \
|
||||
--hash=sha256:85ed077c995e942b6f1b07583e4eb0a8d324d418954fc6af913d36db7c05a5a0 \
|
||||
--hash=sha256:8b0bb634338334385351a1600a73e558ce619af390c2b38386206ac6a27fecfc \
|
||||
--hash=sha256:93ad80d7176aa5788902f207a4e79885f0576134695dfb0fefc15b7a4648d503 \
|
||||
--hash=sha256:97662ce7fb196c785344d00d638fc9ad69e18ee4bfb4000b35a52efe5adcc949 \
|
||||
--hash=sha256:9bb68d3a085c2174c2477eb3ffe84ae9fb4fde8792edb7bcd09a1d8467e30a84 \
|
||||
--hash=sha256:b512aa728bc02354e5ac086ce76c3ce635b62f5fbc32ab7082b5e582d27867bb \
|
||||
--hash=sha256:c6e26c30455600b95d94b1b836085138e82f177351454ee841c148f93a9bad5a \
|
||||
--hash=sha256:d2f6c3c4cb1948d912538217838f6e9960bc4a521d7f9b323b3da579cd14532f \
|
||||
--hash=sha256:e57997ac7fb7ee43140cc03664de5f268813a481dff6245e0075925adc6aa185
|
||||
httpx==0.27.0 \
|
||||
--hash=sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5 \
|
||||
--hash=sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5
|
||||
idna==3.4 \
|
||||
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
|
||||
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
|
||||
itsdangerous==2.1.2 \
|
||||
--hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \
|
||||
--hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a
|
||||
Jinja2==3.1.3 \
|
||||
jinja2==3.1.3 \
|
||||
--hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \
|
||||
--hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90
|
||||
markdown-it-py==3.0.0 \
|
||||
@@ -302,9 +343,9 @@ MarkupSafe==2.1.4 \
|
||||
mdurl==0.1.2 \
|
||||
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
|
||||
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
|
||||
miservice-fork==2.5.0 \
|
||||
--hash=sha256:8ca2d370d5b32f7e330add38aa1912d734aefa7880f16cef9eac110a5a3029e2 \
|
||||
--hash=sha256:97b6360ea53c34fe035ac9d94e8705f305b8fa7fc2b44a7aea182449a76cb622
|
||||
miservice-fork==2.7.0 \
|
||||
--hash=sha256:8e2c91ebe1fc4b3c63b01cbf1818e5d5833d024fd3a8311970d649ad2d49d6e6 \
|
||||
--hash=sha256:8e87ef6d89adceaf3f7a98242cdae1c9135498d77f2c743ec3871d2e42bcbab8
|
||||
multidict==6.0.4 \
|
||||
--hash=sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9 \
|
||||
--hash=sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8 \
|
||||
@@ -340,6 +381,38 @@ multidict==6.0.4 \
|
||||
mutagen==1.47.0 \
|
||||
--hash=sha256:719fadef0a978c31b4cf3c956261b3c58b6948b32023078a2117b1de09f0fc99 \
|
||||
--hash=sha256:edd96f50c5907a9539d8e5bba7245f62c9f520aef333d13392a79a4f70aca719
|
||||
orjson==3.10.6 \
|
||||
--hash=sha256:05ac3d3916023745aa3b3b388e91b9166be1ca02b7c7e41045da6d12985685f0 \
|
||||
--hash=sha256:0943e4c701196b23c240b3d10ed8ecd674f03089198cf503105b474a4f77f21f \
|
||||
--hash=sha256:1335d4ef59ab85cab66fe73fd7a4e881c298ee7f63ede918b7faa1b27cbe5212 \
|
||||
--hash=sha256:1c680b269d33ec444afe2bdc647c9eb73166fa47a16d9a75ee56a374f4a45f43 \
|
||||
--hash=sha256:227df19441372610b20e05bdb906e1742ec2ad7a66ac8350dcfd29a63014a83b \
|
||||
--hash=sha256:446dee5a491b5bc7d8f825d80d9637e7af43f86a331207b9c9610e2f93fee22a \
|
||||
--hash=sha256:450e39ab1f7694465060a0550b3f6d328d20297bf2e06aa947b97c21e5241fbd \
|
||||
--hash=sha256:4bbc6d0af24c1575edc79994c20e1b29e6fb3c6a570371306db0993ecf144dc5 \
|
||||
--hash=sha256:55d43d3feb8f19d07e9f01e5b9be4f28801cf7c60d0fa0d279951b18fae1932b \
|
||||
--hash=sha256:57985ee7e91d6214c837936dc1608f40f330a6b88bb13f5a57ce5257807da143 \
|
||||
--hash=sha256:61272a5aec2b2661f4fa2b37c907ce9701e821b2c1285d5c3ab0207ebd358d38 \
|
||||
--hash=sha256:633a3b31d9d7c9f02d49c4ab4d0a86065c4a6f6adc297d63d272e043472acab5 \
|
||||
--hash=sha256:64c81456d2a050d380786413786b057983892db105516639cb5d3ee3c7fd5148 \
|
||||
--hash=sha256:7275664f84e027dcb1ad5200b8b18373e9c669b2a9ec33d410c40f5ccf4b257e \
|
||||
--hash=sha256:874ce88264b7e655dde4aeaacdc8fd772a7962faadfb41abe63e2a4861abc3dc \
|
||||
--hash=sha256:95a0cce17f969fb5391762e5719575217bd10ac5a189d1979442ee54456393f3 \
|
||||
--hash=sha256:960db0e31c4e52fa0fc3ecbaea5b2d3b58f379e32a95ae6b0ebeaa25b93dfd34 \
|
||||
--hash=sha256:9c1c4b53b24a4c06547ce43e5fee6ec4e0d8fe2d597f4647fc033fd205707365 \
|
||||
--hash=sha256:a6ea7afb5b30b2317e0bee03c8d34c8181bc5a36f2afd4d0952f378972c4efd5 \
|
||||
--hash=sha256:ac3045267e98fe749408eee1593a142e02357c5c99be0802185ef2170086a863 \
|
||||
--hash=sha256:b1ec490e10d2a77c345def52599311849fc063ae0e67cf4f84528073152bb2ba \
|
||||
--hash=sha256:b6f3d167d13a16ed263b52dbfedff52c962bfd3d270b46b7518365bcc2121eed \
|
||||
--hash=sha256:c27bc6a28ae95923350ab382c57113abd38f3928af3c80be6f2ba7eb8d8db0b0 \
|
||||
--hash=sha256:d27456491ca79532d11e507cadca37fb8c9324a3976294f68fb1eff2dc6ced5a \
|
||||
--hash=sha256:df25d9271270ba2133cc88ee83c318372bdc0f2cd6f32e7a450809a111efc45c \
|
||||
--hash=sha256:e54b63d0a7c6c54a5f5f726bc93a2078111ef060fec4ecbf34c5db800ca3b3a7 \
|
||||
--hash=sha256:ea2977b21f8d5d9b758bb3f344a75e55ca78e3ff85595d248eee813ae23ecdfb \
|
||||
--hash=sha256:eadc8fd310edb4bdbd333374f2c8fec6794bbbae99b592f448d8214a5e4050c0 \
|
||||
--hash=sha256:f710f346e4c44a4e8bdf23daa974faede58f83334289df80bc9cd12fe82573c7 \
|
||||
--hash=sha256:f759503a97a6ace19e55461395ab0d618b5a117e8d0fbb20e70cfd68a47327f2 \
|
||||
--hash=sha256:fb0ee33124db6eaa517d00890fc1a55c3bfe1cf78ba4a8899d71a06f2d6ff5c7
|
||||
pycparser==2.21; implementation_name != "cpython" \
|
||||
--hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \
|
||||
--hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206
|
||||
@@ -365,24 +438,267 @@ pycryptodomex==3.19.0 \
|
||||
--hash=sha256:c74eb1f73f788facece7979ce91594dc177e1a9b5d5e3e64697dd58299e5cb4d \
|
||||
--hash=sha256:d4dd3b381ff5a5907a3eb98f5f6d32c64d319a840278ceea1dcfcc65063856f3 \
|
||||
--hash=sha256:edbe083c299835de7e02c8aa0885cb904a75087d35e7bab75ebe5ed336e8c3e2
|
||||
pydantic==2.8.2 \
|
||||
--hash=sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a \
|
||||
--hash=sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8
|
||||
pydantic-core==2.20.1 \
|
||||
--hash=sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d \
|
||||
--hash=sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686 \
|
||||
--hash=sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482 \
|
||||
--hash=sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83 \
|
||||
--hash=sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6 \
|
||||
--hash=sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88 \
|
||||
--hash=sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86 \
|
||||
--hash=sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a \
|
||||
--hash=sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6 \
|
||||
--hash=sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6 \
|
||||
--hash=sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43 \
|
||||
--hash=sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4 \
|
||||
--hash=sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e \
|
||||
--hash=sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203 \
|
||||
--hash=sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24 \
|
||||
--hash=sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc \
|
||||
--hash=sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc \
|
||||
--hash=sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3 \
|
||||
--hash=sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98 \
|
||||
--hash=sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331 \
|
||||
--hash=sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2 \
|
||||
--hash=sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6 \
|
||||
--hash=sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688 \
|
||||
--hash=sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b \
|
||||
--hash=sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0 \
|
||||
--hash=sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840 \
|
||||
--hash=sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c \
|
||||
--hash=sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd \
|
||||
--hash=sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3 \
|
||||
--hash=sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231 \
|
||||
--hash=sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1 \
|
||||
--hash=sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953 \
|
||||
--hash=sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250 \
|
||||
--hash=sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a \
|
||||
--hash=sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20 \
|
||||
--hash=sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703 \
|
||||
--hash=sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac \
|
||||
--hash=sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121 \
|
||||
--hash=sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e \
|
||||
--hash=sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b \
|
||||
--hash=sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906 \
|
||||
--hash=sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9 \
|
||||
--hash=sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7 \
|
||||
--hash=sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b \
|
||||
--hash=sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e \
|
||||
--hash=sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237 \
|
||||
--hash=sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1 \
|
||||
--hash=sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19 \
|
||||
--hash=sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad \
|
||||
--hash=sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0 \
|
||||
--hash=sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94 \
|
||||
--hash=sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312 \
|
||||
--hash=sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f \
|
||||
--hash=sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1 \
|
||||
--hash=sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe \
|
||||
--hash=sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99 \
|
||||
--hash=sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a \
|
||||
--hash=sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a \
|
||||
--hash=sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52 \
|
||||
--hash=sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c \
|
||||
--hash=sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1 \
|
||||
--hash=sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a \
|
||||
--hash=sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f \
|
||||
--hash=sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a \
|
||||
--hash=sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27
|
||||
pygments==2.16.1 \
|
||||
--hash=sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692 \
|
||||
--hash=sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29
|
||||
requests==2.31.0 \
|
||||
--hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \
|
||||
--hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1
|
||||
python-dotenv==1.0.1 \
|
||||
--hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \
|
||||
--hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a
|
||||
python-multipart==0.0.9 \
|
||||
--hash=sha256:03f54688c663f1b7977105f021043b0793151e4cb1c1a9d4a11fc13d622c4026 \
|
||||
--hash=sha256:97ca7b8ea7b05f977dc3849c3ba99d51689822fab725c3703af7c866a0c2b215
|
||||
pyyaml==6.0.1 \
|
||||
--hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \
|
||||
--hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \
|
||||
--hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \
|
||||
--hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \
|
||||
--hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \
|
||||
--hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \
|
||||
--hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \
|
||||
--hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \
|
||||
--hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \
|
||||
--hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \
|
||||
--hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \
|
||||
--hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \
|
||||
--hash=sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef \
|
||||
--hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \
|
||||
--hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \
|
||||
--hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \
|
||||
--hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \
|
||||
--hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \
|
||||
--hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \
|
||||
--hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \
|
||||
--hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \
|
||||
--hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \
|
||||
--hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \
|
||||
--hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f
|
||||
requests==2.32.3 \
|
||||
--hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
|
||||
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
|
||||
rich==13.7.1 \
|
||||
--hash=sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222 \
|
||||
--hash=sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432
|
||||
typing-extensions==4.9.0; python_version < "3.11" \
|
||||
--hash=sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783 \
|
||||
--hash=sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd
|
||||
shellingham==1.5.4 \
|
||||
--hash=sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686 \
|
||||
--hash=sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de
|
||||
sniffio==1.3.1 \
|
||||
--hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \
|
||||
--hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc
|
||||
starlette==0.37.2 \
|
||||
--hash=sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee \
|
||||
--hash=sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823
|
||||
typer==0.12.3 \
|
||||
--hash=sha256:070d7ca53f785acbccba8e7d28b08dcd88f79f1fbda035ade0aecec71ca5c914 \
|
||||
--hash=sha256:49e73131481d804288ef62598d97a1ceef3058905aa536a1134f90891ba35482
|
||||
typing-extensions==4.12.2 \
|
||||
--hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
|
||||
--hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
|
||||
ujson==5.10.0 \
|
||||
--hash=sha256:0de4971a89a762398006e844ae394bd46991f7c385d7a6a3b93ba229e6dac17e \
|
||||
--hash=sha256:129e39af3a6d85b9c26d5577169c21d53821d8cf68e079060602e861c6e5da1b \
|
||||
--hash=sha256:22cffecf73391e8abd65ef5f4e4dd523162a3399d5e84faa6aebbf9583df86d6 \
|
||||
--hash=sha256:2601aa9ecdbee1118a1c2065323bda35e2c5a2cf0797ef4522d485f9d3ef65bd \
|
||||
--hash=sha256:26b0e2d2366543c1bb4fbd457446f00b0187a2bddf93148ac2da07a53fe51569 \
|
||||
--hash=sha256:2987713a490ceb27edff77fb184ed09acdc565db700ee852823c3dc3cffe455f \
|
||||
--hash=sha256:29b443c4c0a113bcbb792c88bea67b675c7ca3ca80c3474784e08bba01c18d51 \
|
||||
--hash=sha256:2a890b706b64e0065f02577bf6d8ca3b66c11a5e81fb75d757233a38c07a1f20 \
|
||||
--hash=sha256:348898dd702fc1c4f1051bc3aacbf894caa0927fe2c53e68679c073375f732cf \
|
||||
--hash=sha256:38665e7d8290188b1e0d57d584eb8110951a9591363316dd41cf8686ab1d0abc \
|
||||
--hash=sha256:38d5d36b4aedfe81dfe251f76c0467399d575d1395a1755de391e58985ab1c2e \
|
||||
--hash=sha256:4573fd1695932d4f619928fd09d5d03d917274381649ade4328091ceca175539 \
|
||||
--hash=sha256:4c4fc16f11ac1612f05b6f5781b384716719547e142cfd67b65d035bd85af165 \
|
||||
--hash=sha256:502bf475781e8167f0f9d0e41cd32879d120a524b22358e7f205294224c71126 \
|
||||
--hash=sha256:57aaf98b92d72fc70886b5a0e1a1ca52c2320377360341715dd3933a18e827b1 \
|
||||
--hash=sha256:59e02cd37bc7c44d587a0ba45347cc815fb7a5fe48de16bf05caa5f7d0d2e816 \
|
||||
--hash=sha256:5b6fee72fa77dc172a28f21693f64d93166534c263adb3f96c413ccc85ef6e64 \
|
||||
--hash=sha256:5b91b5d0d9d283e085e821651184a647699430705b15bf274c7896f23fe9c9d8 \
|
||||
--hash=sha256:604a046d966457b6cdcacc5aa2ec5314f0e8c42bae52842c1e6fa02ea4bda42e \
|
||||
--hash=sha256:618efd84dc1acbd6bff8eaa736bb6c074bfa8b8a98f55b61c38d4ca2c1f7f287 \
|
||||
--hash=sha256:61d0af13a9af01d9f26d2331ce49bb5ac1fb9c814964018ac8df605b5422dcb3 \
|
||||
--hash=sha256:621e34b4632c740ecb491efc7f1fcb4f74b48ddb55e65221995e74e2d00bbff0 \
|
||||
--hash=sha256:6627029ae4f52d0e1a2451768c2c37c0c814ffc04f796eb36244cf16b8e57043 \
|
||||
--hash=sha256:67079b1f9fb29ed9a2914acf4ef6c02844b3153913eb735d4bf287ee1db6e557 \
|
||||
--hash=sha256:6dea1c8b4fc921bf78a8ff00bbd2bfe166345f5536c510671bccececb187c80e \
|
||||
--hash=sha256:6e32abdce572e3a8c3d02c886c704a38a1b015a1fb858004e03d20ca7cecbb21 \
|
||||
--hash=sha256:7663960f08cd5a2bb152f5ee3992e1af7690a64c0e26d31ba7b3ff5b2ee66337 \
|
||||
--hash=sha256:78778a3aa7aafb11e7ddca4e29f46bc5139131037ad628cc10936764282d6753 \
|
||||
--hash=sha256:7c10f4654e5326ec14a46bcdeb2b685d4ada6911050aa8baaf3501e57024b804 \
|
||||
--hash=sha256:7ec0ca8c415e81aa4123501fee7f761abf4b7f386aad348501a26940beb1860f \
|
||||
--hash=sha256:924f7318c31874d6bb44d9ee1900167ca32aa9b69389b98ecbde34c1698a250f \
|
||||
--hash=sha256:94a87f6e151c5f483d7d54ceef83b45d3a9cca7a9cb453dbdbb3f5a6f64033f5 \
|
||||
--hash=sha256:98ba15d8cbc481ce55695beee9f063189dce91a4b08bc1d03e7f0152cd4bbdd5 \
|
||||
--hash=sha256:a245d59f2ffe750446292b0094244df163c3dc96b3ce152a2c837a44e7cda9d1 \
|
||||
--hash=sha256:a5b366812c90e69d0f379a53648be10a5db38f9d4ad212b60af00bd4048d0f00 \
|
||||
--hash=sha256:a65b6af4d903103ee7b6f4f5b85f1bfd0c90ba4eeac6421aae436c9988aa64a2 \
|
||||
--hash=sha256:a9d2edbf1556e4f56e50fab7d8ff993dbad7f54bac68eacdd27a8f55f433578e \
|
||||
--hash=sha256:ab13a2a9e0b2865a6c6db9271f4b46af1c7476bfd51af1f64585e919b7c07fd4 \
|
||||
--hash=sha256:ac56eb983edce27e7f51d05bc8dd820586c6e6be1c5216a6809b0c668bb312b8 \
|
||||
--hash=sha256:b0111b27f2d5c820e7f2dbad7d48e3338c824e7ac4d2a12da3dc6061cc39c8e6 \
|
||||
--hash=sha256:b3cd8f3c5d8c7738257f1018880444f7b7d9b66232c64649f562d7ba86ad4bc1 \
|
||||
--hash=sha256:b9500e61fce0cfc86168b248104e954fead61f9be213087153d272e817ec7b4f \
|
||||
--hash=sha256:ba43cc34cce49cf2d4bc76401a754a81202d8aa926d0e2b79f0ee258cb15d3a4 \
|
||||
--hash=sha256:baed37ea46d756aca2955e99525cc02d9181de67f25515c468856c38d52b5f3b \
|
||||
--hash=sha256:beeaf1c48e32f07d8820c705ff8e645f8afa690cca1544adba4ebfa067efdc88 \
|
||||
--hash=sha256:c18610b9ccd2874950faf474692deee4223a994251bc0a083c114671b64e6518 \
|
||||
--hash=sha256:c66962ca7565605b355a9ed478292da628b8f18c0f2793021ca4425abf8b01e5 \
|
||||
--hash=sha256:caf270c6dba1be7a41125cd1e4fc7ba384bf564650beef0df2dd21a00b7f5770 \
|
||||
--hash=sha256:d7d0e0ceeb8fe2468c70ec0c37b439dd554e2aa539a8a56365fd761edb418988 \
|
||||
--hash=sha256:d8640fb4072d36b08e95a3a380ba65779d356b2fee8696afeb7794cf0902d0a1 \
|
||||
--hash=sha256:e1402f0564a97d2a52310ae10a64d25bcef94f8dd643fcf5d310219d915484f7 \
|
||||
--hash=sha256:ecb24f0bdd899d368b715c9e6664166cf694d1e57be73f17759573a6986dd95a \
|
||||
--hash=sha256:f00ea7e00447918ee0eff2422c4add4c5752b1b60e88fcb3c067d4a21049a720 \
|
||||
--hash=sha256:f3caf9cd64abfeb11a3b661329085c5e167abbe15256b3b68cb5d914ba7396f3 \
|
||||
--hash=sha256:f44bd4b23a0e723bf8b10628288c2c7c335161d6840013d4d5de20e48551773b \
|
||||
--hash=sha256:f77b74475c462cb8b88680471193064d3e715c7c6074b1c8c412cb526466efe9 \
|
||||
--hash=sha256:f8ccb77b3e40b151e20519c6ae6d89bfe3f4c14e8e210d910287f778368bb3d1 \
|
||||
--hash=sha256:fbd8fd427f57a03cff3ad6574b5e299131585d9727c8c366da4624a9069ed746
|
||||
urllib3==2.0.6 \
|
||||
--hash=sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2 \
|
||||
--hash=sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564
|
||||
waitress==3.0.0 \
|
||||
--hash=sha256:005da479b04134cdd9dd602d1ee7c49d79de0537610d653674cc6cbde222b8a1 \
|
||||
--hash=sha256:2a06f242f4ba0cc563444ca3d1998959447477363a2d7e9b8b4d75d35cfd1669
|
||||
uvicorn[standard]==0.30.1 \
|
||||
--hash=sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81 \
|
||||
--hash=sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8
|
||||
uvloop==0.19.0; (sys_platform != "cygwin" and sys_platform != "win32") and platform_python_implementation != "PyPy" \
|
||||
--hash=sha256:0246f4fd1bf2bf702e06b0d45ee91677ee5c31242f39aab4ea6fe0c51aedd0fd \
|
||||
--hash=sha256:02506dc23a5d90e04d4f65c7791e65cf44bd91b37f24cfc3ef6cf2aff05dc7ec \
|
||||
--hash=sha256:2693049be9d36fef81741fddb3f441673ba12a34a704e7b4361efb75cf30befc \
|
||||
--hash=sha256:31e672bb38b45abc4f26e273be83b72a0d28d074d5b370fc4dcf4c4eb15417d2 \
|
||||
--hash=sha256:47bf3e9312f63684efe283f7342afb414eea4d3011542155c7e625cd799c3b12 \
|
||||
--hash=sha256:4ce6b0af8f2729a02a5d1575feacb2a94fc7b2e983868b009d51c9a9d2149bef \
|
||||
--hash=sha256:5138821e40b0c3e6c9478643b4660bd44372ae1e16a322b8fc07478f92684e24 \
|
||||
--hash=sha256:5588bd21cf1fcf06bded085f37e43ce0e00424197e7c10e77afd4bbefffef428 \
|
||||
--hash=sha256:570fc0ed613883d8d30ee40397b79207eedd2624891692471808a95069a007c1 \
|
||||
--hash=sha256:5a05128d315e2912791de6088c34136bfcdd0c7cbc1cf85fd6fd1bb321b7c849 \
|
||||
--hash=sha256:5daa304d2161d2918fa9a17d5635099a2f78ae5b5960e742b2fcfbb7aefaa593 \
|
||||
--hash=sha256:5f17766fb6da94135526273080f3455a112f82570b2ee5daa64d682387fe0dcd \
|
||||
--hash=sha256:7010271303961c6f0fe37731004335401eb9075a12680738731e9c92ddd96ad6 \
|
||||
--hash=sha256:7207272c9520203fea9b93843bb775d03e1cf88a80a936ce760f60bb5add92f3 \
|
||||
--hash=sha256:7b1fd71c3843327f3bbc3237bedcdb6504fd50368ab3e04d0410e52ec293f5b8 \
|
||||
--hash=sha256:91ab01c6cd00e39cde50173ba4ec68a1e578fee9279ba64f5221810a9e786533 \
|
||||
--hash=sha256:cd81bdc2b8219cb4b2556eea39d2e36bfa375a2dd021404f90a62e44efaaf957 \
|
||||
--hash=sha256:da8435a3bd498419ee8c13c34b89b5005130a476bda1d6ca8cfdde3de35cd650 \
|
||||
--hash=sha256:de4313d7f575474c8f5a12e163f6d89c0a878bc49219641d49e6f1444369a90e
|
||||
watchfiles==0.22.0 \
|
||||
--hash=sha256:00095dd368f73f8f1c3a7982a9801190cc88a2f3582dd395b289294f8975172b \
|
||||
--hash=sha256:00ad0bcd399503a84cc688590cdffbe7a991691314dde5b57b3ed50a41319a31 \
|
||||
--hash=sha256:00f39592cdd124b4ec5ed0b1edfae091567c72c7da1487ae645426d1b0ffcad1 \
|
||||
--hash=sha256:030bc4e68d14bcad2294ff68c1ed87215fbd9a10d9dea74e7cfe8a17869785ab \
|
||||
--hash=sha256:052d668a167e9fc345c24203b104c313c86654dd6c0feb4b8a6dfc2462239249 \
|
||||
--hash=sha256:067dea90c43bf837d41e72e546196e674f68c23702d3ef80e4e816937b0a3ffd \
|
||||
--hash=sha256:0bc3b2f93a140df6806c8467c7f51ed5e55a931b031b5c2d7ff6132292e803d6 \
|
||||
--hash=sha256:0c8e0aa0e8cc2a43561e0184c0513e291ca891db13a269d8d47cb9841ced7c71 \
|
||||
--hash=sha256:1235c11510ea557fe21be5d0e354bae2c655a8ee6519c94617fe63e05bca4171 \
|
||||
--hash=sha256:1cc0cba54f47c660d9fa3218158b8963c517ed23bd9f45fe463f08262a4adae1 \
|
||||
--hash=sha256:1d9188979a58a096b6f8090e816ccc3f255f137a009dd4bbec628e27696d67c1 \
|
||||
--hash=sha256:213792c2cd3150b903e6e7884d40660e0bcec4465e00563a5fc03f30ea9c166c \
|
||||
--hash=sha256:2627a91e8110b8de2406d8b2474427c86f5a62bf7d9ab3654f541f319ef22bcb \
|
||||
--hash=sha256:28585744c931576e535860eaf3f2c0ec7deb68e3b9c5a85ca566d69d36d8dd27 \
|
||||
--hash=sha256:2bdadf6b90c099ca079d468f976fd50062905d61fae183f769637cb0f68ba59a \
|
||||
--hash=sha256:2f350cbaa4bb812314af5dab0eb8d538481e2e2279472890864547f3fe2281ed \
|
||||
--hash=sha256:3218a6f908f6a276941422b035b511b6d0d8328edd89a53ae8c65be139073f84 \
|
||||
--hash=sha256:425440e55cd735386ec7925f64d5dde392e69979d4c8459f6bb4e920210407f2 \
|
||||
--hash=sha256:4b9f2a128a32a2c273d63eb1fdbf49ad64852fc38d15b34eaa3f7ca2f0d2b797 \
|
||||
--hash=sha256:52fc9b0dbf54d43301a19b236b4a4614e610605f95e8c3f0f65c3a456ffd7d35 \
|
||||
--hash=sha256:55b7cc10261c2786c41d9207193a85c1db1b725cf87936df40972aab466179b6 \
|
||||
--hash=sha256:581f0a051ba7bafd03e17127735d92f4d286af941dacf94bcf823b101366249e \
|
||||
--hash=sha256:5834e1f8b71476a26df97d121c0c0ed3549d869124ed2433e02491553cb468c2 \
|
||||
--hash=sha256:5e45fb0d70dda1623a7045bd00c9e036e6f1f6a85e4ef2c8ae602b1dfadf7550 \
|
||||
--hash=sha256:61af9efa0733dc4ca462347becb82e8ef4945aba5135b1638bfc20fad64d4f0e \
|
||||
--hash=sha256:68fe0c4d22332d7ce53ad094622b27e67440dacefbaedd29e0794d26e247280c \
|
||||
--hash=sha256:72a44e9481afc7a5ee3291b09c419abab93b7e9c306c9ef9108cb76728ca58d2 \
|
||||
--hash=sha256:7a74436c415843af2a769b36bf043b6ccbc0f8d784814ba3d42fc961cdb0a9dc \
|
||||
--hash=sha256:8c39987a1397a877217be1ac0fb1d8b9f662c6077b90ff3de2c05f235e6a8f96 \
|
||||
--hash=sha256:8fdebb655bb1ba0122402352b0a4254812717a017d2dc49372a1d47e24073795 \
|
||||
--hash=sha256:94ebe84a035993bb7668f58a0ebf998174fb723a39e4ef9fce95baabb42b787f \
|
||||
--hash=sha256:9624a68b96c878c10437199d9a8b7d7e542feddda8d5ecff58fdc8e67b460848 \
|
||||
--hash=sha256:988e981aaab4f3955209e7e28c7794acdb690be1efa7f16f8ea5aba7ffdadacb \
|
||||
--hash=sha256:a8a31bfd98f846c3c284ba694c6365620b637debdd36e46e1859c897123aa232 \
|
||||
--hash=sha256:a927b3034d0672f62fb2ef7ea3c9fc76d063c4b15ea852d1db2dc75fe2c09696 \
|
||||
--hash=sha256:ace7d060432acde5532e26863e897ee684780337afb775107c0a90ae8dbccfd2 \
|
||||
--hash=sha256:aec83c3ba24c723eac14225194b862af176d52292d271c98820199110e31141e \
|
||||
--hash=sha256:b44b70850f0073b5fcc0b31ede8b4e736860d70e2dbf55701e05d3227a154a67 \
|
||||
--hash=sha256:b810a2c7878cbdecca12feae2c2ae8af59bea016a78bc353c184fa1e09f76b68 \
|
||||
--hash=sha256:bbf8a20266136507abf88b0df2328e6a9a7c7309e8daff124dda3803306a9fdb \
|
||||
--hash=sha256:bd4c06100bce70a20c4b81e599e5886cf504c9532951df65ad1133e508bf20be \
|
||||
--hash=sha256:c2444dc7cb9d8cc5ab88ebe792a8d75709d96eeef47f4c8fccb6df7c7bc5be71 \
|
||||
--hash=sha256:c49b76a78c156979759d759339fb62eb0549515acfe4fd18bb151cc07366629c \
|
||||
--hash=sha256:c4a65474fd2b4c63e2c18ac67a0c6c66b82f4e73e2e4d940f837ed3d2fd9d4da \
|
||||
--hash=sha256:c5af2347d17ab0bd59366db8752d9e037982e259cacb2ba06f2c41c08af02c39 \
|
||||
--hash=sha256:c668228833c5619f6618699a2c12be057711b0ea6396aeaece4ded94184304ea \
|
||||
--hash=sha256:c7b978c384e29d6c7372209cbf421d82286a807bbcdeb315427687f8371c340a \
|
||||
--hash=sha256:da1e0a8caebf17976e2ffd00fa15f258e14749db5e014660f53114b676e68538 \
|
||||
--hash=sha256:dc2e8fe41f3cac0660197d95216c42910c2b7e9c70d48e6d84e22f577d106fc1 \
|
||||
--hash=sha256:e0f0a874231e2839abbf473256efffe577d6ee2e3bfa5b540479e892e47c172d \
|
||||
--hash=sha256:f7e1f9c5d1160d03b93fc4b68a0aeb82fe25563e12fbcdc8507f8434ab6f823c
|
||||
websockets==12.0 \
|
||||
--hash=sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b \
|
||||
--hash=sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6 \
|
||||
@@ -434,9 +750,6 @@ websockets==12.0 \
|
||||
--hash=sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870 \
|
||||
--hash=sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5 \
|
||||
--hash=sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7
|
||||
Werkzeug==3.0.1 \
|
||||
--hash=sha256:507e811ecea72b18a404947aded4b3390e1db8f826b494d76550ef45bb3b1dcc \
|
||||
--hash=sha256:90a285dc0e42ad56b34e696398b8122ee4c681833fb35b8334a095d82c56da10
|
||||
yarl==1.9.2 \
|
||||
--hash=sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571 \
|
||||
--hash=sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7 \
|
||||
@@ -469,6 +782,6 @@ yarl==1.9.2 \
|
||||
--hash=sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9 \
|
||||
--hash=sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3 \
|
||||
--hash=sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560
|
||||
yt-dlp==2024.5.16.232713.dev0 \
|
||||
--hash=sha256:42d3c27ab77583ff67ee2ddc94e376ea2a76a561ed8b1836ee04fd1cd23ad88c \
|
||||
--hash=sha256:d431187fa703c9f52225080ae56471272679e44d9363f97b7b3187d37a5e6480
|
||||
yt-dlp==2024.7.9 \
|
||||
--hash=sha256:b50a595abde523b5cc84d788f97e69c642503bd673ba740f709ebf65b5ec6592 \
|
||||
--hash=sha256:e19f00f9e55e90bca1c94bcaf809aa33e51634be9f0de2df84a72d3206934f94
|
||||
|
||||
57
update-static-version.py
Executable file
57
update-static-version.py
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def get_html_files(directory):
|
||||
"""
|
||||
获取指定目录下所有HTML文件的列表。
|
||||
|
||||
:param directory: 搜索HTML文件的目录。
|
||||
:return: 搜索到的HTML文件的路径列表。
|
||||
"""
|
||||
return list(Path(directory).rglob("*.html"))
|
||||
|
||||
|
||||
def update_html_version(html_files, version):
|
||||
"""
|
||||
更新HTML文件中所有以 /static/ 开头的CSS和JS文件引用的版本号。
|
||||
|
||||
:param html_files: 需要更新的HTML文件路径的列表。
|
||||
:param version: 新的版本号字符串。
|
||||
"""
|
||||
pattern = re.compile(r'(/static/.*(css|js))\?version=[^"]*"')
|
||||
# pattern = re.compile(r'(/static/.*html)\?version=[^"]*"')
|
||||
|
||||
for html_file in html_files:
|
||||
if not html_file.exists():
|
||||
print(f"文件 {html_file} 不存在。")
|
||||
continue
|
||||
|
||||
html_content = html_file.read_text()
|
||||
|
||||
# 更新CSS和JS版本号
|
||||
html_content = pattern.sub(rf'\g<1>?version={version}"', html_content)
|
||||
# html_content = pattern.sub(fr'\g<1>"', html_content)
|
||||
|
||||
# 保存更改到HTML文件
|
||||
html_file.write_text(html_content)
|
||||
|
||||
print(f"文件 {html_file} 已更新为使用新的版本号: {version}")
|
||||
|
||||
|
||||
# 使用案例
|
||||
if __name__ == "__main__":
|
||||
import time
|
||||
|
||||
t = str(int(time.time()))
|
||||
|
||||
# 指定目录
|
||||
html_directory = "xiaomusic/static" # 修改为实际的HTML文件目录路径
|
||||
|
||||
# 获取HTML文件列表
|
||||
html_files_to_update = get_html_files(html_directory)
|
||||
|
||||
# 执行更新
|
||||
update_html_version(html_files_to_update, t)
|
||||
@@ -1 +1 @@
|
||||
__version__ = "0.1.48"
|
||||
__version__ = "0.3.10"
|
||||
|
||||
@@ -1,16 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import asyncio
|
||||
|
||||
import uvicorn
|
||||
|
||||
from xiaomusic import __version__
|
||||
from xiaomusic.config import Config
|
||||
from xiaomusic.httpserver import HttpInit
|
||||
from xiaomusic.httpserver import app as HttpApp
|
||||
from xiaomusic.xiaomusic import XiaoMusic
|
||||
|
||||
LOGO = r"""
|
||||
__ __ _ __ __ _
|
||||
\ \/ / (_) __ _ ___ | \/ | _ _ ___ (_) ___
|
||||
\ / | | / _` | / _ \ | |\/| | | | | | / __| | | / __|
|
||||
/ \ | | | (_| | | (_) | | | | | | |_| | \__ \ | | | (__
|
||||
/_/\_\ |_| \__,_| \___/ |_| |_| \__,_| |___/ |_| \___|
|
||||
{}
|
||||
"""
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--port",
|
||||
dest="port",
|
||||
help="监听端口",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--hardware",
|
||||
dest="hardware",
|
||||
help="小爱 hardware",
|
||||
help="小爱音箱型号",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--account",
|
||||
@@ -27,20 +46,6 @@ def main():
|
||||
dest="cookie",
|
||||
help="xiaomi cookie",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--use_command",
|
||||
dest="use_command",
|
||||
action="store_true",
|
||||
default=None,
|
||||
help="use command to tts",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--mute_xiaoai",
|
||||
dest="mute_xiaoai",
|
||||
action="store_true",
|
||||
default=None,
|
||||
help="try to mute xiaoai answer",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--verbose",
|
||||
dest="verbose",
|
||||
@@ -58,13 +63,41 @@ def main():
|
||||
dest="ffmpeg_location",
|
||||
help="ffmpeg bin path",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--enable_config_example",
|
||||
dest="enable_config_example",
|
||||
help="是否输出示例配置文件",
|
||||
action="store_true",
|
||||
)
|
||||
|
||||
print(LOGO.format(f"XiaoMusic v{__version__} by: github.com/hanxi"))
|
||||
|
||||
options = parser.parse_args()
|
||||
config = Config.from_options(options)
|
||||
|
||||
xiaomusic = XiaoMusic(config)
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(xiaomusic.run_forever())
|
||||
HttpInit(xiaomusic)
|
||||
|
||||
from uvicorn.config import LOGGING_CONFIG
|
||||
|
||||
LOGGING_CONFIG["formatters"]["access"] = {
|
||||
"format": f"%(asctime)s [{__version__}] [%(levelname)s] %(filename)s:%(lineno)d: %(message)s",
|
||||
"datefmt": "[%X]",
|
||||
}
|
||||
LOGGING_CONFIG["handlers"]["access"] = {
|
||||
"level": "INFO",
|
||||
"class": "logging.handlers.RotatingFileHandler",
|
||||
"formatter": "access",
|
||||
"filename": config.log_file,
|
||||
"maxBytes": 10 * 1024 * 1024,
|
||||
"backupCount": 1,
|
||||
}
|
||||
uvicorn.run(
|
||||
HttpApp,
|
||||
host=["::", "0.0.0.0"],
|
||||
port=config.port,
|
||||
log_config=LOGGING_CONFIG,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -3,115 +3,164 @@ from __future__ import annotations
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from typing import get_type_hints
|
||||
|
||||
from xiaomusic.utils import validate_proxy
|
||||
|
||||
LATEST_ASK_API = "https://userprofile.mina.mi.com/device_profile/v2/conversation?source=dialogu&hardware={hardware}×tamp={timestamp}&limit=2"
|
||||
COOKIE_TEMPLATE = "deviceId={device_id}; serviceToken={service_token}; userId={user_id}"
|
||||
HARDWARE_COMMAND_DICT = {
|
||||
# hardware: (tts_command, wakeup_command, volume_command)
|
||||
"LX06": ("5-1", "5-5", "2-1"),
|
||||
"L05B": ("5-3", "5-4", "2-1"),
|
||||
"S12": ("5-1", "5-5", "2-1"), # 第一代小爱,型号MDZ-25-DA
|
||||
"S12A": ("5-1", "5-5", "2-1"),
|
||||
"LX01": ("5-1", "5-5", "2-1"),
|
||||
"L06A": ("5-1", "5-5", "2-1"),
|
||||
"LX04": ("5-1", "5-4", "2-1"),
|
||||
"L05C": ("5-3", "5-4", "2-1"),
|
||||
"L17A": ("7-3", "7-4", "2-1"),
|
||||
"X08E": ("7-3", "7-4", "2-1"),
|
||||
"LX05A": ("5-1", "5-5", "2-1"), # 小爱红外版
|
||||
"LX5A": ("5-1", "5-5", "2-1"), # 小爱红外版
|
||||
"L07A": ("5-1", "5-5", "2-1"), # Redmi小爱音箱Play(l7a)
|
||||
"L15A": ("7-3", "7-4", "2-1"),
|
||||
"X6A": ("7-3", "7-4", "2-1"), # 小米智能家庭屏6
|
||||
"X10A": ("7-3", "7-4", "2-1"), # 小米智能家庭屏10
|
||||
# add more here
|
||||
}
|
||||
|
||||
DEFAULT_COMMAND = ("5-1", "5-5", "2-1")
|
||||
# 默认口令
|
||||
def default_key_word_dict():
|
||||
return {
|
||||
"播放歌曲": "play",
|
||||
"播放本地歌曲": "playlocal",
|
||||
"关机": "stop",
|
||||
"下一首": "play_next",
|
||||
"单曲循环": "set_play_type_one",
|
||||
"全部循环": "set_play_type_all",
|
||||
"随机播放": "set_random_play",
|
||||
"分钟后关机": "stop_after_minute",
|
||||
"播放列表": "play_music_list",
|
||||
"刷新列表": "gen_music_list",
|
||||
}
|
||||
|
||||
|
||||
def default_user_key_word_dict():
|
||||
return {
|
||||
"测试自定义口令": 'exec#code1("hello")',
|
||||
"测试链接": 'exec#httpget("https://github.com/hanxi/xiaomusic")',
|
||||
}
|
||||
|
||||
KEY_WORD_DICT = {
|
||||
"播放歌曲": "play",
|
||||
"放歌曲": "play",
|
||||
"下一首": "play_next",
|
||||
"单曲循环": "set_play_type_one",
|
||||
"全部循环": "set_play_type_all",
|
||||
"随机播放": "random_play",
|
||||
"关机": "stop",
|
||||
"停止播放": "stop",
|
||||
"分钟后关机": "stop_after_minute",
|
||||
"播放列表": "play_music_list",
|
||||
"刷新列表": "gen_music_list",
|
||||
"set_volume#": "set_volume",
|
||||
"get_volume#": "get_volume",
|
||||
}
|
||||
|
||||
# 命令参数在前面
|
||||
KEY_WORD_ARG_BEFORE_DICT = {
|
||||
"分钟后关机": True,
|
||||
}
|
||||
|
||||
# 匹配优先级
|
||||
KEY_MATCH_ORDER = [
|
||||
"set_volume#",
|
||||
"get_volume#",
|
||||
"分钟后关机",
|
||||
"播放歌曲",
|
||||
"放歌曲",
|
||||
"下一首",
|
||||
"单曲循环",
|
||||
"全部循环",
|
||||
"随机播放",
|
||||
"关机",
|
||||
"停止播放",
|
||||
"刷新列表",
|
||||
"播放列表",
|
||||
]
|
||||
|
||||
SUPPORT_MUSIC_TYPE = [
|
||||
".mp3",
|
||||
".flac",
|
||||
]
|
||||
# 口令匹配优先级
|
||||
def default_key_match_order():
|
||||
return [
|
||||
"分钟后关机",
|
||||
"播放歌曲",
|
||||
"下一首",
|
||||
"单曲循环",
|
||||
"全部循环",
|
||||
"随机播放",
|
||||
"关机",
|
||||
"刷新列表",
|
||||
"播放列表",
|
||||
]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Device:
|
||||
did: str = ""
|
||||
device_id: str = ""
|
||||
hardware: str = ""
|
||||
name: str = ""
|
||||
play_type: int = ""
|
||||
cur_music: str = ""
|
||||
cur_playlist: str = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
class Config:
|
||||
hardware: str = os.getenv("MI_HARDWARE", "L07A")
|
||||
account: str = os.getenv("MI_USER", "")
|
||||
password: str = os.getenv("MI_PASS", "")
|
||||
mi_did: str = os.getenv("MI_DID", "")
|
||||
mute_xiaoai: bool = True
|
||||
mi_did: str = os.getenv("MI_DID", "") # 逗号分割支持多设备
|
||||
cookie: str = ""
|
||||
use_command: bool = False
|
||||
verbose: bool = os.getenv("XIAOMUSIC_VERBOSE", "").lower() == "true"
|
||||
music_path: str = os.getenv("XIAOMUSIC_MUSIC_PATH", "music")
|
||||
music_path: str = os.getenv(
|
||||
"XIAOMUSIC_MUSIC_PATH", "music"
|
||||
) # 只能是music目录下的子目录
|
||||
download_path: str = os.getenv("XIAOMUSIC_DOWNLOAD_PATH", "")
|
||||
conf_path: str = os.getenv("XIAOMUSIC_CONF_PATH", "conf")
|
||||
hostname: str = os.getenv("XIAOMUSIC_HOSTNAME", "192.168.2.5")
|
||||
port: int = int(os.getenv("XIAOMUSIC_PORT", "8090"))
|
||||
proxy: str | None = os.getenv("XIAOMUSIC_PROXY", None)
|
||||
port: int = int(os.getenv("XIAOMUSIC_PORT", "8090")) # 监听端口
|
||||
public_port: int = int(os.getenv("XIAOMUSIC_PUBLIC_PORT", 0)) # 歌曲访问端口
|
||||
proxy: str = 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("XIAOMUSIC_ACTIVE_CMD", "play,random_play")
|
||||
active_cmd: str = os.getenv(
|
||||
"XIAOMUSIC_ACTIVE_CMD", "play,set_random_play,playlocal,play_music_list,stop"
|
||||
)
|
||||
exclude_dirs: str = os.getenv("XIAOMUSIC_EXCLUDE_DIRS", "@eaDir")
|
||||
music_path_depth: int = int(os.getenv("XIAOMUSIC_MUSIC_PATH_DEPTH", "10"))
|
||||
disable_httpauth: bool = (
|
||||
os.getenv("XIAOMUSIC_DISABLE_HTTPAUTH", "true").lower() == "true"
|
||||
)
|
||||
httpauth_username: str = os.getenv("XIAOMUSIC_HTTPAUTH_USERNAME", "")
|
||||
httpauth_password: str = os.getenv("XIAOMUSIC_HTTPAUTH_PASSWORD", "")
|
||||
music_list_url: str = os.getenv("XIAOMUSIC_MUSIC_LIST_URL", "")
|
||||
music_list_json: str = os.getenv("XIAOMUSIC_MUSIC_LIST_JSON", "")
|
||||
disable_download: bool = (
|
||||
os.getenv("XIAOMUSIC_DISABLE_DOWNLOAD", "false").lower() == "true"
|
||||
)
|
||||
key_word_dict: dict[str, str] = field(default_factory=default_key_word_dict)
|
||||
key_match_order: list[str] = field(default_factory=default_key_match_order)
|
||||
use_music_api: bool = (
|
||||
os.getenv("XIAOMUSIC_USE_MUSIC_API", "false").lower() == "true"
|
||||
)
|
||||
use_music_audio_id: str = os.getenv(
|
||||
"XIAOMUSIC_USE_MUSIC_AUDIO_ID", "1582971365183456177"
|
||||
)
|
||||
use_music_id: str = os.getenv("XIAOMUSIC_USE_MUSIC_ID", "355454500")
|
||||
log_file: str = os.getenv("XIAOMUSIC_LOG_FILE", "/tmp/xiaomusic.txt")
|
||||
# 模糊搜索匹配的最低相似度阈值
|
||||
fuzzy_match_cutoff: float = float(os.getenv("XIAOMUSIC_FUZZY_MATCH_CUTOFF", "0.6"))
|
||||
# 开启模糊搜索
|
||||
enable_fuzzy_match: bool = (
|
||||
os.getenv("XIAOMUSIC_ENABLE_FUZZY_MATCH", "true").lower() == "true"
|
||||
)
|
||||
stop_tts_msg: str = os.getenv("XIAOMUSIC_STOP_TTS_MSG", "收到,再见")
|
||||
enable_config_example: bool = False
|
||||
|
||||
keywords_playlocal: str = os.getenv(
|
||||
"XIAOMUSIC_KEYWORDS_PLAYLOCAL", "播放本地歌曲,本地播放歌曲"
|
||||
)
|
||||
keywords_play: str = os.getenv("XIAOMUSIC_KEYWORDS_PLAY", "播放歌曲,放歌曲")
|
||||
keywords_stop: str = os.getenv("XIAOMUSIC_KEYWORDS_STOP", "关机,暂停,停止,停止播放")
|
||||
user_key_word_dict: dict[str, str] = field(
|
||||
default_factory=default_user_key_word_dict
|
||||
)
|
||||
enable_force_stop: bool = (
|
||||
os.getenv("XIAOMUSIC_ENABLE_FORCE_STOP", "false").lower() == "true"
|
||||
)
|
||||
devices: dict[str, Device] = field(default_factory=dict)
|
||||
group_list: str = os.getenv(
|
||||
"XIAOMUSIC_GROUP_LIST", ""
|
||||
) # did1:group_name,did2:group_name
|
||||
|
||||
def append_keyword(self, keys, action):
|
||||
for key in keys.split(","):
|
||||
self.key_word_dict[key] = action
|
||||
if key not in self.key_match_order:
|
||||
self.key_match_order.append(key)
|
||||
|
||||
def append_user_keyword(self):
|
||||
for k, v in self.user_key_word_dict.items():
|
||||
self.key_word_dict[k] = v
|
||||
self.key_match_order.append(k)
|
||||
|
||||
def init_keyword(self):
|
||||
self.append_keyword(self.keywords_playlocal, "playlocal")
|
||||
self.append_keyword(self.keywords_play, "play")
|
||||
self.append_keyword(self.keywords_stop, "stop")
|
||||
self.append_user_keyword()
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.proxy:
|
||||
validate_proxy(self.proxy)
|
||||
|
||||
@property
|
||||
def tts_command(self) -> str:
|
||||
return HARDWARE_COMMAND_DICT.get(self.hardware, DEFAULT_COMMAND)[0]
|
||||
|
||||
@property
|
||||
def wakeup_command(self) -> str:
|
||||
return HARDWARE_COMMAND_DICT.get(self.hardware, DEFAULT_COMMAND)[1]
|
||||
|
||||
@property
|
||||
def volume_command(self) -> str:
|
||||
return HARDWARE_COMMAND_DICT.get(self.hardware, DEFAULT_COMMAND)[2]
|
||||
self.init_keyword()
|
||||
# 保存配置到 config-example.json 文件
|
||||
if self.enable_config_example:
|
||||
with open("config-example.json", "w") as f:
|
||||
data = asdict(self)
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
@classmethod
|
||||
def from_options(cls, options: argparse.Namespace) -> Config:
|
||||
@@ -123,12 +172,44 @@ class Config:
|
||||
config[key] = value
|
||||
return cls(**config)
|
||||
|
||||
@classmethod
|
||||
def convert_value(cls, k, v, type_hints):
|
||||
if v is not None and k in type_hints:
|
||||
expected_type = type_hints[k]
|
||||
try:
|
||||
if expected_type is bool:
|
||||
converted_value = False
|
||||
if str(v).lower() == "true":
|
||||
converted_value = True
|
||||
elif expected_type == dict[str, Device]:
|
||||
converted_value = {}
|
||||
for kk, vv in v.items():
|
||||
converted_value[kk] = Device(**vv)
|
||||
else:
|
||||
converted_value = expected_type(v)
|
||||
return converted_value
|
||||
except (ValueError, TypeError) as e:
|
||||
print(f"Error converting {k}:{v} to {expected_type}: {e}")
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def read_from_file(cls, config_path: str) -> dict:
|
||||
result = {}
|
||||
with open(config_path, "rb") as f:
|
||||
config = json.load(f)
|
||||
for key, value in config.items():
|
||||
if value is not None and key in cls.__dataclass_fields__:
|
||||
result[key] = value
|
||||
data = json.load(f)
|
||||
type_hints = get_type_hints(cls)
|
||||
|
||||
for k, v in data.items():
|
||||
converted_value = cls.convert_value(k, v, type_hints)
|
||||
if converted_value is not None:
|
||||
result[k] = converted_value
|
||||
return result
|
||||
|
||||
def update_config(self, data):
|
||||
type_hints = get_type_hints(self, globals(), locals())
|
||||
|
||||
for k, v in data.items():
|
||||
converted_value = self.convert_value(k, v, type_hints)
|
||||
if converted_value is not None:
|
||||
setattr(self, k, converted_value)
|
||||
self.init_keyword()
|
||||
|
||||
21
xiaomusic/const.py
Normal file
21
xiaomusic/const.py
Normal file
@@ -0,0 +1,21 @@
|
||||
SUPPORT_MUSIC_TYPE = [
|
||||
".mp3",
|
||||
".flac",
|
||||
".wav",
|
||||
".ape",
|
||||
".ogg",
|
||||
".m4a",
|
||||
]
|
||||
|
||||
LATEST_ASK_API = "https://userprofile.mina.mi.com/device_profile/v2/conversation?source=dialogu&hardware={hardware}×tamp={timestamp}&limit=2"
|
||||
COOKIE_TEMPLATE = "deviceId={device_id}; serviceToken={service_token}; userId={user_id}"
|
||||
|
||||
PLAY_TYPE_ONE = 0 # 单曲循环
|
||||
PLAY_TYPE_ALL = 1 # 全部循环
|
||||
PLAY_TYPE_RND = 2 # 随机播放
|
||||
|
||||
PLAY_TYPE_TTS = {
|
||||
PLAY_TYPE_ONE: "已经设置为单曲循环",
|
||||
PLAY_TYPE_ALL: "已经设置为全部循环",
|
||||
PLAY_TYPE_RND: "已经设置为随机播放",
|
||||
}
|
||||
@@ -1,146 +1,289 @@
|
||||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
from threading import Thread
|
||||
import secrets
|
||||
import shutil
|
||||
import tempfile
|
||||
from contextlib import asynccontextmanager
|
||||
from dataclasses import asdict
|
||||
from typing import Annotated
|
||||
|
||||
from flask import Flask, request, send_from_directory
|
||||
from waitress import serve
|
||||
from fastapi import Depends, FastAPI, HTTPException, Request, status
|
||||
from fastapi.security import HTTPBasic, HTTPBasicCredentials
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import BaseModel
|
||||
from starlette.background import BackgroundTask
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
from xiaomusic import (
|
||||
__version__,
|
||||
)
|
||||
from xiaomusic.config import (
|
||||
KEY_WORD_DICT,
|
||||
from xiaomusic import __version__
|
||||
from xiaomusic.utils import (
|
||||
deepcopy_data_no_sensitive_info,
|
||||
downloadfile,
|
||||
)
|
||||
|
||||
# 隐藏 flask 启动告警
|
||||
# https://gist.github.com/jerblack/735b9953ba1ab6234abb43174210d356
|
||||
# from flask import cli
|
||||
# cli.show_server_banner = lambda *_: None
|
||||
|
||||
app = Flask(__name__)
|
||||
host = "0.0.0.0"
|
||||
port = 8090
|
||||
static_path = "music"
|
||||
xiaomusic = None
|
||||
config = None
|
||||
log = None
|
||||
|
||||
|
||||
@app.route("/allcmds")
|
||||
def allcmds():
|
||||
return KEY_WORD_DICT
|
||||
@asynccontextmanager
|
||||
async def app_lifespan(app):
|
||||
if xiaomusic is not None:
|
||||
task = asyncio.create_task(xiaomusic.run_forever())
|
||||
yield
|
||||
task.cancel()
|
||||
|
||||
|
||||
@app.route("/getversion", methods=["GET"])
|
||||
security = HTTPBasic()
|
||||
|
||||
|
||||
def verification(
|
||||
credentials: Annotated[HTTPBasicCredentials, Depends(security)],
|
||||
):
|
||||
current_username_bytes = credentials.username.encode("utf8")
|
||||
correct_username_bytes = config.httpauth_username.encode("utf8")
|
||||
is_correct_username = secrets.compare_digest(
|
||||
current_username_bytes, correct_username_bytes
|
||||
)
|
||||
current_password_bytes = credentials.password.encode("utf8")
|
||||
correct_password_bytes = config.httpauth_password.encode("utf8")
|
||||
is_correct_password = secrets.compare_digest(
|
||||
current_password_bytes, correct_password_bytes
|
||||
)
|
||||
if not (is_correct_username and is_correct_password):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Incorrect username or password",
|
||||
headers={"WWW-Authenticate": "Basic"},
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def no_verification():
|
||||
return True
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
lifespan=app_lifespan,
|
||||
version=__version__,
|
||||
dependencies=[Depends(verification)],
|
||||
)
|
||||
|
||||
|
||||
def reset_http_server():
|
||||
log.info(f"disable_httpauth:{config.disable_httpauth}")
|
||||
if config.disable_httpauth:
|
||||
app.dependency_overrides[verification] = no_verification
|
||||
else:
|
||||
app.dependency_overrides = {}
|
||||
|
||||
# 更新 music 链接
|
||||
app.router.routes = [route for route in app.router.routes if route.path != "/music"]
|
||||
app.mount("/music", StaticFiles(directory=config.music_path,follow_symlink=True), name="music")
|
||||
|
||||
|
||||
def HttpInit(_xiaomusic):
|
||||
global xiaomusic, config, log
|
||||
xiaomusic = _xiaomusic
|
||||
config = xiaomusic.config
|
||||
log = xiaomusic.log
|
||||
|
||||
folder = os.path.dirname(__file__)
|
||||
app.mount("/static", StaticFiles(directory=f"{folder}/static"), name="static")
|
||||
reset_http_server()
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def read_index():
|
||||
folder = os.path.dirname(__file__)
|
||||
return FileResponse(f"{folder}/static/index.html")
|
||||
|
||||
|
||||
@app.get("/getversion")
|
||||
def getversion():
|
||||
log.debug("getversion %s", __version__)
|
||||
return {
|
||||
"version": __version__,
|
||||
}
|
||||
return {"version": __version__}
|
||||
|
||||
|
||||
@app.route("/getvolume", methods=["GET"])
|
||||
def getvolume():
|
||||
volume = xiaomusic.get_volume_ret()
|
||||
return {
|
||||
"volume": volume,
|
||||
}
|
||||
@app.get("/getvolume")
|
||||
async def getvolume(did: str = ""):
|
||||
if not xiaomusic.did_exist(did):
|
||||
return {"volume": 0}
|
||||
|
||||
volume = await xiaomusic.get_volume(did=did)
|
||||
return {"volume": volume}
|
||||
|
||||
|
||||
@app.route("/searchmusic", methods=["GET"])
|
||||
def searchmusic():
|
||||
name = request.args.get("name")
|
||||
class DidVolume(BaseModel):
|
||||
did: str
|
||||
volume: int = 0
|
||||
|
||||
|
||||
@app.post("/setvolume")
|
||||
async def setvolume(data: DidVolume):
|
||||
did = data.did
|
||||
volume = data.volume
|
||||
if not xiaomusic.did_exist(did):
|
||||
return {"ret": "Did not exist"}
|
||||
|
||||
log.info(f"set_volume {did} {volume}")
|
||||
await xiaomusic.set_volume(did=did, arg1=volume)
|
||||
return {"ret": "OK", "volume": volume}
|
||||
|
||||
|
||||
@app.get("/searchmusic")
|
||||
def searchmusic(name: str = ""):
|
||||
return xiaomusic.searchmusic(name)
|
||||
|
||||
|
||||
@app.route("/playingmusic", methods=["GET"])
|
||||
def playingmusic():
|
||||
return xiaomusic.playingmusic()
|
||||
@app.get("/playingmusic")
|
||||
def playingmusic(did: str = ""):
|
||||
if not xiaomusic.did_exist(did):
|
||||
return {"ret": "Did not exist"}
|
||||
|
||||
is_playing = xiaomusic.isplaying(did)
|
||||
cur_music = xiaomusic.playingmusic(did)
|
||||
return {
|
||||
"ret": "OK",
|
||||
"is_playing": is_playing,
|
||||
"cur_music": cur_music,
|
||||
}
|
||||
|
||||
|
||||
@app.route("/", methods=["GET"])
|
||||
def redirect_to_index():
|
||||
return send_from_directory("static", "index.html")
|
||||
class DidCmd(BaseModel):
|
||||
did: str
|
||||
cmd: str
|
||||
|
||||
|
||||
@app.route("/cmd", methods=["POST"])
|
||||
async def do_cmd():
|
||||
data = request.get_json()
|
||||
cmd = data.get("cmd")
|
||||
@app.post("/cmd")
|
||||
async def do_cmd(data: DidCmd):
|
||||
did = data.did
|
||||
cmd = data.cmd
|
||||
log.info(f"docmd. did:{did} cmd:{cmd}")
|
||||
if not xiaomusic.did_exist(did):
|
||||
return {"ret": "Did not exist"}
|
||||
|
||||
if len(cmd) > 0:
|
||||
log.debug("docmd. cmd:%s", cmd)
|
||||
xiaomusic.set_last_record(cmd)
|
||||
asyncio.create_task(xiaomusic.do_check_cmd(did=did, query=cmd))
|
||||
return {"ret": "OK"}
|
||||
return {"ret": "Unknow cmd"}
|
||||
|
||||
|
||||
@app.route("/getsetting", methods=["GET"])
|
||||
async def getsetting():
|
||||
@app.get("/getsetting")
|
||||
async def getsetting(need_device_list: bool = False):
|
||||
config = xiaomusic.getconfig()
|
||||
log.debug(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,
|
||||
}
|
||||
data = asdict(config)
|
||||
if need_device_list:
|
||||
device_list = await xiaomusic.getalldevices()
|
||||
log.info(f"getsetting device_list: {device_list}")
|
||||
data["device_list"] = device_list
|
||||
return data
|
||||
|
||||
|
||||
@app.route("/savesetting", methods=["POST"])
|
||||
async def savesetting():
|
||||
data = request.get_json()
|
||||
log.info(data)
|
||||
await xiaomusic.saveconfig(data)
|
||||
return "save success"
|
||||
@app.post("/savesetting")
|
||||
async def savesetting(request: Request):
|
||||
try:
|
||||
data_json = await request.body()
|
||||
data = json.loads(data_json.decode("utf-8"))
|
||||
debug_data = deepcopy_data_no_sensitive_info(data)
|
||||
log.info(f"saveconfig: {debug_data}")
|
||||
await xiaomusic.saveconfig(data)
|
||||
reset_http_server()
|
||||
return "save success"
|
||||
except json.JSONDecodeError as err:
|
||||
raise HTTPException(status_code=400, detail="Invalid JSON") from err
|
||||
|
||||
|
||||
@app.route("/musiclist", methods=["GET"])
|
||||
async def musiclist():
|
||||
@app.get("/musiclist")
|
||||
async def musiclist(Verifcation=Depends(verification)):
|
||||
return xiaomusic.get_music_list()
|
||||
|
||||
|
||||
@app.route("/curplaylist", methods=["GET"])
|
||||
async def curplaylist():
|
||||
return xiaomusic.get_cur_play_list()
|
||||
@app.get("/curplaylist")
|
||||
async def curplaylist(did: str = ""):
|
||||
if not xiaomusic.did_exist(did):
|
||||
return ""
|
||||
return xiaomusic.get_cur_play_list(did)
|
||||
|
||||
|
||||
@app.route("/delmusic", methods=["POST"])
|
||||
def delmusic():
|
||||
data = request.get_json()
|
||||
class MusicItem(BaseModel):
|
||||
name: str
|
||||
|
||||
|
||||
@app.post("/delmusic")
|
||||
def delmusic(data: MusicItem):
|
||||
log.info(data)
|
||||
xiaomusic.del_music(data["name"])
|
||||
xiaomusic.del_music(data.name)
|
||||
return "success"
|
||||
|
||||
|
||||
def static_path_handler(filename):
|
||||
log.debug(filename)
|
||||
log.debug(static_path)
|
||||
absolute_path = os.path.abspath(static_path)
|
||||
log.debug(absolute_path)
|
||||
return send_from_directory(absolute_path, filename)
|
||||
class UrlInfo(BaseModel):
|
||||
url: str
|
||||
|
||||
|
||||
def run_app():
|
||||
serve(app, host=host, port=port)
|
||||
@app.post("/downloadjson")
|
||||
async def downloadjson(data: UrlInfo):
|
||||
log.info(data)
|
||||
url = data.url
|
||||
content = ""
|
||||
try:
|
||||
ret = "OK"
|
||||
content = await downloadfile(url)
|
||||
except Exception as e:
|
||||
log.exception(f"Execption {e}")
|
||||
ret = "Download JSON file failed."
|
||||
return {
|
||||
"ret": ret,
|
||||
"content": content,
|
||||
}
|
||||
|
||||
|
||||
def StartHTTPServer(_port, _static_path, _xiaomusic):
|
||||
global port, static_path, xiaomusic, log
|
||||
port = _port
|
||||
static_path = _static_path
|
||||
xiaomusic = _xiaomusic
|
||||
log = xiaomusic.log
|
||||
@app.get("/downloadlog")
|
||||
def downloadlog(Verifcation=Depends(verification)):
|
||||
file_path = xiaomusic.config.log_file
|
||||
if os.path.exists(file_path):
|
||||
# 创建一个临时文件来保存日志的快照
|
||||
temp_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
try:
|
||||
with open(file_path, "rb") as f:
|
||||
shutil.copyfileobj(f, temp_file)
|
||||
temp_file.close()
|
||||
|
||||
app.add_url_rule(
|
||||
f"/{static_path}/<path:filename>", "static_path_handler", static_path_handler
|
||||
)
|
||||
# 使用BackgroundTask在响应发送完毕后删除临时文件
|
||||
def cleanup_temp_file(tmp_file_path):
|
||||
os.remove(tmp_file_path)
|
||||
|
||||
server_thread = Thread(target=run_app)
|
||||
server_thread.daemon = True
|
||||
server_thread.start()
|
||||
xiaomusic.log.info(f"Serving on {host}:{port}")
|
||||
background_task = BackgroundTask(cleanup_temp_file, temp_file.name)
|
||||
return FileResponse(
|
||||
temp_file.name,
|
||||
media_type="text/plain",
|
||||
filename="xiaomusic.txt",
|
||||
background=background_task,
|
||||
)
|
||||
except Exception as e:
|
||||
os.remove(temp_file.name)
|
||||
raise HTTPException(
|
||||
status_code=500, detail="Error capturing log file"
|
||||
) from e
|
||||
else:
|
||||
return {"message": "File not found."}
|
||||
|
||||
|
||||
@app.get("/playurl")
|
||||
async def playurl(did: str, url: str):
|
||||
if not xiaomusic.did_exist(did):
|
||||
return {"ret": "Did not exist"}
|
||||
|
||||
log.info(f"playurl did: {did} url: {url}")
|
||||
return await xiaomusic.play_url(did=did, arg1=url)
|
||||
|
||||
|
||||
@app.post("/debug_play_by_music_url")
|
||||
async def debug_play_by_music_url(request: Request):
|
||||
try:
|
||||
data = await request.body()
|
||||
data_dict = json.loads(data.decode("utf-8"))
|
||||
log.info(f"data:{data_dict}")
|
||||
return await xiaomusic.debug_play_by_music_url(arg1=data_dict)
|
||||
except json.JSONDecodeError as err:
|
||||
raise HTTPException(status_code=400, detail="Invalid JSON") from err
|
||||
|
||||
69
xiaomusic/plugin.py
Normal file
69
xiaomusic/plugin.py
Normal file
@@ -0,0 +1,69 @@
|
||||
import importlib
|
||||
import inspect
|
||||
import pkgutil
|
||||
|
||||
|
||||
class PluginManager:
|
||||
def __init__(self, xiaomusic, plugin_dir="plugins"):
|
||||
self.xiaomusic = xiaomusic
|
||||
self.log = xiaomusic.log
|
||||
self._funcs = {}
|
||||
self._load_plugins(plugin_dir)
|
||||
|
||||
def _load_plugins(self, plugin_dir):
|
||||
# 假设 plugins 已经在搜索路径上
|
||||
package_name = plugin_dir
|
||||
package = importlib.import_module(package_name)
|
||||
|
||||
# 遍历 package 中所有模块并动态导入它们
|
||||
for _, modname, _ in pkgutil.iter_modules(package.__path__, package_name + "."):
|
||||
# 跳过__init__文件
|
||||
if modname.endswith("__init__"):
|
||||
continue
|
||||
module = importlib.import_module(modname)
|
||||
# 将 log 和 xiaomusic 注入模块的命名空间
|
||||
module.log = self.log
|
||||
module.xiaomusic = self.xiaomusic
|
||||
|
||||
# 动态获取模块中与文件名同名的函数
|
||||
function_name = modname.split(".")[-1] # 从模块全名提取函数名
|
||||
if hasattr(module, function_name):
|
||||
self._funcs[function_name] = getattr(module, function_name)
|
||||
else:
|
||||
self.log.error(
|
||||
f"No function named '{function_name}' found in module {modname}"
|
||||
)
|
||||
|
||||
def get_func(self, plugin_name):
|
||||
"""根据插件名获取插件函数"""
|
||||
return self._funcs.get(plugin_name)
|
||||
|
||||
def get_local_namespace(self):
|
||||
"""返回包含所有插件函数的字典,可以用作 exec 要执行的代码的命名空间"""
|
||||
return self._funcs.copy()
|
||||
|
||||
async def execute_plugin(self, code):
|
||||
"""
|
||||
执行指定的插件代码。插件函数可以是同步或异步。
|
||||
:param code: 需要执行的插件函数代码(例如 'plugin1("hello")')
|
||||
"""
|
||||
# 分解代码字符串以获取函数名
|
||||
func_name = code.split("(")[0]
|
||||
|
||||
# 根据解析出的函数名从插件字典中获取函数
|
||||
plugin_func = self.get_func(func_name)
|
||||
|
||||
if not plugin_func:
|
||||
raise ValueError(f"No plugin function named '{func_name}' found.")
|
||||
|
||||
# 检查函数是否是异步函数
|
||||
global_namespace = globals().copy()
|
||||
local_namespace = self.get_local_namespace()
|
||||
if inspect.iscoroutinefunction(plugin_func):
|
||||
# 如果是异步函数,构建执行用的协程对象
|
||||
coroutine = eval(code, global_namespace, local_namespace)
|
||||
# 等待协程执行
|
||||
await coroutine
|
||||
else:
|
||||
# 如果是普通函数,直接执行代码
|
||||
eval(code, global_namespace, local_namespace)
|
||||
@@ -1,8 +1,13 @@
|
||||
$(function(){
|
||||
$container=$("#cmds");
|
||||
append_op_button_name("全部循环");
|
||||
append_op_button_name("单曲循环");
|
||||
append_op_button_name("随机播放");
|
||||
|
||||
const PLAY_TYPE_ONE = 0; // 单曲循环
|
||||
const PLAY_TYPE_ALL = 1; // 全部循环
|
||||
const PLAY_TYPE_RND = 2; // 随机播放
|
||||
append_op_button("play_type_all", "全部循环", "全部循环");
|
||||
append_op_button("play_type_one", "单曲循环", "单曲循环");
|
||||
append_op_button("play_type_rnd", "随机播放", "随机播放");
|
||||
|
||||
append_op_button_name("刷新列表");
|
||||
append_op_button_name("下一首");
|
||||
append_op_button_name("关机");
|
||||
@@ -13,17 +18,67 @@ $(function(){
|
||||
append_op_button_name("30分钟后关机");
|
||||
append_op_button_name("60分钟后关机");
|
||||
|
||||
// 拉取声音
|
||||
sendcmd("get_volume#");
|
||||
$.get("/getvolume", function(data, status) {
|
||||
console.log(data, status, data["volume"]);
|
||||
$("#volume").val(data.volume);
|
||||
// 拉取现有配置
|
||||
$.get("/getsetting", function(data, status) {
|
||||
console.log(data, status);
|
||||
localStorage.setItem('mi_did', data.mi_did);
|
||||
|
||||
var did = localStorage.getItem('cur_did');
|
||||
var dids = [];
|
||||
if (data.mi_did != null) {
|
||||
dids = data.mi_did.split(',');
|
||||
}
|
||||
console.log('cur_did', did);
|
||||
console.log('dids', dids);
|
||||
if ((dids.length > 0) && (did == null || did == "" || !dids.includes(did))) {
|
||||
did = dids[0];
|
||||
localStorage.setItem('cur_did', did);
|
||||
}
|
||||
|
||||
window.did = did;
|
||||
$.get(`/getvolume?did=${did}`, function(data, status) {
|
||||
console.log(data, status, data["volume"]);
|
||||
$("#volume").val(data.volume);
|
||||
});
|
||||
refresh_music_list();
|
||||
|
||||
$("#did").empty();
|
||||
var dids = data.mi_did.split(',');
|
||||
$.each(dids, function(index, value) {
|
||||
var cur_device = Object.values(data.devices).find(device => device.did === value);
|
||||
if (cur_device) {
|
||||
var option = $('<option></option>')
|
||||
.val(value)
|
||||
.text(cur_device.name)
|
||||
.prop('selected', value === did);
|
||||
$("#did").append(option);
|
||||
|
||||
if (cur_device.play_type == PLAY_TYPE_ALL) {
|
||||
$("#play_type_all").css('background-color', '#b1a8f3');
|
||||
$("#play_type_all").text('✔️ 全部循环');
|
||||
} else if (cur_device.play_type == PLAY_TYPE_ONE) {
|
||||
$("#play_type_one").css('background-color', '#b1a8f3');
|
||||
$("#play_type_one").text('✔️ 单曲循环');
|
||||
} else if (cur_device.play_type == PLAY_TYPE_RND) {
|
||||
$("#play_type_rnd").css('background-color', '#b1a8f3');
|
||||
$("#play_type_rnd").text('✔️ 随机播放');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('cur_did', did);
|
||||
$('#did').change(function() {
|
||||
did = $(this).val();
|
||||
localStorage.setItem('cur_did', did);
|
||||
window.did = did;
|
||||
console.log('cur_did', did);
|
||||
})
|
||||
});
|
||||
|
||||
// 拉取版本
|
||||
$.get("/getversion", function(data, status) {
|
||||
console.log(data, status, data["version"]);
|
||||
$("#version").text(`(${data.version})`);
|
||||
$("#version").text(`${data.version}`);
|
||||
});
|
||||
|
||||
// 拉取播放列表
|
||||
@@ -38,7 +93,8 @@ $(function(){
|
||||
$('#music_list').change(function() {
|
||||
const selectedValue = $(this).val();
|
||||
$('#music_name').empty();
|
||||
$.each(data[selectedValue], function(index, item) {
|
||||
const sorted_musics = data[selectedValue].sort(custom_sort_key);
|
||||
$.each(sorted_musics, function(index, item) {
|
||||
$('#music_name').append($('<option></option>').val(item).text(item));
|
||||
});
|
||||
});
|
||||
@@ -46,13 +102,20 @@ $(function(){
|
||||
$('#music_list').trigger('change');
|
||||
|
||||
// 获取当前播放列表
|
||||
$.get("curplaylist", function(data, status) {
|
||||
$('#music_list').val(data);
|
||||
$('#music_list').trigger('change');
|
||||
$.get(`curplaylist?did=${did}`, function(data, status) {
|
||||
if (data != "") {
|
||||
$('#music_list').val(data);
|
||||
$('#music_list').trigger('change');
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 每3秒获取下正在播放的音乐
|
||||
get_playing_music();
|
||||
setInterval(() => {
|
||||
get_playing_music();
|
||||
}, 3000);
|
||||
}
|
||||
refresh_music_list();
|
||||
|
||||
$("#play_music_list").on("click", () => {
|
||||
var music_list = $("#music_list").val();
|
||||
@@ -81,15 +144,25 @@ $(function(){
|
||||
}
|
||||
});
|
||||
|
||||
$("#playurl").on("click", () => {
|
||||
var url = $("#music-url").val();
|
||||
$.get(`/playurl?url=${url}&did=${did}`, function(data, status) {
|
||||
console.log(data);
|
||||
});
|
||||
});
|
||||
|
||||
function append_op_button_name(name) {
|
||||
append_op_button(name, name);
|
||||
append_op_button(null, name, name);
|
||||
}
|
||||
|
||||
function append_op_button(name, cmd) {
|
||||
function append_op_button(id, name, cmd) {
|
||||
// 创建按钮
|
||||
const $button = $("<button>");
|
||||
$button.text(name);
|
||||
$button.attr("type", "button");
|
||||
if (id !== null) {
|
||||
$button.attr("id", id);
|
||||
}
|
||||
|
||||
// 设置按钮点击事件
|
||||
$button.on("click", () => {
|
||||
@@ -107,9 +180,18 @@ $(function(){
|
||||
sendcmd(cmd);
|
||||
});
|
||||
|
||||
$("#volume").on('input', function () {
|
||||
$("#volume").on('change', function () {
|
||||
var value = $(this).val();
|
||||
sendcmd("set_volume#"+value);
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/setvolume",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data: JSON.stringify({did: did, volume: value}),
|
||||
success: () => {
|
||||
},
|
||||
error: () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function sendcmd(cmd) {
|
||||
@@ -117,11 +199,14 @@ $(function(){
|
||||
type: "POST",
|
||||
url: "/cmd",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data: JSON.stringify({cmd: cmd}),
|
||||
data: JSON.stringify({did: did, cmd: cmd}),
|
||||
success: () => {
|
||||
if (cmd == "刷新列表") {
|
||||
setTimeout(refresh_music_list, 3000);
|
||||
}
|
||||
if (["全部循环", "单曲循环", "随机播放"].includes(cmd)) {
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
error: () => {
|
||||
// 请求失败时执行的操作
|
||||
@@ -152,15 +237,34 @@ $(function(){
|
||||
});
|
||||
|
||||
function get_playing_music() {
|
||||
$.get("/playingmusic", function(data, status) {
|
||||
$.get(`/playingmusic?did=${did}`, function(data, status) {
|
||||
console.log(data);
|
||||
$("#playering-music").text(data);
|
||||
if (data.ret == "OK") {
|
||||
if (data.is_playing) {
|
||||
$("#playering-music").text(`【播放中】 ${data.cur_music}`);
|
||||
} else {
|
||||
$("#playering-music").text(`【空闲中】 ${data.cur_music}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 每3秒获取下正在播放的音乐
|
||||
get_playing_music();
|
||||
setInterval(() => {
|
||||
get_playing_music();
|
||||
}, 3000);
|
||||
function custom_sort_key(a, b) {
|
||||
// 使用正则表达式提取数字前缀
|
||||
const numericPrefixA = a.match(/^(\d+)/) ? parseInt(a.match(/^(\d+)/)[1], 10) : null;
|
||||
const numericPrefixB = b.match(/^(\d+)/) ? parseInt(b.match(/^(\d+)/)[1], 10) : null;
|
||||
|
||||
// 如果两个键都有数字前缀,则按数字大小排序
|
||||
if (numericPrefixA !== null && numericPrefixB !== null) {
|
||||
return numericPrefixA - numericPrefixB;
|
||||
}
|
||||
|
||||
// 如果一个键有数字前缀而另一个没有,则有数字前缀的键排在前面
|
||||
if (numericPrefixA !== null) return -1;
|
||||
if (numericPrefixB !== null) return 1;
|
||||
|
||||
// 如果两个键都没有数字前缀,则按照常规字符串排序
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
60
xiaomusic/static/debug.html
Normal file
60
xiaomusic/static/debug.html
Normal file
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Debug For XiaoMusic</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/static/style.css?version=1721391529">
|
||||
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||
<script src="/static/jquery-3.7.1.min.js?version=1721391529"></script>
|
||||
|
||||
<script>
|
||||
var vConsole = new window.VConsole();
|
||||
|
||||
function postJSON() {
|
||||
var data = $('#post-input').val();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/debug_play_by_music_url',
|
||||
data: data,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
success: (err) => {
|
||||
console.log("succ", res);
|
||||
},
|
||||
error: (res) => {
|
||||
console.log("error", res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function sendDebugCmd() {
|
||||
var cmd = $("#cmd").val();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/cmd",
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data: JSON.stringify({cmd: cmd}),
|
||||
success: () => {
|
||||
},
|
||||
error: () => {
|
||||
// 请求失败时执行的操作
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Debug For XiaoMusic</h1>
|
||||
<textarea id="post-input" rows="10" cols="50" placeholder="粘贴json数据..."></textarea><br>
|
||||
<button onclick="postJSON()">提交</button><br>
|
||||
|
||||
<hr>
|
||||
<input id="cmd" type="text"></input>
|
||||
<button onclick="sendDebugCmd()">测试自定义口令</button><br>
|
||||
</body>
|
||||
|
||||
<footer>
|
||||
<p>Powered by <a href="https://github.com/hanxi/xiaomusic" target="_blank">xiaomusic</a></p>
|
||||
</footer>
|
||||
</html>
|
||||
@@ -3,13 +3,31 @@
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>小爱音箱操控面板</title>
|
||||
<script src="/static/jquery-3.7.1.min.js"></script>
|
||||
<script src="/static/app.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
||||
<script src="/static/jquery-3.7.1.min.js?version=1721391529"></script>
|
||||
<script src="/static/app.js?version=1721391529"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/static/style.css?version=1721391529">
|
||||
|
||||
<!--
|
||||
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||
<script>
|
||||
var vConsole = new window.VConsole();
|
||||
</script>
|
||||
-->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h2>小爱音箱操控面板<span id="version">(版本未知)</span></h2>
|
||||
<h2>小爱音箱操控面板
|
||||
(<a id="version" href="https://github.com/hanxi/xiaomusic/blob/main/CHANGELOG.md">
|
||||
版本未知
|
||||
</a>)
|
||||
</h2>
|
||||
<hr>
|
||||
|
||||
<div class="rows">
|
||||
<select id="did">
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id="cmds">
|
||||
</div>
|
||||
<hr>
|
||||
@@ -18,19 +36,19 @@
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#8e43e7" style="height: 48px; width: 48px;"><path d="M550.826667 154.666667a47.786667 47.786667 0 0 0-19.84 4.48L298.666667 298.666667H186.453333A80 80 0 0 0 106.666667 378.453333v267.093334A80 80 0 0 0 186.453333 725.333333H298.666667l232.32 139.52a47.786667 47.786667 0 0 0 19.84 4.48A46.506667 46.506667 0 0 0 597.333333 822.826667V201.173333a46.506667 46.506667 0 0 0-46.506666-46.506666zM554.666667 822.826667c0 3.413333-3.84 3.84-3.84 3.84L320 688.853333l-9.6-6.186666H186.453333A37.12 37.12 0 0 1 149.333333 645.546667V378.453333A37.12 37.12 0 0 1 186.453333 341.333333h123.946667l10.24-6.186666 229.546667-137.6s3.84 0 3.84 3.84zM667.52 346.026667a21.333333 21.333333 0 0 0 0 30.293333 192 192 0 0 1 0 271.36 21.333333 21.333333 0 0 0 0 30.293333 21.333333 21.333333 0 0 0 30.293333 0 234.666667 234.666667 0 0 0 0-331.946666 21.333333 21.333333 0 0 0-30.293333 0z"></path><path d="M804.48 219.52a21.333333 21.333333 0 0 0-30.293333 30.293333 370.986667 370.986667 0 0 1 0 524.373334 21.333333 21.333333 0 0 0 0 30.293333 21.333333 21.333333 0 0 0 30.293333 0 414.08 414.08 0 0 0 0-584.96z"></path></svg>
|
||||
<input id="volume" type="range"></input>
|
||||
<a href="/static/setting.html">
|
||||
<svg fill="#8e43e7" height="64px" width="64px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-11.88 -11.88 77.76 77.76" xml:space="preserve" stroke="#8e43e7" transform="rotate(0)matrix(1, 0, 0, 1, 0, 0)" stroke-width="0.00054"><g id="SVGRepo_bgCarrier" stroke-width="0" transform="translate(0,0), scale(1)"><rect x="-11.88" y="-11.88" width="77.76" height="77.76" rx="18.6624" fill="#addcff" strokewidth="0"></rect></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round" stroke="#CCCCCC" stroke-width="1.512"></g><g id="SVGRepo_iconCarrier"> <g> <path d="M51.22,21h-5.052c-0.812,0-1.481-0.447-1.792-1.197s-0.153-1.54,0.42-2.114l3.572-3.571 c0.525-0.525,0.814-1.224,0.814-1.966c0-0.743-0.289-1.441-0.814-1.967l-4.553-4.553c-1.05-1.05-2.881-1.052-3.933,0l-3.571,3.571 c-0.574,0.573-1.366,0.733-2.114,0.421C33.447,9.313,33,8.644,33,7.832V2.78C33,1.247,31.753,0,30.22,0H23.78 C22.247,0,21,1.247,21,2.78v5.052c0,0.812-0.447,1.481-1.197,1.792c-0.748,0.313-1.54,0.152-2.114-0.421l-3.571-3.571 c-1.052-1.052-2.883-1.05-3.933,0l-4.553,4.553c-0.525,0.525-0.814,1.224-0.814,1.967c0,0.742,0.289,1.44,0.814,1.966l3.572,3.571 c0.573,0.574,0.73,1.364,0.42,2.114S8.644,21,7.832,21H2.78C1.247,21,0,22.247,0,23.78v6.439C0,31.753,1.247,33,2.78,33h5.052 c0.812,0,1.481,0.447,1.792,1.197s0.153,1.54-0.42,2.114l-3.572,3.571c-0.525,0.525-0.814,1.224-0.814,1.966 c0,0.743,0.289,1.441,0.814,1.967l4.553,4.553c1.051,1.051,2.881,1.053,3.933,0l3.571-3.572c0.574-0.573,1.363-0.731,2.114-0.42 c0.75,0.311,1.197,0.98,1.197,1.792v5.052c0,1.533,1.247,2.78,2.78,2.78h6.439c1.533,0,2.78-1.247,2.78-2.78v-5.052 c0-0.812,0.447-1.481,1.197-1.792c0.751-0.312,1.54-0.153,2.114,0.42l3.571,3.572c1.052,1.052,2.883,1.05,3.933,0l4.553-4.553 c0.525-0.525,0.814-1.224,0.814-1.967c0-0.742-0.289-1.44-0.814-1.966l-3.572-3.571c-0.573-0.574-0.73-1.364-0.42-2.114 S45.356,33,46.168,33h5.052c1.533,0,2.78-1.247,2.78-2.78V23.78C54,22.247,52.753,21,51.22,21z M52,30.22 C52,30.65,51.65,31,51.22,31h-5.052c-1.624,0-3.019,0.932-3.64,2.432c-0.622,1.5-0.295,3.146,0.854,4.294l3.572,3.571 c0.305,0.305,0.305,0.8,0,1.104l-4.553,4.553c-0.304,0.304-0.799,0.306-1.104,0l-3.571-3.572c-1.149-1.149-2.794-1.474-4.294-0.854 c-1.5,0.621-2.432,2.016-2.432,3.64v5.052C31,51.65,30.65,52,30.22,52H23.78C23.35,52,23,51.65,23,51.22v-5.052 c0-1.624-0.932-3.019-2.432-3.64c-0.503-0.209-1.021-0.311-1.533-0.311c-1.014,0-1.997,0.4-2.761,1.164l-3.571,3.572 c-0.306,0.306-0.801,0.304-1.104,0l-4.553-4.553c-0.305-0.305-0.305-0.8,0-1.104l3.572-3.571c1.148-1.148,1.476-2.794,0.854-4.294 C10.851,31.932,9.456,31,7.832,31H2.78C2.35,31,2,30.65,2,30.22V23.78C2,23.35,2.35,23,2.78,23h5.052 c1.624,0,3.019-0.932,3.64-2.432c0.622-1.5,0.295-3.146-0.854-4.294l-3.572-3.571c-0.305-0.305-0.305-0.8,0-1.104l4.553-4.553 c0.304-0.305,0.799-0.305,1.104,0l3.571,3.571c1.147,1.147,2.792,1.476,4.294,0.854C22.068,10.851,23,9.456,23,7.832V2.78 C23,2.35,23.35,2,23.78,2h6.439C30.65,2,31,2.35,31,2.78v5.052c0,1.624,0.932,3.019,2.432,3.64 c1.502,0.622,3.146,0.294,4.294-0.854l3.571-3.571c0.306-0.305,0.801-0.305,1.104,0l4.553,4.553c0.305,0.305,0.305,0.8,0,1.104 l-3.572,3.571c-1.148,1.148-1.476,2.794-0.854,4.294c0.621,1.5,2.016,2.432,3.64,2.432h5.052C51.65,23,52,23.35,52,23.78V30.22z"></path> <path d="M27,18c-4.963,0-9,4.037-9,9s4.037,9,9,9s9-4.037,9-9S31.963,18,27,18z M27,34c-3.859,0-7-3.141-7-7s3.141-7,7-7 s7,3.141,7,7S30.859,34,27,34z"></path> </g> </g></svg>
|
||||
<svg fill="#8e43e7" height="48px" width="48px" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-11.88 -11.88 77.76 77.76" xml:space="preserve" stroke="#8e43e7" transform="rotate(0)matrix(1, 0, 0, 1, 0, 0)" stroke-width="0.00054"><g id="SVGRepo_bgCarrier" stroke-width="0" transform="translate(0,0), scale(1)"><rect x="-11.88" y="-11.88" width="77.76" height="77.76" rx="18.6624" fill="#addcff" strokewidth="0"></rect></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round" stroke="#CCCCCC" stroke-width="1.512"></g><g id="SVGRepo_iconCarrier"> <g> <path d="M51.22,21h-5.052c-0.812,0-1.481-0.447-1.792-1.197s-0.153-1.54,0.42-2.114l3.572-3.571 c0.525-0.525,0.814-1.224,0.814-1.966c0-0.743-0.289-1.441-0.814-1.967l-4.553-4.553c-1.05-1.05-2.881-1.052-3.933,0l-3.571,3.571 c-0.574,0.573-1.366,0.733-2.114,0.421C33.447,9.313,33,8.644,33,7.832V2.78C33,1.247,31.753,0,30.22,0H23.78 C22.247,0,21,1.247,21,2.78v5.052c0,0.812-0.447,1.481-1.197,1.792c-0.748,0.313-1.54,0.152-2.114-0.421l-3.571-3.571 c-1.052-1.052-2.883-1.05-3.933,0l-4.553,4.553c-0.525,0.525-0.814,1.224-0.814,1.967c0,0.742,0.289,1.44,0.814,1.966l3.572,3.571 c0.573,0.574,0.73,1.364,0.42,2.114S8.644,21,7.832,21H2.78C1.247,21,0,22.247,0,23.78v6.439C0,31.753,1.247,33,2.78,33h5.052 c0.812,0,1.481,0.447,1.792,1.197s0.153,1.54-0.42,2.114l-3.572,3.571c-0.525,0.525-0.814,1.224-0.814,1.966 c0,0.743,0.289,1.441,0.814,1.967l4.553,4.553c1.051,1.051,2.881,1.053,3.933,0l3.571-3.572c0.574-0.573,1.363-0.731,2.114-0.42 c0.75,0.311,1.197,0.98,1.197,1.792v5.052c0,1.533,1.247,2.78,2.78,2.78h6.439c1.533,0,2.78-1.247,2.78-2.78v-5.052 c0-0.812,0.447-1.481,1.197-1.792c0.751-0.312,1.54-0.153,2.114,0.42l3.571,3.572c1.052,1.052,2.883,1.05,3.933,0l4.553-4.553 c0.525-0.525,0.814-1.224,0.814-1.967c0-0.742-0.289-1.44-0.814-1.966l-3.572-3.571c-0.573-0.574-0.73-1.364-0.42-2.114 S45.356,33,46.168,33h5.052c1.533,0,2.78-1.247,2.78-2.78V23.78C54,22.247,52.753,21,51.22,21z M52,30.22 C52,30.65,51.65,31,51.22,31h-5.052c-1.624,0-3.019,0.932-3.64,2.432c-0.622,1.5-0.295,3.146,0.854,4.294l3.572,3.571 c0.305,0.305,0.305,0.8,0,1.104l-4.553,4.553c-0.304,0.304-0.799,0.306-1.104,0l-3.571-3.572c-1.149-1.149-2.794-1.474-4.294-0.854 c-1.5,0.621-2.432,2.016-2.432,3.64v5.052C31,51.65,30.65,52,30.22,52H23.78C23.35,52,23,51.65,23,51.22v-5.052 c0-1.624-0.932-3.019-2.432-3.64c-0.503-0.209-1.021-0.311-1.533-0.311c-1.014,0-1.997,0.4-2.761,1.164l-3.571,3.572 c-0.306,0.306-0.801,0.304-1.104,0l-4.553-4.553c-0.305-0.305-0.305-0.8,0-1.104l3.572-3.571c1.148-1.148,1.476-2.794,0.854-4.294 C10.851,31.932,9.456,31,7.832,31H2.78C2.35,31,2,30.65,2,30.22V23.78C2,23.35,2.35,23,2.78,23h5.052 c1.624,0,3.019-0.932,3.64-2.432c0.622-1.5,0.295-3.146-0.854-4.294l-3.572-3.571c-0.305-0.305-0.305-0.8,0-1.104l4.553-4.553 c0.304-0.305,0.799-0.305,1.104,0l3.571,3.571c1.147,1.147,2.792,1.476,4.294,0.854C22.068,10.851,23,9.456,23,7.832V2.78 C23,2.35,23.35,2,23.78,2h6.439C30.65,2,31,2.35,31,2.78v5.052c0,1.624,0.932,3.019,2.432,3.64 c1.502,0.622,3.146,0.294,4.294-0.854l3.571-3.571c0.306-0.305,0.801-0.305,1.104,0l4.553,4.553c0.305,0.305,0.305,0.8,0,1.104 l-3.572,3.571c-1.148,1.148-1.476,2.794-0.854,4.294c0.621,1.5,2.016,2.432,3.64,2.432h5.052C51.65,23,52,23.35,52,23.78V30.22z"></path> <path d="M27,18c-4.963,0-9,4.037-9,9s4.037,9,9,9s9-4.037,9-9S31.963,18,27,18z M27,34c-3.859,0-7-3.141-7-7s3.141-7,7-7 s7,3.141,7,7S30.859,34,27,34z"></path> </g> </g></svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div>
|
||||
<div class="rows">
|
||||
<datalist id="autocomplete-list"></datalist>
|
||||
<input id="music-name" type="text" placeholder="请输入搜索关键词(如:MV高清版 周杰伦 七里香)" list="autocomplete-list"></input>
|
||||
<input id="music-filename" type="text" placeholder="请输入保存为的文件名称(如:周杰伦七里香)"></input>
|
||||
</div>
|
||||
<button id="play">播放</button>
|
||||
<div class="container">
|
||||
<div id="playering-music" class="text"></div>
|
||||
<div>
|
||||
<button id="play">播放</button>
|
||||
<div id="playering-music" class="text"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
@@ -39,9 +57,17 @@
|
||||
<select id="music_list"></select>
|
||||
<label for="music_name">歌曲:</label>
|
||||
<select id="music_name"></select>
|
||||
<div>
|
||||
<button id="play_music_list">播放列表歌曲</button>
|
||||
<button id="del_music">删除选中歌曲</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div class="rows">
|
||||
<input id="music-url" type="text" value="https://lhttp.qtfm.cn/live/4915/64k.mp3"></input>
|
||||
<button id="playurl">播放链接</button>
|
||||
</div>
|
||||
<button id="play_music_list">播放列表歌曲</button>
|
||||
<button id="del_music">删除选中歌曲</button>
|
||||
|
||||
<footer>
|
||||
<p>Powered by <a href="https://github.com/hanxi/xiaomusic" target="_blank">xiaomusic</a></p>
|
||||
|
||||
64
xiaomusic/static/m3u.html
Normal file
64
xiaomusic/static/m3u.html
Normal file
@@ -0,0 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>M3U to JSON Converter</title>
|
||||
<link rel="stylesheet" type="text/css" href="/static/style.css?version=1721391529">
|
||||
<!--
|
||||
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||
<script>
|
||||
// VConsole 默认会挂载到 `window.VConsole` 上
|
||||
var vConsole = new window.VConsole();
|
||||
</script>
|
||||
-->
|
||||
<script>
|
||||
function handleFileSelect(evt) {
|
||||
var file = evt.target.files[0];
|
||||
if (file) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
document.getElementById('m3u-input').value = e.target.result;
|
||||
};
|
||||
reader.readAsText(file);
|
||||
} else {
|
||||
alert('无法加载文件');
|
||||
}
|
||||
}
|
||||
|
||||
function convertToJSON() {
|
||||
var m3uContent = document.getElementById('m3u-input').value;
|
||||
var lines = m3uContent.split('\n');
|
||||
console.log(lines);
|
||||
var musicsArray = [];
|
||||
var currentName = '';
|
||||
lines.forEach(function(line) {
|
||||
line = line.trim();
|
||||
if (line.startsWith('#EXTINF:')) {
|
||||
currentName = line.replace(/.*,/g, '');
|
||||
} else if (line.startsWith('http') && currentName !== '') {
|
||||
musicsArray.push({"name": currentName, "type": "radio", "url": line});
|
||||
currentName = ''; // Reset the name for the next entry
|
||||
}
|
||||
});
|
||||
var output = [{
|
||||
"name": "m3u电台",
|
||||
"musics": musicsArray
|
||||
}];
|
||||
|
||||
document.getElementById('json-output').value = JSON.stringify(output, null, 2);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>M3U to JSON Converter</h1>
|
||||
<input type="file" id="file-input" accept=".m3u" onchange="handleFileSelect(event)"/><br>
|
||||
<textarea id="m3u-input" rows="10" cols="50" placeholder="粘贴m3u内容或上传文件..."></textarea><br>
|
||||
<button onclick="convertToJSON()">转换</button><br>
|
||||
<textarea id="json-output" rows="10" cols="50" placeholder="转换后的JSON..."></textarea>
|
||||
</body>
|
||||
<footer>
|
||||
<p>Powered by <a href="https://github.com/hanxi/xiaomusic" target="_blank">xiaomusic</a></p>
|
||||
</footer>
|
||||
</html>
|
||||
|
||||
@@ -3,29 +3,153 @@
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>小爱音箱操控面板</title>
|
||||
<script src="/static/jquery-3.7.1.min.js"></script>
|
||||
<script src="/static/setting.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/static/style.css">
|
||||
<script src="/static/jquery-3.7.1.min.js?version=1721391529"></script>
|
||||
<script src="/static/setting.js?version=1721391529"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/static/style.css?version=1721391529">
|
||||
|
||||
<!--
|
||||
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||
<script>
|
||||
var vConsole = new window.VConsole();
|
||||
</script>
|
||||
-->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h2>小爱音箱设置面板<span id="version">(版本未知)</span></h2>
|
||||
<h2>小爱音箱设置面板
|
||||
(<a id="version" href="https://github.com/hanxi/xiaomusic/blob/main/CHANGELOG.md">
|
||||
版本未知
|
||||
</a>)
|
||||
</h2>
|
||||
<hr>
|
||||
|
||||
<div class="rows">
|
||||
<label for="mi_did">MI_DID:</label>
|
||||
<select id="mi_did"></select>
|
||||
<label for="mi_hardware">MI_HARDWARE:</label>
|
||||
<select id="mi_hardware"></select>
|
||||
<label for="xiaomusic_search">XIAOMUSIC_SEARCH:</label>
|
||||
<select id="xiaomusic_search">
|
||||
<option value="ytsearch:">ytsearch:</option>
|
||||
<option value="bilisearch:">bilisearch:</option>
|
||||
</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="mi_did">*勾选设备(至少勾选1个):</label>
|
||||
<div id="mi_did">
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div id="setting">
|
||||
<div class="rows">
|
||||
<label for="account">*小米账号:</label>
|
||||
<input id="account" type="text" placeholder="填写小米登录账号"></input>
|
||||
|
||||
<label for="password">*小米密码:</label>
|
||||
<input id="password" type="password" placeholder="填写小米登录密码"></input>
|
||||
|
||||
<label for="hostname">*XIAOMUSIC_HOSTNAME(IP或域名):</label>
|
||||
<input id="hostname" type="text"></input>
|
||||
|
||||
<label for="verbose">是否开启调试日志:</label>
|
||||
<select id="verbose">
|
||||
<option value="true" selected>true</option>
|
||||
<option value="false">false</option>
|
||||
</select>
|
||||
|
||||
<div>
|
||||
<button class="save-button">保存</button>
|
||||
<button onclick="location.href='/';">返回首页</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="rows">
|
||||
<label for="group_list">设备分组配置:</label>
|
||||
<input id="group_list" type="text" placeholder="did1:组名1,did2:组名1,did3:组名2"></input>
|
||||
|
||||
<label for="music_path">音乐目录:</label>
|
||||
<input id="music_path" type="text" value="music"></input>
|
||||
|
||||
<label for="download_path">音乐下载目录(必须是music的子目录):</label>
|
||||
<input id="download_path" type="text" value='music/download'></input>
|
||||
|
||||
<label for="conf_path">配置文件目录:</label>
|
||||
<input id="conf_path" type="text"></input>
|
||||
|
||||
<label for="ffmpeg_location">ffmpeg路径:</label>
|
||||
<input id="ffmpeg_location" type="text" value="./ffmpeg/bin"></input>
|
||||
|
||||
<label for="log_file">日志路径:</label>
|
||||
<input id="log_file" type="text" value="/tmp/xiaomusic.txt"></input>
|
||||
|
||||
<label for="active_cmd">允许唤醒的命令:</label>
|
||||
<input id="active_cmd" type="text" value="play,random_play,playlocal,play_music_list,stop"></input>
|
||||
|
||||
<label for="exclude_dirs">忽略目录(逗号分割):</label>
|
||||
<input id="exclude_dirs" type="text" value="@eaDir"></input>
|
||||
|
||||
<label for="music_path_depth">目录深度:</label>
|
||||
<input id="music_path_depth" type="number" value="10"></input>
|
||||
|
||||
<label for="search_prefix">XIAOMUSIC_SEARCH(歌曲下载方式):</label>
|
||||
<select id="search_prefix">
|
||||
<option value="bilisearch:">bilisearch:</option>
|
||||
<option value="ytsearch:">ytsearch:</option>
|
||||
</select>
|
||||
|
||||
<label for="proxy">XIAOMUSIC_PROXY(ytsearch需要):</label>
|
||||
<input id="proxy" type="text" placeholder="http://192.168.2.5:8080"></input>
|
||||
|
||||
<label for="disable_httpauth">关闭密码验证:</label>
|
||||
<select id="disable_httpauth">
|
||||
<option value="true" selected>true</option>
|
||||
<option value="false">false</option>
|
||||
</select>
|
||||
<label for="httpauth_username">web控制台账户:</label>
|
||||
<input id="httpauth_username" type="text" value=""></input>
|
||||
<label for="httpauth_password">web控制台密码:</label>
|
||||
<input id="httpauth_password" type="password" value=""></input>
|
||||
|
||||
<label for="disable_download">关闭下载功能:</label>
|
||||
<select id="disable_download">
|
||||
<option value="true">true</option>
|
||||
<option value="false" selected>false</option>
|
||||
</select>
|
||||
|
||||
<label for="use_music_audio_id">触屏版显示歌曲ID:</label>
|
||||
<input id="use_music_audio_id" type="text" value="1582971365183456177"></input>
|
||||
<label for="use_music_id">触屏版显示歌曲分段ID:</label>
|
||||
<input id="use_music_id" type="text" value="355454500"></input>
|
||||
|
||||
<label for="fuzzy_match_cutoff">模糊匹配阈值(0.1~0.9):</label>
|
||||
<input id="fuzzy_match_cutoff" type="number" value="0.6"></input>
|
||||
|
||||
<label for="enable_fuzzy_match">开启模糊搜索:</label>
|
||||
<select id="enable_fuzzy_match">
|
||||
<option value="true" selected>true</option>
|
||||
<option value="false">false</option>
|
||||
</select>
|
||||
|
||||
<label for="public_port">外网访问端口(0表示跟监听端口一致):</label>
|
||||
<input id="public_port" type="number" value="0"></input>
|
||||
|
||||
<label for="stop_tts_msg">停止提示音:</label>
|
||||
<input id="stop_tts_msg" type="text" value="收到,再见"></input>
|
||||
<label for="keywords_playlocal">播放本地歌曲口令:</label>
|
||||
<input id="keywords_playlocal" type="text" value="播放本地歌曲,本地播放歌曲"></input>
|
||||
<label for="keywords_play">播放歌曲口令:</label>
|
||||
<input id="keywords_play" type="text" value="播放歌曲,放歌曲"></input>
|
||||
<label for="keywords_stop">停止口令:</label>
|
||||
<input id="keywords_stop" type="text" value="关机,暂停,停止,停止播放"></input>
|
||||
|
||||
<label for="music_list_url">歌单地址:</label>
|
||||
<input id="music_list_url" type="text" value="https://gist.githubusercontent.com/hanxi/dda82d964a28f8110f8fba81c3ff8314/raw/example.json"></input>
|
||||
|
||||
<label for="music_list_json">歌单内容:</label>
|
||||
<textarea id="music_list_json" type="text"></textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<button onclick="location.href='/';">返回首页</button>
|
||||
<button id="save">保存</button>
|
||||
<button id="get_music_list">获取歌单</button>
|
||||
<button class="save-button">保存</button>
|
||||
<a class="button" href="/downloadlog" download="xiaomusic.txt">下载日志文件</a>
|
||||
<hr>
|
||||
|
||||
<a href="/static/m3u.html" target="_blank">m3u文件转换工具</a>
|
||||
<hr>
|
||||
<a href="/static/debug.html" target="_blank">调试工具</a>
|
||||
|
||||
<footer>
|
||||
<p>Powered by <a href="https://github.com/hanxi/xiaomusic" target="_blank">xiaomusic</a></p>
|
||||
|
||||
@@ -2,61 +2,103 @@ $(function(){
|
||||
// 拉取版本
|
||||
$.get("/getversion", function(data, status) {
|
||||
console.log(data, status, data["version"]);
|
||||
$("#version").text(`(${data.version})`);
|
||||
$("#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);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function updateCheckbox(selector, mi_did, device_list) {
|
||||
// 清除现有的内容
|
||||
$(selector).empty();
|
||||
|
||||
// 将 mi_did 字符串通过逗号分割转换为数组,以便于判断默认选中项
|
||||
var selected_dids = mi_did.split(',');
|
||||
|
||||
$.each(device_list, function(index, device) {
|
||||
var did = device.miotDID;
|
||||
var hardware = device.hardware;
|
||||
var name = device.name;
|
||||
// 创建复选框元素
|
||||
var checkbox = $('<input>', {
|
||||
type: 'checkbox',
|
||||
id: did,
|
||||
value: `${did}`,
|
||||
class: 'custom-checkbox', // 添加样式类
|
||||
// 如果mi_did中包含了该did,则默认选中
|
||||
checked: selected_dids.indexOf(did) !== -1
|
||||
});
|
||||
|
||||
// 创建标签元素
|
||||
var label = $('<label>', {
|
||||
for: did,
|
||||
class: 'checkbox-label', // 添加样式类
|
||||
text: `【${hardware} ${did}】${name}` // 设定标签内容
|
||||
});
|
||||
|
||||
// 将复选框和标签添加到目标选择器元素中
|
||||
$(selector).append(checkbox).append(label);
|
||||
});
|
||||
}
|
||||
|
||||
function getSelectedDids(containerSelector) {
|
||||
var selectedDids = [];
|
||||
|
||||
// 仅选择给定容器中选中的复选框
|
||||
$(containerSelector + ' .custom-checkbox:checked').each(function() {
|
||||
var did = this.value;
|
||||
selectedDids.push(did);
|
||||
});
|
||||
|
||||
return selectedDids.join(',');
|
||||
}
|
||||
|
||||
// 拉取现有配置
|
||||
$.get("/getsetting", function(data, status) {
|
||||
$.get("/getsetting?need_device_list=true", function(data, status) {
|
||||
console.log(data, status);
|
||||
updateCheckbox("#mi_did", data.mi_did, data.device_list);
|
||||
|
||||
var mi_did_div = $("#mi_did")
|
||||
mi_did_div.empty();
|
||||
$.each(data.mi_did_list, function(index, option){
|
||||
mi_did_div.append($('<option>', {
|
||||
value:option,
|
||||
text:option,
|
||||
}));
|
||||
if (data.mi_did == option) {
|
||||
mi_did_div.val(option);
|
||||
// 初始化显示
|
||||
for (const key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
const $element = $("#" + key);
|
||||
if ($element.length && data[key] !== '') {
|
||||
if (data[key] === true) {
|
||||
$element.val('true');
|
||||
} else if (data[key] === false) {
|
||||
$element.val('false');
|
||||
} else {
|
||||
$element.val(data[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var mi_hardware_div = $("#mi_hardware")
|
||||
mi_hardware_div.empty();
|
||||
$.each(data.mi_hardware_list, function(index, option){
|
||||
mi_hardware_div.append($('<option>', {
|
||||
value:option,
|
||||
text:option,
|
||||
}));
|
||||
if (data.mi_hardware == option) {
|
||||
mi_hardware_div.val(option);
|
||||
}
|
||||
});
|
||||
|
||||
if (data.xiaomusic_search != "") {
|
||||
$("#xiaomusic_search").val(data.xiaomusic_search);
|
||||
}
|
||||
|
||||
if (data.xiaomusic_proxy != "") {
|
||||
$("#xiaomusic_proxy").val(data.xiaomusic_proxy);
|
||||
}
|
||||
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();
|
||||
console.log("mi_did", mi_did);
|
||||
console.log("mi_hardware", mi_hardware);
|
||||
console.log("xiaomusic_search", xiaomusic_search);
|
||||
console.log("xiaomusic_proxy", xiaomusic_proxy);
|
||||
var data = {
|
||||
mi_did: mi_did,
|
||||
mi_hardware: mi_hardware,
|
||||
xiaomusic_search: xiaomusic_search,
|
||||
xiaomusic_proxy: xiaomusic_proxy,
|
||||
};
|
||||
$(".save-button").on("click", () => {
|
||||
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();
|
||||
}
|
||||
});
|
||||
var did_list = getSelectedDids("#mi_did");
|
||||
data["mi_did"] = did_list;
|
||||
console.log(data)
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/savesetting",
|
||||
@@ -64,10 +106,37 @@ $(function(){
|
||||
data: JSON.stringify(data),
|
||||
success: (msg) => {
|
||||
alert(msg);
|
||||
location.reload();
|
||||
},
|
||||
error: (msg) => {
|
||||
alert(msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#get_music_list").on("click", () => {
|
||||
var music_list_url = $("#music_list_url").val();
|
||||
console.log("music_list_url", music_list_url);
|
||||
var data = {
|
||||
url: music_list_url,
|
||||
};
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/downloadjson",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify(data),
|
||||
success: (res) => {
|
||||
if (res.ret == "OK") {
|
||||
$("#music_list_json").val(res.content);
|
||||
} else {
|
||||
console.log(res);
|
||||
alert(res.ret);
|
||||
}
|
||||
},
|
||||
error: (res) => {
|
||||
console.log(res);
|
||||
alert(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
button {
|
||||
.button {
|
||||
line-height: 50px;
|
||||
font-size: 14px;
|
||||
}
|
||||
button, .button {
|
||||
margin: 10px;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
@@ -10,7 +14,7 @@ button {
|
||||
border-radius: 10px;
|
||||
background-color: #008CBA;
|
||||
}
|
||||
button:active {
|
||||
button:active, .button:active {
|
||||
font-weight:bold;
|
||||
background-color: #007CBA;
|
||||
transform: translateY(2px);
|
||||
@@ -25,35 +29,6 @@ input,select {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.container{
|
||||
width: 280px;
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
}
|
||||
@keyframes text-scroll {
|
||||
0% {
|
||||
left: 100%;
|
||||
}
|
||||
25% {
|
||||
left: 50%;
|
||||
}
|
||||
50% {
|
||||
left: 0%;
|
||||
}
|
||||
75% {
|
||||
left: -50%;
|
||||
}
|
||||
100% {
|
||||
left: -100%;
|
||||
}
|
||||
}
|
||||
.text {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
animation: text-scroll 10s linear infinite;
|
||||
}
|
||||
|
||||
.rows {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -67,3 +42,38 @@ footer {
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
textarea{
|
||||
margin: 10px;
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.custom-checkbox {
|
||||
display: inline-block;
|
||||
margin: 10px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: middle; /* 确保与标签垂直居中对齐 */
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
display: inline-block;
|
||||
width: 260px;
|
||||
background-color: #fff;
|
||||
border: 0px solid #ccc;
|
||||
border-radius: 3px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
vertical-align: middle; /* 确保与复选框垂直居中对齐 */
|
||||
margin-left: 1px; /* 给复选框和标签之间一些距离,如果需要的话 */
|
||||
}
|
||||
|
||||
.text {
|
||||
margin: 10px;
|
||||
width: 150px;
|
||||
height: 50px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import difflib
|
||||
import mimetypes
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import string
|
||||
import tempfile
|
||||
from collections.abc import AsyncIterator
|
||||
from http.cookies import SimpleCookie
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import aiohttp
|
||||
import mutagen
|
||||
from requests.utils import cookiejar_from_dict
|
||||
|
||||
from xiaomusic.const import SUPPORT_MUSIC_TYPE
|
||||
|
||||
|
||||
### HELP FUNCTION ###
|
||||
def parse_cookie_string(cookie_string):
|
||||
@@ -63,4 +73,225 @@ def validate_proxy(proxy_str: str) -> bool:
|
||||
|
||||
# 模糊搜索
|
||||
def fuzzyfinder(user_input, collection):
|
||||
return difflib.get_close_matches(user_input, collection, 10, cutoff=0.1)
|
||||
lower_collection = {item.lower(): item for item in collection}
|
||||
user_input = user_input.lower()
|
||||
matches = difflib.get_close_matches(
|
||||
user_input, lower_collection.keys(), n=10, cutoff=0.1
|
||||
)
|
||||
return [lower_collection[match] for match in matches]
|
||||
|
||||
|
||||
def find_best_match(user_input, collection, cutoff=0.6):
|
||||
lower_collection = {item.lower(): item for item in collection}
|
||||
user_input = user_input.lower()
|
||||
matches = difflib.get_close_matches(
|
||||
user_input, lower_collection.keys(), n=1, cutoff=cutoff
|
||||
)
|
||||
return lower_collection[matches[0]] if matches else None
|
||||
|
||||
|
||||
# 歌曲排序
|
||||
def custom_sort_key(s):
|
||||
# 使用正则表达式分别提取字符串的数字前缀和数字后缀
|
||||
prefix_match = re.match(r"^(\d+)", s)
|
||||
suffix_match = re.search(r"(\d+)$", s)
|
||||
|
||||
numeric_prefix = int(prefix_match.group(0)) if prefix_match else None
|
||||
numeric_suffix = int(suffix_match.group(0)) if suffix_match else None
|
||||
|
||||
if numeric_prefix is not None:
|
||||
# 如果前缀是数字,先按前缀数字排序,再按整个字符串排序
|
||||
return (0, numeric_prefix, s)
|
||||
elif numeric_suffix is not None:
|
||||
# 如果后缀是数字,先按前缀字符排序,再按后缀数字排序
|
||||
return (1, s[: suffix_match.start()], numeric_suffix)
|
||||
else:
|
||||
# 如果前缀和后缀都不是数字,按字典序排序
|
||||
return (2, s)
|
||||
|
||||
|
||||
def _get_depth_path(root, directory, depth):
|
||||
# 计算当前目录的深度
|
||||
relative_path = root[len(directory) :].strip(os.sep)
|
||||
path_parts = relative_path.split(os.sep)
|
||||
if len(path_parts) >= depth:
|
||||
return os.path.join(directory, *path_parts[:depth])
|
||||
else:
|
||||
return root
|
||||
|
||||
|
||||
def _append_files_result(result, root, joinpath, files, support_extension):
|
||||
dir_name = os.path.basename(root)
|
||||
if dir_name not in result:
|
||||
result[dir_name] = []
|
||||
for file in files:
|
||||
# 过滤隐藏文件
|
||||
if file.startswith("."):
|
||||
continue
|
||||
# 过滤文件后缀
|
||||
(name, extension) = os.path.splitext(file)
|
||||
if extension.lower() not in support_extension:
|
||||
continue
|
||||
|
||||
result[dir_name].append(os.path.join(joinpath, file))
|
||||
|
||||
|
||||
def traverse_music_directory(
|
||||
directory, depth=10, exclude_dirs=None, support_extension=None
|
||||
):
|
||||
result = {}
|
||||
for root, dirs, files in os.walk(directory, followlinks=True):
|
||||
# 忽略排除的目录
|
||||
dirs[:] = [d for d in dirs if d not in exclude_dirs]
|
||||
|
||||
# 计算当前目录的深度
|
||||
current_depth = root[len(directory) :].count(os.sep) + 1
|
||||
if current_depth > depth:
|
||||
depth_path = _get_depth_path(root, directory, depth - 1)
|
||||
_append_files_result(result, depth_path, root, files, support_extension)
|
||||
else:
|
||||
_append_files_result(result, root, root, files, support_extension)
|
||||
return result
|
||||
|
||||
|
||||
async def downloadfile(url):
|
||||
# 清理和验证URL
|
||||
# 解析URL
|
||||
parsed_url = urlparse(url)
|
||||
# 基础验证:仅允许HTTP和HTTPS协议
|
||||
if parsed_url.scheme not in ("http", "https"):
|
||||
raise Warning(
|
||||
f"Invalid URL scheme: {parsed_url.scheme}. Only HTTP and HTTPS are allowed."
|
||||
)
|
||||
# 构建目标URL
|
||||
cleaned_url = parsed_url.geturl()
|
||||
|
||||
# 使用 aiohttp 创建一个客户端会话来发起请求
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
cleaned_url, timeout=5
|
||||
) as response: # 增加超时以避免长时间挂起
|
||||
# 如果响应不是200,引发异常
|
||||
response.raise_for_status()
|
||||
# 读取响应文本
|
||||
text = await response.text()
|
||||
return text
|
||||
|
||||
|
||||
def is_mp3(url):
|
||||
mt = mimetypes.guess_type(url)
|
||||
if mt and mt[0] == "audio/mpeg":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
async def _get_web_music_duration(session, url, start=0, end=500):
|
||||
duration = 0
|
||||
headers = {"Range": f"bytes={start}-{end}"}
|
||||
async with session.get(url, headers=headers) as response:
|
||||
array_buffer = await response.read()
|
||||
with tempfile.NamedTemporaryFile(delete=False) as tmp:
|
||||
tmp.write(array_buffer)
|
||||
name = tmp.name
|
||||
|
||||
try:
|
||||
if is_mp3(url):
|
||||
m = mutagen.mp3.MP3(name)
|
||||
else:
|
||||
m = mutagen.File(name)
|
||||
duration = m.info.length
|
||||
except Exception:
|
||||
pass
|
||||
os.remove(name)
|
||||
return duration
|
||||
|
||||
|
||||
async def get_web_music_duration(url, start=0, end=500):
|
||||
duration = 0
|
||||
try:
|
||||
parsed_url = urlparse(url)
|
||||
file_path = parsed_url.path
|
||||
_, extension = os.path.splitext(file_path)
|
||||
if extension.lower() not in SUPPORT_MUSIC_TYPE:
|
||||
cleaned_url = parsed_url.geturl()
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
cleaned_url,
|
||||
allow_redirects=True,
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"
|
||||
},
|
||||
) as response:
|
||||
url = str(response.url)
|
||||
# 设置总超时时间为3秒
|
||||
timeout = aiohttp.ClientTimeout(total=3)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
duration = await _get_web_music_duration(session, url, start=0, end=500)
|
||||
if duration <= 0:
|
||||
duration = await _get_web_music_duration(
|
||||
session, url, start=0, end=1000
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
return duration, url
|
||||
|
||||
|
||||
# 获取文件播放时长
|
||||
def get_local_music_duration(filename):
|
||||
duration = 0
|
||||
try:
|
||||
if is_mp3(filename):
|
||||
m = mutagen.mp3.MP3(filename)
|
||||
else:
|
||||
m = mutagen.File(filename)
|
||||
duration = m.info.length
|
||||
except Exception:
|
||||
pass
|
||||
return duration
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
# k1:v1,k2:v2
|
||||
def parse_str_to_dict(s, d1=",", d2=":"):
|
||||
# 初始化一个空字典
|
||||
result = {}
|
||||
parts = s.split(d1)
|
||||
|
||||
for part in parts:
|
||||
# 根据冒号切割
|
||||
subparts = part.split(d2)
|
||||
if len(subparts) == 2: # 防止数据不是成对出现
|
||||
k, v = subparts
|
||||
result[k] = v
|
||||
|
||||
return result
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user