Update On Thu Jun 26 20:39:33 CEST 2025

This commit is contained in:
github-action[bot]
2025-06-26 20:39:34 +02:00
parent 66accaf0df
commit ae5bbde5bc
65 changed files with 2855 additions and 1987 deletions

1
.github/update.log vendored
View File

@@ -1039,3 +1039,4 @@ Update On Sun Jun 22 20:36:41 CEST 2025
Update On Mon Jun 23 20:37:49 CEST 2025
Update On Tue Jun 24 20:37:45 CEST 2025
Update On Wed Jun 25 20:41:50 CEST 2025
Update On Thu Jun 26 20:39:25 CEST 2025

View File

@@ -113,7 +113,7 @@ func NewHostValueByDomain(domain string) (HostValue, error) {
domain = strings.Trim(domain, ".")
item := strings.Split(domain, ".")
if len(item) < 2 {
return HostValue{}, errors.New("invaild domain")
return HostValue{}, errors.New("invalid domain")
}
return HostValue{
IsDomain: true,

View File

@@ -299,7 +299,7 @@ func startPipe(cfg *Config) {
}
}
func safeEuqal(a, b string) bool {
func safeEqual(a, b string) bool {
aBuf := utils.ImmutableBytesFromString(a)
bBuf := utils.ImmutableBytesFromString(b)
return subtle.ConstantTimeCompare(aBuf, bBuf) == 1
@@ -311,7 +311,7 @@ func authentication(secret string) func(http.Handler) http.Handler {
// Browser websocket not support custom header
if r.Header.Get("Upgrade") == "websocket" && r.URL.Query().Get("token") != "" {
token := r.URL.Query().Get("token")
if !safeEuqal(token, secret) {
if !safeEqual(token, secret) {
render.Status(r, http.StatusUnauthorized)
render.JSON(w, r, ErrUnauthorized)
return
@@ -324,7 +324,7 @@ func authentication(secret string) func(http.Handler) http.Handler {
bearer, token, found := strings.Cut(header, " ")
hasInvalidHeader := bearer != "Bearer"
hasInvalidSecret := !found || !safeEuqal(token, secret)
hasInvalidSecret := !found || !safeEqual(token, secret)
if hasInvalidHeader || hasInvalidSecret {
render.Status(r, http.StatusUnauthorized)
render.JSON(w, r, ErrUnauthorized)

View File

@@ -1656,9 +1656,12 @@ dependencies = [
[[package]]
name = "cobs"
version = "0.2.3"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
"thiserror 2.0.12",
]
[[package]]
name = "codespan-reporting"
@@ -7165,9 +7168,9 @@ checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
[[package]]
name = "postcard"
version = "1.1.1"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8"
checksum = "6c1de96e20f51df24ca73cafcc4690e044854d803259db27a00a461cb3b9d17a"
dependencies = [
"cobs",
"embedded-io 0.4.0",

View File

@@ -60,7 +60,7 @@
"@tanstack/react-query": "5.81.2",
"@tanstack/react-router": "1.121.34",
"@tanstack/react-router-devtools": "1.121.34",
"@tanstack/router-plugin": "1.121.34",
"@tanstack/router-plugin": "1.121.37",
"@tauri-apps/plugin-clipboard-manager": "2.2.2",
"@tauri-apps/plugin-dialog": "2.2.2",
"@tauri-apps/plugin-fs": "2.3.0",
@@ -72,7 +72,7 @@
"@types/react": "19.1.8",
"@types/react-dom": "19.1.6",
"@types/validator": "13.15.2",
"@vitejs/plugin-legacy": "6.1.1",
"@vitejs/plugin-legacy": "7.0.0",
"@vitejs/plugin-react": "4.6.0",
"@vitejs/plugin-react-swc": "3.10.2",
"change-case": "5.4.4",
@@ -87,7 +87,7 @@
"unplugin-auto-import": "19.3.0",
"unplugin-icons": "22.1.0",
"validator": "13.15.15",
"vite": "6.3.5",
"vite": "7.0.0",
"vite-plugin-html": "3.2.2",
"vite-plugin-sass-dts": "1.3.31",
"vite-plugin-svgr": "4.3.0",

View File

@@ -30,7 +30,7 @@
"react-i18next": "15.5.3",
"react-use": "17.6.0",
"tailwindcss": "4.1.10",
"vite": "6.3.5",
"vite": "7.0.0",
"vite-tsconfig-paths": "5.1.4"
},
"devDependencies": {

View File

@@ -1,8 +1,8 @@
{
"manifest_version": 1,
"latest": {
"mihomo": "v1.19.10",
"mihomo_alpha": "alpha-166392f",
"mihomo": "v1.19.11",
"mihomo_alpha": "alpha-6a9d428",
"clash_rs": "v0.8.0",
"clash_premium": "2023-09-05-gdcc8d87",
"clash_rs_alpha": "0.8.0-alpha+sha.a1f98a1"
@@ -69,5 +69,5 @@
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
}
},
"updated_at": "2025-06-24T22:21:06.854Z"
"updated_at": "2025-06-25T22:21:15.497Z"
}

View File

@@ -59,7 +59,7 @@
"devDependencies": {
"@commitlint/cli": "19.8.1",
"@commitlint/config-conventional": "19.8.1",
"@eslint/compat": "1.3.0",
"@eslint/compat": "1.3.1",
"@eslint/eslintrc": "3.3.1",
"@ianvs/prettier-plugin-sort-imports": "4.4.2",
"@tauri-apps/cli": "2.5.0",
@@ -78,7 +78,7 @@
"eslint-plugin-html": "8.1.3",
"eslint-plugin-import": "2.32.0",
"eslint-plugin-n": "17.20.0",
"eslint-plugin-prettier": "5.5.0",
"eslint-plugin-prettier": "5.5.1",
"eslint-plugin-promise": "7.2.1",
"eslint-plugin-react": "7.37.5",
"eslint-plugin-react-compiler": "19.1.0-rc.2",
@@ -92,7 +92,7 @@
"postcss-html": "1.8.0",
"postcss-import": "16.1.1",
"postcss-scss": "4.0.9",
"prettier": "3.6.0",
"prettier": "3.6.1",
"prettier-plugin-tailwindcss": "0.6.13",
"prettier-plugin-toml": "2.0.5",
"react-devtools": "6.1.2",
@@ -110,7 +110,7 @@
},
"packageManager": "pnpm@10.12.3",
"engines": {
"node": "22.16.0"
"node": "22.17.0"
},
"pnpm": {
"overrides": {

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,8 @@
#!/bin/bash
# $1: remote name (e.g., origin)
# $2: remote url (e.g., git@github.com:clash-verge-rev/clash-verge-rev.git)
if git diff --cached --name-only | grep -q '^src-tauri/'; then
cargo clippy --manifest-path ./src-tauri/Cargo.toml
if [ $? -ne 0 ]; then
@@ -8,9 +11,9 @@ if git diff --cached --name-only | grep -q '^src-tauri/'; then
fi
fi
# 检查所有 remote url 是否有目标仓库
if git remote -v | grep -Eq 'github\\.com[:/]+clash-verge-rev/clash-verge-rev(\\.git)?'; then
echo "[pre-push] Detected push to clash-verge-rev/clash-verge-rev"
# 只在 push 到 origin 并且 origin 指向目标仓库时执行格式检查
if [ "$1" = "origin" ] && echo "$2" | grep -Eq 'github\.com[:/]+clash-verge-rev/clash-verge-rev(\.git)?$'; then
echo "[pre-push] Detected push to origin (clash-verge-rev/clash-verge-rev)"
echo "[pre-push] Running pnpm format:check..."
pnpm format:check

View File

@@ -13,6 +13,7 @@
- `sidecar` 模式下清理多余的内核进程,防止运行出现异常
- 新 macOS 下 TUN 和系统代理模式托盘图标(暂测)
- 快捷键事件通过系统通知
### 🚀 优化改进
@@ -23,6 +24,10 @@
- 移除了 macOS tray 图标显示网络速率
### 🌐 国际化更新
- 修复部分翻译缺失和不一致问题
## v2.3.1
### 🐞 修复问题
@@ -56,7 +61,6 @@
- 仅在 Ubuntu 22.04/24.04、Fedora 41 的 **GNOME 桌面环境** 做过简单测试,不保证其他 Linux 发行版兼容,后续将逐步适配和优化。
- macOS
- MacOS 下自动升级成功后请关闭程序等待 30 秒重启,因为 MacOS 的端口释放特性,卸载服务后需重启应用等 30 秒才能恢复内核通信。立即启动可能无法正常启动内核。
- 墙贴主要为浅色,深色 Tray 图标存在闪烁问题;
- 彩色 Tray 图标颜色偏淡;
@@ -94,13 +98,11 @@
- 托盘新增当前轻量模式状态显示
- 关闭系统代理时同时断开已建立的连接
- 新增 WebDAV 功能:
- 加入 UA 请求头
- 支持目录重定向
- 备份目录检查与上传重试机制
- 自动订阅更新机制:
- 加入请求超时机制防止卡死
- 支持在代理状态下自动重试订阅更新
- 支持订阅卡片点击切换下次自动更新时间,并显示更新结果提示
@@ -117,13 +119,11 @@
### 🚀 优化改进
- **系统相关:**
- 系统代理 Bypass 设置优化
- 优化代理设置更新逻辑与守卫机制
- Windows 启动方式调整为 Startup 文件夹,解决管理员模式下自启问题
- **性能与稳定性:**
- 全面异步化处理配置加载、UI 启动、事件通知等关键流程,解决卡顿问题
- 优化 MihomoManager 实现与窗口创建流程
- 改进内核日志等级为 `warn`,减少噪音输出
@@ -134,7 +134,6 @@
- 优化缓存 Mihomo proxy 和 providers 信息内存使用
- **前端与界面体验:**
- 切换规则页自动刷新数据
- 非激活订阅编辑时不再触发配置重载
- 优化托盘速率显示macOS 下默认关闭
@@ -145,7 +144,6 @@
- 优化保存机制,使用平滑函数防止卡顿
- **配置增强与安全性:**
- 配置缺失 `secret` 字段时自动补全为 `set-your-secret`
- 强制为 Mihomo 配置补全 `external-controller-cors` 字段(默认不允许跨域,限制本地访问)计划后续支持自定义 cors
- 优化窗口权限设置与状态初始化逻辑
@@ -280,7 +278,6 @@
#### 新增功能
1. **首页**
- 新增首页功能,默认启动页面改为首页。
- 首页流量图卡片显示上传/下载名称。
- 首页支持轻量模式切换。
@@ -288,21 +285,17 @@
- 限制首页配置文件卡片URL长度。
2. **DNS 设置与覆写**
- 新增 DNS 覆写功能。
- 默认启用 DNS 覆写。
3. **解锁测试**
- 新增解锁测试页面。
4. **轻量模式**
- 新增轻量模式及设置。
- 添加自动轻量模式定时器。
5. **系统支持**
- Mihomo(meta)内核升级 1.19.3
- macOS 支持 CMD+W 关闭窗口。
- 新增 macOS 应用菜单。
@@ -317,7 +310,6 @@
#### 修复
1. **系统**
- 修复 Windows 热键崩溃。
- 修复 macOS 无框标题。
- 修复 macOS 静默启动崩溃。
@@ -332,7 +324,6 @@
#### 优化
1. **性能**
- 重构后端,巨幅性能优化。
- 优化首页组件性能。
- 优化流量图表资源使用。
@@ -345,7 +336,6 @@
- 优化修改verge配置性能。
2. **重构**
- 重构后端,巨幅性能优化。
- 优化定时器管理。
- 重构 MihomoManager 处理流量。

View File

@@ -29,22 +29,22 @@
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@juggle/resize-observer": "^3.4.0",
"@mui/icons-material": "^7.1.2",
"@mui/lab": "7.0.0-beta.14",
"@mui/material": "^7.1.2",
"@mui/x-data-grid": "^8.5.3",
"@tauri-apps/api": "2.5.0",
"@tauri-apps/plugin-clipboard-manager": "^2.2.3",
"@tauri-apps/plugin-dialog": "^2.2.2",
"@tauri-apps/plugin-fs": "^2.3.0",
"@tauri-apps/plugin-global-shortcut": "^2.2.1",
"@tauri-apps/plugin-notification": "^2.2.3",
"@tauri-apps/plugin-process": "^2.2.2",
"@tauri-apps/plugin-shell": "2.2.2",
"@tauri-apps/plugin-updater": "2.8.1",
"@tauri-apps/plugin-window-state": "^2.2.3",
"@tauri-apps/api": "2.6.0",
"@tauri-apps/plugin-clipboard-manager": "^2.3.0",
"@tauri-apps/plugin-dialog": "^2.3.0",
"@tauri-apps/plugin-fs": "^2.4.0",
"@tauri-apps/plugin-global-shortcut": "^2.3.0",
"@tauri-apps/plugin-notification": "^2.3.0",
"@tauri-apps/plugin-process": "^2.3.0",
"@tauri-apps/plugin-shell": "2.3.0",
"@tauri-apps/plugin-updater": "2.9.0",
"@tauri-apps/plugin-window-state": "^2.3.0",
"@types/json-schema": "^7.0.15",
"json-schema": "^0.4.0",
"ahooks": "^3.8.5",
@@ -74,24 +74,24 @@
"swr": "^2.3.3",
"tar": "^7.4.3",
"types-pac": "^1.0.3",
"zustand": "^5.0.5"
"zustand": "^5.0.6"
},
"devDependencies": {
"@actions/github": "^6.0.1",
"@tauri-apps/cli": "2.5.0",
"@tauri-apps/cli": "2.6.1",
"@types/js-yaml": "^4.0.9",
"@types/lodash-es": "^4.17.12",
"@types/react": "19.1.8",
"@types/react-dom": "19.1.6",
"@vitejs/plugin-legacy": "^7.0.0",
"@vitejs/plugin-react": "4.5.2",
"@vitejs/plugin-react": "4.6.0",
"adm-zip": "^0.5.16",
"commander": "^14.0.0",
"cross-env": "^7.0.3",
"https-proxy-agent": "^7.0.6",
"meta-json-schema": "^1.19.10",
"meta-json-schema": "^1.19.11",
"node-fetch": "^3.3.2",
"prettier": "^3.5.3",
"prettier": "^3.6.1",
"sass": "^1.89.2",
"terser": "^5.43.1",
"typescript": "^5.8.3",

View File

@@ -21,53 +21,53 @@ importers:
specifier: ^11.14.0
version: 11.14.0(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled':
specifier: ^11.14.0
version: 11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
specifier: ^11.14.1
version: 11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@juggle/resize-observer':
specifier: ^3.4.0
version: 3.4.0
'@mui/icons-material':
specifier: ^7.1.2
version: 7.1.2(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
version: 7.1.2(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/lab':
specifier: 7.0.0-beta.14
version: 7.0.0-beta.14(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
version: 7.0.0-beta.14(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mui/material':
specifier: ^7.1.2
version: 7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
version: 7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mui/x-data-grid':
specifier: ^8.5.3
version: 8.5.3(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
version: 8.5.3(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tauri-apps/api':
specifier: 2.5.0
version: 2.5.0
specifier: 2.6.0
version: 2.6.0
'@tauri-apps/plugin-clipboard-manager':
specifier: ^2.2.3
version: 2.2.3
'@tauri-apps/plugin-dialog':
specifier: ^2.2.2
version: 2.2.2
'@tauri-apps/plugin-fs':
specifier: ^2.3.0
version: 2.3.0
'@tauri-apps/plugin-dialog':
specifier: ^2.3.0
version: 2.3.0
'@tauri-apps/plugin-fs':
specifier: ^2.4.0
version: 2.4.0
'@tauri-apps/plugin-global-shortcut':
specifier: ^2.2.1
version: 2.2.1
specifier: ^2.3.0
version: 2.3.0
'@tauri-apps/plugin-notification':
specifier: ^2.2.3
version: 2.2.3
specifier: ^2.3.0
version: 2.3.0
'@tauri-apps/plugin-process':
specifier: ^2.2.2
version: 2.2.2
specifier: ^2.3.0
version: 2.3.0
'@tauri-apps/plugin-shell':
specifier: 2.2.2
version: 2.2.2
specifier: 2.3.0
version: 2.3.0
'@tauri-apps/plugin-updater':
specifier: 2.8.1
version: 2.8.1
specifier: 2.9.0
version: 2.9.0
'@tauri-apps/plugin-window-state':
specifier: ^2.2.3
version: 2.2.3
specifier: ^2.3.0
version: 2.3.0
'@types/json-schema':
specifier: ^7.0.15
version: 7.0.15
@@ -156,15 +156,15 @@ importers:
specifier: ^1.0.3
version: 1.0.3
zustand:
specifier: ^5.0.5
version: 5.0.5(@types/react@19.1.8)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0))
specifier: ^5.0.6
version: 5.0.6(@types/react@19.1.8)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0))
devDependencies:
'@actions/github':
specifier: ^6.0.1
version: 6.0.1
'@tauri-apps/cli':
specifier: 2.5.0
version: 2.5.0
specifier: 2.6.1
version: 2.6.1
'@types/js-yaml':
specifier: ^4.0.9
version: 4.0.9
@@ -181,8 +181,8 @@ importers:
specifier: ^7.0.0
version: 7.0.0(terser@5.43.1)(vite@7.0.0(sass@1.89.2)(terser@5.43.1)(yaml@2.7.1))
'@vitejs/plugin-react':
specifier: 4.5.2
version: 4.5.2(vite@7.0.0(sass@1.89.2)(terser@5.43.1)(yaml@2.7.1))
specifier: 4.6.0
version: 4.6.0(vite@7.0.0(sass@1.89.2)(terser@5.43.1)(yaml@2.7.1))
adm-zip:
specifier: ^0.5.16
version: 0.5.16
@@ -196,14 +196,14 @@ importers:
specifier: ^7.0.6
version: 7.0.6
meta-json-schema:
specifier: ^1.19.10
version: 1.19.10
specifier: ^1.19.11
version: 1.19.11
node-fetch:
specifier: ^3.3.2
version: 3.3.2
prettier:
specifier: ^3.5.3
version: 3.5.3
specifier: ^3.6.1
version: 3.6.1
sass:
specifier: ^1.89.2
version: 1.89.2
@@ -784,8 +784,8 @@ packages:
'@emotion/sheet@1.4.0':
resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==}
'@emotion/styled@11.14.0':
resolution: {integrity: sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==}
'@emotion/styled@11.14.1':
resolution: {integrity: sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==}
peerDependencies:
'@emotion/react': ^11.0.0-rc.0
'@types/react': '*'
@@ -1273,8 +1273,8 @@ packages:
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
'@rolldown/pluginutils@1.0.0-beta.11':
resolution: {integrity: sha512-L/gAA/hyCSuzTF1ftlzUSI/IKr2POHsv1Dd78GfqkR83KMNuswWD61JxGV2L7nRwBBBSDr6R1gCkdTmoN7W4ag==}
'@rolldown/pluginutils@1.0.0-beta.19':
resolution: {integrity: sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==}
'@rollup/pluginutils@5.1.4':
resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
@@ -1453,106 +1453,106 @@ packages:
peerDependencies:
'@svgr/core': '*'
'@tauri-apps/api@2.5.0':
resolution: {integrity: sha512-Ldux4ip+HGAcPUmuLT8EIkk6yafl5vK0P0c0byzAKzxJh7vxelVtdPONjfgTm96PbN24yjZNESY8CKo8qniluA==}
'@tauri-apps/api@2.6.0':
resolution: {integrity: sha512-hRNcdercfgpzgFrMXWwNDBN0B7vNzOzRepy6ZAmhxi5mDLVPNrTpo9MGg2tN/F7JRugj4d2aF7E1rtPXAHaetg==}
'@tauri-apps/cli-darwin-arm64@2.5.0':
resolution: {integrity: sha512-VuVAeTFq86dfpoBDNYAdtQVLbP0+2EKCHIIhkaxjeoPARR0sLpFHz2zs0PcFU76e+KAaxtEtAJAXGNUc8E1PzQ==}
'@tauri-apps/cli-darwin-arm64@2.6.1':
resolution: {integrity: sha512-67aVLeXcJrl9D+4xQLR8NCQYKXQyZB96Tai+uy53jOY0u+uKvFngjbSS9CmntILFhLWoueDxQj3Ws5OSvjekiA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
'@tauri-apps/cli-darwin-x64@2.5.0':
resolution: {integrity: sha512-hUF01sC06cZVa8+I0/VtsHOk9BbO75rd+YdtHJ48xTdcYaQ5QIwL4yZz9OR1AKBTaUYhBam8UX9Pvd5V2/4Dpw==}
'@tauri-apps/cli-darwin-x64@2.6.1':
resolution: {integrity: sha512-6mQp/VikM0pKVKau1p/NMVyGq1JakOFbk6YlCzwdd04OwmiDuVe9PTxzqcA/JnqWXEhSGlRKeyMXUxqifPBPYw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
'@tauri-apps/cli-linux-arm-gnueabihf@2.5.0':
resolution: {integrity: sha512-LQKqttsK252LlqYyX8R02MinUsfFcy3+NZiJwHFgi5Y3+ZUIAED9cSxJkyNtuY5KMnR4RlpgWyLv4P6akN1xhg==}
'@tauri-apps/cli-linux-arm-gnueabihf@2.6.1':
resolution: {integrity: sha512-iY9cr2k3h2nh6I0bExEWCOgWloN4q0p/evhfNBIAIly1kycy+xWHEsFj2WfzU31Ce8RkqxilPHNuCp36gDM+Yw==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
'@tauri-apps/cli-linux-arm64-gnu@2.5.0':
resolution: {integrity: sha512-mTQufsPcpdHg5RW0zypazMo4L55EfeE5snTzrPqbLX4yCK2qalN7+rnP8O8GT06xhp6ElSP/Ku1M2MR297SByQ==}
'@tauri-apps/cli-linux-arm64-gnu@2.6.1':
resolution: {integrity: sha512-AT+SpHShi/uJipzj+A9kHPDUgZfzHYyl0B3/4UXYtHB9hQfQUmjh9wLadmx0ai/ESyJFxkJJK6FFRvxotQ3gIQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tauri-apps/cli-linux-arm64-musl@2.5.0':
resolution: {integrity: sha512-rQO1HhRUQqyEaal5dUVOQruTRda/TD36s9kv1hTxZiFuSq3558lsTjAcUEnMAtBcBkps20sbyTJNMT0AwYIk8Q==}
'@tauri-apps/cli-linux-arm64-musl@2.6.1':
resolution: {integrity: sha512-CCgE0uqcWTtU48TmK/J03h5x/hxi3PEc11ci3LQ9WqIE15btyhynNzDKbxKwOyDCMcfbDT+MweoiCPnely2ZRA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tauri-apps/cli-linux-riscv64-gnu@2.5.0':
resolution: {integrity: sha512-7oS18FN46yDxyw1zX/AxhLAd7T3GrLj3Ai6s8hZKd9qFVzrAn36ESL7d3G05s8wEtsJf26qjXnVF4qleS3dYsA==}
'@tauri-apps/cli-linux-riscv64-gnu@2.6.1':
resolution: {integrity: sha512-2i3MYr2oKaJk7Tz2FZ+R5x8cV827CudvEXW6FzCER26pfx/PofH/55N7aRQf4+qPXi5O3T+3myq88nRerzHr6g==}
engines: {node: '>= 10'}
cpu: [riscv64]
os: [linux]
'@tauri-apps/cli-linux-x64-gnu@2.5.0':
resolution: {integrity: sha512-SG5sFNL7VMmDBdIg3nO3EzNRT306HsiEQ0N90ILe3ZABYAVoPDO/ttpCO37ApLInTzrq/DLN+gOlC/mgZvLw1w==}
'@tauri-apps/cli-linux-x64-gnu@2.6.1':
resolution: {integrity: sha512-of5i3FW1tjTXECtMdirQsQnVIzcKq1s5Cad9YLVa6agEnFnZbFU3rKQ6/Wfu5SZbjSiI7SBO1hksjIAq1vkVcg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tauri-apps/cli-linux-x64-musl@2.5.0':
resolution: {integrity: sha512-QXDM8zp/6v05PNWju5ELsVwF0VH1n6b5pk2E6W/jFbbiwz80Vs1lACl9pv5kEHkrxBj+aWU/03JzGuIj2g3SkQ==}
'@tauri-apps/cli-linux-x64-musl@2.6.1':
resolution: {integrity: sha512-QfAgg7VIlOrTa2X3fBLRp6ugbC5ZonSWgVhNCLDgHLp5Cga41XOi5qU7ZtZhjjCdcWNiE0DtBQmSb1YVhCp+SA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tauri-apps/cli-win32-arm64-msvc@2.5.0':
resolution: {integrity: sha512-pFSHFK6b+o9y4Un8w0gGLwVyFTZaC3P0kQ7umRt/BLDkzD5RnQ4vBM7CF8BCU5nkwmEBUCZd7Wt3TWZxe41o6Q==}
'@tauri-apps/cli-win32-arm64-msvc@2.6.1':
resolution: {integrity: sha512-ee1h3jwamumGjLEXZA4VsSUcVWTtGpuvxy+nqFfu7wb2k6IcBrFEJGa6yXa7sQjuCAAorLfSIXGuDEJARqnpFw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
'@tauri-apps/cli-win32-ia32-msvc@2.5.0':
resolution: {integrity: sha512-EArv1IaRlogdLAQyGlKmEqZqm5RfHCUMhJoedWu7GtdbOMUfSAz6FMX2boE1PtEmNO4An+g188flLeVErrxEKg==}
'@tauri-apps/cli-win32-ia32-msvc@2.6.1':
resolution: {integrity: sha512-WEZVYekxuG9X9mFJEeJPHsSAl8sHOEEbJQriim+OziFbLA9pv/gfcRRqsbmEJL8uBC8GLTEOdUVolohwXk6S9g==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
'@tauri-apps/cli-win32-x64-msvc@2.5.0':
resolution: {integrity: sha512-lj43EFYbnAta8pd9JnUq87o+xRUR0odz+4rixBtTUwUgdRdwQ2V9CzFtsMu6FQKpFQ6mujRK6P1IEwhL6ADRsQ==}
'@tauri-apps/cli-win32-x64-msvc@2.6.1':
resolution: {integrity: sha512-fBsjPqIIHaaQt7tnjIGmPHu5p/BNBVD4JfOhO3QqIVBzAb+W2bDyIQPdoDMI943soLr/+N10xeTiPu+3L74+dQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
'@tauri-apps/cli@2.5.0':
resolution: {integrity: sha512-rAtHqG0Gh/IWLjN2zTf3nZqYqbo81oMbqop56rGTjrlWk9pTTAjkqOjSL9XQLIMZ3RbeVjveCqqCA0s8RnLdMg==}
'@tauri-apps/cli@2.6.1':
resolution: {integrity: sha512-8NrwfZjeyKH1zwg+Xu4epx8WLjffoiW1Zs9CCFYCJns7uUghzudDm92o+8ROosg5Njlvp1GXBuIRsdrEwBsDhg==}
engines: {node: '>= 10'}
hasBin: true
'@tauri-apps/plugin-clipboard-manager@2.2.3':
resolution: {integrity: sha512-myZTLyBpJ9gnDsywtdgRpAYLxEtSVaJa11s1xoiB6w8cjFtG2/znas4Cz3vqYigJkY0A57tyZUE6tjxavIAzgw==}
'@tauri-apps/plugin-clipboard-manager@2.3.0':
resolution: {integrity: sha512-81NOBA2P+OTY8RLkBwyl9ZR/0CeggLub4F6zxcxUIfFOAqtky7J61+K/MkH2SC1FMxNBxrX0swDuKvkjkHadlA==}
'@tauri-apps/plugin-dialog@2.2.2':
resolution: {integrity: sha512-Pm9qnXQq8ZVhAMFSEPwxvh+nWb2mk7LASVlNEHYaksHvcz8P6+ElR5U5dNL9Ofrm+uwhh1/gYKWswK8JJJAh6A==}
'@tauri-apps/plugin-dialog@2.3.0':
resolution: {integrity: sha512-ylSBvYYShpGlKKh732ZuaHyJ5Ie1JR71QCXewCtsRLqGdc8Is4xWdz6t43rzXyvkItM9syNPMvFVcvjgEy+/GA==}
'@tauri-apps/plugin-fs@2.3.0':
resolution: {integrity: sha512-G9gEyYVUaaxhdRJBgQTTLmzAe0vtHYxYyN1oTQzU3zwvb8T+tVLcAqCdFMWHq0qGeGbmynI5whvYpcXo5LvZ1w==}
'@tauri-apps/plugin-fs@2.4.0':
resolution: {integrity: sha512-Sp8AdDcbyXyk6LD6Pmdx44SH3LPeNAvxR2TFfq/8CwqzfO1yOyV+RzT8fov0NNN7d9nvW7O7MtMAptJ42YXA5g==}
'@tauri-apps/plugin-global-shortcut@2.2.1':
resolution: {integrity: sha512-b64/TI1t5LIi2JY4OWlYjZpPRq60T5GVVL/no27sUuxaNUZY8dVtwsMtDUgxUpln2yR+P2PJsYlqY5V8sLSxEw==}
'@tauri-apps/plugin-global-shortcut@2.3.0':
resolution: {integrity: sha512-WbAz0ElhpP+0kzQZRScdCC7UQ7OPH8PAn//fsBNu7+ywihsnVSVOg1L9YhieAtLNtAlnmFI69Yl5AGaA3ge5IQ==}
'@tauri-apps/plugin-notification@2.2.3':
resolution: {integrity: sha512-IlMdSVFsrKg0eIHBloFFosnWbbz6JdwBywfZrYZnE1+acgXvNS3T1YB5w9R6UXw+KKQ94ODBu7JF7a1YUiAK6A==}
'@tauri-apps/plugin-notification@2.3.0':
resolution: {integrity: sha512-QDwXo9VzAlH97c0veuf19TZI6cRBPfJDl2O6hNEDvI66j60lOO9z+PL6MJrj8A6Y+t55r7mGhe3rQWLmOre2HA==}
'@tauri-apps/plugin-process@2.2.2':
resolution: {integrity: sha512-1HuR+uGcokQxlgbS0DheFyMpJSuVGuy3Yh3Eq5o3Jm/sEW+44JaVVgYWM0efpDPA8oT5wpabTFEOZHvKfp8dCg==}
'@tauri-apps/plugin-process@2.3.0':
resolution: {integrity: sha512-0DNj6u+9csODiV4seSxxRbnLpeGYdojlcctCuLOCgpH9X3+ckVZIEj6H7tRQ7zqWr7kSTEWnrxtAdBb0FbtrmQ==}
'@tauri-apps/plugin-shell@2.2.2':
resolution: {integrity: sha512-fg9XKWfzRQsN8p+Zrk82WeHvXFvGVnG0/mTlujQdLWNnO5cM6WD9qCrHbFytScVS+WhmRAkuypQPcxeKKl3VBg==}
'@tauri-apps/plugin-shell@2.3.0':
resolution: {integrity: sha512-6GIRxO2z64uxPX4CCTuhQzefvCC0ew7HjdBhMALiGw74vFBDY95VWueAHOHgNOMV4UOUAFupyidN9YulTe5xlA==}
'@tauri-apps/plugin-updater@2.8.1':
resolution: {integrity: sha512-VVQ3wCfM+zok/e0QNBT0oBaFu3gBbzzMsRHzS2yxl7VOCh9dWuZo4yyl29OfaExxSvcixWJ9BZ6pWmKdUt8fCg==}
'@tauri-apps/plugin-updater@2.9.0':
resolution: {integrity: sha512-j++sgY8XpeDvzImTrzWA08OqqGqgkNyxczLD7FjNJJx/uXxMZFz5nDcfkyoI/rCjYuj2101Tci/r/HFmOmoxCg==}
'@tauri-apps/plugin-window-state@2.2.3':
resolution: {integrity: sha512-Iqqzugs6lxpa9JPOe4O33lkCUyMGvh9dqnXof1tK4dP2wU7jKa7W3MLwVyo6c3oVl3dUCm73wkB3RJ0exR0SPg==}
'@tauri-apps/plugin-window-state@2.3.0':
resolution: {integrity: sha512-BfhM0gm6jsF+VyYeOZ3eNqDfRJ2YPMh0a5qesD8AizVGv7wVB3cGLqh6EaeMpGl7y6kP9lvEMYkDRHuqKbcsgw==}
'@types/babel__core@7.20.5':
resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
@@ -1631,8 +1631,8 @@ packages:
terser: ^5.16.0
vite: ^7.0.0
'@vitejs/plugin-react@4.5.2':
resolution: {integrity: sha512-QNVT3/Lxx99nMQWJWF7K4N6apUEuT0KlZA3mx/mVaoGj3smm/8rc8ezz15J1pcbcjDK0V15rpHetVfya08r76Q==}
'@vitejs/plugin-react@4.6.0':
resolution: {integrity: sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==}
engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies:
vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0
@@ -2265,8 +2265,8 @@ packages:
resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==}
engines: {node: '>=18'}
meta-json-schema@1.19.10:
resolution: {integrity: sha512-eLj5v4hlnqeHacRXDiE+/dFR2Ly0MQKCMXqRNZzbwyPXu0QPMkFu9+mYlZDHZErUJlXKM2RLbnkfVoHvxcm3DA==}
meta-json-schema@1.19.11:
resolution: {integrity: sha512-qIcE1GmsF2b2CNMl7/C1w9nLaGOI1tP8/DrAZm0bJ+tkUAoKL1G2ZsdRUUiKFAy2Z0mbmQ8GCQ/+IBhjMRxCmQ==}
engines: {node: '>=18', pnpm: '>=9'}
micromark-core-commonmark@2.0.3:
@@ -2471,8 +2471,8 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
prettier@3.5.3:
resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
prettier@3.6.1:
resolution: {integrity: sha512-5xGWRa90Sp2+x1dQtNpIpeOQpTDBs9cZDmA/qs2vDNN2i18PdapqY7CmBeyLlMuGqXJRIOPaCaVZTLNQRWUH/A==}
engines: {node: '>=14'}
hasBin: true
@@ -2943,8 +2943,8 @@ packages:
engines: {node: '>= 14'}
hasBin: true
zustand@5.0.5:
resolution: {integrity: sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==}
zustand@5.0.6:
resolution: {integrity: sha512-ihAqNeUVhe0MAD+X8M5UzqyZ9k3FFZLBTtqo6JLPwV53cbRB/mJwBI0PxcIgqhBBHlEs8G45OTDTMq3gNcLq3A==}
engines: {node: '>=12.20.0'}
peerDependencies:
'@types/react': '>=18.0.0'
@@ -3716,7 +3716,7 @@ snapshots:
'@emotion/sheet@1.4.0': {}
'@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)':
'@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.6
'@emotion/babel-plugin': 11.13.5
@@ -3865,19 +3865,19 @@ snapshots:
'@mui/core-downloads-tracker@7.1.2': {}
'@mui/icons-material@7.1.2(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)':
'@mui/icons-material@7.1.2(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.6
'@mui/material': 7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mui/material': 7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react: 19.1.0
optionalDependencies:
'@types/react': 19.1.8
'@mui/lab@7.0.0-beta.14(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
'@mui/lab@7.0.0-beta.14(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.6
'@mui/material': 7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/material': 7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/types': 7.4.3(@types/react@19.1.8)
'@mui/utils': 7.1.1(@types/react@19.1.8)(react@19.1.0)
clsx: 2.1.1
@@ -3886,14 +3886,14 @@ snapshots:
react-dom: 19.1.0(react@19.1.0)
optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@types/react': 19.1.8
'@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
'@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.6
'@mui/core-downloads-tracker': 7.1.2
'@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/types': 7.4.3(@types/react@19.1.8)
'@mui/utils': 7.1.1(@types/react@19.1.8)(react@19.1.0)
'@popperjs/core': 2.11.8
@@ -3907,7 +3907,7 @@ snapshots:
react-transition-group: 4.4.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@types/react': 19.1.8
'@mui/private-theming@7.1.1(@types/react@19.1.8)(react@19.1.0)':
@@ -3919,7 +3919,7 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.8
'@mui/styled-engine@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(react@19.1.0)':
'@mui/styled-engine@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.6
'@emotion/cache': 11.14.0
@@ -3930,13 +3930,13 @@ snapshots:
react: 19.1.0
optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)':
'@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.6
'@mui/private-theming': 7.1.1(@types/react@19.1.8)(react@19.1.0)
'@mui/styled-engine': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(react@19.1.0)
'@mui/styled-engine': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(react@19.1.0)
'@mui/types': 7.4.3(@types/react@19.1.8)
'@mui/utils': 7.1.1(@types/react@19.1.8)(react@19.1.0)
clsx: 2.1.1
@@ -3945,7 +3945,7 @@ snapshots:
react: 19.1.0
optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@types/react': 19.1.8
'@mui/types@7.4.3(@types/react@19.1.8)':
@@ -3966,13 +3966,13 @@ snapshots:
optionalDependencies:
'@types/react': 19.1.8
'@mui/x-data-grid@8.5.3(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
'@mui/x-data-grid@8.5.3(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@mui/material@7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.6
'@mui/material': 7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/material': 7.1.2(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/utils': 7.1.1(@types/react@19.1.8)(react@19.1.0)
'@mui/x-internals': 8.5.3(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/x-internals': 8.5.3(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
clsx: 2.1.1
prop-types: 15.8.1
react: 19.1.0
@@ -3980,14 +3980,14 @@ snapshots:
use-sync-external-store: 1.5.0(react@19.1.0)
optionalDependencies:
'@emotion/react': 11.14.0(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@emotion/styled': 11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
transitivePeerDependencies:
- '@types/react'
'@mui/x-internals@8.5.3(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)':
'@mui/x-internals@8.5.3(@mui/system@7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)':
dependencies:
'@babel/runtime': 7.27.6
'@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/system': 7.1.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0))(@types/react@19.1.8)(react@19.1.0)
'@mui/utils': 7.1.1(@types/react@19.1.8)(react@19.1.0)
react: 19.1.0
reselect: 5.1.1
@@ -4115,7 +4115,7 @@ snapshots:
'@popperjs/core@2.11.8': {}
'@rolldown/pluginutils@1.0.0-beta.11': {}
'@rolldown/pluginutils@1.0.0-beta.19': {}
'@rollup/pluginutils@5.1.4(rollup@4.40.2)':
dependencies:
@@ -4255,90 +4255,90 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@tauri-apps/api@2.5.0': {}
'@tauri-apps/api@2.6.0': {}
'@tauri-apps/cli-darwin-arm64@2.5.0':
'@tauri-apps/cli-darwin-arm64@2.6.1':
optional: true
'@tauri-apps/cli-darwin-x64@2.5.0':
'@tauri-apps/cli-darwin-x64@2.6.1':
optional: true
'@tauri-apps/cli-linux-arm-gnueabihf@2.5.0':
'@tauri-apps/cli-linux-arm-gnueabihf@2.6.1':
optional: true
'@tauri-apps/cli-linux-arm64-gnu@2.5.0':
'@tauri-apps/cli-linux-arm64-gnu@2.6.1':
optional: true
'@tauri-apps/cli-linux-arm64-musl@2.5.0':
'@tauri-apps/cli-linux-arm64-musl@2.6.1':
optional: true
'@tauri-apps/cli-linux-riscv64-gnu@2.5.0':
'@tauri-apps/cli-linux-riscv64-gnu@2.6.1':
optional: true
'@tauri-apps/cli-linux-x64-gnu@2.5.0':
'@tauri-apps/cli-linux-x64-gnu@2.6.1':
optional: true
'@tauri-apps/cli-linux-x64-musl@2.5.0':
'@tauri-apps/cli-linux-x64-musl@2.6.1':
optional: true
'@tauri-apps/cli-win32-arm64-msvc@2.5.0':
'@tauri-apps/cli-win32-arm64-msvc@2.6.1':
optional: true
'@tauri-apps/cli-win32-ia32-msvc@2.5.0':
'@tauri-apps/cli-win32-ia32-msvc@2.6.1':
optional: true
'@tauri-apps/cli-win32-x64-msvc@2.5.0':
'@tauri-apps/cli-win32-x64-msvc@2.6.1':
optional: true
'@tauri-apps/cli@2.5.0':
'@tauri-apps/cli@2.6.1':
optionalDependencies:
'@tauri-apps/cli-darwin-arm64': 2.5.0
'@tauri-apps/cli-darwin-x64': 2.5.0
'@tauri-apps/cli-linux-arm-gnueabihf': 2.5.0
'@tauri-apps/cli-linux-arm64-gnu': 2.5.0
'@tauri-apps/cli-linux-arm64-musl': 2.5.0
'@tauri-apps/cli-linux-riscv64-gnu': 2.5.0
'@tauri-apps/cli-linux-x64-gnu': 2.5.0
'@tauri-apps/cli-linux-x64-musl': 2.5.0
'@tauri-apps/cli-win32-arm64-msvc': 2.5.0
'@tauri-apps/cli-win32-ia32-msvc': 2.5.0
'@tauri-apps/cli-win32-x64-msvc': 2.5.0
'@tauri-apps/cli-darwin-arm64': 2.6.1
'@tauri-apps/cli-darwin-x64': 2.6.1
'@tauri-apps/cli-linux-arm-gnueabihf': 2.6.1
'@tauri-apps/cli-linux-arm64-gnu': 2.6.1
'@tauri-apps/cli-linux-arm64-musl': 2.6.1
'@tauri-apps/cli-linux-riscv64-gnu': 2.6.1
'@tauri-apps/cli-linux-x64-gnu': 2.6.1
'@tauri-apps/cli-linux-x64-musl': 2.6.1
'@tauri-apps/cli-win32-arm64-msvc': 2.6.1
'@tauri-apps/cli-win32-ia32-msvc': 2.6.1
'@tauri-apps/cli-win32-x64-msvc': 2.6.1
'@tauri-apps/plugin-clipboard-manager@2.2.3':
'@tauri-apps/plugin-clipboard-manager@2.3.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@tauri-apps/plugin-dialog@2.2.2':
'@tauri-apps/plugin-dialog@2.3.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@tauri-apps/plugin-fs@2.3.0':
'@tauri-apps/plugin-fs@2.4.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@tauri-apps/plugin-global-shortcut@2.2.1':
'@tauri-apps/plugin-global-shortcut@2.3.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@tauri-apps/plugin-notification@2.2.3':
'@tauri-apps/plugin-notification@2.3.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@tauri-apps/plugin-process@2.2.2':
'@tauri-apps/plugin-process@2.3.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@tauri-apps/plugin-shell@2.2.2':
'@tauri-apps/plugin-shell@2.3.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@tauri-apps/plugin-updater@2.8.1':
'@tauri-apps/plugin-updater@2.9.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@tauri-apps/plugin-window-state@2.2.3':
'@tauri-apps/plugin-window-state@2.3.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/api': 2.6.0
'@types/babel__core@7.20.5':
dependencies:
@@ -4428,12 +4428,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@vitejs/plugin-react@4.5.2(vite@7.0.0(sass@1.89.2)(terser@5.43.1)(yaml@2.7.1))':
'@vitejs/plugin-react@4.6.0(vite@7.0.0(sass@1.89.2)(terser@5.43.1)(yaml@2.7.1))':
dependencies:
'@babel/core': 7.27.4
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.4)
'@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.27.4)
'@rolldown/pluginutils': 1.0.0-beta.11
'@rolldown/pluginutils': 1.0.0-beta.19
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
vite: 7.0.0(sass@1.89.2)(terser@5.43.1)(yaml@2.7.1)
@@ -5133,7 +5133,7 @@ snapshots:
meow@13.2.0: {}
meta-json-schema@1.19.10: {}
meta-json-schema@1.19.11: {}
micromark-core-commonmark@2.0.3:
dependencies:
@@ -5319,7 +5319,7 @@ snapshots:
monaco-types: 0.1.0
monaco-worker-manager: 2.0.1(monaco-editor@0.52.2)
path-browserify: 1.0.1
prettier: 3.5.3
prettier: 3.6.1
vscode-languageserver-textdocument: 1.0.12
vscode-languageserver-types: 3.17.5
vscode-uri: 3.1.0
@@ -5406,7 +5406,7 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
prettier@3.5.3: {}
prettier@3.6.1: {}
prop-types@15.8.1:
dependencies:
@@ -5869,7 +5869,7 @@ snapshots:
yaml@2.7.1: {}
zustand@5.0.5(@types/react@19.1.8)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)):
zustand@5.0.6(@types/react@19.1.8)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)):
optionalDependencies:
'@types/react': 19.1.8
react: 19.1.0

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,7 @@ regex = "1.11.1"
sysproxy = { git = "https://github.com/clash-verge-rev/sysproxy-rs" }
image = "0.25.6"
imageproc = "0.25.0"
tauri = { version = "2.6.0", features = [
tauri = { version = "2.6.1", features = [
"protocol-asset",
"devtools",
"tray-icon",
@@ -57,9 +57,9 @@ tauri = { version = "2.6.0", features = [
network-interface = { version = "2.0.1", features = ["serde"] }
tauri-plugin-shell = "2.3.0"
tauri-plugin-dialog = "2.3.0"
tauri-plugin-fs = "2.3.0"
tauri-plugin-process = "2.2.2"
tauri-plugin-clipboard-manager = "2.2.3"
tauri-plugin-fs = "2.4.0"
tauri-plugin-process = "2.3.0"
tauri-plugin-clipboard-manager = "2.3.0"
tauri-plugin-deep-link = "2.4.0"
tauri-plugin-devtools = "2.0.0"
tauri-plugin-window-state = "2.3.0"
@@ -81,6 +81,7 @@ hmac = "0.12.1"
sha2 = "0.10.9"
hex = "0.4.3"
scopeguard = "1.2.0"
tauri-plugin-notification = "2"
[target.'cfg(windows)'.dependencies]
runas = "=1.2.0"
@@ -106,7 +107,7 @@ users = "0.11.0"
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
tauri-plugin-autostart = "2.5.0"
tauri-plugin-global-shortcut = "2.3.0"
tauri-plugin-updater = "2.8.1"
tauri-plugin-updater = "2.9.0"
[features]
default = ["custom-protocol"]

View File

@@ -17,6 +17,7 @@
"autostart:allow-enable",
"autostart:allow-disable",
"autostart:allow-is-enabled",
"core:window:allow-set-theme"
"core:window:allow-set-theme",
"notification:default"
]
}

View File

@@ -1,3 +1,4 @@
use crate::utils::notification::{notify_event, NotificationEvent};
use crate::{
config::Config, core::handle, feat, logging, logging_error,
module::lightweight::entry_lightweight_mode, utils::logging::Type,
@@ -133,14 +134,11 @@ impl Hotkey {
manager.unregister(hotkey)?;
}
let f = match func.trim() {
let app_handle_clone = app_handle.clone();
let f: Box<dyn Fn() + Send + Sync> = match func.trim() {
"open_or_close_dashboard" => {
logging!(
debug,
Type::Hotkey,
"Registering open_or_close_dashboard function"
);
|| {
let app_handle = app_handle_clone.clone();
Box::new(move || {
logging!(
debug,
Type::Hotkey,
@@ -162,18 +160,75 @@ impl Hotkey {
Type::Hotkey,
"=== Hotkey Dashboard Window Operation End ==="
);
}
notify_event(&app_handle, NotificationEvent::DashboardToggled);
})
}
"clash_mode_rule" => {
let app_handle = app_handle_clone.clone();
Box::new(move || {
feat::change_clash_mode("rule".into());
notify_event(
&app_handle,
NotificationEvent::ClashModeChanged { mode: "Rule" },
);
})
}
"clash_mode_global" => {
let app_handle = app_handle_clone.clone();
Box::new(move || {
feat::change_clash_mode("global".into());
notify_event(
&app_handle,
NotificationEvent::ClashModeChanged { mode: "Global" },
);
})
}
"clash_mode_direct" => {
let app_handle = app_handle_clone.clone();
Box::new(move || {
feat::change_clash_mode("direct".into());
notify_event(
&app_handle,
NotificationEvent::ClashModeChanged { mode: "Direct" },
);
})
}
"toggle_system_proxy" => {
let app_handle = app_handle_clone.clone();
Box::new(move || {
feat::toggle_system_proxy();
notify_event(&app_handle, NotificationEvent::SystemProxyToggled);
})
}
"toggle_tun_mode" => {
let app_handle = app_handle_clone.clone();
Box::new(move || {
feat::toggle_tun_mode(None);
notify_event(&app_handle, NotificationEvent::TunModeToggled);
})
}
"entry_lightweight_mode" => {
let app_handle = app_handle_clone.clone();
Box::new(move || {
entry_lightweight_mode();
notify_event(&app_handle, NotificationEvent::LightweightModeEntered);
})
}
"quit" => {
let app_handle = app_handle_clone.clone();
Box::new(move || {
feat::quit();
notify_event(&app_handle, NotificationEvent::AppQuit);
})
}
"clash_mode_rule" => || feat::change_clash_mode("rule".into()),
"clash_mode_global" => || feat::change_clash_mode("global".into()),
"clash_mode_direct" => || feat::change_clash_mode("direct".into()),
"toggle_system_proxy" => || feat::toggle_system_proxy(),
"toggle_tun_mode" => || feat::toggle_tun_mode(None),
"entry_lightweight_mode" => || entry_lightweight_mode(),
"quit" => || feat::quit(),
#[cfg(target_os = "macos")]
"hide" => || feat::hide(),
"hide" => {
let app_handle = app_handle_clone.clone();
Box::new(move || {
feat::hide();
notify_event(&app_handle, NotificationEvent::AppHidden);
})
}
_ => {
logging!(error, Type::Hotkey, "Invalid function: {}", func);
bail!("invalid function \"{func}\"");

View File

@@ -125,6 +125,7 @@ pub fn run() {
#[allow(unused_mut)]
let mut builder = tauri::Builder::default()
.plugin(tauri_plugin_notification::init())
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_process::init())

View File

@@ -5,6 +5,7 @@ pub mod i18n;
pub mod init;
pub mod logging;
pub mod network;
pub mod notification;
pub mod resolve;
pub mod server;
pub mod tmpl;

View File

@@ -0,0 +1,70 @@
use tauri::AppHandle;
use tauri_plugin_notification::NotificationExt;
pub enum NotificationEvent<'a> {
DashboardToggled,
ClashModeChanged {
mode: &'a str,
},
SystemProxyToggled,
TunModeToggled,
LightweightModeEntered,
AppQuit,
#[cfg(target_os = "macos")]
AppHidden,
}
fn notify(app: &AppHandle, title: &str, body: &str) {
app.notification()
.builder()
.title(title)
.body(body)
.show()
.ok();
}
pub fn notify_event(app: &AppHandle, event: NotificationEvent) {
use crate::utils::i18n::t;
match event {
NotificationEvent::DashboardToggled => {
notify(app, &t("DashboardToggledTitle"), &t("DashboardToggledBody"));
}
NotificationEvent::ClashModeChanged { mode } => {
notify(
app,
&t("ClashModeChangedTitle"),
&t_with_args("ClashModeChangedBody", mode),
);
}
NotificationEvent::SystemProxyToggled => {
notify(
app,
&t("SystemProxyToggledTitle"),
&t("SystemProxyToggledBody"),
);
}
NotificationEvent::TunModeToggled => {
notify(app, &t("TunModeToggledTitle"), &t("TunModeToggledBody"));
}
NotificationEvent::LightweightModeEntered => {
notify(
app,
&t("LightweightModeEnteredTitle"),
&t("LightweightModeEnteredBody"),
);
}
NotificationEvent::AppQuit => {
notify(app, &t("AppQuitTitle"), &t("AppQuitBody"));
}
#[cfg(target_os = "macos")]
NotificationEvent::AppHidden => {
notify(app, &t("AppHiddenTitle"), &t("AppHiddenBody"));
}
}
}
// 辅助函数带参数的i18n
fn t_with_args(key: &str, mode: &str) -> String {
use crate::utils::i18n::t;
t(key).replace("{mode}", mode)
}

View File

@@ -1,7 +1,9 @@
import { AppDataProvider } from "./providers/app-data-provider";
import Layout from "./pages/_layout";
import { useNotificationPermission } from "./hooks/useNotificationPermission";
function App() {
useNotificationPermission();
return (
<AppDataProvider>
<Layout />

View File

@@ -0,0 +1,8 @@
import { setupNotificationPermission } from "../utils/notification-permission";
import { useEffect } from "react";
export function useNotificationPermission() {
useEffect(() => {
setupNotificationPermission();
}, []);
}

View File

@@ -624,5 +624,20 @@
"No (IP Banned By Disney+)": "No (IP Banned By Disney+)",
"Unsupported Country/Region": "Unsupported Country/Region",
"Failed (Network Connection)": "Failed (Network Connection)",
"Invalid Profile URL": "Invalid profile URL. Please enter a URL starting with http:// or https://"
"DashboardToggledTitle": "Dashboard Toggled",
"DashboardToggledBody": "Dashboard visibility toggled by hotkey",
"ClashModeChangedTitle": "Clash Mode Changed",
"ClashModeChangedBody": "Switched to {mode} mode",
"SystemProxyToggledTitle": "System Proxy Toggled",
"SystemProxyToggledBody": "System proxy state toggled by hotkey",
"TunModeToggledTitle": "TUN Mode Toggled",
"TunModeToggledBody": "TUN mode toggled by hotkey",
"LightweightModeEnteredTitle": "Lightweight Mode",
"LightweightModeEnteredBody": "Entered lightweight mode by hotkey",
"AppQuitTitle": "APP Quit",
"AppQuitBody": "APP quit by hotkey",
"AppHiddenTitle": "APP Hidden",
"AppHiddenBody": "APP window hidden by hotkey",
"Invalid Profile URL": "Invalid profile URL. Please enter a URL starting with http:// or https://",
"Saved Successfully": "Saved successfully"
}

View File

@@ -624,5 +624,20 @@
"No (IP Banned By Disney+)": "不支持IP被Disney+禁止)",
"Unsupported Country/Region": "不支持的国家/地区",
"Failed (Network Connection)": "测试失败(网络连接问题)",
"Invalid Profile URL": "无效的订阅链接,请输入以 http:// 或 https:// 开头的地址"
"DashboardToggledTitle": "仪表盘已切换",
"DashboardToggledBody": "已通过快捷键切换仪表盘显示状态",
"ClashModeChangedTitle": "Clash 模式切换",
"ClashModeChangedBody": "已切换为 {mode} 模式",
"SystemProxyToggledTitle": "系统代理切换",
"SystemProxyToggledBody": "已通过快捷键切换系统代理状态",
"TunModeToggledTitle": "TUN 模式切换",
"TunModeToggledBody": "已通过快捷键切换 TUN 模式",
"LightweightModeEnteredTitle": "轻量模式",
"LightweightModeEnteredBody": "已通过快捷键进入轻量模式",
"AppQuitTitle": "应用退出",
"AppQuitBody": "已通过快捷键退出应用",
"AppHiddenTitle": "应用隐藏",
"AppHiddenBody": "已通过快捷键隐藏应用窗口",
"Invalid Profile URL": "无效的订阅链接,请输入以 http:// 或 https:// 开头的地址",
"Saved Successfully": "保存成功"
}

View File

@@ -0,0 +1,17 @@
import {
isPermissionGranted,
requestPermission,
} from "@tauri-apps/plugin-notification";
export async function setupNotificationPermission() {
let permission = await isPermissionGranted();
if (!permission) {
const result = await requestPermission();
permission = result === "granted";
}
if (permission) {
console.log("通知权限已授予");
} else {
console.log("通知权限被拒绝");
}
}

View File

@@ -2,6 +2,17 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [2.33.9](https://github.com/filebrowser/filebrowser/compare/v2.33.8...v2.33.9) (2025-06-26)
### Bug Fixes
* check exact match on command allow list ([e2e1e49](https://github.com/filebrowser/filebrowser/commit/e2e1e4913085cca8917e0f69171dc28d3c6af1b6))
* remove auth token from /api/command ([d5b39a1](https://github.com/filebrowser/filebrowser/commit/d5b39a14fd3fc0d1c364116b41289484df7c27b2))
* remove unused import ([c232d41](https://github.com/filebrowser/filebrowser/commit/c232d41f903d3026ec290bbe819b6c59a933048e))
### [2.33.8](https://github.com/filebrowser/filebrowser/compare/v2.33.7...v2.33.8) (2025-06-25)
### [2.33.7](https://github.com/filebrowser/filebrowser/compare/v2.33.6...v2.33.7) (2025-06-25)

View File

@@ -38,6 +38,9 @@ File Browser is a **create-your-own-cloud-kind** of software where you can insta
| :----------------------: | :----------------------: | :----------------------: |
| ![](./docs/assets/4.jpg) | ![](./docs/assets/5.jpg) | ![](./docs/assets/6.jpg) |
> [!CAUTION]
>
> The **command execution** functionality has been disabled for all existent and new installations by default from version v2.33.8 and onwards, due to continuous and known security vulnerabilities. You should only use this feature if you are aware of all of the security risks involved. For more up to date information, consult issue [#5199](https://github.com/filebrowser/filebrowser/issues/5199).
## Install

View File

@@ -68,7 +68,7 @@ func addServerFlags(flags *pflag.FlagSet) {
flags.Int("img-processors", 4, "image processors count") //nolint:gomnd
flags.Bool("disable-thumbnails", false, "disable image thumbnails")
flags.Bool("disable-preview-resize", false, "disable resize of image previews")
flags.Bool("disable-exec", false, "disables Command Runner feature")
flags.Bool("disable-exec", true, "disables Command Runner feature")
flags.Bool("disable-type-detection-by-header", false, "disables type detection by reading file headers")
}
@@ -262,6 +262,13 @@ func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server {
disableExec := getBoolParam(flags, "disable-exec")
server.EnableExec = !disableExec
if server.EnableExec {
log.Println("WARNING: Command Runner feature enabled!")
log.Println("WARNING: This feature has known security vulnerabilities and should not")
log.Println("WARNING: you fully understand the risks involved. For more information")
log.Println("WARNING: read https://github.com/filebrowser/filebrowser/issues/5199")
}
if val, set := getStringParamB(flags, "token-expiration-time"); set {
server.TokenExpirationTime = val
}

View File

@@ -1,6 +1,5 @@
import { removePrefix } from "./utils";
import { baseURL } from "@/utils/constants";
import { useAuthStore } from "@/stores/auth";
import { removePrefix } from "./utils";
const ssl = window.location.protocol === "https:";
const protocol = ssl ? "wss:" : "ws:";
@@ -11,10 +10,8 @@ export default function command(
onmessage: WebSocket["onmessage"],
onclose: WebSocket["onclose"]
) {
const authStore = useAuthStore();
url = removePrefix(url);
url = `${protocol}//${window.location.host}${baseURL}/api/command${url}?auth=${authStore.jwt}`;
url = `${protocol}//${window.location.host}${baseURL}/api/command${url}`;
const conn = new window.WebSocket(url);
conn.onopen = () => conn.send(command);

View File

@@ -8,7 +8,7 @@ import (
// ParseCommand parses the command taking in account if the current
// instance uses a shell to run the commands or just calls the binary
// directyly.
// directly.
func ParseCommand(s *settings.Settings, raw string) ([]string, error) {
var command []string

View File

@@ -2,7 +2,7 @@ package users
import (
"path/filepath"
"regexp"
"slices"
"github.com/spf13/afero"
@@ -111,11 +111,5 @@ func (u *User) CanExecute(command string) bool {
return false
}
for _, cmd := range u.Commands {
if regexp.MustCompile(cmd).MatchString(command) {
return true
}
}
return false
return slices.Contains(u.Commands, command)
}

View File

@@ -0,0 +1,235 @@
From: Daniel Golle <daniel@makrotopia.org>
Date: Thu, 26 Jun 2025 00:54:32 +0100
Subject: [PATCH] arm64: dts: mt7988a: complete dtsi
Work-in-progress patch to complete mt7988a.dtsi
--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
@@ -193,7 +193,7 @@
};
pio: pinctrl@1001f000 {
- compatible = "mediatek,mt7988-pinctrl";
+ compatible = "mediatek,mt7988-pinctrl", "syscon";
reg = <0 0x1001f000 0 0x1000>,
<0 0x11c10000 0 0x1000>,
<0 0x11d00000 0 0x1000>,
@@ -212,6 +212,13 @@
interrupt-parent = <&gic>;
#interrupt-cells = <2>;
+ snfi_pins: snfi-pins {
+ mux {
+ function = "flash";
+ groups = "snfi";
+ };
+ };
+
pcie0_pins: pcie0-pins {
mux {
function = "pcie";
@@ -278,6 +285,60 @@
status = "disabled";
};
+ sgmiisys0: syscon@10060000 {
+ compatible = "mediatek,mt7988-sgmiisys",
+ "mediatek,mt7988-sgmiisys0",
+ "syscon",
+ "simple-mfd";
+ reg = <0 0x10060000 0 0x1000>;
+ resets = <&watchdog 1>;
+ #clock-cells = <1>;
+
+ sgmiipcs0: pcs {
+ compatible = "mediatek,mt7988-sgmii";
+ clocks = <&topckgen CLK_TOP_SGM_0_SEL>,
+ <&sgmiisys0 CLK_SGM0_TX_EN>,
+ <&sgmiisys0 CLK_SGM0_RX_EN>;
+ clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx";
+ #pcs-cells = <0>;
+ };
+ };
+
+ sgmiisys1: syscon@10070000 {
+ compatible = "mediatek,mt7988-sgmiisys",
+ "mediatek,mt7988-sgmiisys1",
+ "syscon",
+ "simple-mfd";
+ reg = <0 0x10070000 0 0x1000>;
+ resets = <&watchdog 2>;
+ #clock-cells = <1>;
+
+ sgmiipcs1: pcs {
+ compatible = "mediatek,mt7988-sgmii";
+ clocks = <&topckgen CLK_TOP_SGM_1_SEL>,
+ <&sgmiisys1 CLK_SGM1_TX_EN>,
+ <&sgmiisys1 CLK_SGM1_RX_EN>;
+ clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx";
+ #pcs-cells = <0>;
+ };
+ };
+
+ usxgmiisys0: pcs@10080000 {
+ compatible = "mediatek,mt7988-usxgmiisys";
+ reg = <0 0x10080000 0 0x1000>;
+ resets = <&watchdog 12>;
+ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>;
+ #pcs-cells = <0>;
+ };
+
+ usxgmiisys1: pcs@10081000 {
+ compatible = "mediatek,mt7988-usxgmiisys";
+ reg = <0 0x10081000 0 0x1000>;
+ resets = <&watchdog 13>;
+ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>;
+ #pcs-cells = <0>;
+ };
+
mcusys: mcusys@100e0000 {
compatible = "mediatek,mt7988-mcusys", "syscon";
reg = <0 0x100e0000 0 0x1000>;
@@ -319,6 +380,32 @@
status = "disabled";
};
+ snand: spi@11001000 {
+ compatible = "mediatek,mt7986-snand";
+ reg = <0 0x11001000 0 0x1000>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_SPINFI>,
+ <&infracfg CLK_INFRA_NFI>,
+ <&infracfg CLK_INFRA_66M_NFI_HCK>;
+ clock-names = "pad_clk", "nfi_clk", "nfi_hclk";
+ nand-ecc-engine = <&bch>;
+ mediatek,quad-spi;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&snfi_pins>;
+ status = "disabled";
+ };
+
+ bch: ecc@11002000 {
+ compatible = "mediatek,mt7686-ecc";
+ reg = <0 0x11002000 0 0x1000>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_NFI>;
+ clock-names = "nfiecc_clk";
+ status = "disabled";
+ };
+
i2c0: i2c@11003000 {
compatible = "mediatek,mt7981-i2c";
reg = <0 0x11003000 0 0x1000>,
@@ -425,7 +512,7 @@
<0 0x0f0f0018 0 0x20>;
};
- usb@11190000 {
+ ssusb0: usb@11190000 {
compatible = "mediatek,mt7988-xhci", "mediatek,mtk-xhci";
reg = <0 0x11190000 0 0x2e00>,
<0 0x11193e00 0 0x0100>;
@@ -459,6 +546,35 @@
status = "disabled";
};
+ afe: audio-controller@11210000 {
+ compatible = "mediatek,mt79xx-audio";
+ reg = <0 0x11210000 0 0x9000>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_66M_AUD_SLV_BCK>,
+ <&infracfg CLK_INFRA_AUD_26M>,
+ <&infracfg CLK_INFRA_AUD_L>,
+ <&infracfg CLK_INFRA_AUD_AUD>,
+ <&infracfg CLK_INFRA_AUD_EG2>,
+ <&topckgen CLK_TOP_AUD_SEL>,
+ <&topckgen CLK_TOP_AUD_I2S_M>;
+ clock-names = "aud_bus_ck",
+ "aud_26m_ck",
+ "aud_l_ck",
+ "aud_aud_ck",
+ "aud_eg2_ck",
+ "aud_sel",
+ "aud_i2s_m";
+ assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>,
+ <&topckgen CLK_TOP_A1SYS_SEL>,
+ <&topckgen CLK_TOP_AUD_L_SEL>,
+ <&topckgen CLK_TOP_A_TUNER_SEL>;
+ assigned-clock-parents = <&apmixedsys CLK_APMIXED_APLL2>,
+ <&topckgen CLK_TOP_APLL2_D4>,
+ <&apmixedsys CLK_APMIXED_APLL2>,
+ <&topckgen CLK_TOP_APLL2_D4>;
+ status = "disabled";
+ };
+
mmc0: mmc@11230000 {
compatible = "mediatek,mt7988-mmc";
reg = <0 0x11230000 0 0x1000>,
@@ -721,6 +837,10 @@
#address-cells = <1>;
#size-cells = <1>;
+ cpufreq_calibration: calib@278 {
+ reg = <0x278 0x1>;
+ };
+
lvts_calibration: calib@918 {
reg = <0x918 0x28>;
};
@@ -984,12 +1104,16 @@
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
+ pcs-handle = <&sgmiipcs1>, <&usxgmiisys1>;
+ phys = <&xfi_tphy1>;
status = "disabled";
};
gmac2: mac@2 {
compatible = "mediatek,eth-mac";
reg = <2>;
+ pcs-handle = <&sgmiipcs0>, <&usxgmiisys0>;
+ phys = <&xfi_tphy0>;
status = "disabled";
};
@@ -1002,9 +1126,37 @@
reg = <15>;
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "internal";
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2p5gbe_led0: i2p5gbe-led0@0 {
+ reg = <0>;
+ function = LED_FUNCTION_LAN;
+ status = "disabled";
+ };
+
+ i2p5gbe_led1: i2p5gbe-led1@1 {
+ reg = <1>;
+ function = LED_FUNCTION_LAN;
+ status = "disabled";
+ };
+ };
};
};
};
+
+ crypto: crypto@15600000 {
+ compatible = "inside-secure,safexcel-eip197b";
+ reg = <0 0x15600000 0 0x180000>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ring0", "ring1", "ring2", "ring3";
+ status = "okay";
+ };
};
thermal-zones {

View File

@@ -56,7 +56,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
dtb-$(CONFIG_ARCH_MEDIATEK) += mt8173-elm-hana.dtb
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-emmc.dtso
@@ -0,0 +1,33 @@
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2021 MediaTek Inc.
@@ -87,6 +87,33 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ no-sd;
+ no-sdio;
+ status = "okay";
+
+ card@0 {
+ compatible = "mmc-card";
+ reg = <0>;
+
+ partitions {
+ compatible = "gpt-partitions";
+
+ block-partition-env {
+ partname = "ubootenv";
+ nvmem-layout {
+ compatible = "u-boot,env-layout";
+ };
+ };
+
+ emmc_root: block-partition-production {
+ partname = "production";
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/chosen";
+ __overlay__ {
+ rootdisk-emmc = <&emmc_root>;
+ };
+ };
+};
@@ -397,7 +424,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+};
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-sd.dtso
@@ -0,0 +1,31 @@
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2023 MediaTek Inc.
@@ -412,7 +439,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+/ {
+ compatible = "mediatek,mt7988a-rfb", "mediatek,mt7988a";
+
+ fragment@1 {
+ fragment@0 {
+ target-path = <&mmc0>;
+ __overlay__ {
+ pinctrl-names = "default", "state_uhs";
@@ -426,12 +453,39 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ vqmmc-supply = <&reg_3p3v>;
+ no-mmc;
+ status = "okay";
+
+ card@0 {
+ compatible = "mmc-card";
+ reg = <0>;
+
+ partitions {
+ compatible = "gpt-partitions";
+
+ block-partition-env {
+ partname = "ubootenv";
+ nvmem-layout {
+ compatible = "u-boot,env-layout";
+ };
+ };
+
+ sd_root: block-partition-production {
+ partname = "production";
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/chosen";
+ __overlay__ {
+ rootdisk-sd = <&sd_root>;
+ };
+ };
+};
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-snfi-nand.dtso
@@ -0,0 +1,70 @@
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2022 MediaTek Inc.
@@ -456,39 +510,38 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ spi-max-frequency = <52000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ mediatek,nmbm;
+ mediatek,bmt-max-ratio = <1>;
+ mediatek,bmt-max-reserved-blocks = <64>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "BL2";
+ reg = <0x00000 0x0100000>;
+ reg = <0x00000 0x0200000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u-boot-env";
+ reg = <0x0100000 0x0080000>;
+ };
+
+ partition@180000 {
+ label = "Factory";
+ reg = <0x180000 0x0400000>;
+ };
+
+ partition@580000 {
+ label = "FIP";
+ reg = <0x580000 0x0200000>;
+ };
+
+ partition@780000 {
+ ubi_part: partition@200000 {
+ label = "ubi";
+ reg = <0x780000 0x7080000>;
+ reg = <0x0200000 0x7e00000>;
+ compatible = "linux,ubi";
+
+ volumes {
+ ubi-volume-ubootenv {
+ volname = "ubootenv";
+ nvmem-layout {
+ compatible = "u-boot,env-redundant-bool";
+ };
+ };
+
+ ubi-volume-ubootenv2 {
+ volname = "ubootenv2";
+ nvmem-layout {
+ compatible = "u-boot,env-redundant-bool";
+ };
+ };
+
+ snfi_root: ubi-volume-fit {
+ volname = "fit";
+ };
+ };
+ };
+ };
+ };
@@ -501,6 +554,18 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ status = "okay";
+ };
+ };
+
+ fragment@2 {
+ target-path = "/chosen";
+ __overlay__ {
+ /*
+ * U-Boot currently cannot detect diffrentiate between
+ * SD and SNFI boot media and always uses rootdisk-sd in
+ * both cases
+ */
+ rootdisk-sd = <&snfi_root>;
+ };
+ };
+};
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand-factory.dtso
@@ -594,7 +659,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+};
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtso
@@ -0,0 +1,66 @@
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2022 MediaTek Inc.
@@ -622,9 +687,6 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ spi-max-frequency = <52000000>;
+ spi-tx-bus-width = <4>;
+ spi-rx-bus-width = <4>;
+ mediatek,nmbm;
+ mediatek,bmt-max-ratio = <1>;
+ mediatek,bmt-max-reserved-blocks = <64>;
+
+ partitions {
+ compatible = "fixed-partitions";
@@ -633,37 +695,51 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+
+ partition@0 {
+ label = "BL2";
+ reg = <0x00000 0x0100000>;
+ reg = <0x00000 0x0200000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u-boot-env";
+ reg = <0x0100000 0x0080000>;
+ };
+
+ partition@180000 {
+ label = "Factory";
+ reg = <0x180000 0x0400000>;
+ };
+
+ partition@580000 {
+ label = "FIP";
+ reg = <0x580000 0x0200000>;
+ };
+
+ partition@780000 {
+ ubi_part: partition@200000 {
+ label = "ubi";
+ reg = <0x780000 0x7080000>;
+ reg = <0x0200000 0x7e00000>;
+ compatible = "linux,ubi";
+
+ volumes {
+ ubi-volume-ubootenv {
+ volname = "ubootenv";
+ nvmem-layout {
+ compatible = "u-boot,env-redundant-bool";
+ };
+ };
+
+ ubi-volume-ubootenv2 {
+ volname = "ubootenv2";
+ nvmem-layout {
+ compatible = "u-boot,env-redundant-bool";
+ };
+ };
+
+ ubi_root: ubi-volume-fit {
+ volname = "fit";
+ };
+
+ };
+ };
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/chosen";
+ __overlay__ {
+ rootdisk-spim-nand = <&ubi_root>;
+ };
+ };
+};
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nor.dtso
@@ -0,0 +1,61 @@
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2022 MediaTek Inc.
@@ -717,13 +793,21 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+ label = "FIP";
+ reg = <0x250000 0x80000>;
+ };
+ partition@2D0000 {
+ nor_root: partition@2D0000 {
+ label = "firmware";
+ reg = <0x2d0000 0x1d30000>;
+ compatible = "denx,fit";
+ };
+ };
+ };
+ };
+
+ fragment@1 {
+ target-path = "/chosen";
+ __overlay__ {
+ rootdisk-nor = <&nor_root>;
+ };
+ };
+};
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dts
@@ -744,7 +828,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+/ {
+ model = "MediaTek MT7988A Reference Board";
+ compatible = "mediatek,mt7988a-rfb",
+ "mediatek,mt7988";
+ "mediatek,mt7988a";
+
+ chosen {
+ bootargs = "console=ttyS0,115200n1 loglevel=8 \
@@ -1198,233 +1282,3 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+&xsphy {
+ status = "okay";
+};
--- a/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7988a.dtsi
@@ -193,7 +193,7 @@
};
pio: pinctrl@1001f000 {
- compatible = "mediatek,mt7988-pinctrl";
+ compatible = "mediatek,mt7988-pinctrl", "syscon";
reg = <0 0x1001f000 0 0x1000>,
<0 0x11c10000 0 0x1000>,
<0 0x11d00000 0 0x1000>,
@@ -212,6 +212,13 @@
interrupt-parent = <&gic>;
#interrupt-cells = <2>;
+ snfi_pins: snfi-pins {
+ mux {
+ function = "flash";
+ groups = "snfi";
+ };
+ };
+
pcie0_pins: pcie0-pins {
mux {
function = "pcie";
@@ -278,6 +285,60 @@
status = "disabled";
};
+ sgmiisys0: syscon@10060000 {
+ compatible = "mediatek,mt7988-sgmiisys",
+ "mediatek,mt7988-sgmiisys0",
+ "syscon",
+ "simple-mfd";
+ reg = <0 0x10060000 0 0x1000>;
+ resets = <&watchdog 1>;
+ #clock-cells = <1>;
+
+ sgmiipcs0: pcs {
+ compatible = "mediatek,mt7988-sgmii";
+ clocks = <&topckgen CLK_TOP_SGM_0_SEL>,
+ <&sgmiisys0 CLK_SGM0_TX_EN>,
+ <&sgmiisys0 CLK_SGM0_RX_EN>;
+ clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx";
+ #pcs-cells = <0>;
+ };
+ };
+
+ sgmiisys1: syscon@10070000 {
+ compatible = "mediatek,mt7988-sgmiisys",
+ "mediatek,mt7988-sgmiisys1",
+ "syscon",
+ "simple-mfd";
+ reg = <0 0x10070000 0 0x1000>;
+ resets = <&watchdog 2>;
+ #clock-cells = <1>;
+
+ sgmiipcs1: pcs {
+ compatible = "mediatek,mt7988-sgmii";
+ clocks = <&topckgen CLK_TOP_SGM_1_SEL>,
+ <&sgmiisys1 CLK_SGM1_TX_EN>,
+ <&sgmiisys1 CLK_SGM1_RX_EN>;
+ clock-names = "sgmii_sel", "sgmii_tx", "sgmii_rx";
+ #pcs-cells = <0>;
+ };
+ };
+
+ usxgmiisys0: pcs@10080000 {
+ compatible = "mediatek,mt7988-usxgmiisys";
+ reg = <0 0x10080000 0 0x1000>;
+ resets = <&watchdog 12>;
+ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>;
+ #pcs-cells = <0>;
+ };
+
+ usxgmiisys1: pcs@10081000 {
+ compatible = "mediatek,mt7988-usxgmiisys";
+ reg = <0 0x10081000 0 0x1000>;
+ resets = <&watchdog 13>;
+ clocks = <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>;
+ #pcs-cells = <0>;
+ };
+
mcusys: mcusys@100e0000 {
compatible = "mediatek,mt7988-mcusys", "syscon";
reg = <0 0x100e0000 0 0x1000>;
@@ -319,6 +380,32 @@
status = "disabled";
};
+ snand: spi@11001000 {
+ compatible = "mediatek,mt7986-snand";
+ reg = <0 0x11001000 0 0x1000>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_SPINFI>,
+ <&infracfg CLK_INFRA_NFI>,
+ <&infracfg CLK_INFRA_66M_NFI_HCK>;
+ clock-names = "pad_clk", "nfi_clk", "nfi_hclk";
+ nand-ecc-engine = <&bch>;
+ mediatek,quad-spi;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&snfi_pins>;
+ status = "disabled";
+ };
+
+ bch: ecc@11002000 {
+ compatible = "mediatek,mt7686-ecc";
+ reg = <0 0x11002000 0 0x1000>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_NFI>;
+ clock-names = "nfiecc_clk";
+ status = "disabled";
+ };
+
i2c0: i2c@11003000 {
compatible = "mediatek,mt7981-i2c";
reg = <0 0x11003000 0 0x1000>,
@@ -425,7 +512,7 @@
<0 0x0f0f0018 0 0x20>;
};
- usb@11190000 {
+ ssusb0: usb@11190000 {
compatible = "mediatek,mt7988-xhci", "mediatek,mtk-xhci";
reg = <0 0x11190000 0 0x2e00>,
<0 0x11193e00 0 0x0100>;
@@ -459,6 +546,35 @@
status = "disabled";
};
+ afe: audio-controller@11210000 {
+ compatible = "mediatek,mt79xx-audio";
+ reg = <0 0x11210000 0 0x9000>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&infracfg CLK_INFRA_66M_AUD_SLV_BCK>,
+ <&infracfg CLK_INFRA_AUD_26M>,
+ <&infracfg CLK_INFRA_AUD_L>,
+ <&infracfg CLK_INFRA_AUD_AUD>,
+ <&infracfg CLK_INFRA_AUD_EG2>,
+ <&topckgen CLK_TOP_AUD_SEL>,
+ <&topckgen CLK_TOP_AUD_I2S_M>;
+ clock-names = "aud_bus_ck",
+ "aud_26m_ck",
+ "aud_l_ck",
+ "aud_aud_ck",
+ "aud_eg2_ck",
+ "aud_sel",
+ "aud_i2s_m";
+ assigned-clocks = <&topckgen CLK_TOP_AUD_SEL>,
+ <&topckgen CLK_TOP_A1SYS_SEL>,
+ <&topckgen CLK_TOP_AUD_L_SEL>,
+ <&topckgen CLK_TOP_A_TUNER_SEL>;
+ assigned-clock-parents = <&apmixedsys CLK_APMIXED_APLL2>,
+ <&topckgen CLK_TOP_APLL2_D4>,
+ <&apmixedsys CLK_APMIXED_APLL2>,
+ <&topckgen CLK_TOP_APLL2_D4>;
+ status = "disabled";
+ };
+
mmc0: mmc@11230000 {
compatible = "mediatek,mt7988-mmc";
reg = <0 0x11230000 0 0x1000>,
@@ -721,6 +837,10 @@
#address-cells = <1>;
#size-cells = <1>;
+ cpufreq_calibration: calib@278 {
+ reg = <0x278 0x1>;
+ };
+
lvts_calibration: calib@918 {
reg = <0x918 0x28>;
};
@@ -984,12 +1104,16 @@
gmac1: mac@1 {
compatible = "mediatek,eth-mac";
reg = <1>;
+ pcs-handle = <&sgmiipcs1>, <&usxgmiisys1>;
+ phys = <&xfi_tphy1>;
status = "disabled";
};
gmac2: mac@2 {
compatible = "mediatek,eth-mac";
reg = <2>;
+ pcs-handle = <&sgmiipcs0>, <&usxgmiisys0>;
+ phys = <&xfi_tphy0>;
status = "disabled";
};
@@ -1002,9 +1126,37 @@
reg = <15>;
compatible = "ethernet-phy-ieee802.3-c45";
phy-mode = "internal";
+
+ leds {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ i2p5gbe_led0: i2p5gbe-led0@0 {
+ reg = <0>;
+ function = LED_FUNCTION_LAN;
+ status = "disabled";
+ };
+
+ i2p5gbe_led1: i2p5gbe-led1@1 {
+ reg = <1>;
+ function = LED_FUNCTION_LAN;
+ status = "disabled";
+ };
+ };
};
};
};
+
+ crypto: crypto@15600000 {
+ compatible = "inside-secure,safexcel-eip197b";
+ reg = <0 0x15600000 0 0x180000>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ring0", "ring1", "ring2", "ring3";
+ status = "okay";
+ };
};
thermal-zones {

View File

@@ -0,0 +1,45 @@
From patchwork Fri Apr 19 16:59:07 2024
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Daniel Golle <daniel@makrotopia.org>
X-Patchwork-Id: 13636668
Return-Path:
<linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org>
Date: Fri, 19 Apr 2024 17:59:07 +0100
From: Daniel Golle <daniel@makrotopia.org>
To: "Rafael J. Wysocki" <rafael@kernel.org>,
Viresh Kumar <viresh.kumar@linaro.org>,
Matthias Brugger <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>,
linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org
Subject: [PATCH] cpufreq: mediatek: Add support for MT7988A
Message-ID:
<acf4fb446aacfbf6ce7b6e94bf3aad303e0ad4d1.1713545923.git.daniel@makrotopia.org>
Content-Disposition: inline
List-Id: <linux-mediatek.lists.infradead.org>
From: Sam Shih <sam.shih@mediatek.com>
This add cpufreq support for mediatek MT7988A SoC.
The platform data of MT7988A is different from previous MediaTek SoCs,
so we add a new compatible and platform data for it.
Signed-off-by: Sam Shih <sam.shih@mediatek.com>
---
drivers/cpufreq/mediatek-cpufreq.c | 10 ++++++++++
1 file changed, 10 insertions(+)
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -744,6 +744,7 @@ static const struct of_device_id mtk_cpu
{ .compatible = "mediatek,mt7622", .data = &mt7622_platform_data },
{ .compatible = "mediatek,mt7623", .data = &mt7623_platform_data },
{ .compatible = "mediatek,mt7988a", .data = &mt7988_platform_data },
+ { .compatible = "mediatek,mt7988d", .data = &mt7988_platform_data },
{ .compatible = "mediatek,mt8167", .data = &mt8516_platform_data },
{ .compatible = "mediatek,mt817x", .data = &mt2701_platform_data },
{ .compatible = "mediatek,mt8173", .data = &mt2701_platform_data },

View File

@@ -113,7 +113,7 @@ func NewHostValueByDomain(domain string) (HostValue, error) {
domain = strings.Trim(domain, ".")
item := strings.Split(domain, ".")
if len(item) < 2 {
return HostValue{}, errors.New("invaild domain")
return HostValue{}, errors.New("invalid domain")
}
return HostValue{
IsDomain: true,

View File

@@ -299,7 +299,7 @@ func startPipe(cfg *Config) {
}
}
func safeEuqal(a, b string) bool {
func safeEqual(a, b string) bool {
aBuf := utils.ImmutableBytesFromString(a)
bBuf := utils.ImmutableBytesFromString(b)
return subtle.ConstantTimeCompare(aBuf, bBuf) == 1
@@ -311,7 +311,7 @@ func authentication(secret string) func(http.Handler) http.Handler {
// Browser websocket not support custom header
if r.Header.Get("Upgrade") == "websocket" && r.URL.Query().Get("token") != "" {
token := r.URL.Query().Get("token")
if !safeEuqal(token, secret) {
if !safeEqual(token, secret) {
render.Status(r, http.StatusUnauthorized)
render.JSON(w, r, ErrUnauthorized)
return
@@ -324,7 +324,7 @@ func authentication(secret string) func(http.Handler) http.Handler {
bearer, token, found := strings.Cut(header, " ")
hasInvalidHeader := bearer != "Bearer"
hasInvalidSecret := !found || !safeEuqal(token, secret)
hasInvalidSecret := !found || !safeEqual(token, secret)
if hasInvalidHeader || hasInvalidSecret {
render.Status(r, http.StatusUnauthorized)
render.JSON(w, r, ErrUnauthorized)

View File

@@ -6,12 +6,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=adguardhome
PKG_VERSION:=0.107.62
PKG_VERSION:=0.107.63
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/AdGuardHome/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=e912d941badfb4b50a53aa93578530f24d43de7e5a200860a81b674d0cb75917
PKG_HASH:=f445eb98fc1beba326433da7c999799fe36c7f15297fdebe59a41914eaffe3ad
PKG_BUILD_DIR:=$(BUILD_DIR)/AdGuardHome-$(PKG_VERSION)
PKG_LICENSE:=GPL-3.0-only
@@ -58,7 +58,7 @@ define Download/adguardhome-frontend
URL:=https://github.com/AdguardTeam/AdGuardHome/releases/download/v$(PKG_VERSION)/
URL_FILE:=AdGuardHome_frontend.tar.gz
FILE:=$(FRONTEND_FILE)
HASH:=29d81f9167893a1f0aa88fc2ffa1392b925ca5521c56d8fe1b84237d747b3c15
HASH:=74bda6f7c7334342b33fff50a0cdff4e206f84a471bab983ee16d3f6f112c53a
endef
define Build/Prepare

View File

@@ -8,12 +8,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ddns-go
PKG_VERSION:=6.10.0
PKG_VERSION:=6.11.0
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/jeessy2/ddns-go/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=26655ad6b9d09dd75c16f588a17dab8f6927d1e56356be6a2d6d31b74bb83849
PKG_HASH:=49e2e3374911c5d0c1124dba1e6a565c2e810be9328d0b05d1cfbafb8c937958
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE

View File

@@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=filebrowser
PKG_VERSION:=2.33.7
PKG_VERSION:=2.33.8
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/filebrowser/filebrowser/tar.gz/v${PKG_VERSION}?
PKG_HASH:=64b17e544fe9c7cc97578bd441c9b6282e25aca9f517a8a191cdde274974a00a
PKG_HASH:=77151e5c623fcde1675d9b87b9eaf3d23912afdf33cb146397d4ca66e18389db
PKG_LICENSE:=Apache-2.0
PKG_LICENSE_FILES:=LICENSE

View File

@@ -11,7 +11,7 @@ PKG_ARCH_quickstart:=$(ARCH)
PKG_NAME:=quickstart
PKG_VERSION:=0.10.3
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/prebuilt/
PKG_HASH:=b6fd09b8f71a0c56758c9819102268fdf464fe70ca0d6e7f83c5e75e024dee94

View File

@@ -4,7 +4,12 @@ START=93
USE_PROCD=1
start_service() {
/usr/sbin/quickstart uciChange
local seconds
for seconds in $(seq 0 2); do
/usr/sbin/quickstart uciChange | grep -q -e OK -e code:501 && break
sleep 1 && continue
break
done
}
service_triggers()

View File

@@ -4,7 +4,7 @@
include $(TOPDIR)/rules.mk
LUCI_TITLE:=FullCombo Shark! supplies maximum customization of mihomo on OpenWrt.
LUCI_TITLE:=FullCombo Shark! supplies flexible customization of mihomo on OpenWrt.
LUCI_PKGARCH:=all
LUCI_DEPENDS:= \
+mihomo \

View File

@@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mihomo
PKG_VERSION:=1.19.10
PKG_VERSION:=1.19.11
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/metacubex/mihomo/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=a0ca7bb23fcfa067e8a58a9618879a507881dbca321a8eb0550948b1d26296c0
PKG_HASH:=72730aff2c89f1cba60bfc9318e17ac8161db4e6c69bd24b54eb37f9fa646540
PKG_MAINTAINER:=Anya Lin <hukk1996@gmail.com>
PKG_LICENSE:=GPL-2.0

View File

@@ -5,7 +5,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=naiveproxy
PKG_VERSION:=137.0.7151.44-2
PKG_VERSION:=138.0.7204.35-1
PKG_RELEASE:=1
# intel 80386 & riscv64 & cortex-a76
@@ -20,47 +20,47 @@ else ifeq ($(ARCH_PREBUILT),riscv64_riscv64)
endif
ifeq ($(ARCH_PACKAGES),aarch64_cortex-a53)
PKG_HASH:=db0527adea0cde274873c28c0562c00f9aff7488ce02bf582ebbb3bf22f198fd
PKG_HASH:=45c8b1f19d53f3e0c30bd591a0ba29e511295f7eb9c5ebeaee9dcb483e477d44
else ifeq ($(ARCH_PACKAGES),aarch64_cortex-a72)
PKG_HASH:=ce0fbd501e11f515e0dac203157346201727ffec62ebc9f25c37db959e3b5b00
PKG_HASH:=2eb876e77a067f93e50370a1d7ebef497f948e76a732a698aac17b777c2e02da
else ifeq ($(ARCH_PACKAGES),aarch64_generic)
PKG_HASH:=7e3778ded1fe210c180127c7fac4913e1b0fa624f27d4f9a581ca56315cac72d
PKG_HASH:=b0303b6c1147d563454605e3e2fda651aa40a8a7189b3c15245389557539b516
else ifeq ($(ARCH_PACKAGES),arm_arm1176jzf-s_vfp)
PKG_HASH:=29d3585aa2cb790d15803a25d3fd4a831296bdb4ae3eaa2f0ac52b5bc09abba4
PKG_HASH:=11f3aa85008935a7bce61e69117d0fec66b31ce7a8394d1ccb47f1fb66d00c35
else ifeq ($(ARCH_PACKAGES),arm_arm926ej-s)
PKG_HASH:=6469b5ff3745bcce8c6055566f4f92d692fa58ff912ff1a356ac540fbdac3bc0
PKG_HASH:=c5838f4149efbc7b2e01d6f2c94f7585edc3b51ebc072e88f4e8d6e709125b02
else ifeq ($(ARCH_PACKAGES),arm_cortex-a15_neon-vfpv4)
PKG_HASH:=76dcb85944194bf5cb7caa971696cb74dd134167afa37b4a5476562932a9aac1
PKG_HASH:=a514d92010d2999ddbfe073e61dc9ea7f58414845077114979950ff5078a72ee
else ifeq ($(ARCH_PACKAGES),arm_cortex-a5_vfpv4)
PKG_HASH:=3f62e2f52423b2983a6ef569e99c797ac1322a34afbd0a6288514a7e936ec124
PKG_HASH:=1e2677d68d9c81b7505ada6ed146177e53dca708fa878c5105b87812df20c797
else ifeq ($(ARCH_PACKAGES),arm_cortex-a7)
PKG_HASH:=b57eb5b8f54d418d435e2e141618d0875f9463e1428cd994f3dbd9bd7d47258d
PKG_HASH:=e9047f458ecba7cfc4c722d0180c1a4d823d9edbde41e4abce0f293c52712b0f
else ifeq ($(ARCH_PACKAGES),arm_cortex-a7_neon-vfpv4)
PKG_HASH:=25123b03d30add7b91bb265b26ec9533749b50f1e42c12dec709e593e8a5dc11
PKG_HASH:=954cea8e06240e6391d7057765335c6ac20fdbc42dcde9d20c2e4aa55a75a9e1
else ifeq ($(ARCH_PACKAGES),arm_cortex-a7_vfpv4)
PKG_HASH:=0f7f19b24ca5c60dbfb2b9979fe1e814843909803557e04a9c06e921b8e2b6dd
PKG_HASH:=6d739e11f4df930139744d982ee9e98050cf6778ff0af90bf5e128f789f26b61
else ifeq ($(ARCH_PACKAGES),arm_cortex-a8_vfpv3)
PKG_HASH:=3cd99622d737e09098b9b117d4525a8b4586bd1bdd93b8c6b305b8bf1479a72a
PKG_HASH:=8f3de0015d28c341d8dd303bd770ffaf4cf05767a4af3612218da78a54d01c6e
else ifeq ($(ARCH_PACKAGES),arm_cortex-a9)
PKG_HASH:=1895d5d943abdab61f4d518700dcf21167f6e633213ee2fe438e5782e3a8c39a
PKG_HASH:=bf15aaaf307ac86cbd3fc9c9a8a107103d2682ba227f54fd2d2a2def252b8fca
else ifeq ($(ARCH_PACKAGES),arm_cortex-a9_neon)
PKG_HASH:=13478da67df395e4e2cc37ffab22b2875d9a88cd0ec14b7af7f9936f0364b471
PKG_HASH:=c5788e9ce8eef9d526390ef04966668ffd9e9f40af194257fb9600362585032f
else ifeq ($(ARCH_PACKAGES),arm_cortex-a9_vfpv3-d16)
PKG_HASH:=efd1a5a5f19c5a14991f8f607a9e636be7e205fdac5afbaeb811c26762583f28
PKG_HASH:=5c93593112ad72c75d35fc41b6d6ed3c1115dcf8aa30f9bc61303696f31fa551
else ifeq ($(ARCH_PACKAGES),arm_mpcore)
PKG_HASH:=d23f160bf4e1a22e7997d589bedbde8368e4b842ee6f4e0c1dba3c6825d42ef6
PKG_HASH:=ee481d71ff9735e221f8a58601690f11315613f4e77678bbe3ab25236d5ad36a
else ifeq ($(ARCH_PACKAGES),arm_xscale)
PKG_HASH:=b82aaaada7cf3261a58a8f30bdd2710dcc021435cf310a1cec25f6fed6788428
PKG_HASH:=3719a7d151c1d80250388cea32f74165772d8cc21b8bfa9c6a8db312ae19a0b8
else ifeq ($(ARCH_PACKAGES),mipsel_24kc)
PKG_HASH:=277405ce386c56172e8e0ca2d98beec5bf5034f77a1224de201119abc5cd92b5
PKG_HASH:=1aa0c1fbe81242cf4c14a6c83fd32f8548a3691233c2078a640619c2b3bfd7c4
else ifeq ($(ARCH_PACKAGES),mipsel_mips32)
PKG_HASH:=4e31ac05f877cc36cf9296377bb4edbfc0b91657c39e5c9dfe36ea63500cf5a0
PKG_HASH:=9f909d879602a0feeb2535e0859339a0496cdd948fb2f64c491bc5cf324f93f0
else ifeq ($(ARCH_PACKAGES),riscv64)
PKG_HASH:=deceede3b36871a785ece5f1465517b7cfa42d014f5c21eb23a4ea9b6821d4a8
PKG_HASH:=df183679a499ce65f3ff2e7561a551dd890c4acd6bfdeb97fdf729c97d195bac
else ifeq ($(ARCH_PACKAGES),x86)
PKG_HASH:=0181e0b33b961a50d3d17a25513d28d8e0286fb1db417da5875cbec9341dd073
PKG_HASH:=f9ca7ee068b2317c8a9e1155ed692cb99d3ba35f5ea4e0dcb56d63efa8764839
else ifeq ($(ARCH_PACKAGES),x86_64)
PKG_HASH:=0c633a5dfe7d929cac0b3f389522c47ac46db9a9491724c7e1e7ef7380b2299e
PKG_HASH:=c6a6526432d76a2a19412869fd37a99ffa9f832c992791fc26983965ad3f0726
else
PKG_HASH:=dummy
endif

View File

@@ -21,13 +21,13 @@ define Download/geoip
HASH:=58bf8f086473cad7df77f032815eb8d96bbd4a1aaef84c4f7da18cf1a3bb947a
endef
GEOSITE_VER:=20250608120644
GEOSITE_VER:=20250625164437
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
define Download/geosite
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
URL_FILE:=dlc.dat
FILE:=$(GEOSITE_FILE)
HASH:=67ededbc0cb18f93415e2e003cb45cb04fc32ba4a829f7d18074d3bdd88ab629
HASH:=dffd807d696a2a51193b52171089bdc523a690ae3b37defecbe9546d4d3e15ca
endef
GEOSITE_IRAN_VER:=202506230044

View File

@@ -1,9 +1,10 @@
using ReactiveUI;
using SQLite;
namespace ServiceLib.Models;
[Serializable]
public class ProfileItem
public class ProfileItem: ReactiveObject
{
public ProfileItem()
{

View File

@@ -1,3 +1,5 @@
using ReactiveUI.Fody.Helpers;
namespace ServiceLib.Models;
[Serializable]
@@ -5,13 +7,28 @@ public class ProfileItemModel : ProfileItem
{
public bool IsActive { get; set; }
public string SubRemarks { get; set; }
[Reactive]
public int Delay { get; set; }
public decimal Speed { get; set; }
public int Sort { get; set; }
[Reactive]
public string DelayVal { get; set; }
[Reactive]
public string SpeedVal { get; set; }
[Reactive]
public string TodayUp { get; set; }
[Reactive]
public string TodayDown { get; set; }
[Reactive]
public string TotalUp { get; set; }
[Reactive]
public string TotalDown { get; set; }
}

View File

@@ -304,7 +304,7 @@ public class ProfilesViewModel : MyReactiveObject
{
item.SpeedVal = result.Speed ?? string.Empty;
}
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
//_profileItems.Replace(item, JsonUtils.DeepCopy(item));
}
public void UpdateStatistics(ServerSpeedItem update)
@@ -319,16 +319,16 @@ public class ProfilesViewModel : MyReactiveObject
item.TotalDown = Utils.HumanFy(update.TotalDown);
item.TotalUp = Utils.HumanFy(update.TotalUp);
if (SelectedProfile?.IndexId == item.IndexId)
{
var temp = JsonUtils.DeepCopy(item);
_profileItems.Replace(item, temp);
SelectedProfile = temp;
}
else
{
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
}
//if (SelectedProfile?.IndexId == item.IndexId)
//{
// var temp = JsonUtils.DeepCopy(item);
// _profileItems.Replace(item, temp);
// SelectedProfile = temp;
//}
//else
//{
// _profileItems.Replace(item, JsonUtils.DeepCopy(item));
//}
}
}
catch

View File

@@ -779,3 +779,5 @@ brian6932
iednod55
maxbin123
nullpos
anlar
eason1478

View File

@@ -4,6 +4,25 @@
# To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master
-->
### 2025.06.25
#### Extractor changes
- [Add `_search_nuxt_json` helper](https://github.com/yt-dlp/yt-dlp/commit/51887484e46ab6015c041cb1ab626a55f25a03bd) ([#13386](https://github.com/yt-dlp/yt-dlp/issues/13386)) by [bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K)
- **brightcove**: new: [Improve metadata extraction](https://github.com/yt-dlp/yt-dlp/commit/e6bd4a3da295b760ab20b39c18ce8934d312c2bf) ([#13461](https://github.com/yt-dlp/yt-dlp/issues/13461)) by [doe1080](https://github.com/doe1080)
- **huya**: live: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/2600849badb0d08c55b58dcc77a13af6ba423da6) ([#13520](https://github.com/yt-dlp/yt-dlp/issues/13520)) by [doe1080](https://github.com/doe1080)
- **hypergryph**: [Improve metadata extraction](https://github.com/yt-dlp/yt-dlp/commit/1722c55400ff30bb5aee5dd7a262f0b7e9ce2f0e) ([#13415](https://github.com/yt-dlp/yt-dlp/issues/13415)) by [doe1080](https://github.com/doe1080), [eason1478](https://github.com/eason1478)
- **lsm**: [Fix extractors](https://github.com/yt-dlp/yt-dlp/commit/c57412d1f9cf0124adc972a47858ac42b740c61d) ([#13126](https://github.com/yt-dlp/yt-dlp/issues/13126)) by [Caesim404](https://github.com/Caesim404)
- **mave**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/1838a1ce5d4ade80770ba9162eaffc9a1607dc70) ([#13380](https://github.com/yt-dlp/yt-dlp/issues/13380)) by [anlar](https://github.com/anlar)
- **sportdeutschland**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/a4ce4327c9836691d3b6b00e44a90b6741601ed8) ([#13519](https://github.com/yt-dlp/yt-dlp/issues/13519)) by [DTrombett](https://github.com/DTrombett)
- **sproutvideo**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/5b559d0072b7164daf06bacdc41c6f11283452c8) ([#13544](https://github.com/yt-dlp/yt-dlp/issues/13544)) by [bashonly](https://github.com/bashonly)
- **tv8.it**: [Support slugless URLs](https://github.com/yt-dlp/yt-dlp/commit/3bd30291601c47fa4a257983473884103ecab0c7) ([#13478](https://github.com/yt-dlp/yt-dlp/issues/13478)) by [DTrombett](https://github.com/DTrombett)
- **youtube**
- [Check any `ios` m3u8 formats prior to download](https://github.com/yt-dlp/yt-dlp/commit/8f94b76cbf7bbd9dfd8762c63cdea04f90f1297f) ([#13524](https://github.com/yt-dlp/yt-dlp/issues/13524)) by [bashonly](https://github.com/bashonly)
- [Improve player context payloads](https://github.com/yt-dlp/yt-dlp/commit/ff6f94041aeee19c5559e1c1cd693960a1c1dd14) ([#13539](https://github.com/yt-dlp/yt-dlp/issues/13539)) by [bashonly](https://github.com/bashonly)
#### Misc. changes
- **test**: `traversal`: [Fix morsel tests for Python 3.14](https://github.com/yt-dlp/yt-dlp/commit/73bf10211668e4a59ccafd790e06ee82d9fea9ea) ([#13471](https://github.com/yt-dlp/yt-dlp/issues/13471)) by [Grub4K](https://github.com/Grub4K)
### 2025.06.09
#### Extractor changes

View File

@@ -590,7 +590,7 @@ The only reliable way to check if a site is supported is to try it.
- **Hungama**
- **HungamaAlbumPlaylist**
- **HungamaSong**
- **huya:live**: huya.com
- **huya:live**: 虎牙直播
- **huya:video**: 虎牙视频
- **Hypem**
- **Hytale**
@@ -776,6 +776,7 @@ The only reliable way to check if a site is supported is to try it.
- **massengeschmack.tv**
- **Masters**
- **MatchTV**
- **Mave**
- **MBN**: mbn.co.kr (매일방송)
- **MDR**: MDR.DE
- **MedalTV**
@@ -832,7 +833,7 @@ The only reliable way to check if a site is supported is to try it.
- **Mojevideo**: mojevideo.sk
- **Mojvideo**
- **Monstercat**
- **MonsterSirenHypergryphMusic**
- **monstersiren**: 塞壬唱片
- **Motherless**
- **MotherlessGallery**
- **MotherlessGroup**

View File

@@ -5,47 +5,46 @@ import time
from .common import FileDownloader
from .external import FFmpegFD
from ..networking import Request
from ..utils import DownloadError, str_or_none, try_get
from ..networking.websocket import WebSocketResponse
from ..utils import DownloadError, str_or_none, truncate_string
from ..utils.traversal import traverse_obj
class NiconicoLiveFD(FileDownloader):
""" Downloads niconico live without being stopped """
def real_download(self, filename, info_dict):
video_id = info_dict['video_id']
ws_url = info_dict['url']
ws_extractor = info_dict['ws']
ws_origin_host = info_dict['origin']
live_quality = info_dict.get('live_quality', 'high')
live_latency = info_dict.get('live_latency', 'high')
video_id = info_dict['id']
opts = info_dict['downloader_options']
quality, ws_extractor, ws_url = opts['max_quality'], opts['ws'], opts['ws_url']
dl = FFmpegFD(self.ydl, self.params or {})
new_info_dict = info_dict.copy()
new_info_dict.update({
'protocol': 'm3u8',
})
new_info_dict['protocol'] = 'm3u8'
def communicate_ws(reconnect):
if reconnect:
ws = self.ydl.urlopen(Request(ws_url, headers={'Origin': f'https://{ws_origin_host}'}))
# Support --load-info-json as if it is a reconnect attempt
if reconnect or not isinstance(ws_extractor, WebSocketResponse):
ws = self.ydl.urlopen(Request(
ws_url, headers={'Origin': 'https://live.nicovideo.jp'}))
if self.ydl.params.get('verbose', False):
self.to_screen('[debug] Sending startWatching request')
self.write_debug('Sending startWatching request')
ws.send(json.dumps({
'type': 'startWatching',
'data': {
'reconnect': True,
'room': {
'commentable': True,
'protocol': 'webSocket',
},
'stream': {
'quality': live_quality,
'protocol': 'hls+fmp4',
'latency': live_latency,
'accessRightMethod': 'single_cookie',
'chasePlay': False,
'latency': 'high',
'protocol': 'hls',
'quality': quality,
},
'room': {
'protocol': 'webSocket',
'commentable': True,
},
'reconnect': True,
},
'type': 'startWatching',
}))
else:
ws = ws_extractor
@@ -58,7 +57,6 @@ class NiconicoLiveFD(FileDownloader):
if not data or not isinstance(data, dict):
continue
if data.get('type') == 'ping':
# pong back
ws.send(r'{"type":"pong"}')
ws.send(r'{"type":"keepSeat"}')
elif data.get('type') == 'disconnect':
@@ -66,12 +64,10 @@ class NiconicoLiveFD(FileDownloader):
return True
elif data.get('type') == 'error':
self.write_debug(data)
message = try_get(data, lambda x: x['body']['code'], str) or recv
message = traverse_obj(data, ('body', 'code', {str_or_none}), default=recv)
return DownloadError(message)
elif self.ydl.params.get('verbose', False):
if len(recv) > 100:
recv = recv[:100] + '...'
self.to_screen(f'[debug] Server said: {recv}')
self.write_debug(f'Server response: {truncate_string(recv, 100)}')
def ws_main():
reconnect = False
@@ -81,7 +77,8 @@ class NiconicoLiveFD(FileDownloader):
if ret is True:
return
except BaseException as e:
self.to_screen('[{}] {}: Connection error occured, reconnecting after 10 seconds: {}'.format('niconico:live', video_id, str_or_none(e)))
self.to_screen(
f'[niconico:live] {video_id}: Connection error occured, reconnecting after 10 seconds: {e}')
time.sleep(10)
continue
finally:

View File

@@ -1107,6 +1107,7 @@ from .markiza import (
from .massengeschmacktv import MassengeschmackTVIE
from .masters import MastersIE
from .matchtv import MatchTVIE
from .mave import MaveIE
from .mbn import MBNIE
from .mdr import MDRIE
from .medaltv import MedalTVIE

View File

@@ -1226,6 +1226,26 @@ class BilibiliSpaceVideoIE(BilibiliSpaceBaseIE):
'id': '313580179',
},
'playlist_mincount': 92,
}, {
# Hidden-mode collection
'url': 'https://space.bilibili.com/3669403/video',
'info_dict': {
'id': '3669403',
},
'playlist': [{
'info_dict': {
'_type': 'playlist',
'id': '3669403_3958082',
'title': '合集·直播回放',
'description': '',
'uploader': '月路Yuel',
'uploader_id': '3669403',
'timestamp': int,
'upload_date': str,
'thumbnail': str,
},
}],
'params': {'playlist_items': '7'},
}]
def _real_extract(self, url):
@@ -1282,8 +1302,14 @@ class BilibiliSpaceVideoIE(BilibiliSpaceBaseIE):
}
def get_entries(page_data):
for entry in traverse_obj(page_data, ('list', 'vlist')) or []:
yield self.url_result(f'https://www.bilibili.com/video/{entry["bvid"]}', BiliBiliIE, entry['bvid'])
for entry in traverse_obj(page_data, ('list', 'vlist', ..., {dict})):
if traverse_obj(entry, ('meta', 'attribute')) == 156:
# hidden-mode collection doesn't show its videos in uploads; extract as playlist instead
yield self.url_result(
f'https://space.bilibili.com/{entry["mid"]}/lists/{entry["meta"]["id"]}?type=season',
BilibiliCollectionListIE, f'{entry["mid"]}_{entry["meta"]["id"]}')
else:
yield self.url_result(f'https://www.bilibili.com/video/{entry["bvid"]}', BiliBiliIE, entry['bvid'])
metadata, paged_list = self._extract_playlist(fetch_page, get_metadata, get_entries)
return self.playlist_result(paged_list, playlist_id)

View File

@@ -11,7 +11,7 @@ from ..utils.traversal import traverse_obj
class CloudyCDNIE(InfoExtractor):
_VALID_URL = r'(?:https?:)?//embed\.cloudycdn\.services/(?P<site_id>[^/?#]+)/media/(?P<id>[\w-]+)'
_VALID_URL = r'(?:https?:)?//embed\.(?P<domain>cloudycdn\.services|backscreen\.com)/(?P<site_id>[^/?#]+)/media/(?P<id>[\w-]+)'
_EMBED_REGEX = [rf'<iframe[^>]+\bsrc=[\'"](?P<url>{_VALID_URL})']
_TESTS = [{
'url': 'https://embed.cloudycdn.services/ltv/media/46k_d23-6000-105?',
@@ -23,7 +23,7 @@ class CloudyCDNIE(InfoExtractor):
'duration': 1442,
'upload_date': '20231121',
'title': 'D23-6000-105_cetstud',
'thumbnail': 'https://store.cloudycdn.services/tmsp00060/assets/media/660858/placeholder1700589200.jpg',
'thumbnail': 'https://store.bstrm.net/tmsp00060/assets/media/660858/placeholder1700589200.jpg',
},
}, {
'url': 'https://embed.cloudycdn.services/izm/media/26e_lv-8-5-1',
@@ -33,7 +33,7 @@ class CloudyCDNIE(InfoExtractor):
'ext': 'mp4',
'title': 'LV-8-5-1',
'timestamp': 1669767167,
'thumbnail': 'https://store.cloudycdn.services/tmsp00120/assets/media/488306/placeholder1679423604.jpg',
'thumbnail': 'https://store.bstrm.net/tmsp00120/assets/media/488306/placeholder1679423604.jpg',
'duration': 1205,
'upload_date': '20221130',
},
@@ -48,9 +48,21 @@ class CloudyCDNIE(InfoExtractor):
'duration': 1673,
'title': 'D24-6000-074-cetstud',
'timestamp': 1718902233,
'thumbnail': 'https://store.cloudycdn.services/tmsp00060/assets/media/788392/placeholder1718903938.jpg',
'thumbnail': 'https://store.bstrm.net/tmsp00060/assets/media/788392/placeholder1718903938.jpg',
},
'params': {'format': 'bv'},
}, {
'url': 'https://embed.backscreen.com/ltv/media/32j_z25-0600-127?',
'md5': '9b6fa09ac1a4de53d4f42b94affc3b42',
'info_dict': {
'id': '32j_z25-0600-127',
'ext': 'mp4',
'title': 'Z25-0600-127-DZ',
'duration': 1906,
'thumbnail': 'https://store.bstrm.net/tmsp00060/assets/media/977427/placeholder1746633646.jpg',
'timestamp': 1746632402,
'upload_date': '20250507',
},
}]
_WEBPAGE_TESTS = [{
'url': 'https://www.tavaklase.lv/video/es-esmu-mina-um-2/',
@@ -60,17 +72,17 @@ class CloudyCDNIE(InfoExtractor):
'ext': 'mp4',
'upload_date': '20230223',
'duration': 629,
'thumbnail': 'https://store.cloudycdn.services/tmsp00120/assets/media/518407/placeholder1678748124.jpg',
'thumbnail': 'https://store.bstrm.net/tmsp00120/assets/media/518407/placeholder1678748124.jpg',
'timestamp': 1677181513,
'title': 'LIB-2',
},
}]
def _real_extract(self, url):
site_id, video_id = self._match_valid_url(url).group('site_id', 'id')
domain, site_id, video_id = self._match_valid_url(url).group('domain', 'site_id', 'id')
data = self._download_json(
f'https://player.cloudycdn.services/player/{site_id}/media/{video_id}/',
f'https://player.{domain}/player/{site_id}/media/{video_id}/',
video_id, data=urlencode_postdata({
'version': '6.4.0',
'referer': url,

View File

@@ -263,6 +263,9 @@ class InfoExtractor:
* http_chunk_size Chunk size for HTTP downloads
* ffmpeg_args Extra arguments for ffmpeg downloader (input)
* ffmpeg_args_out Extra arguments for ffmpeg downloader (output)
* ws (NiconicoLiveFD only) WebSocketResponse
* ws_url (NiconicoLiveFD only) Websockets URL
* max_quality (NiconicoLiveFD only) Max stream quality string
* is_dash_periods Whether the format is a result of merging
multiple DASH periods.
RTMP formats can also have the additional fields: page_url,

View File

@@ -7,12 +7,13 @@ import urllib.parse
from .common import InfoExtractor
from ..utils import (
ExtractorError,
clean_html,
int_or_none,
parse_duration,
str_or_none,
try_get,
unescapeHTML,
unified_strdate,
update_url,
update_url_query,
url_or_none,
)
@@ -22,8 +23,8 @@ from ..utils.traversal import traverse_obj
class HuyaLiveIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.|m\.)?huya\.com/(?!(?:video/play/))(?P<id>[^/#?&]+)(?:\D|$)'
IE_NAME = 'huya:live'
IE_DESC = 'huya.com'
TESTS = [{
IE_DESC = '虎牙直播'
_TESTS = [{
'url': 'https://www.huya.com/572329',
'info_dict': {
'id': '572329',
@@ -149,63 +150,94 @@ class HuyaVideoIE(InfoExtractor):
'id': '1002412640',
'ext': 'mp4',
'title': '8月3日',
'thumbnail': r're:https?://.*\.jpg',
'duration': 14,
'categories': ['主机游戏'],
'duration': 14.0,
'uploader': '虎牙-ATS欧卡车队青木',
'uploader_id': '1564376151',
'upload_date': '20240803',
'view_count': int,
'comment_count': int,
'like_count': int,
'thumbnail': r're:https?://.+\.jpg',
'timestamp': 1722675433,
},
},
{
}, {
'url': 'https://www.huya.com/video/play/556054543.html',
'info_dict': {
'id': '556054543',
'ext': 'mp4',
'title': '我不挑事 也不怕事',
'thumbnail': r're:https?://.*\.jpg',
'duration': 1864,
'categories': ['英雄联盟'],
'description': 'md5:58184869687d18ce62dc7b4b2ad21201',
'duration': 1864.0,
'uploader': '卡尔',
'uploader_id': '367138632',
'upload_date': '20210811',
'view_count': int,
'comment_count': int,
'like_count': int,
'tags': 'count:4',
'thumbnail': r're:https?://.+\.jpg',
'timestamp': 1628675950,
},
}, {
# Only m3u8 available
'url': 'https://www.huya.com/video/play/1063345618.html',
'info_dict': {
'id': '1063345618',
'ext': 'mp4',
'title': '峡谷第一中黑铁上钻石顶级教学对抗elo',
'categories': ['英雄联盟'],
'comment_count': int,
'duration': 21603.0,
'like_count': int,
'thumbnail': r're:https?://.+\.jpg',
'timestamp': 1749668803,
'upload_date': '20250611',
'uploader': '北枫CC',
'uploader_id': '2183525275',
'view_count': int,
},
}]
def _real_extract(self, url: str):
video_id = self._match_id(url)
video_data = self._download_json(
'https://liveapi.huya.com/moment/getMomentContent', video_id,
query={'videoId': video_id})['data']['moment']['videoInfo']
moment = self._download_json(
'https://liveapi.huya.com/moment/getMomentContent',
video_id, query={'videoId': video_id})['data']['moment']
formats = []
for definition in traverse_obj(video_data, ('definitions', lambda _, v: url_or_none(v['url']))):
formats.append({
'url': definition['url'],
**traverse_obj(definition, {
'format_id': ('defName', {str}),
'width': ('width', {int_or_none}),
'height': ('height', {int_or_none}),
for definition in traverse_obj(moment, (
'videoInfo', 'definitions', lambda _, v: url_or_none(v['m3u8']),
)):
fmts = self._extract_m3u8_formats(definition['m3u8'], video_id, 'mp4', fatal=False)
for fmt in fmts:
fmt.update(**traverse_obj(definition, {
'filesize': ('size', {int_or_none}),
}),
})
'format_id': ('defName', {str}),
'height': ('height', {int_or_none}),
'quality': ('definition', {int_or_none}),
'width': ('width', {int_or_none}),
}))
formats.extend(fmts)
return {
'id': video_id,
'formats': formats,
**traverse_obj(video_data, {
**traverse_obj(moment, {
'comment_count': ('commentCount', {int_or_none}),
'description': ('content', {clean_html}, filter),
'like_count': ('favorCount', {int_or_none}),
'timestamp': ('cTime', {int_or_none}),
}),
**traverse_obj(moment, ('videoInfo', {
'title': ('videoTitle', {str}),
'thumbnail': ('videoCover', {url_or_none}),
'categories': ('category', {str}, filter, all, filter),
'duration': ('videoDuration', {parse_duration}),
'tags': ('tags', ..., {str}, filter, all, filter),
'thumbnail': (('videoBigCover', 'videoCover'), {url_or_none}, {update_url(query=None)}, any),
'uploader': ('nickName', {str}),
'uploader_id': ('uid', {str_or_none}),
'upload_date': ('videoUploadTime', {unified_strdate}),
'view_count': ('videoPlayNum', {int_or_none}),
'comment_count': ('videoCommentNum', {int_or_none}),
'like_count': ('favorCount', {int_or_none}),
}),
})),
}

View File

@@ -167,11 +167,11 @@ class LSMLTVEmbedIE(InfoExtractor):
'duration': 1442,
'upload_date': '20231121',
'title': 'D23-6000-105_cetstud',
'thumbnail': 'https://store.cloudycdn.services/tmsp00060/assets/media/660858/placeholder1700589200.jpg',
'thumbnail': 'https://store.bstrm.net/tmsp00060/assets/media/660858/placeholder1700589200.jpg',
},
}, {
'url': 'https://ltv.lsm.lv/embed?enablesdkjs=1&c=eyJpdiI6IncwVzZmUFk2MU12enVWK1I3SUcwQ1E9PSIsInZhbHVlIjoid3FhV29vamc3T2sxL1RaRmJ5Rm1GTXozU0o2dVczdUtLK0cwZEZJMDQ2a3ZIRG5DK2pneGlnbktBQy9uazVleHN6VXhxdWIweWNvcHRDSnlISlNYOHlVZ1lpcTUrcWZSTUZPQW14TVdkMW9aOUtRWVNDcFF4eWpHNGcrT0VZbUNFQStKQk91cGpndW9FVjJIa0lpbkh3PT0iLCJtYWMiOiIyZGI1NDJlMWRlM2QyMGNhOGEwYTM2MmNlN2JlOGRhY2QyYjdkMmEzN2RlOTEzYTVkNzI1ODlhZDlhZjU4MjQ2IiwidGFnIjoiIn0=',
'md5': 'a1711e190fe680fdb68fd8413b378e87',
'md5': 'f236cef2fd5953612754e4e66be51e7a',
'info_dict': {
'id': 'wUnFArIPDSY',
'ext': 'mp4',
@@ -198,6 +198,8 @@ class LSMLTVEmbedIE(InfoExtractor):
'uploader_url': 'https://www.youtube.com/@LTV16plus',
'like_count': int,
'description': 'md5:7ff0c42ba971e3c13e4b8a2ff03b70b5',
'media_type': 'livestream',
'timestamp': 1652550741,
},
}]
@@ -208,7 +210,7 @@ class LSMLTVEmbedIE(InfoExtractor):
r'window\.ltvEmbedPayload\s*=', webpage, 'embed json', video_id)
embed_type = traverse_obj(data, ('source', 'name', {str}))
if embed_type == 'telia':
if embed_type in ('backscreen', 'telia'): # 'telia' only for backwards compat
ie_key = 'CloudyCDN'
embed_url = traverse_obj(data, ('source', 'embed_url', {url_or_none}))
elif embed_type == 'youtube':
@@ -226,9 +228,9 @@ class LSMLTVEmbedIE(InfoExtractor):
class LSMReplayIE(InfoExtractor):
_VALID_URL = r'https?://replay\.lsm\.lv/[^/?#]+/(?:ieraksts|statja)/[^/?#]+/(?P<id>\d+)'
_VALID_URL = r'https?://replay\.lsm\.lv/[^/?#]+/(?:skaties/|klausies/)?(?:ieraksts|statja)/[^/?#]+/(?P<id>\d+)'
_TESTS = [{
'url': 'https://replay.lsm.lv/lv/ieraksts/ltv/311130/4-studija-zolitudes-tragedija-un-incupes-stacija',
'url': 'https://replay.lsm.lv/lv/skaties/ieraksts/ltv/311130/4-studija-zolitudes-tragedija-un-incupes-stacija',
'md5': '64f72a360ca530d5ed89c77646c9eee5',
'info_dict': {
'id': '46k_d23-6000-105',
@@ -241,20 +243,23 @@ class LSMReplayIE(InfoExtractor):
'thumbnail': 'https://ltv.lsm.lv/storage/media/8/7/large/5/1f9604e1.jpg',
},
}, {
'url': 'https://replay.lsm.lv/lv/ieraksts/lr/183522/138-nepilniga-kompensejamo-zalu-sistema-pat-menesiem-dzena-pacientus-pa-aptiekam',
'md5': '719b33875cd1429846eeeaeec6df2830',
'url': 'https://replay.lsm.lv/lv/klausies/ieraksts/lr/183522/138-nepilniga-kompensejamo-zalu-sistema-pat-menesiem-dzena-pacientus-pa-aptiekam',
'md5': '84feb80fd7e6ec07744726a9f01cda4d',
'info_dict': {
'id': 'a342781',
'ext': 'mp3',
'id': '183522',
'ext': 'm4a',
'duration': 1823,
'title': '#138 Nepilnīgā kompensējamo zāļu sistēma pat mēnešiem dzenā pacientus pa aptiekām',
'thumbnail': 'https://pic.latvijasradio.lv/public/assets/media/9/d/large_fd4675ac.jpg',
'upload_date': '20231102',
'timestamp': 1698921060,
'timestamp': 1698913860,
'description': 'md5:7bac3b2dd41e44325032943251c357b1',
},
}, {
'url': 'https://replay.lsm.lv/ru/statja/ltv/311130/4-studija-zolitudes-tragedija-un-incupes-stacija',
'url': 'https://replay.lsm.lv/ru/skaties/statja/ltv/355067/v-kengaragse-nacalas-ukladka-relsov',
'only_matching': True,
}, {
'url': 'https://replay.lsm.lv/lv/ieraksts/ltv/311130/4-studija-zolitudes-tragedija-un-incupes-stacija',
'only_matching': True,
}]
@@ -267,12 +272,24 @@ class LSMReplayIE(InfoExtractor):
data = self._search_nuxt_data(
self._fix_nuxt_data(webpage), video_id, context_name='__REPLAY__')
playback_type = data['playback']['type']
if playback_type == 'playable_audio_lr':
playback_data = {
'formats': self._extract_m3u8_formats(data['playback']['service']['hls_url'], video_id),
}
elif playback_type == 'embed':
playback_data = {
'_type': 'url_transparent',
'url': data['playback']['service']['url'],
}
else:
raise ExtractorError(f'Unsupported playback type "{playback_type}"')
return {
'_type': 'url_transparent',
'id': video_id,
**playback_data,
**traverse_obj(data, {
'url': ('playback', 'service', 'url', {url_or_none}),
'title': ('mediaItem', 'title'),
'description': ('mediaItem', ('lead', 'body')),
'duration': ('mediaItem', 'duration', {int_or_none}),

View File

@@ -0,0 +1,107 @@
import re
from .common import InfoExtractor
from ..utils import (
clean_html,
int_or_none,
parse_iso8601,
urljoin,
)
from ..utils.traversal import require, traverse_obj
class MaveIE(InfoExtractor):
_VALID_URL = r'https?://(?P<channel>[\w-]+)\.mave\.digital/(?P<id>ep-\d+)'
_TESTS = [{
'url': 'https://ochenlichnoe.mave.digital/ep-25',
'md5': 'aa3e513ef588b4366df1520657cbc10c',
'info_dict': {
'id': '4035f587-914b-44b6-aa5a-d76685ad9bc2',
'ext': 'mp3',
'display_id': 'ochenlichnoe-ep-25',
'title': 'Между мной и миром: психология самооценки',
'description': 'md5:4b7463baaccb6982f326bce5c700382a',
'uploader': 'Самарский университет',
'channel': 'Очень личное',
'channel_id': 'ochenlichnoe',
'channel_url': 'https://ochenlichnoe.mave.digital/',
'view_count': int,
'like_count': int,
'dislike_count': int,
'duration': 3744,
'thumbnail': r're:https://.+/storage/podcasts/.+\.jpg',
'series': 'Очень личное',
'series_id': '2e0c3749-6df2-4946-82f4-50691419c065',
'season': 'Season 3',
'season_number': 3,
'episode': 'Episode 3',
'episode_number': 3,
'timestamp': 1747817300,
'upload_date': '20250521',
},
}, {
'url': 'https://budem.mave.digital/ep-12',
'md5': 'e1ce2780fcdb6f17821aa3ca3e8c919f',
'info_dict': {
'id': '41898bb5-ff57-4797-9236-37a8e537aa21',
'ext': 'mp3',
'display_id': 'budem-ep-12',
'title': 'Екатерина Михайлова: "Горе от ума" не про женщин написана',
'description': 'md5:fa3bdd59ee829dfaf16e3efcb13f1d19',
'uploader': 'Полина Цветкова+Евгения Акопова',
'channel': 'Все там будем',
'channel_id': 'budem',
'channel_url': 'https://budem.mave.digital/',
'view_count': int,
'like_count': int,
'dislike_count': int,
'age_limit': 18,
'duration': 3664,
'thumbnail': r're:https://.+/storage/podcasts/.+\.jpg',
'series': 'Все там будем',
'series_id': 'fe9347bf-c009-4ebd-87e8-b06f2f324746',
'season': 'Season 2',
'season_number': 2,
'episode': 'Episode 5',
'episode_number': 5,
'timestamp': 1735538400,
'upload_date': '20241230',
},
}]
_API_BASE_URL = 'https://api.mave.digital/'
def _real_extract(self, url):
channel_id, slug = self._match_valid_url(url).group('channel', 'id')
display_id = f'{channel_id}-{slug}'
webpage = self._download_webpage(url, display_id)
data = traverse_obj(
self._search_nuxt_json(webpage, display_id),
('data', lambda _, v: v['activeEpisodeData'], any, {require('podcast data')}))
return {
'display_id': display_id,
'channel_id': channel_id,
'channel_url': f'https://{channel_id}.mave.digital/',
'vcodec': 'none',
'thumbnail': re.sub(r'_\d+(?=\.(?:jpg|png))', '', self._og_search_thumbnail(webpage, default='')) or None,
**traverse_obj(data, ('activeEpisodeData', {
'url': ('audio', {urljoin(self._API_BASE_URL)}),
'id': ('id', {str}),
'title': ('title', {str}),
'description': ('description', {clean_html}),
'duration': ('duration', {int_or_none}),
'season_number': ('season', {int_or_none}),
'episode_number': ('number', {int_or_none}),
'view_count': ('listenings', {int_or_none}),
'like_count': ('reactions', lambda _, v: v['type'] == 'like', 'count', {int_or_none}, any),
'dislike_count': ('reactions', lambda _, v: v['type'] == 'dislike', 'count', {int_or_none}, any),
'age_limit': ('is_explicit', {bool}, {lambda x: 18 if x else None}),
'timestamp': ('publish_date', {parse_iso8601}),
})),
**traverse_obj(data, ('podcast', 'podcast', {
'series_id': ('id', {str}),
'series': ('title', {str}),
'channel': ('title', {str}),
'uploader': ('author', {str}),
})),
}

View File

@@ -4,16 +4,15 @@ import itertools
import json
import re
import time
import urllib.parse
from .common import InfoExtractor, SearchInfoExtractor
from ..networking import Request
from ..networking.exceptions import HTTPError
from ..utils import (
ExtractorError,
OnDemandPagedList,
clean_html,
determine_ext,
extract_attributes,
float_or_none,
int_or_none,
parse_bitrate,
@@ -22,9 +21,8 @@ from ..utils import (
parse_qs,
parse_resolution,
qualities,
remove_start,
str_or_none,
unescapeHTML,
truncate_string,
unified_timestamp,
update_url_query,
url_basename,
@@ -32,7 +30,11 @@ from ..utils import (
urlencode_postdata,
urljoin,
)
from ..utils.traversal import find_element, require, traverse_obj
from ..utils.traversal import (
find_element,
require,
traverse_obj,
)
class NiconicoBaseIE(InfoExtractor):
@@ -806,41 +808,39 @@ class NiconicoLiveIE(NiconicoBaseIE):
def _real_extract(self, url):
video_id = self._match_id(url)
webpage, urlh = self._download_webpage_handle(f'https://live.nicovideo.jp/watch/{video_id}', video_id)
webpage = self._download_webpage(url, video_id, expected_status=404)
if err_msg := traverse_obj(webpage, ({find_element(cls='message')}, {clean_html})):
raise ExtractorError(err_msg, expected=True)
embedded_data = self._parse_json(unescapeHTML(self._search_regex(
r'<script\s+id="embedded-data"\s*data-props="(.+?)"', webpage, 'embedded data')), video_id)
ws_url = traverse_obj(embedded_data, ('site', 'relive', 'webSocketUrl'))
if not ws_url:
raise ExtractorError('The live hasn\'t started yet or already ended.', expected=True)
ws_url = update_url_query(ws_url, {
'frontend_id': traverse_obj(embedded_data, ('site', 'frontendId')) or '9',
})
hostname = remove_start(urllib.parse.urlparse(urlh.url).hostname, 'sp.')
embedded_data = traverse_obj(webpage, (
{find_element(tag='script', id='embedded-data', html=True)},
{extract_attributes}, 'data-props', {json.loads}))
frontend_id = traverse_obj(embedded_data, ('site', 'frontendId', {str_or_none}), default='9')
ws_url = traverse_obj(embedded_data, (
'site', 'relive', 'webSocketUrl', {url_or_none}, {require('websocket URL')}))
ws_url = update_url_query(ws_url, {'frontend_id': frontend_id})
ws = self._request_webpage(
Request(ws_url, headers={'Origin': f'https://{hostname}'}),
video_id=video_id, note='Connecting to WebSocket server')
ws_url, video_id, 'Connecting to WebSocket server',
headers={'Origin': 'https://live.nicovideo.jp'})
self.write_debug('Sending HLS server request')
ws.send(json.dumps({
'type': 'startWatching',
'data': {
'reconnect': False,
'room': {
'commentable': True,
'protocol': 'webSocket',
},
'stream': {
'quality': 'abr',
'protocol': 'hls',
'latency': 'high',
'accessRightMethod': 'single_cookie',
'chasePlay': False,
'latency': 'high',
'protocol': 'hls',
'quality': 'abr',
},
'room': {
'protocol': 'webSocket',
'commentable': True,
},
'reconnect': False,
},
'type': 'startWatching',
}))
while True:
@@ -860,17 +860,15 @@ class NiconicoLiveIE(NiconicoBaseIE):
raise ExtractorError('Disconnected at middle of extraction')
elif data.get('type') == 'error':
self.write_debug(recv)
message = traverse_obj(data, ('body', 'code')) or recv
message = traverse_obj(data, ('body', 'code', {str_or_none}), default=recv)
raise ExtractorError(message)
elif self.get_param('verbose', False):
if len(recv) > 100:
recv = recv[:100] + '...'
self.write_debug(f'Server said: {recv}')
self.write_debug(f'Server response: {truncate_string(recv, 100)}')
title = traverse_obj(embedded_data, ('program', 'title')) or self._html_search_meta(
('og:title', 'twitter:title'), webpage, 'live title', fatal=False)
raw_thumbs = traverse_obj(embedded_data, ('program', 'thumbnail')) or {}
raw_thumbs = traverse_obj(embedded_data, ('program', 'thumbnail', {dict})) or {}
thumbnails = []
for name, value in raw_thumbs.items():
if not isinstance(value, dict):
@@ -897,31 +895,30 @@ class NiconicoLiveIE(NiconicoBaseIE):
cookie['domain'], cookie['name'], cookie['value'],
expire_time=unified_timestamp(cookie.get('expires')), path=cookie['path'], secure=cookie['secure'])
fmt_common = {
'live_latency': 'high',
'origin': hostname,
'protocol': 'niconico_live',
'video_id': video_id,
'ws': ws,
}
q_iter = (q for q in qualities[1:] if not q.startswith('audio_')) # ignore initial 'abr'
a_map = {96: 'audio_low', 192: 'audio_high'}
formats = self._extract_m3u8_formats(m3u8_url, video_id, ext='mp4', live=True)
for fmt in formats:
fmt['protocol'] = 'niconico_live'
if fmt.get('acodec') == 'none':
fmt['format_id'] = next(q_iter, fmt['format_id'])
elif fmt.get('vcodec') == 'none':
abr = parse_bitrate(fmt['url'].lower())
fmt.update({
'abr': abr,
'acodec': 'mp4a.40.2',
'format_id': a_map.get(abr, fmt['format_id']),
})
fmt.update(fmt_common)
return {
'id': video_id,
'title': title,
'downloader_options': {
'max_quality': traverse_obj(embedded_data, ('program', 'stream', 'maxQuality', {str})) or 'normal',
'ws': ws,
'ws_url': ws_url,
},
**traverse_obj(embedded_data, {
'view_count': ('program', 'statistics', 'watchCount'),
'comment_count': ('program', 'statistics', 'commentCount'),

View File

@@ -213,7 +213,7 @@ class CieloTVItIE(SkyItIE): # XXX: Do not subclass from concrete IE
class TV8ItIE(SkyItVideoIE): # XXX: Do not subclass from concrete IE
IE_NAME = 'tv8.it'
_VALID_URL = r'https?://(?:www\.)?tv8\.it/(?:show)?video/[0-9a-z-]+-(?P<id>\d+)'
_VALID_URL = r'https?://(?:www\.)?tv8\.it/(?:show)?video/(?:[0-9a-z-]+-)?(?P<id>\d+)'
_TESTS = [{
'url': 'https://www.tv8.it/video/ogni-mattina-ucciso-asino-di-andrea-lo-cicero-630529',
'md5': '9ab906a3f75ea342ed928442f9dabd21',
@@ -227,6 +227,19 @@ class TV8ItIE(SkyItVideoIE): # XXX: Do not subclass from concrete IE
'thumbnail': 'https://videoplatform.sky.it/still/2020/11/18/1605717753954_ogni-mattina-ucciso-asino-di-andrea-lo-cicero_videostill_1.jpg',
},
'params': {'skip_download': 'm3u8'},
}, {
'url': 'https://www.tv8.it/video/964361',
'md5': '1e58e807154658a16edc29e45be38107',
'info_dict': {
'id': '964361',
'ext': 'mp4',
'title': 'GialappaShow - S.4 Ep.2',
'description': 'md5:60bb4ff5af18bbeeaedabc1de5f9e1e2',
'duration': 8030,
'thumbnail': 'https://videoplatform.sky.it/captures/494/2024/11/06/964361/964361_1730888412914_thumb_494.jpg',
'timestamp': 1730821499,
'upload_date': '20241105',
},
}]
_DOMAIN = 'mtv8'

View File

@@ -25,6 +25,7 @@ class SportDeutschlandIE(InfoExtractor):
'upload_date': '20230114',
'timestamp': 1673733618,
},
'skip': 'not found',
}, {
'url': 'https://sportdeutschland.tv/deutscherbadmintonverband/bwf-tour-1-runde-feld-1-yonex-gainward-german-open-2022-0',
'info_dict': {
@@ -41,6 +42,7 @@ class SportDeutschlandIE(InfoExtractor):
'upload_date': '20220309',
'timestamp': 1646860727.0,
},
'skip': 'not found',
}, {
'url': 'https://sportdeutschland.tv/ggcbremen/formationswochenende-latein-2023',
'info_dict': {
@@ -68,6 +70,7 @@ class SportDeutschlandIE(InfoExtractor):
'live_status': 'was_live',
},
}],
'skip': 'not found',
}, {
'url': 'https://sportdeutschland.tv/dtb/gymnastik-international-tag-1',
'info_dict': {
@@ -82,13 +85,30 @@ class SportDeutschlandIE(InfoExtractor):
'live_status': 'is_live',
},
'skip': 'live',
}, {
'url': 'https://sportdeutschland.tv/rostock-griffins/gfl2-rostock-griffins-vs-elmshorn-fighting-pirates',
'md5': '35c11a19395c938cdd076b93bda54cde',
'info_dict': {
'id': '9f27a97d-1544-4d0b-aa03-48d92d17a03a',
'ext': 'mp4',
'title': 'GFL2: Rostock Griffins vs. Elmshorn Fighting Pirates',
'display_id': 'rostock-griffins/gfl2-rostock-griffins-vs-elmshorn-fighting-pirates',
'channel': 'Rostock Griffins',
'channel_url': 'https://sportdeutschland.tv/rostock-griffins',
'live_status': 'was_live',
'description': 'md5:60cb00067e55dafa27b0933a43d72862',
'channel_id': '9635f21c-3f67-4584-9ce4-796e9a47276b',
'timestamp': 1749913117,
'upload_date': '20250614',
},
}]
def _process_video(self, asset_id, video):
is_live = video['type'] == 'mux_live'
token = self._download_json(
f'https://api.sportdeutschland.tv/api/frontend/asset-token/{asset_id}',
video['id'], query={'type': video['type'], 'playback_id': video['src']})['token']
f'https://api.sportdeutschland.tv/api/web/personal/asset-token/{asset_id}',
video['id'], query={'type': video['type'], 'playback_id': video['src']},
headers={'Referer': 'https://sportdeutschland.tv/'})['token']
formats, subtitles = self._extract_m3u8_formats_and_subtitles(
f'https://stream.mux.com/{video["src"]}.m3u8?token={token}', video['id'], live=is_live)

View File

@@ -41,6 +41,7 @@ class SproutVideoIE(InfoExtractor):
'duration': 703,
'thumbnail': r're:https?://images\.sproutvideo\.com/.+\.jpg',
},
'skip': 'Account Disabled',
}, {
# http formats 'sd' and 'hd' are available
'url': 'https://videos.sproutvideo.com/embed/119cd6bc1a18e6cd98/30751a1761ae5b90',
@@ -97,11 +98,21 @@ class SproutVideoIE(InfoExtractor):
def _real_extract(self, url):
url, smuggled_data = unsmuggle_url(url, {})
video_id = self._match_id(url)
webpage = self._download_webpage(
url, video_id, headers=traverse_obj(smuggled_data, {'Referer': 'referer'}))
webpage = self._download_webpage(url, video_id, headers={
**traverse_obj(smuggled_data, {'Referer': 'referer'}),
# yt-dlp's default Chrome user-agents are too old
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; rv:140.0) Gecko/20100101 Firefox/140.0',
})
data = self._search_json(
r'var\s+dat\s*=\s*["\']', webpage, 'data', video_id, contains_pattern=r'[A-Za-z0-9+/=]+',
end_pattern=r'["\'];', transform_source=lambda x: base64.b64decode(x).decode())
r'var\s+(?:dat|playerInfo)\s*=\s*["\']', webpage, 'player info', video_id,
contains_pattern=r'[A-Za-z0-9+/=]+', end_pattern=r'["\'];',
transform_source=lambda x: base64.b64decode(x).decode())
# SproutVideo may send player info for 'SMPTE Color Monitor Test' [a791d7b71b12ecc52e]
# e.g. if the user-agent we used with the webpage request is too old
video_uid = data['videoUid']
if video_id != video_uid:
raise ExtractorError(f'{self.IE_NAME} sent the wrong video data ({video_uid})')
formats, subtitles = [], {}
headers = {

View File

@@ -1,8 +1,8 @@
# Autogenerated by devscripts/update-version.py
__version__ = '2025.06.09'
__version__ = '2025.06.25'
RELEASE_GIT_HEAD = '339614a173c74b42d63e858c446a9cae262a13af'
RELEASE_GIT_HEAD = '1838a1ce5d4ade80770ba9162eaffc9a1607dc70'
VARIANT = None
@@ -12,4 +12,4 @@ CHANNEL = 'stable'
ORIGIN = 'yt-dlp/yt-dlp'
_pkg_version = '2025.06.09'
_pkg_version = '2025.06.25'