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 Mon Jul 28 20:43:06 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
)
const (
ReleaseChannel = "release"
AlphaChannel = "alpha"
)
// CoreUpdater is the mihomo updater.
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go
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()
defer u.mu.Unlock()
_, err = os.Stat(currentExePath)
info, err := os.Stat(currentExePath)
if err != nil {
return fmt.Errorf("check currentExePath %q: %w", currentExePath, err)
}
baseURL := baseAlphaURL
versionURL := versionAlphaURL
if !strings.HasPrefix(C.Version, "alpha") {
switch strings.ToLower(channel) {
case ReleaseChannel:
baseURL = baseReleaseURL
versionURL = versionReleaseURL
case AlphaChannel:
break
default: // auto
if !strings.HasPrefix(C.Version, "alpha") {
baseURL = baseReleaseURL
versionURL = versionReleaseURL
}
}
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)
if latestVersion == C.Version {
if latestVersion == C.Version && !force {
// 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)
}
@@ -136,7 +149,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) {
return fmt.Errorf("downloading: %w", err)
}
err = u.unpack(updateDir, packagePath)
err = u.unpack(updateDir, packagePath, info.Mode())
if err != nil {
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.
func (u *CoreUpdater) unpack(updateDir, packagePath string) error {
func (u *CoreUpdater) unpack(updateDir, packagePath string, fileMode os.FileMode) error {
log.Infoln("updater: unpacking package")
if strings.HasSuffix(packagePath, ".zip") {
_, err := u.zipFileUnpack(packagePath, updateDir)
_, err := u.zipFileUnpack(packagePath, updateDir, fileMode)
if err != nil {
return fmt.Errorf(".zip unpack failed: %w", err)
}
} else if strings.HasSuffix(packagePath, ".gz") {
_, err := u.gzFileUnpack(packagePath, updateDir)
_, err := u.gzFileUnpack(packagePath, updateDir, fileMode)
if err != nil {
return fmt.Errorf(".gz unpack failed: %w", err)
}
@@ -295,7 +308,7 @@ func (u *CoreUpdater) clean(updateDir string) {
// Existing files are overwritten
// All files are created inside outDir, subdirectories are not created
// 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)
if err != nil {
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)
// 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 {
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
// All files are created inside 'outDir', subdirectories are not created
// 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)
if err != nil {
return "", fmt.Errorf("zip.OpenReader(): %w", err)
@@ -394,7 +407,7 @@ func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string) (outputName string,
}
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 {
return "", fmt.Errorf("os.OpenFile(): %w", err)
}

View File

@@ -22,7 +22,7 @@ require (
github.com/metacubex/chacha v0.1.5
github.com/metacubex/fswatch v0.1.1
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/sing v0.5.4
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/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/quic-go v0.53.1-0.20250628094454-fda5262d1d9c h1:ABQzmOaZddM3q0OYeoZEc0XF+KW+dUdPNvY/c5rsunI=
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 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs=
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/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
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
}
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 {
log.Warnln("%s", err)
render.Status(r, http.StatusInternalServerError)

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
"mihomo_alpha": "alpha-0f1baeb",
"clash_rs": "v0.8.1",
"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": {
"mihomo": {
@@ -69,5 +69,5 @@
"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-toml": "2.0.6",
"react-devtools": "6.1.5",
"stylelint": "16.22.0",
"stylelint": "16.23.0",
"stylelint-config-html": "1.1.0",
"stylelint-config-recess-order": "7.1.0",
"stylelint-config-standard": "38.0.0",

View File

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

View File

@@ -33,6 +33,11 @@ const (
MaxPackageFileSize = 32 * 1024 * 1024
)
const (
ReleaseChannel = "release"
AlphaChannel = "alpha"
)
// CoreUpdater is the mihomo updater.
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go
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()
defer u.mu.Unlock()
_, err = os.Stat(currentExePath)
info, err := os.Stat(currentExePath)
if err != nil {
return fmt.Errorf("check currentExePath %q: %w", currentExePath, err)
}
baseURL := baseAlphaURL
versionURL := versionAlphaURL
if !strings.HasPrefix(C.Version, "alpha") {
switch strings.ToLower(channel) {
case ReleaseChannel:
baseURL = baseReleaseURL
versionURL = versionReleaseURL
case AlphaChannel:
break
default: // auto
if !strings.HasPrefix(C.Version, "alpha") {
baseURL = baseReleaseURL
versionURL = versionReleaseURL
}
}
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)
if latestVersion == C.Version {
if latestVersion == C.Version && !force {
// 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)
}
@@ -136,7 +149,7 @@ func (u *CoreUpdater) Update(currentExePath string) (err error) {
return fmt.Errorf("downloading: %w", err)
}
err = u.unpack(updateDir, packagePath)
err = u.unpack(updateDir, packagePath, info.Mode())
if err != nil {
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.
func (u *CoreUpdater) unpack(updateDir, packagePath string) error {
func (u *CoreUpdater) unpack(updateDir, packagePath string, fileMode os.FileMode) error {
log.Infoln("updater: unpacking package")
if strings.HasSuffix(packagePath, ".zip") {
_, err := u.zipFileUnpack(packagePath, updateDir)
_, err := u.zipFileUnpack(packagePath, updateDir, fileMode)
if err != nil {
return fmt.Errorf(".zip unpack failed: %w", err)
}
} else if strings.HasSuffix(packagePath, ".gz") {
_, err := u.gzFileUnpack(packagePath, updateDir)
_, err := u.gzFileUnpack(packagePath, updateDir, fileMode)
if err != nil {
return fmt.Errorf(".gz unpack failed: %w", err)
}
@@ -295,7 +308,7 @@ func (u *CoreUpdater) clean(updateDir string) {
// Existing files are overwritten
// All files are created inside outDir, subdirectories are not created
// 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)
if err != nil {
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)
// 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 {
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
// All files are created inside 'outDir', subdirectories are not created
// 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)
if err != nil {
return "", fmt.Errorf("zip.OpenReader(): %w", err)
@@ -394,7 +407,7 @@ func (u *CoreUpdater) zipFileUnpack(zipfile, outDir string) (outputName string,
}
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 {
return "", fmt.Errorf("os.OpenFile(): %w", err)
}

View File

@@ -22,7 +22,7 @@ require (
github.com/metacubex/chacha v0.1.5
github.com/metacubex/fswatch v0.1.1
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/sing v0.5.4
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/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/quic-go v0.53.1-0.20250628094454-fda5262d1d9c h1:ABQzmOaZddM3q0OYeoZEc0XF+KW+dUdPNvY/c5rsunI=
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 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs=
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/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
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
}
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 {
log.Warnln("%s", err)
render.Status(r, http.StatusInternalServerError)

View File

@@ -6,12 +6,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=adguardhome
PKG_VERSION:=0.107.63
PKG_VERSION:=0.107.64
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:=f445eb98fc1beba326433da7c999799fe36c7f15297fdebe59a41914eaffe3ad
PKG_HASH:=a6b61d3c102fa47072a7230382d438f3d408f74ffae3aff7d330adad90ed169c
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:=74bda6f7c7334342b33fff50a0cdff4e206f84a471bab983ee16d3f6f112c53a
HASH:=f0c1e4d6e673d4d26d52947cdb220682aa554158d331fa044576d1794b82e325
endef
define Build/Prepare

View File

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

View File

@@ -223,4 +223,28 @@ public static class FileManager
// 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 ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_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 DefaultNetwork = "tcp";

View File

@@ -1,6 +1,7 @@
using System.Diagnostics;
using System.Text;
using CliWrap;
using CliWrap.Buffered;
namespace ServiceLib.Handler;
@@ -11,6 +12,7 @@ public class CoreAdminHandler
private Config _config;
private Action<bool, string>? _updateFunc;
private int _linuxSudoPid = -1;
private const string _tag = "CoreAdminHandler";
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)
{
StringBuilder sb = new();
sb.AppendLine("#!/bin/bash");
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()
{
@@ -87,35 +92,27 @@ public class CoreAdminHandler
return;
}
var cmdLine = $"pkill -P {_linuxSudoPid} ; kill {_linuxSudoPid}";
var shFilePath = await CreateLinuxShellFile(cmdLine, "kill_as_sudo.sh");
try
{
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)
.WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd))
.ExecuteAsync();
UpdateFunc(false, result.StandardOutput.ToString());
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
_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)
{
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
if (!File.Exists(fileName))
{
var contents = EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName);
await File.AppendAllTextAsync(fileName, contents);
await Utils.SetLinuxChmod(fileName);
}
var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false);
await Utils.GetCliWrapOutput(fileName, args);
}

View File

@@ -23,14 +23,7 @@ public class ProxySettingOSX
private static async Task ExecCmd(List<string> args)
{
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
if (!File.Exists(fileName))
{
var contents = EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName);
await File.AppendAllTextAsync(fileName, contents);
await Utils.SetLinuxChmod(fileName);
}
var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false);
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\dns_singbox_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\proxy_set_linux_sh" />
<EmbeddedResource Include="Sample\proxy_set_osx_sh" />

View File

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

View File

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

View File

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

View File

@@ -28,13 +28,13 @@ jobs:
fail-fast: true
matrix:
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:
# atleast one of each CPython/PyPy tests must be in windows
- os: windows-latest
python-version: '3.9'
- os: windows-latest
python-version: pypy-3.10
python-version: pypy-3.11
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}

View File

@@ -25,7 +25,7 @@ jobs:
fail-fast: false
matrix:
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:
- uses: actions/checkout@v4
- 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`).
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:
```shell

View File

@@ -172,7 +172,7 @@ python3 -m pip install -U --pre "yt-dlp[default]"
```
## 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
<!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:
raise http.cookiejar.LoadError(f'invalid length {len(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}')
return line

View File

@@ -33,7 +33,6 @@ from ..utils import (
unified_timestamp,
url_or_none,
urlhandle_detect_ext,
variadic,
)
@@ -232,6 +231,23 @@ class ArchiveOrgIE(InfoExtractor):
'release_date': '19950402',
'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
@@ -274,34 +290,40 @@ class ArchiveOrgIE(InfoExtractor):
m = metadata['metadata']
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,
'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}',
'location': m.get('venue'),
'release_year': int_or_none(m.get('year'))}
})
for f in metadata['files']:
if f['name'] in entries:
entries[f['name']] = merge_dicts(entries[f['name']], {
'id': identifier + '/' + f['name'],
'title': f.get('title') or f['name'],
'display_id': f['name'],
'description': clean_html(f.get('description')),
'creators': traverse_obj(f, ('creator', {variadic}, {lambda x: x[0] and list(x)})),
'duration': parse_duration(f.get('length')),
'track_number': int_or_none(f.get('track')),
'album': f.get('album'),
'discnumber': int_or_none(f.get('disc')),
'release_year': int_or_none(f.get('year'))})
**traverse_obj(f, {
'title': (('title', 'name'), {str}, any),
'display_id': ('name', {str}),
'description': ('description', ({str}, (..., all, {' '.join})), {clean_html}, filter, any),
'creators': ('creator', (None, ...), {str}, filter, all, filter),
'duration': ('length', {parse_duration}),
'track_number': ('track', {int_or_none}),
'album': ('album', {str}),
'discnumber': ('disc', {int_or_none}),
'release_year': ('year', {int_or_none}),
}),
})
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']]
else:
continue