Update On Wed Jul 30 20:44:11 CEST 2025

This commit is contained in:
github-action[bot]
2025-07-30 20:44:11 +02:00
parent 7cc11da0e8
commit f4a75f30e8
33 changed files with 419 additions and 237 deletions

1
.github/update.log vendored
View File

@@ -1074,3 +1074,4 @@ Update On Sat Jul 26 20:38:09 CEST 2025
Update On Sun Jul 27 20:38:58 CEST 2025 Update On Sun Jul 27 20:38:58 CEST 2025
Update On Mon Jul 28 20:43:06 CEST 2025 Update On Mon Jul 28 20:43:06 CEST 2025
Update On Tue Jul 29 20:43:03 CEST 2025 Update On Tue Jul 29 20:43:03 CEST 2025
Update On Wed Jul 30 20:44:03 CEST 2025

View File

@@ -33,6 +33,11 @@ const (
MaxPackageFileSize = 32 * 1024 * 1024 MaxPackageFileSize = 32 * 1024 * 1024
) )
const (
ReleaseChannel = "release"
AlphaChannel = "alpha"
)
// CoreUpdater is the mihomo updater. // CoreUpdater is the mihomo updater.
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go // modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go
type CoreUpdater struct { type CoreUpdater struct {
@@ -69,20 +74,28 @@ func (u *CoreUpdater) CoreBaseName() string {
} }
} }
func (u *CoreUpdater) Update(currentExePath string) (err error) { func (u *CoreUpdater) Update(currentExePath string, channel string, force bool) (err error) {
u.mu.Lock() u.mu.Lock()
defer u.mu.Unlock() defer u.mu.Unlock()
_, err = os.Stat(currentExePath) info, err := os.Stat(currentExePath)
if err != nil { if err != nil {
return fmt.Errorf("check currentExePath %q: %w", currentExePath, err) return fmt.Errorf("check currentExePath %q: %w", currentExePath, err)
} }
baseURL := baseAlphaURL baseURL := baseAlphaURL
versionURL := versionAlphaURL versionURL := versionAlphaURL
if !strings.HasPrefix(C.Version, "alpha") { switch strings.ToLower(channel) {
case ReleaseChannel:
baseURL = baseReleaseURL baseURL = baseReleaseURL
versionURL = versionReleaseURL versionURL = versionReleaseURL
case AlphaChannel:
break
default: // auto
if !strings.HasPrefix(C.Version, "alpha") {
baseURL = baseReleaseURL
versionURL = versionReleaseURL
}
} }
latestVersion, err := u.getLatestVersion(versionURL) latestVersion, err := u.getLatestVersion(versionURL)
@@ -91,7 +104,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) {
} }
log.Infoln("current version %s, latest version %s", C.Version, latestVersion) log.Infoln("current version %s, latest version %s", C.Version, latestVersion)
if latestVersion == C.Version { if latestVersion == C.Version && !force {
// don't change this output, some downstream dependencies on the upgrader's output fields // don't change this output, some downstream dependencies on the upgrader's output fields
return fmt.Errorf("update error: already using latest version %s", C.Version) return fmt.Errorf("update error: already using latest version %s", C.Version)
} }
@@ -136,7 +149,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) {
return fmt.Errorf("downloading: %w", err) return fmt.Errorf("downloading: %w", err)
} }
err = u.unpack(updateDir, packagePath) err = u.unpack(updateDir, packagePath, info.Mode())
if err != nil { if err != nil {
return fmt.Errorf("unpacking: %w", err) return fmt.Errorf("unpacking: %w", err)
} }
@@ -230,16 +243,16 @@ func (u *CoreUpdater) download(updateDir, packagePath, packageURL string) (err e
} }
// unpack extracts the files from the downloaded archive. // unpack extracts the files from the downloaded archive.
func (u *CoreUpdater) unpack(updateDir, packagePath string) error { func (u *CoreUpdater) unpack(updateDir, packagePath string, fileMode os.FileMode) error {
log.Infoln("updater: unpacking package") log.Infoln("updater: unpacking package")
if strings.HasSuffix(packagePath, ".zip") { if strings.HasSuffix(packagePath, ".zip") {
_, err := u.zipFileUnpack(packagePath, updateDir) _, err := u.zipFileUnpack(packagePath, updateDir, fileMode)
if err != nil { if err != nil {
return fmt.Errorf(".zip unpack failed: %w", err) return fmt.Errorf(".zip unpack failed: %w", err)
} }
} else if strings.HasSuffix(packagePath, ".gz") { } else if strings.HasSuffix(packagePath, ".gz") {
_, err := u.gzFileUnpack(packagePath, updateDir) _, err := u.gzFileUnpack(packagePath, updateDir, fileMode)
if err != nil { if err != nil {
return fmt.Errorf(".gz unpack failed: %w", err) return fmt.Errorf(".gz unpack failed: %w", err)
} }
@@ -295,7 +308,7 @@ func (u *CoreUpdater) clean(updateDir string) {
// Existing files are overwritten // Existing files are overwritten
// All files are created inside outDir, subdirectories are not created // All files are created inside outDir, subdirectories are not created
// Return the output file name // Return the output file name
func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, err error) { func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string, fileMode os.FileMode) (outputName string, err error) {
f, err := os.Open(gzfile) f, err := os.Open(gzfile)
if err != nil { if err != nil {
return "", fmt.Errorf("os.Open(): %w", err) return "", fmt.Errorf("os.Open(): %w", err)
@@ -330,7 +343,7 @@ func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, er
outputName = filepath.Join(outDir, originalName) outputName = filepath.Join(outDir, originalName)
// Create the output file // Create the output file
wc, err := os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755) wc, err := os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileMode)
if err != nil { if err != nil {
return "", fmt.Errorf("os.OpenFile(%s): %w", outputName, err) return "", fmt.Errorf("os.OpenFile(%s): %w", outputName, err)
} }
@@ -355,7 +368,7 @@ func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, er
// Existing files are overwritten // Existing files are overwritten
// All files are created inside 'outDir', subdirectories are not created // All files are created inside 'outDir', subdirectories are not created
// Return the output file name // Return the output file name
func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string) (outputName string, err error) { func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string, fileMode os.FileMode) (outputName string, err error) {
zrc, err := zip.OpenReader(zipfile) zrc, err := zip.OpenReader(zipfile)
if err != nil { if err != nil {
return "", fmt.Errorf("zip.OpenReader(): %w", err) return "", fmt.Errorf("zip.OpenReader(): %w", err)
@@ -394,7 +407,7 @@ func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string) (outputName string,
} }
var wc io.WriteCloser var wc io.WriteCloser
wc, err = os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fi.Mode()) wc, err = os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileMode)
if err != nil { if err != nil {
return "", fmt.Errorf("os.OpenFile(): %w", err) return "", fmt.Errorf("os.OpenFile(): %w", err)
} }

View File

@@ -22,7 +22,7 @@ require (
github.com/metacubex/chacha v0.1.5 github.com/metacubex/chacha v0.1.5
github.com/metacubex/fswatch v0.1.1 github.com/metacubex/fswatch v0.1.1
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295
github.com/metacubex/randv2 v0.2.0 github.com/metacubex/randv2 v0.2.0
github.com/metacubex/sing v0.5.4 github.com/metacubex/sing v0.5.4
github.com/metacubex/sing-mux v0.3.2 github.com/metacubex/sing-mux v0.3.2

View File

@@ -112,8 +112,8 @@ github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA=
github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c h1:ABQzmOaZddM3q0OYeoZEc0XF+KW+dUdPNvY/c5rsunI= github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs=
github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c/go.mod h1:eWlAK3zsKI0P8UhYpXlIsl3mtW4D6MpMNuYLIu8CKWI= github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=

View File

@@ -32,7 +32,11 @@ func upgradeCore(w http.ResponseWriter, r *http.Request) {
return return
} }
err = updater.DefaultCoreUpdater.Update(execPath) query := r.URL.Query()
channel := query.Get("channel")
force := query.Get("force") == "true"
err = updater.DefaultCoreUpdater.Update(execPath, channel, force)
if err != nil { if err != nil {
log.Warnln("%s", err) log.Warnln("%s", err)
render.Status(r, http.StatusInternalServerError) render.Status(r, http.StatusInternalServerError)

View File

@@ -31,7 +31,7 @@
"country-code-emoji": "2.3.0", "country-code-emoji": "2.3.0",
"country-emoji": "1.5.6", "country-emoji": "1.5.6",
"dayjs": "1.11.13", "dayjs": "1.11.13",
"framer-motion": "12.23.11", "framer-motion": "12.23.12",
"i18next": "25.3.2", "i18next": "25.3.2",
"jotai": "2.12.5", "jotai": "2.12.5",
"json-schema": "0.4.0", "json-schema": "0.4.0",
@@ -56,12 +56,12 @@
"@csstools/normalize.css": "12.1.1", "@csstools/normalize.css": "12.1.1",
"@emotion/babel-plugin": "11.13.5", "@emotion/babel-plugin": "11.13.5",
"@emotion/react": "11.14.0", "@emotion/react": "11.14.0",
"@iconify/json": "2.2.363", "@iconify/json": "2.2.364",
"@monaco-editor/react": "4.7.0", "@monaco-editor/react": "4.7.0",
"@tanstack/react-query": "5.83.0", "@tanstack/react-query": "5.83.0",
"@tanstack/react-router": "1.130.2", "@tanstack/react-router": "1.130.8",
"@tanstack/react-router-devtools": "1.130.2", "@tanstack/react-router-devtools": "1.130.8",
"@tanstack/router-plugin": "1.130.2", "@tanstack/router-plugin": "1.130.8",
"@tauri-apps/plugin-clipboard-manager": "2.3.0", "@tauri-apps/plugin-clipboard-manager": "2.3.0",
"@tauri-apps/plugin-dialog": "2.3.0", "@tauri-apps/plugin-dialog": "2.3.0",
"@tauri-apps/plugin-fs": "2.4.0", "@tauri-apps/plugin-fs": "2.4.0",

View File

@@ -23,7 +23,7 @@
"@vitejs/plugin-react": "4.7.0", "@vitejs/plugin-react": "4.7.0",
"ahooks": "3.9.0", "ahooks": "3.9.0",
"d3": "7.9.0", "d3": "7.9.0",
"framer-motion": "12.23.11", "framer-motion": "12.23.12",
"react": "19.1.1", "react": "19.1.1",
"react-dom": "19.1.1", "react-dom": "19.1.1",
"react-error-boundary": "6.0.0", "react-error-boundary": "6.0.0",

View File

@@ -5,7 +5,7 @@
"mihomo_alpha": "alpha-0f1baeb", "mihomo_alpha": "alpha-0f1baeb",
"clash_rs": "v0.8.1", "clash_rs": "v0.8.1",
"clash_premium": "2023-09-05-gdcc8d87", "clash_premium": "2023-09-05-gdcc8d87",
"clash_rs_alpha": "0.8.1-alpha+sha.a70dccc" "clash_rs_alpha": "0.8.1-alpha+sha.b628d65"
}, },
"arch_template": { "arch_template": {
"mihomo": { "mihomo": {
@@ -69,5 +69,5 @@
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
} }
}, },
"updated_at": "2025-07-28T22:21:35.653Z" "updated_at": "2025-07-29T22:21:38.343Z"
} }

View File

@@ -97,7 +97,7 @@
"prettier-plugin-tailwindcss": "0.6.14", "prettier-plugin-tailwindcss": "0.6.14",
"prettier-plugin-toml": "2.0.6", "prettier-plugin-toml": "2.0.6",
"react-devtools": "6.1.5", "react-devtools": "6.1.5",
"stylelint": "16.22.0", "stylelint": "16.23.0",
"stylelint-config-html": "1.1.0", "stylelint-config-html": "1.1.0",
"stylelint-config-recess-order": "7.1.0", "stylelint-config-recess-order": "7.1.0",
"stylelint-config-standard": "38.0.0", "stylelint-config-standard": "38.0.0",

View File

@@ -140,26 +140,26 @@ importers:
specifier: 6.1.5 specifier: 6.1.5
version: 6.1.5(bufferutil@4.0.8)(utf-8-validate@5.0.10) version: 6.1.5(bufferutil@4.0.8)(utf-8-validate@5.0.10)
stylelint: stylelint:
specifier: 16.22.0 specifier: 16.23.0
version: 16.22.0(typescript@5.8.3) version: 16.23.0(typescript@5.8.3)
stylelint-config-html: stylelint-config-html:
specifier: 1.1.0 specifier: 1.1.0
version: 1.1.0(postcss-html@1.8.0)(stylelint@16.22.0(typescript@5.8.3)) version: 1.1.0(postcss-html@1.8.0)(stylelint@16.23.0(typescript@5.8.3))
stylelint-config-recess-order: stylelint-config-recess-order:
specifier: 7.1.0 specifier: 7.1.0
version: 7.1.0(stylelint-order@7.0.0(stylelint@16.22.0(typescript@5.8.3)))(stylelint@16.22.0(typescript@5.8.3)) version: 7.1.0(stylelint-order@7.0.0(stylelint@16.23.0(typescript@5.8.3)))(stylelint@16.23.0(typescript@5.8.3))
stylelint-config-standard: stylelint-config-standard:
specifier: 38.0.0 specifier: 38.0.0
version: 38.0.0(stylelint@16.22.0(typescript@5.8.3)) version: 38.0.0(stylelint@16.23.0(typescript@5.8.3))
stylelint-declaration-block-no-ignored-properties: stylelint-declaration-block-no-ignored-properties:
specifier: 2.8.0 specifier: 2.8.0
version: 2.8.0(stylelint@16.22.0(typescript@5.8.3)) version: 2.8.0(stylelint@16.23.0(typescript@5.8.3))
stylelint-order: stylelint-order:
specifier: 7.0.0 specifier: 7.0.0
version: 7.0.0(stylelint@16.22.0(typescript@5.8.3)) version: 7.0.0(stylelint@16.23.0(typescript@5.8.3))
stylelint-scss: stylelint-scss:
specifier: 6.12.1 specifier: 6.12.1
version: 6.12.1(stylelint@16.22.0(typescript@5.8.3)) version: 6.12.1(stylelint@16.23.0(typescript@5.8.3))
tailwindcss: tailwindcss:
specifier: 4.1.11 specifier: 4.1.11
version: 4.1.11 version: 4.1.11
@@ -250,7 +250,7 @@ importers:
version: 4.1.11 version: 4.1.11
'@tanstack/router-zod-adapter': '@tanstack/router-zod-adapter':
specifier: 1.81.5 specifier: 1.81.5
version: 1.81.5(@tanstack/react-router@1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.13) version: 1.81.5(@tanstack/react-router@1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.13)
'@tauri-apps/api': '@tauri-apps/api':
specifier: 2.6.0 specifier: 2.6.0
version: 2.6.0 version: 2.6.0
@@ -273,8 +273,8 @@ importers:
specifier: 1.11.13 specifier: 1.11.13
version: 1.11.13 version: 1.11.13
framer-motion: framer-motion:
specifier: 12.23.11 specifier: 12.23.12
version: 12.23.11(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) version: 12.23.12(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
i18next: i18next:
specifier: 25.3.2 specifier: 25.3.2
version: 25.3.2(typescript@5.8.3) version: 25.3.2(typescript@5.8.3)
@@ -343,8 +343,8 @@ importers:
specifier: 11.14.0 specifier: 11.14.0
version: 11.14.0(@types/react@19.1.8)(react@19.1.1) version: 11.14.0(@types/react@19.1.8)(react@19.1.1)
'@iconify/json': '@iconify/json':
specifier: 2.2.363 specifier: 2.2.364
version: 2.2.363 version: 2.2.364
'@monaco-editor/react': '@monaco-editor/react':
specifier: 4.7.0 specifier: 4.7.0
version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@@ -352,14 +352,14 @@ importers:
specifier: 5.83.0 specifier: 5.83.0
version: 5.83.0(react@19.1.1) version: 5.83.0(react@19.1.1)
'@tanstack/react-router': '@tanstack/react-router':
specifier: 1.130.2 specifier: 1.130.8
version: 1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) version: 1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tanstack/react-router-devtools': '@tanstack/react-router-devtools':
specifier: 1.130.2 specifier: 1.130.8
version: 1.130.2(@tanstack/react-router@1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.130.2)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3) version: 1.130.8(@tanstack/react-router@1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.130.8)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)
'@tanstack/router-plugin': '@tanstack/router-plugin':
specifier: 1.130.2 specifier: 1.130.8
version: 1.130.2(@tanstack/react-router@1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.0.6(@types/node@22.16.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.89.2)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.0)) version: 1.130.8(@tanstack/react-router@1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.0.6(@types/node@22.16.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.89.2)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.0))
'@tauri-apps/plugin-clipboard-manager': '@tauri-apps/plugin-clipboard-manager':
specifier: 2.3.0 specifier: 2.3.0
version: 2.3.0 version: 2.3.0
@@ -496,8 +496,8 @@ importers:
specifier: 7.9.0 specifier: 7.9.0
version: 7.9.0 version: 7.9.0
framer-motion: framer-motion:
specifier: 12.23.11 specifier: 12.23.12
version: 12.23.11(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1) version: 12.23.12(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react: react:
specifier: 19.1.1 specifier: 19.1.1
version: 19.1.1 version: 19.1.1
@@ -1749,8 +1749,8 @@ packages:
'@vue/compiler-sfc': '@vue/compiler-sfc':
optional: true optional: true
'@iconify/json@2.2.363': '@iconify/json@2.2.364':
resolution: {integrity: sha512-iSNBti18BhOizJSZCQr/1Mqp9kyqncQfSUElkScsQ0KyLNU2XUNuQ93JAMYtqJbtqtdjjWKidCJu9yfksIQmxA==} resolution: {integrity: sha512-+ekQRRGXObKZ4JK+GszoxWn6jSo9ItRNrIBXdfO+e3ySqZIDkNS7AVHuQ8+2ta8WlgBliU9Vth1aFAa0iSvB1w==}
'@iconify/types@2.0.0': '@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
@@ -1785,8 +1785,8 @@ packages:
'@juggle/resize-observer@3.4.0': '@juggle/resize-observer@3.4.0':
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
'@keyv/serialize@1.0.3': '@keyv/serialize@1.1.0':
resolution: {integrity: sha512-qnEovoOp5Np2JDGonIDL6Ayihw0RhnRh6vxPuHo4RDn1UOzwEo4AeIfpL6UGIrsceWrCMiVPgwRjbHu4vYFc3g==} resolution: {integrity: sha512-RlDgexML7Z63Q8BSaqhXdCYNBy/JQnqYIwxofUrNLGCblOMHp+xux2Q8nLMLlPpgHQPoU0Do8Z6btCpRBEqZ8g==}
'@material/material-color-utilities@0.3.0': '@material/material-color-utilities@0.3.0':
resolution: {integrity: sha512-ztmtTd6xwnuh2/xu+Vb01btgV8SQWYCaK56CkRK8gEkWe5TuDyBcYJ0wgkMRn+2VcE9KUmhvkz+N9GHrqw/C0g==} resolution: {integrity: sha512-ztmtTd6xwnuh2/xu+Vb01btgV8SQWYCaK56CkRK8gEkWe5TuDyBcYJ0wgkMRn+2VcE9KUmhvkz+N9GHrqw/C0g==}
@@ -2993,16 +2993,16 @@ packages:
peerDependencies: peerDependencies:
react: ^18 || ^19 react: ^18 || ^19
'@tanstack/react-router-devtools@1.130.2': '@tanstack/react-router-devtools@1.130.8':
resolution: {integrity: sha512-GjtTcZBYSHLfL42dw3bOgAJ0u0NPABvUBIoeh7bue9SrlCdj6KArVT1215yXRWSsJZEEfhmnLf0EjzjB3rcBvg==} resolution: {integrity: sha512-tJ9A7fBJNaoaWzg8pAxelYDTd+JA7q0XyLvTGBEWv9xnK1Xke8APlCupBIVHqJ/sq7xaSJXTxEs9HxM+njwOhQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
peerDependencies: peerDependencies:
'@tanstack/react-router': ^1.130.2 '@tanstack/react-router': ^1.130.8
react: '>=18.0.0 || >=19.0.0' react: '>=18.0.0 || >=19.0.0'
react-dom: '>=18.0.0 || >=19.0.0' react-dom: '>=18.0.0 || >=19.0.0'
'@tanstack/react-router@1.130.2': '@tanstack/react-router@1.130.8':
resolution: {integrity: sha512-gDWChae5jszlBs/IYSZ46QS85iyfDrfukalV5hU2tU52Q7a3IAtr7SPSIVkClZsU4JT4GwZ35NcGHzDQ/8NQzA==} resolution: {integrity: sha512-ZLM609RhmvKO1jWwssG3f/b0AAnsESNshVqYF3aNshjbkGnIkdG4+qi3rhORNcQvl3e6cX0u0SQfCndooexgKw==}
engines: {node: '>=12'} engines: {node: '>=12'}
peerDependencies: peerDependencies:
react: '>=18.0.0 || >=19.0.0' react: '>=18.0.0 || >=19.0.0'
@@ -3027,15 +3027,15 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
'@tanstack/router-core@1.130.2': '@tanstack/router-core@1.130.8':
resolution: {integrity: sha512-d5hYEEAvNUImpoomTlP2tRelX4JiNx3g2uk6xAO/aPKuMYdfntBSV7xbKuWZEhSwqeN2Z4qD3YyQEXBa4Fu7Mg==} resolution: {integrity: sha512-R/hbOAVeuRpU5/NNX2i8cDXZIjNUFThEkPQKw3JCr+OWYXKFJ2KBaaUkuGx7V83075mezsQZ9TTPDSaurTbj3w==}
engines: {node: '>=12'} engines: {node: '>=12'}
'@tanstack/router-devtools-core@1.130.2': '@tanstack/router-devtools-core@1.130.8':
resolution: {integrity: sha512-RuTBG2KmFSSuSebuuvskGTVaFWrRHM/jSSbtjxytWAJgU4XFnjXWI5axLPpooc+UbpkD9cLPTFZ9OVXmlWntcQ==} resolution: {integrity: sha512-pVHUrB6Io5kAdW6kzbP79gzwLl2Pqyu47KWVgdcQDK6DcbNnjcowhY1ud9ilPfoPA7CLnVau+NMbjIccio5OQA==}
engines: {node: '>=12'} engines: {node: '>=12'}
peerDependencies: peerDependencies:
'@tanstack/router-core': ^1.130.2 '@tanstack/router-core': ^1.130.8
csstype: ^3.0.10 csstype: ^3.0.10
solid-js: '>=1.9.5' solid-js: '>=1.9.5'
tiny-invariant: ^1.3.3 tiny-invariant: ^1.3.3
@@ -3043,16 +3043,16 @@ packages:
csstype: csstype:
optional: true optional: true
'@tanstack/router-generator@1.130.2': '@tanstack/router-generator@1.130.8':
resolution: {integrity: sha512-MBvlPwMhgC07f4xBGVpx7bMvzi7KLUhKN4muRpdYozTqC+UditVJi9zNEktNKzUVngTwGgti5LC7k4J7zRT40w==} resolution: {integrity: sha512-Kb1Ga+VfXMQml8404G2HXlzJ+6es3ClO81k0CevWw9kdeHqpGXe6oEK7Otpz6w2IWjWtDT9gCFa5dKifrunN/g==}
engines: {node: '>=12'} engines: {node: '>=12'}
'@tanstack/router-plugin@1.130.2': '@tanstack/router-plugin@1.130.8':
resolution: {integrity: sha512-Cw2VYsWEJKEbedzohsF35ej105V6Kq52oDwt8G5xjzBLaVTvTJCAOeK7w8kLwRt1tp+cI8lNlhU7J3VAI/vuEQ==} resolution: {integrity: sha512-V1kMoKV5yX21Q9QxzpKgJ+o1jIMnFrpfDO1UCMqEpJmOq2hA0MsEOVaeU643Nfp6Gmx1EirMW4NEMFLtXGuCqw==}
engines: {node: '>=12'} engines: {node: '>=12'}
peerDependencies: peerDependencies:
'@rsbuild/core': '>=1.0.2' '@rsbuild/core': '>=1.0.2'
'@tanstack/react-router': ^1.130.2 '@tanstack/react-router': ^1.130.8
vite: '>=5.0.0 || >=6.0.0' vite: '>=5.0.0 || >=6.0.0'
vite-plugin-solid: ^2.11.2 vite-plugin-solid: ^2.11.2
webpack: '>=5.92.0' webpack: '>=5.92.0'
@@ -4010,8 +4010,8 @@ packages:
resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==}
engines: {node: '>=8'} engines: {node: '>=8'}
cacheable@1.10.0: cacheable@1.10.3:
resolution: {integrity: sha512-SSgQTAnhd7WlJXnGlIi4jJJOiHzgnM5wRMEPaXAU4kECTAMpBoYKoZ9i5zHmclIEZbxcu3j7yY/CF8DTmwIsHg==} resolution: {integrity: sha512-M6p10iJ/VT0wT7TLIGUnm958oVrU2cUK8pQAVU21Zu7h8rbk/PeRtRWrvHJBql97Bhzk3g1N6+2VKC+Rjxna9Q==}
call-bind-apply-helpers@1.0.1: call-bind-apply-helpers@1.0.1:
resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==} resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==}
@@ -5158,8 +5158,8 @@ packages:
engines: {node: '>= 0.4.0'} engines: {node: '>= 0.4.0'}
hasBin: true hasBin: true
file-entry-cache@10.1.1: file-entry-cache@10.1.3:
resolution: {integrity: sha512-zcmsHjg2B2zjuBgjdnB+9q0+cWcgWfykIcsDkWDB4GTPtl1eXUA+gTI6sO0u01AqK3cliHryTU55/b2Ow1hfZg==} resolution: {integrity: sha512-D+w75Ub8T55yor7fPgN06rkCAUbAYw2vpxJmmjv/GDAcvCnv9g7IvHhIZoxzRZThrXPFI2maeY24pPbtyYU7Lg==}
file-entry-cache@8.0.0: file-entry-cache@8.0.0:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
@@ -5191,8 +5191,8 @@ packages:
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
engines: {node: '>=16'} engines: {node: '>=16'}
flat-cache@6.1.10: flat-cache@6.1.12:
resolution: {integrity: sha512-B6/v1f0NwjxzmeOhzfXPGWpKBVA207LS7lehaVKQnFrVktcFRfkzjZZ2gwj2i1TkEUMQht7ZMJbABUT5N+V1Nw==} resolution: {integrity: sha512-U+HqqpZPPXP5d24bWuRzjGqVqUcw64k4nZAbruniDwdRg0H10tvN7H6ku1tjhA4rg5B9GS3siEvwO2qjJJ6f8Q==}
flatted@3.3.3: flatted@3.3.3:
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
@@ -5220,8 +5220,8 @@ packages:
fraction.js@4.3.7: fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
framer-motion@12.23.11: framer-motion@12.23.12:
resolution: {integrity: sha512-VzNi+exyI3bn7Pzvz1Fjap1VO9gQu8mxrsSsNamMidsZ8AA8W2kQsR+YQOciEUbMtkKAWIbPHPttfn5e9jqqJQ==} resolution: {integrity: sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==}
peerDependencies: peerDependencies:
'@emotion/is-prop-valid': '*' '@emotion/is-prop-valid': '*'
react: ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0
@@ -5483,8 +5483,8 @@ packages:
hoist-non-react-statics@3.3.2: hoist-non-react-statics@3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
hookified@1.9.1: hookified@1.11.0:
resolution: {integrity: sha512-u3pxtGhKjcSXnGm1CX6aXS9xew535j3lkOCegbA6jdyh0BaAjTbXI4aslKstCr6zUNtoCxFGFKwjbSHdGrMB8g==} resolution: {integrity: sha512-aDdIN3GyU5I6wextPplYdfmWCo+aLmjjVbntmX6HLD5RCi/xKsivYEBhnRD+d9224zFf008ZpLMPlWF0ZodYZw==}
html-minifier-terser@6.1.0: html-minifier-terser@6.1.0:
resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==}
@@ -6051,8 +6051,8 @@ packages:
keyv@4.5.4: keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
keyv@5.3.3: keyv@5.4.0:
resolution: {integrity: sha512-Rwu4+nXI9fqcxiEHtbkvoes2X+QfkTRo1TMkPfwzipGsJlJO/z69vqB4FNl9xJ3xCpAcbkvmEabZfPzrwN3+gQ==} resolution: {integrity: sha512-TMckyVjEoacG5IteUpUrOBsFORtheqziVyyY2dLUwg1jwTb8u48LX4TgmtogkNl9Y9unaEJ1luj10fGyjMGFOQ==}
kind-of@6.0.3: kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
@@ -6495,8 +6495,8 @@ packages:
peerDependencies: peerDependencies:
monaco-editor: '>=0.36' monaco-editor: '>=0.36'
motion-dom@12.23.9: motion-dom@12.23.12:
resolution: {integrity: sha512-6Sv++iWS8XMFCgU1qwKj9l4xuC47Hp4+2jvPfyTXkqDg2tTzSgX6nWKD4kNFXk0k7llO59LZTPuJigza4A2K1A==} resolution: {integrity: sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==}
motion-utils@12.23.6: motion-utils@12.23.6:
resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==}
@@ -7866,8 +7866,8 @@ packages:
peerDependencies: peerDependencies:
stylelint: ^16.0.2 stylelint: ^16.0.2
stylelint@16.22.0: stylelint@16.23.0:
resolution: {integrity: sha512-SVEMTdjKNV4ollUrIY9ordZ36zHv2/PHzPjfPMau370MlL2VYXeLgSNMMiEbLGRO8RmD2R8/BVUeF2DfnfkC0w==} resolution: {integrity: sha512-69T5aS2LUY306ekt1Q1oaSPwz/jaG9HjyMix3UMrai1iEbuOafBe2Dh8xlyczrxFAy89qcKyZWWtc42XLx3Bbw==}
engines: {node: '>=18.12.0'} engines: {node: '>=18.12.0'}
hasBin: true hasBin: true
@@ -9997,7 +9997,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@iconify/json@2.2.363': '@iconify/json@2.2.364':
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
pathe: 1.1.2 pathe: 1.1.2
@@ -10051,9 +10051,7 @@ snapshots:
'@juggle/resize-observer@3.4.0': {} '@juggle/resize-observer@3.4.0': {}
'@keyv/serialize@1.0.3': '@keyv/serialize@1.1.0': {}
dependencies:
buffer: 6.0.3
'@material/material-color-utilities@0.3.0': {} '@material/material-color-utilities@0.3.0': {}
@@ -11142,10 +11140,10 @@ snapshots:
'@tanstack/query-core': 5.83.0 '@tanstack/query-core': 5.83.0
react: 19.1.1 react: 19.1.1
'@tanstack/react-router-devtools@1.130.2(@tanstack/react-router@1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.130.2)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)': '@tanstack/react-router-devtools@1.130.8(@tanstack/react-router@1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.130.8)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.5)(tiny-invariant@1.3.3)':
dependencies: dependencies:
'@tanstack/react-router': 1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tanstack/react-router': 1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tanstack/router-devtools-core': 1.130.2(@tanstack/router-core@1.130.2)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3) '@tanstack/router-devtools-core': 1.130.8(@tanstack/router-core@1.130.8)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)
react: 19.1.1 react: 19.1.1
react-dom: 19.1.1(react@19.1.1) react-dom: 19.1.1(react@19.1.1)
transitivePeerDependencies: transitivePeerDependencies:
@@ -11154,11 +11152,11 @@ snapshots:
- solid-js - solid-js
- tiny-invariant - tiny-invariant
'@tanstack/react-router@1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': '@tanstack/react-router@1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
dependencies: dependencies:
'@tanstack/history': 1.129.7 '@tanstack/history': 1.129.7
'@tanstack/react-store': 0.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tanstack/react-store': 0.7.0(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tanstack/router-core': 1.130.2 '@tanstack/router-core': 1.130.8
isbot: 5.1.28 isbot: 5.1.28
react: 19.1.1 react: 19.1.1
react-dom: 19.1.1(react@19.1.1) react-dom: 19.1.1(react@19.1.1)
@@ -11184,7 +11182,7 @@ snapshots:
react: 19.1.1 react: 19.1.1
react-dom: 19.1.1(react@19.1.1) react-dom: 19.1.1(react@19.1.1)
'@tanstack/router-core@1.130.2': '@tanstack/router-core@1.130.8':
dependencies: dependencies:
'@tanstack/history': 1.129.7 '@tanstack/history': 1.129.7
'@tanstack/store': 0.7.0 '@tanstack/store': 0.7.0
@@ -11194,9 +11192,9 @@ snapshots:
tiny-invariant: 1.3.3 tiny-invariant: 1.3.3
tiny-warning: 1.0.3 tiny-warning: 1.0.3
'@tanstack/router-devtools-core@1.130.2(@tanstack/router-core@1.130.2)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)': '@tanstack/router-devtools-core@1.130.8(@tanstack/router-core@1.130.8)(csstype@3.1.3)(solid-js@1.9.5)(tiny-invariant@1.3.3)':
dependencies: dependencies:
'@tanstack/router-core': 1.130.2 '@tanstack/router-core': 1.130.8
clsx: 2.1.1 clsx: 2.1.1
goober: 2.1.16(csstype@3.1.3) goober: 2.1.16(csstype@3.1.3)
solid-js: 1.9.5 solid-js: 1.9.5
@@ -11204,9 +11202,9 @@ snapshots:
optionalDependencies: optionalDependencies:
csstype: 3.1.3 csstype: 3.1.3
'@tanstack/router-generator@1.130.2': '@tanstack/router-generator@1.130.8':
dependencies: dependencies:
'@tanstack/router-core': 1.130.2 '@tanstack/router-core': 1.130.8
'@tanstack/router-utils': 1.129.7 '@tanstack/router-utils': 1.129.7
'@tanstack/virtual-file-routes': 1.129.7 '@tanstack/virtual-file-routes': 1.129.7
prettier: 3.6.2 prettier: 3.6.2
@@ -11217,7 +11215,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@tanstack/router-plugin@1.130.2(@tanstack/react-router@1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.0.6(@types/node@22.16.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.89.2)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.0))': '@tanstack/router-plugin@1.130.8(@tanstack/react-router@1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.0.6(@types/node@22.16.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.89.2)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.0))':
dependencies: dependencies:
'@babel/core': 7.28.0 '@babel/core': 7.28.0
'@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0) '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.0)
@@ -11225,8 +11223,8 @@ snapshots:
'@babel/template': 7.27.2 '@babel/template': 7.27.2
'@babel/traverse': 7.28.0 '@babel/traverse': 7.28.0
'@babel/types': 7.28.1 '@babel/types': 7.28.1
'@tanstack/router-core': 1.130.2 '@tanstack/router-core': 1.130.8
'@tanstack/router-generator': 1.130.2 '@tanstack/router-generator': 1.130.8
'@tanstack/router-utils': 1.129.7 '@tanstack/router-utils': 1.129.7
'@tanstack/virtual-file-routes': 1.129.7 '@tanstack/virtual-file-routes': 1.129.7
babel-dead-code-elimination: 1.0.10 babel-dead-code-elimination: 1.0.10
@@ -11234,7 +11232,7 @@ snapshots:
unplugin: 2.3.5 unplugin: 2.3.5
zod: 3.25.76 zod: 3.25.76
optionalDependencies: optionalDependencies:
'@tanstack/react-router': 1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tanstack/react-router': 1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
vite: 7.0.6(@types/node@22.16.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.89.2)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.0) vite: 7.0.6(@types/node@22.16.5)(jiti@2.4.2)(less@4.2.0)(lightningcss@1.30.1)(sass-embedded@1.89.2)(sass@1.83.0)(stylus@0.62.0)(terser@5.36.0)(tsx@4.20.3)(yaml@2.8.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@@ -11250,9 +11248,9 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.13)': '@tanstack/router-zod-adapter@1.81.5(@tanstack/react-router@1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(zod@4.0.13)':
dependencies: dependencies:
'@tanstack/react-router': 1.130.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) '@tanstack/react-router': 1.130.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
zod: 4.0.13 zod: 4.0.13
'@tanstack/store@0.7.0': {} '@tanstack/store@0.7.0': {}
@@ -12318,10 +12316,10 @@ snapshots:
normalize-url: 6.1.0 normalize-url: 6.1.0
responselike: 2.0.1 responselike: 2.0.1
cacheable@1.10.0: cacheable@1.10.3:
dependencies: dependencies:
hookified: 1.9.1 hookified: 1.11.0
keyv: 5.3.3 keyv: 5.4.0
call-bind-apply-helpers@1.0.1: call-bind-apply-helpers@1.0.1:
dependencies: dependencies:
@@ -13723,9 +13721,9 @@ snapshots:
figlet@1.8.2: {} figlet@1.8.2: {}
file-entry-cache@10.1.1: file-entry-cache@10.1.3:
dependencies: dependencies:
flat-cache: 6.1.10 flat-cache: 6.1.12
file-entry-cache@8.0.0: file-entry-cache@8.0.0:
dependencies: dependencies:
@@ -13759,11 +13757,11 @@ snapshots:
flatted: 3.3.3 flatted: 3.3.3
keyv: 4.5.4 keyv: 4.5.4
flat-cache@6.1.10: flat-cache@6.1.12:
dependencies: dependencies:
cacheable: 1.10.0 cacheable: 1.10.3
flatted: 3.3.3 flatted: 3.3.3
hookified: 1.9.1 hookified: 1.11.0
flatted@3.3.3: {} flatted@3.3.3: {}
@@ -13790,9 +13788,9 @@ snapshots:
fraction.js@4.3.7: {} fraction.js@4.3.7: {}
framer-motion@12.23.11(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1): framer-motion@12.23.12(@emotion/is-prop-valid@1.3.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
dependencies: dependencies:
motion-dom: 12.23.9 motion-dom: 12.23.12
motion-utils: 12.23.6 motion-utils: 12.23.6
tslib: 2.8.1 tslib: 2.8.1
optionalDependencies: optionalDependencies:
@@ -14129,7 +14127,7 @@ snapshots:
dependencies: dependencies:
react-is: 16.13.1 react-is: 16.13.1
hookified@1.9.1: {} hookified@1.11.0: {}
html-minifier-terser@6.1.0: html-minifier-terser@6.1.0:
dependencies: dependencies:
@@ -14640,9 +14638,9 @@ snapshots:
dependencies: dependencies:
json-buffer: 3.0.1 json-buffer: 3.0.1
keyv@5.3.3: keyv@5.4.0:
dependencies: dependencies:
'@keyv/serialize': 1.0.3 '@keyv/serialize': 1.1.0
kind-of@6.0.3: {} kind-of@6.0.3: {}
@@ -15202,7 +15200,7 @@ snapshots:
vscode-uri: 3.0.8 vscode-uri: 3.0.8
yaml: 2.7.0 yaml: 2.7.0
motion-dom@12.23.9: motion-dom@12.23.12:
dependencies: dependencies:
motion-utils: 12.23.6 motion-utils: 12.23.6
@@ -16581,36 +16579,36 @@ snapshots:
dependencies: dependencies:
inline-style-parser: 0.2.3 inline-style-parser: 0.2.3
stylelint-config-html@1.1.0(postcss-html@1.8.0)(stylelint@16.22.0(typescript@5.8.3)): stylelint-config-html@1.1.0(postcss-html@1.8.0)(stylelint@16.23.0(typescript@5.8.3)):
dependencies: dependencies:
postcss-html: 1.8.0 postcss-html: 1.8.0
stylelint: 16.22.0(typescript@5.8.3) stylelint: 16.23.0(typescript@5.8.3)
stylelint-config-recess-order@7.1.0(stylelint-order@7.0.0(stylelint@16.22.0(typescript@5.8.3)))(stylelint@16.22.0(typescript@5.8.3)): stylelint-config-recess-order@7.1.0(stylelint-order@7.0.0(stylelint@16.23.0(typescript@5.8.3)))(stylelint@16.23.0(typescript@5.8.3)):
dependencies: dependencies:
stylelint: 16.22.0(typescript@5.8.3) stylelint: 16.23.0(typescript@5.8.3)
stylelint-order: 7.0.0(stylelint@16.22.0(typescript@5.8.3)) stylelint-order: 7.0.0(stylelint@16.23.0(typescript@5.8.3))
stylelint-config-recommended@16.0.0(stylelint@16.22.0(typescript@5.8.3)): stylelint-config-recommended@16.0.0(stylelint@16.23.0(typescript@5.8.3)):
dependencies: dependencies:
stylelint: 16.22.0(typescript@5.8.3) stylelint: 16.23.0(typescript@5.8.3)
stylelint-config-standard@38.0.0(stylelint@16.22.0(typescript@5.8.3)): stylelint-config-standard@38.0.0(stylelint@16.23.0(typescript@5.8.3)):
dependencies: dependencies:
stylelint: 16.22.0(typescript@5.8.3) stylelint: 16.23.0(typescript@5.8.3)
stylelint-config-recommended: 16.0.0(stylelint@16.22.0(typescript@5.8.3)) stylelint-config-recommended: 16.0.0(stylelint@16.23.0(typescript@5.8.3))
stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.22.0(typescript@5.8.3)): stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.23.0(typescript@5.8.3)):
dependencies: dependencies:
stylelint: 16.22.0(typescript@5.8.3) stylelint: 16.23.0(typescript@5.8.3)
stylelint-order@7.0.0(stylelint@16.22.0(typescript@5.8.3)): stylelint-order@7.0.0(stylelint@16.23.0(typescript@5.8.3)):
dependencies: dependencies:
postcss: 8.5.6 postcss: 8.5.6
postcss-sorting: 9.1.0(postcss@8.5.6) postcss-sorting: 9.1.0(postcss@8.5.6)
stylelint: 16.22.0(typescript@5.8.3) stylelint: 16.23.0(typescript@5.8.3)
stylelint-scss@6.12.1(stylelint@16.22.0(typescript@5.8.3)): stylelint-scss@6.12.1(stylelint@16.23.0(typescript@5.8.3)):
dependencies: dependencies:
css-tree: 3.1.0 css-tree: 3.1.0
is-plain-object: 5.0.0 is-plain-object: 5.0.0
@@ -16620,9 +16618,9 @@ snapshots:
postcss-resolve-nested-selector: 0.1.6 postcss-resolve-nested-selector: 0.1.6
postcss-selector-parser: 7.1.0 postcss-selector-parser: 7.1.0
postcss-value-parser: 4.2.0 postcss-value-parser: 4.2.0
stylelint: 16.22.0(typescript@5.8.3) stylelint: 16.23.0(typescript@5.8.3)
stylelint@16.22.0(typescript@5.8.3): stylelint@16.23.0(typescript@5.8.3):
dependencies: dependencies:
'@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
'@csstools/css-tokenizer': 3.0.4 '@csstools/css-tokenizer': 3.0.4
@@ -16637,7 +16635,7 @@ snapshots:
debug: 4.4.1 debug: 4.4.1
fast-glob: 3.3.3 fast-glob: 3.3.3
fastest-levenshtein: 1.0.16 fastest-levenshtein: 1.0.16
file-entry-cache: 10.1.1 file-entry-cache: 10.1.3
global-modules: 2.0.0 global-modules: 2.0.0
globby: 11.1.0 globby: 11.1.0
globjoin: 0.1.4 globjoin: 0.1.4

View File

@@ -33,6 +33,11 @@ const (
MaxPackageFileSize = 32 * 1024 * 1024 MaxPackageFileSize = 32 * 1024 * 1024
) )
const (
ReleaseChannel = "release"
AlphaChannel = "alpha"
)
// CoreUpdater is the mihomo updater. // CoreUpdater is the mihomo updater.
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go // modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go
type CoreUpdater struct { type CoreUpdater struct {
@@ -69,20 +74,28 @@ func (u *CoreUpdater) CoreBaseName() string {
} }
} }
func (u *CoreUpdater) Update(currentExePath string) (err error) { func (u *CoreUpdater) Update(currentExePath string, channel string, force bool) (err error) {
u.mu.Lock() u.mu.Lock()
defer u.mu.Unlock() defer u.mu.Unlock()
_, err = os.Stat(currentExePath) info, err := os.Stat(currentExePath)
if err != nil { if err != nil {
return fmt.Errorf("check currentExePath %q: %w", currentExePath, err) return fmt.Errorf("check currentExePath %q: %w", currentExePath, err)
} }
baseURL := baseAlphaURL baseURL := baseAlphaURL
versionURL := versionAlphaURL versionURL := versionAlphaURL
if !strings.HasPrefix(C.Version, "alpha") { switch strings.ToLower(channel) {
case ReleaseChannel:
baseURL = baseReleaseURL baseURL = baseReleaseURL
versionURL = versionReleaseURL versionURL = versionReleaseURL
case AlphaChannel:
break
default: // auto
if !strings.HasPrefix(C.Version, "alpha") {
baseURL = baseReleaseURL
versionURL = versionReleaseURL
}
} }
latestVersion, err := u.getLatestVersion(versionURL) latestVersion, err := u.getLatestVersion(versionURL)
@@ -91,7 +104,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) {
} }
log.Infoln("current version %s, latest version %s", C.Version, latestVersion) log.Infoln("current version %s, latest version %s", C.Version, latestVersion)
if latestVersion == C.Version { if latestVersion == C.Version && !force {
// don't change this output, some downstream dependencies on the upgrader's output fields // don't change this output, some downstream dependencies on the upgrader's output fields
return fmt.Errorf("update error: already using latest version %s", C.Version) return fmt.Errorf("update error: already using latest version %s", C.Version)
} }
@@ -136,7 +149,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) {
return fmt.Errorf("downloading: %w", err) return fmt.Errorf("downloading: %w", err)
} }
err = u.unpack(updateDir, packagePath) err = u.unpack(updateDir, packagePath, info.Mode())
if err != nil { if err != nil {
return fmt.Errorf("unpacking: %w", err) return fmt.Errorf("unpacking: %w", err)
} }
@@ -230,16 +243,16 @@ func (u *CoreUpdater) download(updateDir, packagePath, packageURL string) (err e
} }
// unpack extracts the files from the downloaded archive. // unpack extracts the files from the downloaded archive.
func (u *CoreUpdater) unpack(updateDir, packagePath string) error { func (u *CoreUpdater) unpack(updateDir, packagePath string, fileMode os.FileMode) error {
log.Infoln("updater: unpacking package") log.Infoln("updater: unpacking package")
if strings.HasSuffix(packagePath, ".zip") { if strings.HasSuffix(packagePath, ".zip") {
_, err := u.zipFileUnpack(packagePath, updateDir) _, err := u.zipFileUnpack(packagePath, updateDir, fileMode)
if err != nil { if err != nil {
return fmt.Errorf(".zip unpack failed: %w", err) return fmt.Errorf(".zip unpack failed: %w", err)
} }
} else if strings.HasSuffix(packagePath, ".gz") { } else if strings.HasSuffix(packagePath, ".gz") {
_, err := u.gzFileUnpack(packagePath, updateDir) _, err := u.gzFileUnpack(packagePath, updateDir, fileMode)
if err != nil { if err != nil {
return fmt.Errorf(".gz unpack failed: %w", err) return fmt.Errorf(".gz unpack failed: %w", err)
} }
@@ -295,7 +308,7 @@ func (u *CoreUpdater) clean(updateDir string) {
// Existing files are overwritten // Existing files are overwritten
// All files are created inside outDir, subdirectories are not created // All files are created inside outDir, subdirectories are not created
// Return the output file name // Return the output file name
func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, err error) { func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string, fileMode os.FileMode) (outputName string, err error) {
f, err := os.Open(gzfile) f, err := os.Open(gzfile)
if err != nil { if err != nil {
return "", fmt.Errorf("os.Open(): %w", err) return "", fmt.Errorf("os.Open(): %w", err)
@@ -330,7 +343,7 @@ func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, er
outputName = filepath.Join(outDir, originalName) outputName = filepath.Join(outDir, originalName)
// Create the output file // Create the output file
wc, err := os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755) wc, err := os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileMode)
if err != nil { if err != nil {
return "", fmt.Errorf("os.OpenFile(%s): %w", outputName, err) return "", fmt.Errorf("os.OpenFile(%s): %w", outputName, err)
} }
@@ -355,7 +368,7 @@ func (u *CoreUpdater) gzFileUnpack(gzfile, outDir string) (outputName string, er
// Existing files are overwritten // Existing files are overwritten
// All files are created inside 'outDir', subdirectories are not created // All files are created inside 'outDir', subdirectories are not created
// Return the output file name // Return the output file name
func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string) (outputName string, err error) { func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string, fileMode os.FileMode) (outputName string, err error) {
zrc, err := zip.OpenReader(zipfile) zrc, err := zip.OpenReader(zipfile)
if err != nil { if err != nil {
return "", fmt.Errorf("zip.OpenReader(): %w", err) return "", fmt.Errorf("zip.OpenReader(): %w", err)
@@ -394,7 +407,7 @@ func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string) (outputName string,
} }
var wc io.WriteCloser var wc io.WriteCloser
wc, err = os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fi.Mode()) wc, err = os.OpenFile(outputName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fileMode)
if err != nil { if err != nil {
return "", fmt.Errorf("os.OpenFile(): %w", err) return "", fmt.Errorf("os.OpenFile(): %w", err)
} }

View File

@@ -22,7 +22,7 @@ require (
github.com/metacubex/chacha v0.1.5 github.com/metacubex/chacha v0.1.5
github.com/metacubex/fswatch v0.1.1 github.com/metacubex/fswatch v0.1.1
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295
github.com/metacubex/randv2 v0.2.0 github.com/metacubex/randv2 v0.2.0
github.com/metacubex/sing v0.5.4 github.com/metacubex/sing v0.5.4
github.com/metacubex/sing-mux v0.3.2 github.com/metacubex/sing-mux v0.3.2

View File

@@ -112,8 +112,8 @@ github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo=
github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA=
github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c h1:ABQzmOaZddM3q0OYeoZEc0XF+KW+dUdPNvY/c5rsunI= github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs=
github.com/metacubex/quic-go v0.53.1-0.20250628094454-fda5262d1d9c/go.mod h1:eWlAK3zsKI0P8UhYpXlIsl3mtW4D6MpMNuYLIu8CKWI= github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295/go.mod h1:1lktQFtCD17FZliVypbrDHwbsFSsmz2xz2TRXydvB5c=
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs= github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY= github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w=

View File

@@ -32,7 +32,11 @@ func upgradeCore(w http.ResponseWriter, r *http.Request) {
return return
} }
err = updater.DefaultCoreUpdater.Update(execPath) query := r.URL.Query()
channel := query.Get("channel")
force := query.Get("force") == "true"
err = updater.DefaultCoreUpdater.Update(execPath, channel, force)
if err != nil { if err != nil {
log.Warnln("%s", err) log.Warnln("%s", err)
render.Status(r, http.StatusInternalServerError) render.Status(r, http.StatusInternalServerError)

View File

@@ -6,12 +6,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=adguardhome PKG_NAME:=adguardhome
PKG_VERSION:=0.107.63 PKG_VERSION:=0.107.64
PKG_RELEASE:=1 PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/AdGuardHome/tar.gz/v$(PKG_VERSION)? PKG_SOURCE_URL:=https://codeload.github.com/AdguardTeam/AdGuardHome/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=f445eb98fc1beba326433da7c999799fe36c7f15297fdebe59a41914eaffe3ad PKG_HASH:=a6b61d3c102fa47072a7230382d438f3d408f74ffae3aff7d330adad90ed169c
PKG_BUILD_DIR:=$(BUILD_DIR)/AdGuardHome-$(PKG_VERSION) PKG_BUILD_DIR:=$(BUILD_DIR)/AdGuardHome-$(PKG_VERSION)
PKG_LICENSE:=GPL-3.0-only 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:=https://github.com/AdguardTeam/AdGuardHome/releases/download/v$(PKG_VERSION)/
URL_FILE:=AdGuardHome_frontend.tar.gz URL_FILE:=AdGuardHome_frontend.tar.gz
FILE:=$(FRONTEND_FILE) FILE:=$(FRONTEND_FILE)
HASH:=74bda6f7c7334342b33fff50a0cdff4e206f84a471bab983ee16d3f6f112c53a HASH:=f0c1e4d6e673d4d26d52947cdb220682aa554158d331fa044576d1794b82e325
endef endef
define Build/Prepare define Build/Prepare

View File

@@ -599,18 +599,18 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.41" version = "4.5.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
] ]
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.41" version = "4.5.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@@ -1024,7 +1024,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.60.2", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@@ -1977,7 +1977,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"windows-targets 0.53.2", "windows-targets 0.48.5",
] ]
[[package]] [[package]]
@@ -2741,7 +2741,7 @@ dependencies = [
"once_cell", "once_cell",
"socket2 0.5.10", "socket2 0.5.10",
"tracing", "tracing",
"windows-sys 0.59.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@@ -3062,7 +3062,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys 0.59.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@@ -3744,7 +3744,7 @@ dependencies = [
"getrandom 0.3.3", "getrandom 0.3.3",
"once_cell", "once_cell",
"rustix", "rustix",
"windows-sys 0.59.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]

View File

@@ -223,4 +223,28 @@ public static class FileManager
// ignored // ignored
} }
} }
/// <summary>
/// Creates a Linux shell file with the specified contents.
/// </summary>
/// <param name="fileName"></param>
/// <param name="contents"></param>
/// <param name="overwrite"></param>
/// <returns></returns>
public static async Task<string> CreateLinuxShellFile(string fileName, string contents, bool overwrite)
{
var shFilePath = Utils.GetBinConfigPath(fileName);
// Check if the file already exists and if we should overwrite it
if (!overwrite && File.Exists(shFilePath))
{
return shFilePath;
}
File.Delete(shFilePath);
await File.WriteAllTextAsync(shFilePath, contents);
await Utils.SetLinuxChmod(shFilePath);
return shFilePath;
}
} }

View File

@@ -38,6 +38,8 @@ public class Global
public const string PacFileName = NamespaceSample + "pac"; public const string PacFileName = NamespaceSample + "pac";
public const string ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh"; public const string ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh";
public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh"; public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh";
public const string KillAsSudoOSXShellFileName = NamespaceSample + "kill_as_sudo_osx_sh";
public const string KillAsSudoLinuxShellFileName = NamespaceSample + "kill_as_sudo_linux_sh";
public const string DefaultSecurity = "auto"; public const string DefaultSecurity = "auto";
public const string DefaultNetwork = "tcp"; public const string DefaultNetwork = "tcp";

View File

@@ -1,6 +1,7 @@
using System.Diagnostics; using System.Diagnostics;
using System.Text; using System.Text;
using CliWrap; using CliWrap;
using CliWrap.Buffered;
namespace ServiceLib.Handler; namespace ServiceLib.Handler;
@@ -11,6 +12,7 @@ public class CoreAdminHandler
private Config _config; private Config _config;
private Action<bool, string>? _updateFunc; private Action<bool, string>? _updateFunc;
private int _linuxSudoPid = -1; private int _linuxSudoPid = -1;
private const string _tag = "CoreAdminHandler";
public async Task Init(Config config, Action<bool, string> updateFunc) public async Task Init(Config config, Action<bool, string> updateFunc)
{ {
@@ -31,8 +33,11 @@ public class CoreAdminHandler
public async Task<Process?> RunProcessAsLinuxSudo(string fileName, CoreInfo coreInfo, string configPath) public async Task<Process?> RunProcessAsLinuxSudo(string fileName, CoreInfo coreInfo, string configPath)
{ {
StringBuilder sb = new();
sb.AppendLine("#!/bin/bash");
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}"; var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh"); sb.AppendLine($"sudo -S {cmdLine}");
var shFilePath = await FileManager.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true);
Process proc = new() Process proc = new()
{ {
@@ -87,35 +92,27 @@ public class CoreAdminHandler
return; return;
} }
var cmdLine = $"pkill -P {_linuxSudoPid} ; kill {_linuxSudoPid}"; try
var shFilePath = await CreateLinuxShellFile(cmdLine, "kill_as_sudo.sh"); {
var shellFileName = Utils.IsOSX() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName;
var shFilePath = await FileManager.CreateLinuxShellFile("kill_as_sudo.sh", EmbedUtils.GetEmbedText(shellFileName), true);
if (shFilePath.Contains(' '))
{
shFilePath = shFilePath.AppendQuotes();
}
var arg = new List<string>() { "-c", $"sudo -S {shFilePath} {_linuxSudoPid}" };
var result = await Cli.Wrap(Global.LinuxBash)
.WithArguments(arg)
.WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd))
.ExecuteBufferedAsync();
await Cli.Wrap(shFilePath) UpdateFunc(false, result.StandardOutput.ToString());
.WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd)) }
.ExecuteAsync(); catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
_linuxSudoPid = -1; _linuxSudoPid = -1;
} }
private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName)
{
var shFilePath = Utils.GetBinConfigPath(fileName);
File.Delete(shFilePath);
var sb = new StringBuilder();
sb.AppendLine("#!/bin/sh");
if (Utils.IsAdministrator())
{
sb.AppendLine($"{cmdLine}");
}
else
{
sb.AppendLine($"sudo -S {cmdLine}");
}
await File.WriteAllTextAsync(shFilePath, sb.ToString());
await Utils.SetLinuxChmod(shFilePath);
return shFilePath;
}
} }

View File

@@ -18,14 +18,7 @@ public class ProxySettingLinux
private static async Task ExecCmd(List<string> args) private static async Task ExecCmd(List<string> args)
{ {
var fileName = Utils.GetBinConfigPath(_proxySetFileName); var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false);
if (!File.Exists(fileName))
{
var contents = EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName);
await File.AppendAllTextAsync(fileName, contents);
await Utils.SetLinuxChmod(fileName);
}
await Utils.GetCliWrapOutput(fileName, args); await Utils.GetCliWrapOutput(fileName, args);
} }

View File

@@ -23,14 +23,7 @@ public class ProxySettingOSX
private static async Task ExecCmd(List<string> args) private static async Task ExecCmd(List<string> args)
{ {
var fileName = Utils.GetBinConfigPath(_proxySetFileName); var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false);
if (!File.Exists(fileName))
{
var contents = EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName);
await File.AppendAllTextAsync(fileName, contents);
await Utils.SetLinuxChmod(fileName);
}
await Utils.GetCliWrapOutput(fileName, args); await Utils.GetCliWrapOutput(fileName, args);
} }

View File

@@ -0,0 +1,61 @@
#!/bin/bash
#
# Process Terminator Script for Linux
# This script forcibly terminates a process and all its child processes
#
# Check if PID argument is provided
if [ $# -ne 1 ]; then
echo "Usage: $0 <PID>"
exit 1
fi
PID=$1
# Validate that input is a valid PID (numeric)
if ! [[ "$PID" =~ ^[0-9]+$ ]]; then
echo "Error: The PID must be a numeric value"
exit 1
fi
# Check if the process exists
if ! ps -p $PID > /dev/null; then
echo "Warning: No process found with PID $PID"
exit 0
fi
# Recursive function to find and kill all child processes
kill_children() {
local parent=$1
local children=$(ps -o pid --no-headers --ppid "$parent")
# Output information about processes being terminated
echo "Processing children of PID: $parent..."
# Process each child
for child in $children; do
# Recursively find and kill child's children first
kill_children "$child"
# Force kill the child process
echo "Terminating child process: $child"
kill -9 "$child" 2>/dev/null || true
done
}
echo "============================================"
echo "Starting termination of process $PID and all its children"
echo "============================================"
# Find and kill all child processes
kill_children "$PID"
# Finally kill the main process
echo "Terminating main process: $PID"
kill -9 "$PID" 2>/dev/null || true
echo "============================================"
echo "Process $PID and all its children have been terminated"
echo "============================================"
exit 0

View File

@@ -0,0 +1,56 @@
#!/bin/bash
#
# Process Terminator Script for macOS
# This script forcibly terminates a process and all its descendant processes
#
# Check if PID argument is provided
if [ $# -ne 1 ]; then
echo "Usage: $0 <PID>"
exit 1
fi
PID=$1
# Validate that input is a valid PID (numeric)
if ! [[ "$PID" =~ ^[0-9]+$ ]]; then
echo "Error: The PID must be a numeric value"
exit 1
fi
# Check if the process exists - using kill -0 which is more reliable on macOS
if ! kill -0 $PID 2>/dev/null; then
echo "Warning: No process found with PID $PID"
exit 0
fi
# Recursive function to find and kill all descendant processes
kill_descendants() {
local parent=$1
# Use ps -axo for macOS to ensure all processes are included
local children=$(ps -axo pid=,ppid= | awk -v ppid=$parent '$2==ppid {print $1}')
echo "Processing children of PID: $parent..."
for child in $children; do
kill_descendants "$child"
echo "Terminating child process: $child"
kill -9 "$child" 2>/dev/null || true
done
}
echo "============================================"
echo "Starting termination of process $PID and all its descendants"
echo "============================================"
# Find and kill all descendant processes
kill_descendants "$PID"
# Finally kill the main process
echo "Terminating main process: $PID"
kill -9 "$PID" 2>/dev/null || true
echo "============================================"
echo "Process $PID and all its descendants have been terminated"
echo "============================================"
exit 0

View File

@@ -28,6 +28,8 @@
<EmbeddedResource Include="Sample\custom_routing_white" /> <EmbeddedResource Include="Sample\custom_routing_white" />
<EmbeddedResource Include="Sample\dns_singbox_normal" /> <EmbeddedResource Include="Sample\dns_singbox_normal" />
<EmbeddedResource Include="Sample\dns_v2ray_normal" /> <EmbeddedResource Include="Sample\dns_v2ray_normal" />
<EmbeddedResource Include="Sample\kill_as_sudo_linux_sh" />
<EmbeddedResource Include="Sample\kill_as_sudo_osx_sh" />
<EmbeddedResource Include="Sample\pac" /> <EmbeddedResource Include="Sample\pac" />
<EmbeddedResource Include="Sample\proxy_set_linux_sh" /> <EmbeddedResource Include="Sample\proxy_set_linux_sh" />
<EmbeddedResource Include="Sample\proxy_set_osx_sh" /> <EmbeddedResource Include="Sample\proxy_set_osx_sh" />

View File

@@ -519,7 +519,7 @@ public class CoreConfigSingboxService
{ {
try try
{ {
var listen = "::"; var listen = "0.0.0.0";
singboxConfig.inbounds = []; singboxConfig.inbounds = [];
if (!_config.TunModeItem.EnableTun if (!_config.TunModeItem.EnableTun

View File

@@ -66,8 +66,7 @@ public partial class SudoPasswordInputView : UserControl
{ {
// Use sudo echo command to verify password // Use sudo echo command to verify password
var arg = new List<string>() { "-c", "sudo -S echo SUDO_CHECK" }; var arg = new List<string>() { "-c", "sudo -S echo SUDO_CHECK" };
var result = await CliWrap.Cli var result = await CliWrap.Cli.Wrap(Global.LinuxBash)
.Wrap(Global.LinuxBash)
.WithArguments(arg) .WithArguments(arg)
.WithStandardInputPipe(CliWrap.PipeSource.FromString(password)) .WithStandardInputPipe(CliWrap.PipeSource.FromString(password))
.ExecuteBufferedAsync(); .ExecuteBufferedAsync();

View File

@@ -37,7 +37,7 @@ jobs:
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
# CPython 3.9 is in quick-test # CPython 3.9 is in quick-test
python-version: ['3.10', '3.11', '3.12', '3.13', pypy-3.10] python-version: ['3.10', '3.11', '3.12', '3.13', pypy-3.11]
include: include:
# atleast one of each CPython/PyPy tests must be in windows # atleast one of each CPython/PyPy tests must be in windows
- os: windows-latest - os: windows-latest
@@ -49,7 +49,7 @@ jobs:
- os: windows-latest - os: windows-latest
python-version: '3.13' python-version: '3.13'
- os: windows-latest - os: windows-latest
python-version: pypy-3.10 python-version: pypy-3.11
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}

View File

@@ -28,13 +28,13 @@ jobs:
fail-fast: true fail-fast: true
matrix: matrix:
os: [ubuntu-latest] os: [ubuntu-latest]
python-version: ['3.10', '3.11', '3.12', '3.13', pypy-3.10] python-version: ['3.10', '3.11', '3.12', '3.13', pypy-3.11]
include: include:
# atleast one of each CPython/PyPy tests must be in windows # atleast one of each CPython/PyPy tests must be in windows
- os: windows-latest - os: windows-latest
python-version: '3.9' python-version: '3.9'
- os: windows-latest - os: windows-latest
python-version: pypy-3.10 python-version: pypy-3.11
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}

View File

@@ -25,7 +25,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, windows-latest] os: [ubuntu-latest, windows-latest]
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', pypy-3.10, pypy-3.11] python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', pypy-3.11]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}

View File

@@ -272,7 +272,7 @@ After you have ensured this site is distributing its content legally, you can fo
You can use `hatch fmt` to automatically fix problems. Rules that the linter/formatter enforces should not be disabled with `# noqa` unless a maintainer requests it. The only exception allowed is for old/printf-style string formatting in GraphQL query templates (use `# noqa: UP031`). You can use `hatch fmt` to automatically fix problems. Rules that the linter/formatter enforces should not be disabled with `# noqa` unless a maintainer requests it. The only exception allowed is for old/printf-style string formatting in GraphQL query templates (use `# noqa: UP031`).
1. Make sure your code works under all [Python](https://www.python.org/) versions supported by yt-dlp, namely CPython >=3.9 and PyPy >=3.10. Backward compatibility is not required for even older versions of Python. 1. Make sure your code works under all [Python](https://www.python.org/) versions supported by yt-dlp, namely CPython >=3.9 and PyPy >=3.11. Backward compatibility is not required for even older versions of Python.
1. When the tests pass, [add](https://git-scm.com/docs/git-add) the new files, [commit](https://git-scm.com/docs/git-commit) them and [push](https://git-scm.com/docs/git-push) the result, like this: 1. When the tests pass, [add](https://git-scm.com/docs/git-add) the new files, [commit](https://git-scm.com/docs/git-commit) them and [push](https://git-scm.com/docs/git-push) the result, like this:
```shell ```shell

View File

@@ -172,7 +172,7 @@ python3 -m pip install -U --pre "yt-dlp[default]"
``` ```
## DEPENDENCIES ## DEPENDENCIES
Python versions 3.9+ (CPython) and 3.10+ (PyPy) are supported. Other versions and implementations may or may not work correctly. Python versions 3.9+ (CPython) and 3.11+ (PyPy) are supported. Other versions and implementations may or may not work correctly.
<!-- Python 3.5+ uses VC++14 and it is already embedded in the binary created <!-- Python 3.5+ uses VC++14 and it is already embedded in the binary created
<!x-- https://www.microsoft.com/en-us/download/details.aspx?id=26999 --x> <!x-- https://www.microsoft.com/en-us/download/details.aspx?id=26999 --x>

View File

@@ -1335,7 +1335,7 @@ class YoutubeDLCookieJar(http.cookiejar.MozillaCookieJar):
if len(cookie_list) != self._ENTRY_LEN: if len(cookie_list) != self._ENTRY_LEN:
raise http.cookiejar.LoadError(f'invalid length {len(cookie_list)}') raise http.cookiejar.LoadError(f'invalid length {len(cookie_list)}')
cookie = self._CookieFileEntry(*cookie_list) cookie = self._CookieFileEntry(*cookie_list)
if cookie.expires_at and not cookie.expires_at.isdigit(): if cookie.expires_at and not re.fullmatch(r'[0-9]+(?:\.[0-9]+)?', cookie.expires_at):
raise http.cookiejar.LoadError(f'invalid expires at {cookie.expires_at}') raise http.cookiejar.LoadError(f'invalid expires at {cookie.expires_at}')
return line return line

View File

@@ -33,7 +33,6 @@ from ..utils import (
unified_timestamp, unified_timestamp,
url_or_none, url_or_none,
urlhandle_detect_ext, urlhandle_detect_ext,
variadic,
) )
@@ -232,6 +231,23 @@ class ArchiveOrgIE(InfoExtractor):
'release_date': '19950402', 'release_date': '19950402',
'timestamp': 1084927901, 'timestamp': 1084927901,
}, },
}, {
# metadata['metadata']['description'] is a list of strings instead of str
'url': 'https://archive.org/details/pra-KZ1908.02',
'info_dict': {
'id': 'pra-KZ1908.02',
'ext': 'mp3',
'display_id': 'KZ1908.02_01.wav',
'title': 'Crips and Bloods speak about gang life',
'description': 'md5:2b56b35ff021311e3554b47a285e70b3',
'uploader': 'jake@archive.org',
'duration': 1733.74,
'track': 'KZ1908.02 01',
'track_number': 1,
'timestamp': 1336026026,
'upload_date': '20120503',
'release_year': 1992,
},
}] }]
@staticmethod @staticmethod
@@ -274,34 +290,40 @@ class ArchiveOrgIE(InfoExtractor):
m = metadata['metadata'] m = metadata['metadata']
identifier = m['identifier'] identifier = m['identifier']
info = { info = traverse_obj(m, {
'title': ('title', {str}),
'description': ('description', ({str}, (..., all, {' '.join})), {clean_html}, filter, any),
'uploader': (('uploader', 'adder'), {str}, any),
'creators': ('creator', (None, ...), {str}, filter, all, filter),
'license': ('licenseurl', {url_or_none}),
'release_date': ('date', {unified_strdate}),
'timestamp': (('publicdate', 'addeddate'), {unified_timestamp}, any),
'location': ('venue', {str}),
'release_year': ('year', {int_or_none}),
})
info.update({
'id': identifier, 'id': identifier,
'title': m['title'],
'description': clean_html(m.get('description')),
'uploader': dict_get(m, ['uploader', 'adder']),
'creators': traverse_obj(m, ('creator', {variadic}, {lambda x: x[0] and list(x)})),
'license': m.get('licenseurl'),
'release_date': unified_strdate(m.get('date')),
'timestamp': unified_timestamp(dict_get(m, ['publicdate', 'addeddate'])),
'webpage_url': f'https://archive.org/details/{identifier}', 'webpage_url': f'https://archive.org/details/{identifier}',
'location': m.get('venue'), })
'release_year': int_or_none(m.get('year'))}
for f in metadata['files']: for f in metadata['files']:
if f['name'] in entries: if f['name'] in entries:
entries[f['name']] = merge_dicts(entries[f['name']], { entries[f['name']] = merge_dicts(entries[f['name']], {
'id': identifier + '/' + f['name'], 'id': identifier + '/' + f['name'],
'title': f.get('title') or f['name'], **traverse_obj(f, {
'display_id': f['name'], 'title': (('title', 'name'), {str}, any),
'description': clean_html(f.get('description')), 'display_id': ('name', {str}),
'creators': traverse_obj(f, ('creator', {variadic}, {lambda x: x[0] and list(x)})), 'description': ('description', ({str}, (..., all, {' '.join})), {clean_html}, filter, any),
'duration': parse_duration(f.get('length')), 'creators': ('creator', (None, ...), {str}, filter, all, filter),
'track_number': int_or_none(f.get('track')), 'duration': ('length', {parse_duration}),
'album': f.get('album'), 'track_number': ('track', {int_or_none}),
'discnumber': int_or_none(f.get('disc')), 'album': ('album', {str}),
'release_year': int_or_none(f.get('year'))}) 'discnumber': ('disc', {int_or_none}),
'release_year': ('year', {int_or_none}),
}),
})
entry = entries[f['name']] entry = entries[f['name']]
elif traverse_obj(f, 'original', expected_type=str) in entries: elif traverse_obj(f, ('original', {str})) in entries:
entry = entries[f['original']] entry = entries[f['original']]
else: else:
continue continue