From 643032245f2b27d24405f4a54ba3dee16c89a48c Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Sat, 6 Dec 2025 19:36:48 +0100 Subject: [PATCH] Update On Sat Dec 6 19:36:47 CET 2025 --- .github/update.log | 1 + .../process/process_freebsd_amd64.go | 4 + clash-nyanpasu/manifest/version.json | 6 +- filebrowser/CHANGELOG.md | 17 ++ filebrowser/Dockerfile | 2 +- filebrowser/auth/hook.go | 4 +- filebrowser/auth/proxy.go | 4 +- filebrowser/cmd/config.go | 12 +- filebrowser/errors/errors.go | 2 +- filebrowser/files/file.go | 6 +- .../src/components/files/CsvViewer.vue | 59 +++- filebrowser/frontend/src/i18n/ar.json | 5 + filebrowser/frontend/src/i18n/bg.json | 5 + filebrowser/frontend/src/i18n/ca.json | 5 + filebrowser/frontend/src/i18n/cs.json | 5 + filebrowser/frontend/src/i18n/de.json | 23 +- filebrowser/frontend/src/i18n/el.json | 5 + filebrowser/frontend/src/i18n/en.json | 5 + filebrowser/frontend/src/i18n/es.json | 5 + filebrowser/frontend/src/i18n/fa.json | 5 + filebrowser/frontend/src/i18n/fr.json | 5 + filebrowser/frontend/src/i18n/he.json | 5 + filebrowser/frontend/src/i18n/hr.json | 5 + filebrowser/frontend/src/i18n/hu.json | 5 + filebrowser/frontend/src/i18n/is.json | 5 + filebrowser/frontend/src/i18n/it.json | 5 + filebrowser/frontend/src/i18n/ja.json | 5 + filebrowser/frontend/src/i18n/ko.json | 5 + filebrowser/frontend/src/i18n/nl-be.json | 5 + filebrowser/frontend/src/i18n/no.json | 5 + filebrowser/frontend/src/i18n/pl.json | 5 + filebrowser/frontend/src/i18n/pt-br.json | 5 + filebrowser/frontend/src/i18n/pt.json | 5 + filebrowser/frontend/src/i18n/ro.json | 5 + filebrowser/frontend/src/i18n/ru.json | 5 + filebrowser/frontend/src/i18n/sk.json | 5 + filebrowser/frontend/src/i18n/sv-se.json | 5 + filebrowser/frontend/src/i18n/tr.json | 5 + filebrowser/frontend/src/i18n/uk.json | 5 + filebrowser/frontend/src/i18n/vi.json | 5 + filebrowser/frontend/src/i18n/zh-cn.json | 5 + filebrowser/frontend/src/i18n/zh-tw.json | 5 + filebrowser/frontend/src/utils/csv.ts | 7 +- filebrowser/go.mod | 2 +- filebrowser/go.sum | 4 +- filebrowser/http/auth.go | 6 +- filebrowser/http/commands.go | 2 +- filebrowser/http/data.go | 2 +- filebrowser/http/headers.go | 2 +- filebrowser/http/http.go | 2 +- filebrowser/http/preview.go | 2 +- filebrowser/http/preview_enum.go | 2 +- filebrowser/http/public.go | 2 +- filebrowser/http/public_test.go | 2 +- filebrowser/http/raw.go | 2 +- filebrowser/http/resource.go | 14 +- filebrowser/http/search.go | 2 +- filebrowser/http/settings.go | 2 +- filebrowser/http/share.go | 8 +- filebrowser/http/static.go | 2 +- filebrowser/http/subtitle.go | 2 +- filebrowser/http/tus_handlers.go | 2 +- filebrowser/http/users.go | 12 +- filebrowser/http/utils.go | 2 +- filebrowser/settings/storage.go | 4 +- filebrowser/share/storage.go | 4 +- filebrowser/storage/bolt/auth.go | 4 +- filebrowser/storage/bolt/share.go | 12 +- filebrowser/storage/bolt/users.go | 10 +- filebrowser/storage/bolt/utils.go | 4 +- filebrowser/users/password.go | 6 +- filebrowser/users/storage.go | 8 +- filebrowser/users/users.go | 6 +- .../process/process_freebsd_amd64.go | 4 + openwrt-packages/filebrowser/Makefile | 4 +- .../model/cbi/passwall/client/node_config.lua | 4 +- .../cbi/passwall/client/node_subscribe.lua | 9 +- .../passwall/client/node_subscribe_config.lua | 9 +- .../cbi/passwall/client/socks_config.lua | 54 ++-- .../model/cbi/passwall/client/type/ray.lua | 44 +-- .../cbi/passwall/client/type/sing-box.lua | 44 +-- .../luci-app-passwall/luasrc/passwall/api.lua | 8 +- .../view/passwall/cbi/nodes_multiselect.htm | 260 ++++++++++++++++++ .../luci-app-passwall/po/zh-cn/passwall.po | 6 + sing-box/common/dialer/default.go | 15 +- sing-box/constant/timeout.go | 2 +- sing-box/docs/changelog.md | 24 +- sing-box/docs/configuration/shared/dial.md | 27 +- sing-box/docs/configuration/shared/dial.zh.md | 26 ++ sing-box/docs/configuration/shared/listen.md | 22 ++ .../docs/configuration/shared/listen.zh.md | 22 ++ sing-box/option/outbound.go | 38 +-- .../luasrc/controller/passwall.lua | 10 + .../view/passwall/node_list/node_list.htm | 81 +++++- small/v2ray-geodata/Makefile | 4 +- v2rayng/README.md | 2 +- .../src/main/java/com/v2ray/ang/AppConfig.kt | 3 +- v2rayng/V2rayNG/gradle/libs.versions.toml | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- yt-dlp/yt_dlp/extractor/loom.py | 66 +++-- 100 files changed, 977 insertions(+), 248 deletions(-) create mode 100644 openwrt-passwall/luci-app-passwall/luasrc/view/passwall/cbi/nodes_multiselect.htm diff --git a/.github/update.log b/.github/update.log index f43936d03b..4d5e11ded2 100644 --- a/.github/update.log +++ b/.github/update.log @@ -1203,3 +1203,4 @@ Update On Tue Dec 2 19:43:40 CET 2025 Update On Wed Dec 3 19:42:45 CET 2025 Update On Thu Dec 4 19:44:01 CET 2025 Update On Fri Dec 5 19:41:34 CET 2025 +Update On Sat Dec 6 19:36:39 CET 2025 diff --git a/clash-meta/component/process/process_freebsd_amd64.go b/clash-meta/component/process/process_freebsd_amd64.go index cb43c5ffd3..a6d00c8e15 100644 --- a/clash-meta/component/process/process_freebsd_amd64.go +++ b/clash-meta/component/process/process_freebsd_amd64.go @@ -197,6 +197,10 @@ func newSearcher(major int) *searcher { case 12: fallthrough case 13: + fallthrough + case 14: + fallthrough + case 15: s = &searcher{ headSize: 64, tcpItemSize: 744, diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 875ddc165d..44a3134202 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,10 +2,10 @@ "manifest_version": 1, "latest": { "mihomo": "v1.19.17", - "mihomo_alpha": "alpha-6539b50", + "mihomo_alpha": "alpha-f44aa22", "clash_rs": "v0.9.2", "clash_premium": "2023-09-05-gdcc8d87", - "clash_rs_alpha": "0.9.2-alpha+sha.e1f8fbb" + "clash_rs_alpha": "0.9.2-alpha+sha.81f5ac5" }, "arch_template": { "mihomo": { @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-12-04T22:21:10.965Z" + "updated_at": "2025-12-05T22:21:23.531Z" } diff --git a/filebrowser/CHANGELOG.md b/filebrowser/CHANGELOG.md index e9eef70a10..05671b1d3c 100644 --- a/filebrowser/CHANGELOG.md +++ b/filebrowser/CHANGELOG.md @@ -2,6 +2,23 @@ All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. +## [2.51.0](https://github.com/filebrowser/filebrowser/compare/v2.50.0...v2.51.0) (2025-12-06) + + +### Features + +* update translations ([2d88c06](https://github.com/filebrowser/filebrowser/commit/2d88c067611e936056dbbf04247f1c1c709b2a09)) + + +### Bug Fixes + +* added column separator select (comma, semicolon and both) in CSV viewer ([#5604](https://github.com/filebrowser/filebrowser/issues/5604)) ([204a3f0](https://github.com/filebrowser/filebrowser/commit/204a3f0eeaa0c68781b60651bf27c4b27eac44e6)) + + +### Refactorings + +* cleanup package names ([#5605](https://github.com/filebrowser/filebrowser/issues/5605)) ([f029c30](https://github.com/filebrowser/filebrowser/commit/f029c3005e450cfbebb074c42dbdf65db9c8d56a)) + ## [2.50.0](https://github.com/filebrowser/filebrowser/compare/v2.49.0...v2.50.0) (2025-11-30) diff --git a/filebrowser/Dockerfile b/filebrowser/Dockerfile index 8bd825da85..92bbe1d464 100644 --- a/filebrowser/Dockerfile +++ b/filebrowser/Dockerfile @@ -1,5 +1,5 @@ ## Multistage build: First stage fetches dependencies -FROM alpine:3.22 AS fetcher +FROM alpine:3.23 AS fetcher # install and copy ca-certificates, mailcap, and tini-static; download JSON.sh RUN apk update && \ diff --git a/filebrowser/auth/hook.go b/filebrowser/auth/hook.go index ec3c5bfb05..9bb389690d 100644 --- a/filebrowser/auth/hook.go +++ b/filebrowser/auth/hook.go @@ -11,7 +11,7 @@ import ( "slices" "strings" - fbErrors "github.com/filebrowser/filebrowser/v2/errors" + fberrors "github.com/filebrowser/filebrowser/v2/errors" "github.com/filebrowser/filebrowser/v2/files" "github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/users" @@ -146,7 +146,7 @@ func (a *HookAuth) GetValues(s string) { // SaveUser updates the existing user or creates a new one when not found func (a *HookAuth) SaveUser() (*users.User, error) { u, err := a.Users.Get(a.Server.Root, a.Cred.Username) - if err != nil && !errors.Is(err, fbErrors.ErrNotExist) { + if err != nil && !errors.Is(err, fberrors.ErrNotExist) { return nil, err } diff --git a/filebrowser/auth/proxy.go b/filebrowser/auth/proxy.go index 301aa292f8..3f4a627ca1 100644 --- a/filebrowser/auth/proxy.go +++ b/filebrowser/auth/proxy.go @@ -4,7 +4,7 @@ import ( "errors" "net/http" - fbErrors "github.com/filebrowser/filebrowser/v2/errors" + fberrors "github.com/filebrowser/filebrowser/v2/errors" "github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/users" ) @@ -21,7 +21,7 @@ type ProxyAuth struct { func (a ProxyAuth) Auth(r *http.Request, usr users.Store, setting *settings.Settings, srv *settings.Server) (*users.User, error) { username := r.Header.Get(a.Header) user, err := usr.Get(srv.Root, username) - if errors.Is(err, fbErrors.ErrNotExist) { + if errors.Is(err, fberrors.ErrNotExist) { return a.createUser(usr, setting, srv, username) } return user, err diff --git a/filebrowser/cmd/config.go b/filebrowser/cmd/config.go index 93ba29dfb3..4766c389b1 100644 --- a/filebrowser/cmd/config.go +++ b/filebrowser/cmd/config.go @@ -2,7 +2,7 @@ package cmd import ( "encoding/json" - nerrors "errors" + "errors" "fmt" "os" "strings" @@ -12,7 +12,7 @@ import ( "github.com/spf13/pflag" "github.com/filebrowser/filebrowser/v2/auth" - "github.com/filebrowser/filebrowser/v2/errors" + fberrors "github.com/filebrowser/filebrowser/v2/errors" "github.com/filebrowser/filebrowser/v2/settings" ) @@ -104,7 +104,7 @@ func getProxyAuth(flags *pflag.FlagSet, defaultAuther map[string]interface{}) (a } if header == "" { - return nil, nerrors.New("you must set the flag 'auth.header' for method 'proxy'") + return nil, errors.New("you must set the flag 'auth.header' for method 'proxy'") } return &auth.ProxyAuth{Header: header}, nil @@ -163,7 +163,7 @@ func getHookAuth(flags *pflag.FlagSet, defaultAuther map[string]interface{}) (au } if command == "" { - return nil, nerrors.New("you must set the flag 'auth.command' for method 'hook'") + return nil, errors.New("you must set the flag 'auth.command' for method 'hook'") } return &auth.HookAuth{Command: command}, nil @@ -186,7 +186,7 @@ func getAuthentication(flags *pflag.FlagSet, defaults ...interface{}) (settings. case auth.MethodHookAuth: auther, err = getHookAuth(flags, defaultAuther) default: - return "", nil, errors.ErrInvalidAuthMethod + return "", nil, fberrors.ErrInvalidAuthMethod } if err != nil { @@ -361,7 +361,7 @@ func getSettings(flags *pflag.FlagSet, set *settings.Settings, ser *settings.Ser flags.Visit(visit) } - err := nerrors.Join(errs...) + err := errors.Join(errs...) if err != nil { return nil, err } diff --git a/filebrowser/errors/errors.go b/filebrowser/errors/errors.go index 5fd760c212..85258e5b52 100644 --- a/filebrowser/errors/errors.go +++ b/filebrowser/errors/errors.go @@ -1,4 +1,4 @@ -package errors +package fberrors import ( "errors" diff --git a/filebrowser/files/file.go b/filebrowser/files/file.go index 0f96440ed3..5ce0aee772 100644 --- a/filebrowser/files/file.go +++ b/filebrowser/files/file.go @@ -23,7 +23,7 @@ import ( "github.com/spf13/afero" - fbErrors "github.com/filebrowser/filebrowser/v2/errors" + fberrors "github.com/filebrowser/filebrowser/v2/errors" "github.com/filebrowser/filebrowser/v2/rules" ) @@ -168,7 +168,7 @@ func stat(opts *FileOptions) (*FileInfo, error) { // algorithm. The checksums data is saved on File object. func (i *FileInfo) Checksum(algo string) error { if i.IsDir { - return fbErrors.ErrIsDirectory + return fberrors.ErrIsDirectory } if i.Checksums == nil { @@ -193,7 +193,7 @@ func (i *FileInfo) Checksum(algo string) error { case "sha512": h = sha512.New() default: - return fbErrors.ErrInvalidOption + return fberrors.ErrInvalidOption } _, err = io.Copy(h, reader) diff --git a/filebrowser/frontend/src/components/files/CsvViewer.vue b/filebrowser/frontend/src/components/files/CsvViewer.vue index 180cf7e21a..4f66fff075 100644 --- a/filebrowser/frontend/src/components/files/CsvViewer.vue +++ b/filebrowser/frontend/src/components/files/CsvViewer.vue @@ -25,9 +25,29 @@ -
- info - Showing {{ data.rows.length }} rows +
@@ -35,7 +55,7 @@ diff --git a/openwrt-passwall/luci-app-passwall/po/zh-cn/passwall.po b/openwrt-passwall/luci-app-passwall/po/zh-cn/passwall.po index f6ca3935d1..04d5303a6f 100644 --- a/openwrt-passwall/luci-app-passwall/po/zh-cn/passwall.po +++ b/openwrt-passwall/luci-app-passwall/po/zh-cn/passwall.po @@ -388,6 +388,9 @@ msgstr "置顶" msgid "Select" msgstr "选择" +msgid "Selected:" +msgstr "已选:" + msgid "DeSelect" msgstr "反选" @@ -2016,3 +2019,6 @@ msgstr "调整节点分组" msgid "Currently using %s node" msgstr "当前使用的 %s 节点" + +msgid "Search nodes..." +msgstr "搜索节点…" diff --git a/sing-box/common/dialer/default.go b/sing-box/common/dialer/default.go index 06f637a3ae..6373f2d177 100644 --- a/sing-box/common/dialer/default.go +++ b/sing-box/common/dialer/default.go @@ -143,9 +143,18 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial } else { dialer.Timeout = C.TCPConnectTimeout } - // TODO: Add an option to customize the keep alive period - dialer.KeepAlive = C.TCPKeepAliveInitial - dialer.Control = control.Append(dialer.Control, control.SetKeepAlivePeriod(C.TCPKeepAliveInitial, C.TCPKeepAliveInterval)) + if options.TCPKeepAlive >= 0 { + keepIdle := time.Duration(options.TCPKeepAlive) + if keepIdle == 0 { + keepIdle = C.TCPKeepAliveInitial + } + keepInterval := time.Duration(options.TCPKeepAliveInterval) + if keepInterval == 0 { + keepInterval = C.TCPKeepAliveInterval + } + dialer.KeepAlive = keepIdle + dialer.Control = control.Append(dialer.Control, control.SetKeepAlivePeriod(keepIdle, keepInterval)) + } var udpFragment bool if options.UDPFragment != nil { udpFragment = *options.UDPFragment diff --git a/sing-box/constant/timeout.go b/sing-box/constant/timeout.go index eb0fd34c05..e1bc7ccdf2 100644 --- a/sing-box/constant/timeout.go +++ b/sing-box/constant/timeout.go @@ -3,7 +3,7 @@ package constant import "time" const ( - TCPKeepAliveInitial = 10 * time.Minute + TCPKeepAliveInitial = 5 * time.Minute TCPKeepAliveInterval = 75 * time.Second TCPConnectTimeout = 5 * time.Second TCPTimeout = 15 * time.Second diff --git a/sing-box/docs/changelog.md b/sing-box/docs/changelog.md index 0ef84e0ffd..b65ba9fbfe 100644 --- a/sing-box/docs/changelog.md +++ b/sing-box/docs/changelog.md @@ -5,13 +5,29 @@ icon: material/alert-decagram #### 1.13.0-alpha.28 * Update quic-go to v0.57.1 +* Add `tcp_keep_alive` and `tcp_keep_alive_interval` options for dial fields **1** +* Update default TCP keep-alive initial period from 10 minutes to 5 minutes * Fixes and improvements -Unfortunately, for non-technical reasons, we are currently unable to notarize a standalone version of the macOS client: -because system extensions require signatures to function, we have had to temporarily halt its release. +**1**: -We plan to fix the App Store release issue and launch a new standalone desktop client, but until then, -only clients on TestFlight will be available (unless you have an Apple Developer Program and compile from source code). +See [Dial Fields](/configuration/shared/dial/#tcp_keep_alive). + +__Unfortunately, for non-technical reasons, we are currently unable to notarize the standalone version of the macOS client: +because system extensions require signatures to function, we have had to temporarily halt its release.__ + +__We plan to fix the App Store release issue and launch a new standalone desktop client, but until then, +only clients on TestFlight will be available (unless you have an Apple Developer Program and compile from source code).__ + +#### 1.12.13 + +* Fixes and improvements + +__Unfortunately, for non-technical reasons, we are currently unable to notarize the standalone version of the macOS client: +because system extensions require signatures to function, we have had to temporarily halt its release.__ + +__We plan to fix the App Store release issue and launch a new standalone desktop client, but until then, +only clients on TestFlight will be available (unless you have an Apple Developer Program and compile from source code).__ #### 1.12.12 diff --git a/sing-box/docs/configuration/shared/dial.md b/sing-box/docs/configuration/shared/dial.md index f48f355d9b..49922e60c0 100644 --- a/sing-box/docs/configuration/shared/dial.md +++ b/sing-box/docs/configuration/shared/dial.md @@ -2,6 +2,11 @@ icon: material/new-box --- +!!! quote "Changes in sing-box 1.13.0" + + :material-plus: [tcp_keep_alive](#tcp_keep_alive) + :material-plus: [tcp_keep_alive_interval](#tcp_keep_alive_interval) + !!! quote "Changes in sing-box 1.12.0" :material-plus: [domain_resolver](#domain_resolver) @@ -29,8 +34,10 @@ icon: material/new-box "connect_timeout": "", "tcp_fast_open": false, "tcp_multi_path": false, + "tcp_keep_alive": "", + "tcp_keep_alive_interval": "", "udp_fragment": false, - + "domain_resolver": "", // or {} "network_strategy": "", "network_type": [], @@ -112,6 +119,24 @@ Enable TCP Fast Open. Enable TCP Multi Path. +#### tcp_keep_alive + +!!! question "Since sing-box 1.13.0" + + Default value changed from `10m` to `5m`. + +TCP keep-alive initial period. + +`5m` will be used by default. + +#### tcp_keep_alive_interval + +!!! question "Since sing-box 1.13.0" + +TCP keep-alive interval. + +`75s` will be used by default. + #### udp_fragment Enable UDP fragmentation. diff --git a/sing-box/docs/configuration/shared/dial.zh.md b/sing-box/docs/configuration/shared/dial.zh.md index babb43e983..1280897f5e 100644 --- a/sing-box/docs/configuration/shared/dial.zh.md +++ b/sing-box/docs/configuration/shared/dial.zh.md @@ -2,6 +2,11 @@ icon: material/new-box --- +!!! quote "sing-box 1.13.0 中的更改" + + :material-plus: [tcp_keep_alive](#tcp_keep_alive) + :material-plus: [tcp_keep_alive_interval](#tcp_keep_alive_interval) + !!! quote "sing-box 1.12.0 中的更改" :material-plus: [domain_resolver](#domain_resolver) @@ -29,7 +34,10 @@ icon: material/new-box "connect_timeout": "", "tcp_fast_open": false, "tcp_multi_path": false, + "tcp_keep_alive": "", + "tcp_keep_alive_interval": "", "udp_fragment": false, + "domain_resolver": "", // 或 {} "network_strategy": "", "network_type": [], @@ -109,6 +117,24 @@ icon: material/new-box 启用 TCP Multi Path。 +#### tcp_keep_alive + +!!! question "自 sing-box 1.13.0 起" + + 默认值从 `10m` 更改为 `5m`。 + +TCP keep-alive 初始周期。 + +默认使用 `5m`。 + +#### tcp_keep_alive_interval + +!!! question "自 sing-box 1.13.0 起" + +TCP keep-alive 间隔。 + +默认使用 `75s`。 + #### udp_fragment 启用 UDP 分段。 diff --git a/sing-box/docs/configuration/shared/listen.md b/sing-box/docs/configuration/shared/listen.md index 4040e42f07..5feb2bcc9b 100644 --- a/sing-box/docs/configuration/shared/listen.md +++ b/sing-box/docs/configuration/shared/listen.md @@ -2,6 +2,10 @@ icon: material/new-box --- +!!! quote "Changes in sing-box 1.13.0" + + :material-alert: [tcp_keep_alive](#tcp_keep_alive) + !!! quote "Changes in sing-box 1.12.0" :material-plus: [netns](#netns) @@ -29,6 +33,8 @@ icon: material/new-box "netns": "", "tcp_fast_open": false, "tcp_multi_path": false, + "tcp_keep_alive": "", + "tcp_keep_alive_interval": "", "udp_fragment": false, "udp_timeout": "", "detour": "", @@ -101,6 +107,22 @@ Enable TCP Fast Open. Enable TCP Multi Path. +#### tcp_keep_alive + +!!! question "Since sing-box 1.13.0" + + Default value changed from `10m` to `5m`. + +TCP keep-alive initial period. + +`5m` will be used by default. + +#### tcp_keep_alive_interval + +TCP keep-alive interval. + +`75s` will be used by default. + #### udp_fragment Enable UDP fragmentation. diff --git a/sing-box/docs/configuration/shared/listen.zh.md b/sing-box/docs/configuration/shared/listen.zh.md index cd12036ca3..c99aeff5c4 100644 --- a/sing-box/docs/configuration/shared/listen.zh.md +++ b/sing-box/docs/configuration/shared/listen.zh.md @@ -2,6 +2,10 @@ icon: material/new-box --- +!!! quote "sing-box 1.13.0 中的更改" + + :material-alert: [tcp_keep_alive](#tcp_keep_alive) + !!! quote "Changes in sing-box 1.12.0" :material-plus: [netns](#netns) @@ -29,6 +33,8 @@ icon: material/new-box "netns": "", "tcp_fast_open": false, "tcp_multi_path": false, + "tcp_keep_alive": "", + "tcp_keep_alive_interval": "", "udp_fragment": false, "udp_timeout": "", "detour": "", @@ -101,6 +107,22 @@ icon: material/new-box 启用 TCP Multi Path。 +#### tcp_keep_alive + +!!! question "自 sing-box 1.13.0 起" + + 默认值从 `10m` 更改为 `5m`。 + +TCP keep-alive 初始周期。 + +默认使用 `5m`。 + +#### tcp_keep_alive_interval + +TCP keep-alive 间隔。 + +默认使用 `75s`。 + #### udp_fragment 启用 UDP 分段。 diff --git a/sing-box/option/outbound.go b/sing-box/option/outbound.go index 2520d000f8..3f0651e8a0 100644 --- a/sing-box/option/outbound.go +++ b/sing-box/option/outbound.go @@ -65,24 +65,26 @@ type DialerOptionsWrapper interface { } type DialerOptions struct { - Detour string `json:"detour,omitempty"` - BindInterface string `json:"bind_interface,omitempty"` - Inet4BindAddress *badoption.Addr `json:"inet4_bind_address,omitempty"` - Inet6BindAddress *badoption.Addr `json:"inet6_bind_address,omitempty"` - ProtectPath string `json:"protect_path,omitempty"` - RoutingMark FwMark `json:"routing_mark,omitempty"` - ReuseAddr bool `json:"reuse_addr,omitempty"` - NetNs string `json:"netns,omitempty"` - ConnectTimeout badoption.Duration `json:"connect_timeout,omitempty"` - TCPFastOpen bool `json:"tcp_fast_open,omitempty"` - TCPMultiPath bool `json:"tcp_multi_path,omitempty"` - UDPFragment *bool `json:"udp_fragment,omitempty"` - UDPFragmentDefault bool `json:"-"` - DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"` - NetworkStrategy *NetworkStrategy `json:"network_strategy,omitempty"` - NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"` - FallbackNetworkType badoption.Listable[InterfaceType] `json:"fallback_network_type,omitempty"` - FallbackDelay badoption.Duration `json:"fallback_delay,omitempty"` + Detour string `json:"detour,omitempty"` + BindInterface string `json:"bind_interface,omitempty"` + Inet4BindAddress *badoption.Addr `json:"inet4_bind_address,omitempty"` + Inet6BindAddress *badoption.Addr `json:"inet6_bind_address,omitempty"` + ProtectPath string `json:"protect_path,omitempty"` + RoutingMark FwMark `json:"routing_mark,omitempty"` + ReuseAddr bool `json:"reuse_addr,omitempty"` + NetNs string `json:"netns,omitempty"` + ConnectTimeout badoption.Duration `json:"connect_timeout,omitempty"` + TCPFastOpen bool `json:"tcp_fast_open,omitempty"` + TCPMultiPath bool `json:"tcp_multi_path,omitempty"` + TCPKeepAlive badoption.Duration `json:"tcp_keep_alive,omitempty"` + TCPKeepAliveInterval badoption.Duration `json:"tcp_keep_alive_interval,omitempty"` + UDPFragment *bool `json:"udp_fragment,omitempty"` + UDPFragmentDefault bool `json:"-"` + DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"` + NetworkStrategy *NetworkStrategy `json:"network_strategy,omitempty"` + NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"` + FallbackNetworkType badoption.Listable[InterfaceType] `json:"fallback_network_type,omitempty"` + FallbackDelay badoption.Duration `json:"fallback_delay,omitempty"` // Deprecated: migrated to domain resolver DomainStrategy DomainStrategy `json:"domain_strategy,omitempty"` diff --git a/small/luci-app-passwall/luasrc/controller/passwall.lua b/small/luci-app-passwall/luasrc/controller/passwall.lua index 0c7400dd5a..6b5ed1211f 100644 --- a/small/luci-app-passwall/luasrc/controller/passwall.lua +++ b/small/luci-app-passwall/luasrc/controller/passwall.lua @@ -85,6 +85,7 @@ function index() entry({"admin", "services", appname, "reassign_group"}, call("reassign_group")).leaf = true entry({"admin", "services", appname, "get_node"}, call("get_node")).leaf = true entry({"admin", "services", appname, "save_node_order"}, call("save_node_order")).leaf = true + entry({"admin", "services", appname, "save_node_list_opt"}, call("save_node_list_opt")).leaf = true entry({"admin", "services", appname, "update_rules"}, call("update_rules")).leaf = true entry({"admin", "services", appname, "subscribe_del_node"}, call("subscribe_del_node")).leaf = true entry({"admin", "services", appname, "subscribe_del_all"}, call("subscribe_del_all")).leaf = true @@ -655,6 +656,15 @@ function reassign_group() http_write_json({ status = "ok" }) end +function save_node_list_opt() + local option = http.formvalue("option") or "" + local value = http.formvalue("value") or "" + if option ~= "" then + api.sh_uci_set(appname, "@global_other[0]", option, value, true) + end + http_write_json({ status = "ok" }) +end + function update_rules() local update = http.formvalue("update") luci.sys.call("lua /usr/share/passwall/rule_update.lua log '" .. update .. "' > /dev/null 2>&1 &") diff --git a/small/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/small/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm index 494c0912ea..707452e8a0 100644 --- a/small/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm +++ b/small/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm @@ -160,6 +160,11 @@ table td, .table .td { background-color: rgba(131, 191, 255, 0.7) !important; box-shadow: 0 4px 6px rgba(0,0,0,0.1); } + +/* hide save button */ +.cbi-page-actions { + display: none !important; +} <% if api.is_js_luci() then -%> @@ -215,7 +220,7 @@ table td, .table .td { //" let show_node_info = "<%=api.uci_get_type("global_other", "show_node_info", "0")%>" - + var node_list = []; var ajax = { @@ -552,7 +557,7 @@ table td, .table .td { ); } } - + function ping_node(cbi_id, dom, type) { var full = get_address_full(cbi_id); if ((type == "icmp" && full.address != "" ) || (type == "tcping" && full.address != "" && full.port != "")) { @@ -862,10 +867,10 @@ table td, .table .td { return str; } - XHR.get('<%=api.url("get_node")%>', null, - function(x, result) { + function loadNodeList() { + XHR.get('<%=api.url("get_node")%>', null, function(x, result) { var node_list = result - + var group_nodes = {} for (let i = 0; i < node_list.length; i++) { let _node = node_list[i] @@ -877,7 +882,7 @@ table td, .table .td { } group_nodes[_node.group].push(_node) } - + var tab_ul_html = '' tab_content_html += '' var tab_html = tab_ul_html + tab_content_html - + document.getElementById("node_list").innerHTML = tab_html - + for (let group in group_nodes) { cbi_t_add("passwall.nodes", group) } - + if (default_group) { cbi_t_switch("passwall.nodes", default_group) } @@ -983,12 +988,60 @@ table td, .table .td { } } } - + get_now_use_node(); pingAllNodes(); + }); + } + + loadNodeList(); + + //Node list option saving logic + document.addEventListener("DOMContentLoaded", function () { + function waitForElement(selector, callback) { + const el = document.querySelector(selector); + if (el) return callback(el); + const observer = new MutationObserver(() => { + const el = document.querySelector(selector); + if (el) { + observer.disconnect(); + callback(el); + } + }); + observer.observe(document.body, { childList: true, subtree: true }); } - ); + + function onChange(option, value) { + XHR.get('<%=api.url("save_node_list_opt")%>', { + option: option, + value: value + }, function(x) { + if (x && x.status == 200) { + document.getElementById("node_list").innerHTML = ""; + loadNodeList(); + } else { + alert("<%:Error%>"); + } + }); + } + + waitForElement('input[type="checkbox"][name*="passwall"][name*="show_node_info"]', function(el) { + el.addEventListener("change", () => { + el.blur(); + show_node_info = el.checked ? "1" : "0"; + onChange("show_node_info", show_node_info); + }); + }); + + waitForElement('select[name*="passwall"][name*="auto_detection_time"]', function(el) { + el.addEventListener("change", () => { + el.blur(); + auto_detection_time = el.value; + onChange("auto_detection_time", auto_detection_time); + }); + }); + }); //]]> diff --git a/small/v2ray-geodata/Makefile b/small/v2ray-geodata/Makefile index 48c2aa0c58..5f6967a879 100644 --- a/small/v2ray-geodata/Makefile +++ b/small/v2ray-geodata/Makefile @@ -21,13 +21,13 @@ define Download/geoip HASH:=6878dbacfb1fcb1ee022f63ed6934bcefc95a3c4ba10c88f1131fb88dbf7c337 endef -GEOSITE_VER:=20251205081953 +GEOSITE_VER:=20251206075552 GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER) define Download/geosite URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/ URL_FILE:=dlc.dat FILE:=$(GEOSITE_FILE) - HASH:=c99135dc54376b37185fd27a814435ab923f37ca6e6a784169cf743347c94beb + HASH:=f1276502c556709de5cc6c7581cb2e9369721c37dc6142aacf5771f7c60106f6 endef GEOSITE_IRAN_VER:=202512010051 diff --git a/v2rayng/README.md b/v2rayng/README.md index af99cf4546..87bd86507f 100644 --- a/v2rayng/README.md +++ b/v2rayng/README.md @@ -3,7 +3,7 @@ A V2Ray client for Android, support [Xray core](https://github.com/XTLS/Xray-core) and [v2fly core](https://github.com/v2fly/v2ray-core) [![API](https://img.shields.io/badge/API-21%2B-yellow.svg?style=flat)](https://developer.android.com/about/versions/lollipop) -[![Kotlin Version](https://img.shields.io/badge/Kotlin-2.2.0-blue.svg)](https://kotlinlang.org) +[![Kotlin Version](https://img.shields.io/badge/Kotlin-2.2.21-blue.svg)](https://kotlinlang.org) [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayNG)](https://github.com/2dust/v2rayNG/commits/master) [![CodeFactor](https://www.codefactor.io/repository/github/2dust/v2rayng/badge)](https://www.codefactor.io/repository/github/2dust/v2rayng) [![GitHub Releases](https://img.shields.io/github/downloads/2dust/v2rayNG/latest/total?logo=github)](https://github.com/2dust/v2rayNG/releases) diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt index ef6ffadbca..7f46835c2f 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/AppConfig.kt @@ -112,7 +112,8 @@ object AppConfig { const val TG_CHANNEL_URL = "https://t.me/github_2dust" const val DELAY_TEST_URL = "https://www.gstatic.com/generate_204" const val DELAY_TEST_URL2 = "https://www.google.com/generate_204" - const val IP_API_URL = "https://speed.cloudflare.com/meta" +// const val IP_API_URL = "https://speed.cloudflare.com/meta" + const val IP_API_URL = "https://api.ip.sb/geoip" /** DNS server addresses. */ const val DNS_PROXY = "1.1.1.1" diff --git a/v2rayng/V2rayNG/gradle/libs.versions.toml b/v2rayng/V2rayNG/gradle/libs.versions.toml index de4f7c100b..8c4f253047 100644 --- a/v2rayng/V2rayNG/gradle/libs.versions.toml +++ b/v2rayng/V2rayNG/gradle/libs.versions.toml @@ -1,8 +1,8 @@ [versions] -agp = "8.12.3" +agp = "8.13.1" desugarJdkLibs = "2.1.5" gradleLicensePlugin = "0.9.8" -kotlin = "2.2.20" +kotlin = "2.2.21" coreKtx = "1.16.0" junit = "4.13.2" junitVersion = "1.3.0" diff --git a/v2rayng/V2rayNG/gradle/wrapper/gradle-wrapper.properties b/v2rayng/V2rayNG/gradle/wrapper/gradle-wrapper.properties index 116f5b742c..f5e6168642 100644 --- a/v2rayng/V2rayNG/gradle/wrapper/gradle-wrapper.properties +++ b/v2rayng/V2rayNG/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Nov 14 12:42:51 BDT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/yt-dlp/yt_dlp/extractor/loom.py b/yt-dlp/yt_dlp/extractor/loom.py index b0878c33e2..ad989fc38f 100644 --- a/yt-dlp/yt_dlp/extractor/loom.py +++ b/yt-dlp/yt_dlp/extractor/loom.py @@ -8,12 +8,10 @@ from ..utils import ( ExtractorError, determine_ext, filter_dict, - get_first, int_or_none, parse_iso8601, update_url, url_or_none, - variadic, ) from ..utils.traversal import traverse_obj @@ -51,7 +49,7 @@ class LoomIE(InfoExtractor): }, { # m3u8 raw-url, mp4 transcoded-url, cdn url == raw-url, vtt sub and json subs 'url': 'https://www.loom.com/share/9458bcbf79784162aa62ffb8dd66201b', - 'md5': '51737ec002969dd28344db4d60b9cbbb', + 'md5': '7b6bfdef8181c4ffc376e18919a4dcc2', 'info_dict': { 'id': '9458bcbf79784162aa62ffb8dd66201b', 'ext': 'mp4', @@ -71,12 +69,13 @@ class LoomIE(InfoExtractor): 'ext': 'webm', 'title': 'OMFG clown', 'description': 'md5:285c5ee9d62aa087b7e3271b08796815', - 'uploader': 'MrPumkin B', + 'uploader': 'Brailey Bragg', 'upload_date': '20210924', 'timestamp': 1632519618, 'duration': 210, }, 'params': {'skip_download': 'dash'}, + 'expected_warnings': ['Failed to parse JSON'], # transcoded-url no longer available }, { # password-protected 'url': 'https://www.loom.com/share/50e26e8aeb7940189dff5630f95ce1f4', @@ -91,10 +90,11 @@ class LoomIE(InfoExtractor): 'duration': 35, }, 'params': {'videopassword': 'seniorinfants2'}, + 'expected_warnings': ['Failed to parse JSON'], # transcoded-url no longer available }, { # embed, transcoded-url endpoint sends empty JSON response, split video and audio HLS formats 'url': 'https://www.loom.com/embed/ddcf1c1ad21f451ea7468b1e33917e4e', - 'md5': 'b321d261656848c184a94e3b93eae28d', + 'md5': 'f983a0f02f24331738b2f43aecb05256', 'info_dict': { 'id': 'ddcf1c1ad21f451ea7468b1e33917e4e', 'ext': 'mp4', @@ -119,11 +119,12 @@ class LoomIE(InfoExtractor): 'duration': 247, 'timestamp': 1676274030, }, + 'skip': '404 Not Found', }] _GRAPHQL_VARIABLES = { 'GetVideoSource': { - 'acceptableMimes': ['DASH', 'M3U8', 'MP4'], + 'acceptableMimes': ['DASH', 'M3U8', 'MP4', 'WEBM'], }, } _GRAPHQL_QUERIES = { @@ -192,6 +193,12 @@ class LoomIE(InfoExtractor): id nullableRawCdnUrl(acceptableMimes: $acceptableMimes, password: $password) { url + credentials { + Policy + Signature + KeyPairId + __typename + } __typename } __typename @@ -240,9 +247,9 @@ class LoomIE(InfoExtractor): } }\n'''), } - _APOLLO_GRAPHQL_VERSION = '0a1856c' + _APOLLO_GRAPHQL_VERSION = '45a5bd4' - def _call_graphql_api(self, operations, video_id, note=None, errnote=None): + def _call_graphql_api(self, operation_name, video_id, note=None, errnote=None, fatal=True): password = self.get_param('videopassword') return self._download_json( 'https://www.loom.com/graphql', video_id, note or 'Downloading GraphQL JSON', @@ -252,7 +259,9 @@ class LoomIE(InfoExtractor): 'x-loom-request-source': f'loom_web_{self._APOLLO_GRAPHQL_VERSION}', 'apollographql-client-name': 'web', 'apollographql-client-version': self._APOLLO_GRAPHQL_VERSION, - }, data=json.dumps([{ + 'graphql-operation-name': operation_name, + 'Origin': 'https://www.loom.com', + }, data=json.dumps({ 'operationName': operation_name, 'variables': { 'videoId': video_id, @@ -260,7 +269,7 @@ class LoomIE(InfoExtractor): **self._GRAPHQL_VARIABLES.get(operation_name, {}), }, 'query': self._GRAPHQL_QUERIES[operation_name], - } for operation_name in variadic(operations)], separators=(',', ':')).encode()) + }, separators=(',', ':')).encode(), fatal=fatal) def _call_url_api(self, endpoint, video_id): response = self._download_json( @@ -275,7 +284,7 @@ class LoomIE(InfoExtractor): }, separators=(',', ':')).encode()) return traverse_obj(response, ('url', {url_or_none})) - def _extract_formats(self, video_id, metadata, gql_data): + def _extract_formats(self, video_id, metadata, video_data): formats = [] video_properties = traverse_obj(metadata, ('video_properties', { 'width': ('width', {int_or_none}), @@ -330,7 +339,7 @@ class LoomIE(InfoExtractor): transcoded_url = self._call_url_api('transcoded-url', video_id) formats.extend(get_formats(transcoded_url, 'transcoded', quality=-1)) # transcoded quality - cdn_url = get_first(gql_data, ('data', 'getVideo', 'nullableRawCdnUrl', 'url', {url_or_none})) + cdn_url = traverse_obj(video_data, ('data', 'getVideo', 'nullableRawCdnUrl', 'url', {url_or_none})) # cdn_url is usually a dupe, but the raw-url/transcoded-url endpoints could return errors valid_urls = [update_url(url, query=None) for url in (raw_url, transcoded_url) if url] if cdn_url and update_url(cdn_url, query=None) not in valid_urls: @@ -338,10 +347,21 @@ class LoomIE(InfoExtractor): return formats + def _get_subtitles(self, video_id): + subs_data = self._call_graphql_api( + 'FetchVideoTranscript', video_id, 'Downloading GraphQL subtitles JSON', fatal=False) + return filter_dict({ + 'en': traverse_obj(subs_data, ( + 'data', 'fetchVideoTranscript', + ('source_url', 'captions_source_url'), { + 'url': {url_or_none}, + })) or None, + }) + def _real_extract(self, url): video_id = self._match_id(url) - metadata = get_first( - self._call_graphql_api('GetVideoSSR', video_id, 'Downloading GraphQL metadata JSON'), + metadata = traverse_obj( + self._call_graphql_api('GetVideoSSR', video_id, 'Downloading GraphQL metadata JSON', fatal=False), ('data', 'getVideo', {dict})) or {} if metadata.get('__typename') == 'VideoPasswordMissingOrIncorrect': @@ -350,22 +370,19 @@ class LoomIE(InfoExtractor): 'This video is password-protected, use the --video-password option', expected=True) raise ExtractorError('Invalid video password', expected=True) - gql_data = self._call_graphql_api(['FetchChapters', 'FetchVideoTranscript', 'GetVideoSource'], video_id) + video_data = self._call_graphql_api( + 'GetVideoSource', video_id, 'Downloading GraphQL video JSON') + chapter_data = self._call_graphql_api( + 'FetchChapters', video_id, 'Downloading GraphQL chapters JSON', fatal=False) duration = traverse_obj(metadata, ('video_properties', 'duration', {int_or_none})) return { 'id': video_id, 'duration': duration, 'chapters': self._extract_chapters_from_description( - get_first(gql_data, ('data', 'fetchVideoChapters', 'content', {str})), duration) or None, - 'formats': self._extract_formats(video_id, metadata, gql_data), - 'subtitles': filter_dict({ - 'en': traverse_obj(gql_data, ( - ..., 'data', 'fetchVideoTranscript', - ('source_url', 'captions_source_url'), { - 'url': {url_or_none}, - })) or None, - }), + traverse_obj(chapter_data, ('data', 'fetchVideoChapters', 'content', {str})), duration) or None, + 'formats': self._extract_formats(video_id, metadata, video_data), + 'subtitles': self.extract_subtitles(video_id), **traverse_obj(metadata, { 'title': ('name', {str}), 'description': ('description', {str}), @@ -376,6 +393,7 @@ class LoomIE(InfoExtractor): class LoomFolderIE(InfoExtractor): + _WORKING = False IE_NAME = 'loom:folder' _VALID_URL = r'https?://(?:www\.)?loom\.com/share/folder/(?P[\da-f]{32})' _TESTS = [{