From 9e781f8d942ad8a86ac178b50633ffc67e4da4ea Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Sat, 6 Jul 2024 20:29:38 +0200 Subject: [PATCH] Update On Sat Jul 6 20:29:38 CEST 2024 --- .github/update.log | 1 + clash-nyanpasu/backend/Cargo.lock | 2 + clash-nyanpasu/backend/tauri/Cargo.toml | 4 + clash-nyanpasu/backend/tauri/src/main.rs | 8 + .../backend/tauri/src/utils/resolve.rs | 59 ++- clash-nyanpasu/frontend/nyanpasu/package.json | 2 +- .../src/components/app/app-container.tsx | 15 +- .../src/components/app/app-drawer.tsx | 9 +- clash-nyanpasu/manifest/version.json | 4 +- clash-nyanpasu/package.json | 2 +- clash-nyanpasu/pnpm-lock.yaml | 186 +++---- clash-verge-rev/UPDATELOG.md | 15 + clash-verge-rev/package.json | 8 +- clash-verge-rev/pnpm-lock.yaml | 156 +++--- clash-verge-rev/src-tauri/Cargo.lock | 489 ++++++++++-------- clash-verge-rev/src-tauri/Cargo.toml | 2 +- clash-verge-rev/src-tauri/tauri.conf.json | 2 +- .../src/components/profile/group-item.tsx | 2 +- .../profile/groups-editor-viewer.tsx | 67 ++- .../profile/proxies-editor-viewer.tsx | 77 +-- .../src/components/profile/proxy-item.tsx | 2 +- .../src/components/profile/rule-item.tsx | 15 +- .../profile/rules-editor-viewer.tsx | 24 +- .../setting/mods/sysproxy-viewer.tsx | 4 +- clash-verge-rev/src/services/types.d.ts | 55 +- clash-verge-rev/src/utils/uri-parser.ts | 93 +++- geoip/lib/common.go | 21 + geoip/lib/container.go | 183 +++++++ geoip/lib/{func.go => converter.go} | 16 - geoip/lib/entry.go | 328 ++++++++++++ geoip/lib/error.go | 2 + geoip/lib/lib.go | 425 +-------------- geoip/plugin/maxmind/country_csv.go | 17 +- geoip/plugin/maxmind/mmdb_in.go | 25 +- geoip/plugin/plaintext/text_in.go | 8 +- geoip/plugin/singbox/srs_in.go | 29 +- geoip/plugin/special/cutter.go | 4 +- geoip/plugin/special/private.go | 4 +- geoip/plugin/special/stdin.go | 29 +- geoip/plugin/special/stdout.go | 32 +- geoip/plugin/special/test.go | 4 +- geoip/plugin/v2ray/dat_in.go | 26 +- geoip/plugin/v2ray/dat_out.go | 6 +- .../base-files/files/bin/config_generate | 8 +- .../files/zzz-default-settings | 28 +- .../arm64/boot/dts/qcom/ipq6000-360v6.dts | 8 +- .../arm64/boot/dts/qcom/ipq6010-re-cs-02.dts | 3 +- openwrt-packages/adguardhome/Makefile | 7 +- .../root/usr/share/passwall/iptables.sh | 2 +- .../root/usr/share/passwall/nftables.sh | 2 +- .../shadowsocks/src/relay/tcprelay/aead.rs | 4 +- shadowsocks-rust/src/service/local.rs | 4 +- shadowsocks-rust/src/service/manager.rs | 2 +- shadowsocks-rust/src/service/server.rs | 4 +- shadowsocks-rust/src/vparser/mod.rs | 2 +- .../root/usr/share/passwall/iptables.sh | 2 +- .../root/usr/share/passwall/nftables.sh | 2 +- v2rayu/Build/appdmg.sh | 4 - v2rayu/Build/build.plist | 20 +- v2rayu/Build/publish.sh | 13 - v2rayu/Build/release.sh | 45 +- v2rayu/Build/sign.sh | 23 - v2rayu/Build/sign_update | Bin 303168 -> 0 bytes v2rayu/Podfile | 7 +- v2rayu/Podfile.lock | 10 +- v2rayu/V2rayU.xcodeproj/project.pbxproj | 50 +- v2rayu/V2rayU/AppVersion.swift | 153 ++++-- v2rayu/V2rayU/Base.lproj/PreferenceDns.xib | 10 +- v2rayu/V2rayU/Info.plist | 12 +- v2rayu/V2rayU/Ping.swift | 2 - .../Preference/PreferenceSubscription.swift | 1 - v2rayu/V2rayU/V2rayLaunch.swift | 1 - v2rayu/V2rayU/V2rayServer.swift | 1 - v2rayu/V2rayU/V2raySubscription.swift | 1 - v2rayu/V2rayU/en.lproj/Localizable.strings | 1 - v2rayu/V2rayU/zh-HK.lproj/Localizable.strings | 1 - .../zh-HK.lproj/PreferenceRouting.strings | 58 +-- .../zh-Hans.lproj/PreferenceRouting.strings | 56 +- xray-core/go.mod | 2 +- xray-core/go.sum | 4 +- .../youtube_dl/extractor/yandexmusic.py | 1 + yt-dlp/yt_dlp/extractor/_extractors.py | 1 + yt-dlp/yt_dlp/extractor/abematv.py | 4 + yt-dlp/yt_dlp/extractor/cellebrite.py | 69 +-- yt-dlp/yt_dlp/extractor/chzzk.py | 37 +- yt-dlp/yt_dlp/extractor/swearnet.py | 64 +-- yt-dlp/yt_dlp/extractor/vidyard.py | 426 +++++++++++++++ yt-dlp/yt_dlp/extractor/vimeo.py | 87 ++-- yt-dlp/yt_dlp/utils/_utils.py | 37 +- 89 files changed, 2270 insertions(+), 1471 deletions(-) create mode 100644 geoip/lib/common.go create mode 100644 geoip/lib/container.go rename geoip/lib/{func.go => converter.go} (79%) create mode 100644 geoip/lib/entry.go delete mode 100755 v2rayu/Build/publish.sh delete mode 100755 v2rayu/Build/sign.sh delete mode 100755 v2rayu/Build/sign_update create mode 100644 yt-dlp/yt_dlp/extractor/vidyard.py diff --git a/.github/update.log b/.github/update.log index 75e1d8b45d..1af448faa1 100644 --- a/.github/update.log +++ b/.github/update.log @@ -694,3 +694,4 @@ Update On Tue Jul 2 20:34:08 CEST 2024 Update On Wed Jul 3 20:29:03 CEST 2024 Update On Thu Jul 4 20:30:48 CEST 2024 Update On Fri Jul 5 20:32:45 CEST 2024 +Update On Sat Jul 6 20:29:28 CEST 2024 diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index a98c7ec087..a0cedb8c3f 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -869,6 +869,7 @@ dependencies = [ "base64 0.22.1", "chrono", "clap", + "cocoa 0.25.0", "ctrlc", "dashmap 6.0.1", "deelevate", @@ -890,6 +891,7 @@ dependencies = [ "md-5", "nanoid", "num_cpus", + "objc", "once_cell", "open 5.2.0", "parking_lot", diff --git a/clash-nyanpasu/backend/tauri/Cargo.toml b/clash-nyanpasu/backend/tauri/Cargo.toml index f752c5fede..e4a544d04c 100644 --- a/clash-nyanpasu/backend/tauri/Cargo.toml +++ b/clash-nyanpasu/backend/tauri/Cargo.toml @@ -101,6 +101,10 @@ md-5 = "0.10.6" hex = "0.4" rand = "0.8" +[target.'cfg(target_os = "macos")'.dependencies] +cocoa = "0.25.0" +objc = "0.2.7" + [target.'cfg(windows)'.dependencies] deelevate = "0.2.0" winreg = { version = "0.52", features = ["transactions"] } diff --git a/clash-nyanpasu/backend/tauri/src/main.rs b/clash-nyanpasu/backend/tauri/src/main.rs index ddbfc2e161..6e5d8266d3 100644 --- a/clash-nyanpasu/backend/tauri/src/main.rs +++ b/clash-nyanpasu/backend/tauri/src/main.rs @@ -3,6 +3,14 @@ windows_subsystem = "windows" )] +#[cfg(target_os = "macos")] +#[macro_use] +extern crate cocoa; + +#[cfg(target_os = "macos")] +#[macro_use] +extern crate objc; + mod cmds; mod config; mod core; diff --git a/clash-nyanpasu/backend/tauri/src/utils/resolve.rs b/clash-nyanpasu/backend/tauri/src/utils/resolve.rs index fe90206959..006faa00b7 100644 --- a/clash-nyanpasu/backend/tauri/src/utils/resolve.rs +++ b/clash-nyanpasu/backend/tauri/src/utils/resolve.rs @@ -17,6 +17,40 @@ use serde_yaml::Mapping; use std::net::TcpListener; use tauri::{api::process::Command, App, AppHandle, Manager}; +#[cfg(target_os = "macos")] +fn set_window_controls_pos(window: cocoa::base::id, x: f64, y: f64) { + use cocoa::{ + appkit::{NSView, NSWindow, NSWindowButton}, + foundation::NSRect, + }; + + unsafe { + let close = window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); + let miniaturize = window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); + let zoom = window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); + + let title_bar_container_view = close.superview().superview(); + + let close_rect: NSRect = msg_send![close, frame]; + let button_height = close_rect.size.height; + + let title_bar_frame_height = button_height + y; + let mut title_bar_rect = NSView::frame(title_bar_container_view); + title_bar_rect.size.height = title_bar_frame_height; + title_bar_rect.origin.y = NSView::frame(window).size.height - title_bar_frame_height; + let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; + + let window_buttons = vec![close, miniaturize, zoom]; + let space_between = NSView::frame(miniaturize).origin.x - NSView::frame(close).origin.x; + + for (i, button) in window_buttons.into_iter().enumerate() { + let mut rect: NSRect = NSView::frame(button); + rect.origin.x = x + (i as f64 * space_between); + button.setFrameOrigin(rect.origin); + } + } +} + pub fn find_unused_port() -> Result { match TcpListener::bind("127.0.0.1:0") { Ok(listener) => { @@ -244,6 +278,18 @@ pub fn create_window(app_handle: &AppHandle) { #[cfg(target_os = "macos")] { + fn set_controls_and_log_error(app_handle: &tauri::AppHandle, window_name: &str) { + match app_handle.get_window(window_name).unwrap().ns_window() { + Ok(raw_window) => { + let window_id: cocoa::base::id = raw_window as _; + set_window_controls_pos(window_id, 33.0, 26.0); + } + Err(err) => { + log::error!(target: "app", "failed to get ns_window, {err}"); + } + } + } + match builder .decorations(true) .hidden_title(true) @@ -252,9 +298,16 @@ pub fn create_window(app_handle: &AppHandle) { { Ok(win) => { #[cfg(debug_assertions)] - { - win.open_devtools(); - } + win.open_devtools(); + + set_controls_and_log_error(&app_handle, "main"); + + let app_handle_clone = app_handle.clone(); + win.on_window_event(move |event| { + if let tauri::WindowEvent::Resized(_) = event { + set_controls_and_log_error(&app_handle_clone, "main"); + } + }); } Err(err) => { log::error!(target: "app", "failed to create window, {err}"); diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 3b4cafd30f..fbb6052e6c 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -19,7 +19,7 @@ "@mui/icons-material": "5.16.0", "@mui/lab": "5.0.0-alpha.171", "@mui/material": "5.16.0", - "@mui/x-data-grid": "7.8.0", + "@mui/x-data-grid": "7.9.0", "@nyanpasu/interface": "workspace:^", "@nyanpasu/ui": "workspace:^", "@tauri-apps/api": "1.6.0", diff --git a/clash-nyanpasu/frontend/nyanpasu/src/components/app/app-container.tsx b/clash-nyanpasu/frontend/nyanpasu/src/components/app/app-container.tsx index 239605ddc9..b3329a0873 100644 --- a/clash-nyanpasu/frontend/nyanpasu/src/components/app/app-container.tsx +++ b/clash-nyanpasu/frontend/nyanpasu/src/components/app/app-container.tsx @@ -6,6 +6,7 @@ import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import { LayoutControl } from "../layout/layout-control"; import styles from "./app-container.module.scss"; import AppDrawer from "./app-drawer"; +import { alpha, useTheme } from "@mui/material"; const OS = getSystem(); @@ -21,6 +22,8 @@ export const AppContainer = ({ // wait: 100, // }); + const { palette } = useTheme(); + return ( )} -
+ {OS === "macos" && ( +
+ )} + +
{children}
diff --git a/clash-nyanpasu/frontend/nyanpasu/src/components/app/app-drawer.tsx b/clash-nyanpasu/frontend/nyanpasu/src/components/app/app-drawer.tsx index bd9aaca7b1..60c623036f 100644 --- a/clash-nyanpasu/frontend/nyanpasu/src/components/app/app-drawer.tsx +++ b/clash-nyanpasu/frontend/nyanpasu/src/components/app/app-drawer.tsx @@ -7,6 +7,8 @@ import { useState } from "react"; import { Panel } from "react-resizable-panels"; import AnimatedLogo from "../layout/animated-logo"; import RouteListItem from "./modules/route-list-item"; +import { classNames } from "@/utils"; +import getSystem from "@/utils/get-system"; export const AppDrawer = ({ isDrawer }: { isDrawer?: boolean }) => { const { palette } = useTheme(); @@ -21,7 +23,7 @@ export const AppDrawer = ({ isDrawer }: { isDrawer?: boolean }) => { className={clsx( isDrawer ? ["max-w-60", "min-w-28"] : "w-full", "p-4", - "pt-8", + getSystem() === "macos" ? "pt-14" : "pt-8", "h-full", "flex", "flex-col", @@ -70,7 +72,10 @@ export const AppDrawer = ({ isDrawer }: { isDrawer?: boolean }) => { const DrawerTitle = () => { return (
=12.0.0'} - peerDependencies: - '@types/react': npm:types-react@rc - react: npm:react@rc - peerDependenciesMeta: - '@types/react': - optional: true - '@mui/private-theming@5.16.0': resolution: {integrity: sha512-sYpubkO1MZOnxNyVOClrPNOTs0MfuRVVnAvCeMaOaXt6GimgQbnUcshYv2pSr6PFj+Mqzdff/FYOBceK8u5QgA==} engines: {node: '>=12.0.0'} @@ -1202,22 +1192,6 @@ packages: '@emotion/styled': optional: true - '@mui/system@5.15.20': - resolution: {integrity: sha512-LoMq4IlAAhxzL2VNUDBTQxAb4chnBe8JvRINVNDiMtHE2PiPOoHlhOPutSxEbaL5mkECPVWSv6p8JEV+uykwIA==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@types/react': npm:types-react@rc - react: npm:react@rc - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@types/react': - optional: true - '@mui/system@5.16.0': resolution: {integrity: sha512-9YbkC2m3+pNumAvubYv+ijLtog6puJ0fJ6rYfzfLCM47pWrw3m+30nXNM8zMgDaKL6vpfWJcCXm+LPaWBpy7sw==} engines: {node: '>=12.0.0'} @@ -1242,16 +1216,6 @@ packages: '@types/react': optional: true - '@mui/utils@5.15.20': - resolution: {integrity: sha512-mAbYx0sovrnpAu1zHc3MDIhPqL8RPVC5W5xcO1b7PiSCJPtckIZmBkp8hefamAvUiAV8gpfMOM6Zb+eSisbI2A==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': npm:types-react@rc - react: npm:react@rc - peerDependenciesMeta: - '@types/react': - optional: true - '@mui/utils@5.16.0': resolution: {integrity: sha512-kLLi5J1xY+mwtUlMb8Ubdxf4qFAA1+U7WPBvjM/qQ4CIwLCohNb0sHo1oYPufjSIH/Z9+dhVxD7dJlfGjd1AVA==} engines: {node: '>=12.0.0'} @@ -1262,14 +1226,20 @@ packages: '@types/react': optional: true - '@mui/x-data-grid@7.8.0': - resolution: {integrity: sha512-X3t6EVSZ28vVKY9NfqKcClchw2o/KmHsywybp1tNFevIJiwjZSp7NDJ091GyTqMgyDt1Dy5z2hGxoTDUYYfeGg==} + '@mui/x-data-grid@7.9.0': + resolution: {integrity: sha512-RkrVD+tfcR/h3j2p2uqohxA00C5tCJIV5gb5+2ap8XdM0Y8XMF81bB8UADWenU5W83UTErWvtU7n4gCl7hJO9g==} engines: {node: '>=14.0.0'} peerDependencies: '@mui/material': ^5.15.14 react: npm:react@rc react-dom: npm:react-dom@rc + '@mui/x-internals@7.9.0': + resolution: {integrity: sha512-RJRrM6moaDZ8S11gDt8OKVclKm2v9khpIyLkpenNze+tT4dQYoU3liW5P2t31hA4Na/T6JQKNosB4qmB2TYfZw==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: npm:react@rc + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1935,8 +1905,8 @@ packages: '@types/node@20.12.10': resolution: {integrity: sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw==} - '@types/node@20.14.9': - resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} + '@types/node@20.14.10': + resolution: {integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==} '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -5905,11 +5875,11 @@ snapshots: '@babel/helper-validator-identifier': 7.24.5 to-fast-properties: 2.0.0 - '@commitlint/cli@19.3.0(@types/node@20.14.9)(typescript@5.5.3)': + '@commitlint/cli@19.3.0(@types/node@20.14.10)(typescript@5.5.3)': dependencies: '@commitlint/format': 19.3.0 '@commitlint/lint': 19.2.2 - '@commitlint/load': 19.2.0(@types/node@20.14.9)(typescript@5.5.3) + '@commitlint/load': 19.2.0(@types/node@20.14.10)(typescript@5.5.3) '@commitlint/read': 19.2.1 '@commitlint/types': 19.0.3 execa: 8.0.1 @@ -5956,7 +5926,7 @@ snapshots: '@commitlint/rules': 19.0.3 '@commitlint/types': 19.0.3 - '@commitlint/load@19.2.0(@types/node@20.14.9)(typescript@5.5.3)': + '@commitlint/load@19.2.0(@types/node@20.14.10)(typescript@5.5.3)': dependencies: '@commitlint/config-validator': 19.0.3 '@commitlint/execute-rule': 19.0.0 @@ -5964,7 +5934,7 @@ snapshots: '@commitlint/types': 19.0.3 chalk: 5.3.0 cosmiconfig: 9.0.0(typescript@5.5.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.14.10)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -6338,13 +6308,13 @@ snapshots: postcss: 7.0.32 purgecss: 2.3.0 - '@generouted/react-router@1.19.5(react-router-dom@6.24.1(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': + '@generouted/react-router@1.19.5(react-router-dom@6.24.1(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': dependencies: fast-glob: 3.3.2 - generouted: 1.19.5(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) + generouted: 1.19.5(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)) react: 19.0.0-rc-fb9a90fa48-20240614 react-router-dom: 6.24.1(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614) - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) + vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) '@humanwhocodes/config-array@0.11.14': dependencies: @@ -6450,15 +6420,6 @@ snapshots: '@emotion/styled': 11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) '@types/react': types-react@19.0.0-rc.1 - '@mui/private-theming@5.15.20(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': - dependencies: - '@babel/runtime': 7.24.7 - '@mui/utils': 5.15.20(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - prop-types: 15.8.1 - react: 19.0.0-rc-fb9a90fa48-20240614 - optionalDependencies: - '@types/react': types-react@19.0.0-rc.1 - '@mui/private-theming@5.16.0(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': dependencies: '@babel/runtime': 7.24.7 @@ -6479,22 +6440,6 @@ snapshots: '@emotion/react': 11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) '@emotion/styled': 11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - '@mui/system@5.15.20(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': - dependencies: - '@babel/runtime': 7.24.7 - '@mui/private-theming': 5.15.20(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - '@mui/styled-engine': 5.15.14(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614) - '@mui/types': 7.2.14(types-react@19.0.0-rc.1) - '@mui/utils': 5.15.20(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - clsx: 2.1.1 - csstype: 3.1.3 - prop-types: 15.8.1 - react: 19.0.0-rc-fb9a90fa48-20240614 - optionalDependencies: - '@emotion/react': 11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - '@types/react': types-react@19.0.0-rc.1 - '@mui/system@5.16.0(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': dependencies: '@babel/runtime': 7.24.7 @@ -6515,16 +6460,6 @@ snapshots: optionalDependencies: '@types/react': types-react@19.0.0-rc.1 - '@mui/utils@5.15.20(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': - dependencies: - '@babel/runtime': 7.24.7 - '@types/prop-types': 15.7.12 - prop-types: 15.8.1 - react: 19.0.0-rc-fb9a90fa48-20240614 - react-is: 18.3.1 - optionalDependencies: - '@types/react': types-react@19.0.0-rc.1 - '@mui/utils@5.16.0(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': dependencies: '@babel/runtime': 7.24.7 @@ -6535,12 +6470,13 @@ snapshots: optionalDependencies: '@types/react': types-react@19.0.0-rc.1 - '@mui/x-data-grid@7.8.0(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@mui/material@5.16.0(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': + '@mui/x-data-grid@7.9.0(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@mui/material@5.16.0(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': dependencies: '@babel/runtime': 7.24.7 '@mui/material': 5.16.0(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react-dom@19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - '@mui/system': 5.15.20(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) - '@mui/utils': 5.15.20(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) + '@mui/system': 5.16.0(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1))(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) + '@mui/utils': 5.16.0(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) + '@mui/x-internals': 7.9.0(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) clsx: 2.1.1 prop-types: 15.8.1 react: 19.0.0-rc-fb9a90fa48-20240614 @@ -6551,6 +6487,14 @@ snapshots: - '@emotion/styled' - '@types/react' + '@mui/x-internals@7.9.0(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1)': + dependencies: + '@babel/runtime': 7.24.7 + '@mui/utils': 5.16.0(react@19.0.0-rc-fb9a90fa48-20240614)(types-react@19.0.0-rc.1) + react: 19.0.0-rc-fb9a90fa48-20240614 + transitivePeerDependencies: + - '@types/react' + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -7039,12 +6983,12 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/responselike': 1.0.3 '@types/conventional-commits-parser@5.0.0': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/d3-array@3.2.1': {} @@ -7178,7 +7122,7 @@ snapshots: '@types/fs-extra@11.0.4': dependencies: '@types/jsonfile': 6.1.4 - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/geojson@7946.0.14': {} @@ -7194,11 +7138,11 @@ snapshots: '@types/jsonfile@6.1.4': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/keyv@3.1.4': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/lodash-es@4.17.12': dependencies: @@ -7218,7 +7162,7 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@20.14.9': + '@types/node@20.14.10': dependencies: undici-types: 5.26.5 @@ -7240,7 +7184,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 '@types/unist@2.0.10': {} @@ -7248,7 +7192,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 optional: true '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@8.57.0)(typescript@5.5.3))(eslint@8.57.0)(typescript@5.5.3)': @@ -7334,21 +7278,21 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-react-swc@3.7.0(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': + '@vitejs/plugin-react-swc@3.7.0(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': dependencies: '@swc/core': 1.6.1 - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) + vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - '@swc/helpers' - '@vitejs/plugin-react@4.3.1(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': + '@vitejs/plugin-react@4.3.1(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0))': dependencies: '@babel/core': 7.24.5 '@babel/plugin-transform-react-jsx-self': 7.24.5(@babel/core@7.24.5) '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.5) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) + vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - supports-color @@ -7836,9 +7780,9 @@ snapshots: dependencies: is-what: 3.14.1 - cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.9)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): + cosmiconfig-typescript-loader@5.0.0(@types/node@20.14.10)(cosmiconfig@9.0.0(typescript@5.5.3))(typescript@5.5.3): dependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 cosmiconfig: 9.0.0(typescript@5.5.3) jiti: 1.21.0 typescript: 5.5.3 @@ -8829,9 +8773,9 @@ snapshots: functions-have-names@1.2.3: {} - generouted@1.19.5(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): + generouted@1.19.5(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) + vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) gensync@1.0.0-beta.2: {} @@ -11345,43 +11289,43 @@ snapshots: esbuild: 0.19.12 monaco-editor: 0.50.0 - vite-plugin-sass-dts@1.3.22(postcss@8.4.39)(prettier@3.3.2)(sass@1.77.6)(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): + vite-plugin-sass-dts@1.3.22(postcss@8.4.39)(prettier@3.3.2)(sass@1.77.6)(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: postcss: 8.4.39 postcss-js: 4.0.1(postcss@8.4.39) prettier: 3.3.2 sass: 1.77.6 - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) + vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) - vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): + vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: '@rollup/pluginutils': 5.1.0(rollup@4.17.2) '@svgr/core': 8.1.0(typescript@5.5.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.5.3)) - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) + vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - rollup - supports-color - typescript - vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): + vite-tsconfig-paths@4.3.2(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0)): dependencies: debug: 4.3.4 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.5.3) optionalDependencies: - vite: 5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) + vite: 5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0) transitivePeerDependencies: - supports-color - typescript - vite@5.3.3(@types/node@20.14.9)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0): + vite@5.3.3(@types/node@20.14.10)(less@4.2.0)(sass@1.77.6)(stylus@0.62.0): dependencies: esbuild: 0.21.5 postcss: 8.4.39 rollup: 4.17.2 optionalDependencies: - '@types/node': 20.14.9 + '@types/node': 20.14.10 fsevents: 2.3.3 less: 4.2.0 sass: 1.77.6 diff --git a/clash-verge-rev/UPDATELOG.md b/clash-verge-rev/UPDATELOG.md index 6794960775..93d9da646a 100644 --- a/clash-verge-rev/UPDATELOG.md +++ b/clash-verge-rev/UPDATELOG.md @@ -1,3 +1,18 @@ +## v1.7.3 + +### Features + +- 支持可视化编辑订阅代理组 +- 支持可视化编辑订阅节点 +- 支持可视化编辑订阅规则 +- 扩展脚本支持订阅名称参数 `function main(config, profileName)` + +### Bugs Fixes + +- 代理绕过格式检查错误 + +--- + ## v1.7.2 ### Break Changes diff --git a/clash-verge-rev/package.json b/clash-verge-rev/package.json index ca2b6a4dc1..e736201cad 100644 --- a/clash-verge-rev/package.json +++ b/clash-verge-rev/package.json @@ -1,6 +1,6 @@ { "name": "clash-verge", - "version": "1.7.2", + "version": "1.7.3", "license": "GPL-3.0-only", "scripts": { "dev": "tauri dev", @@ -24,10 +24,10 @@ "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", "@juggle/resize-observer": "^3.4.0", - "@mui/icons-material": "^5.15.21", + "@mui/icons-material": "^5.16.0", "@mui/lab": "5.0.0-alpha.149", - "@mui/material": "^5.15.21", - "@mui/x-data-grid": "^7.8.0", + "@mui/material": "^5.16.0", + "@mui/x-data-grid": "^7.9.0", "@tauri-apps/api": "^1.6.0", "@types/json-schema": "^7.0.15", "ahooks": "^3.8.0", diff --git a/clash-verge-rev/pnpm-lock.yaml b/clash-verge-rev/pnpm-lock.yaml index f0404aff8a..0f0f0e4c45 100644 --- a/clash-verge-rev/pnpm-lock.yaml +++ b/clash-verge-rev/pnpm-lock.yaml @@ -26,17 +26,17 @@ importers: specifier: ^3.4.0 version: 3.4.0 "@mui/icons-material": - specifier: ^5.15.21 - version: 5.15.21(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + specifier: ^5.16.0 + version: 5.16.0(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/lab": specifier: 5.0.0-alpha.149 - version: 5.0.0-alpha.149(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 5.0.0-alpha.149(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/material": - specifier: ^5.15.21 - version: 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^5.16.0 + version: 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/x-data-grid": - specifier: ^7.8.0 - version: 7.8.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^7.9.0 + version: 7.9.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@tauri-apps/api": specifier: ^1.6.0 version: 1.6.0 @@ -154,10 +154,10 @@ importers: version: 4.4.10 "@vitejs/plugin-legacy": specifier: ^5.4.1 - version: 5.4.1(terser@5.31.1)(vite@5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) + version: 5.4.1(terser@5.31.1)(vite@5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1)) "@vitejs/plugin-react": specifier: ^4.3.1 - version: 4.3.1(vite@5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) + version: 4.3.1(vite@5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1)) adm-zip: specifier: ^0.5.14 version: 0.5.14 @@ -193,13 +193,13 @@ importers: version: 5.5.3 vite: specifier: ^5.3.3 - version: 5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) + version: 5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1) vite-plugin-monaco-editor: specifier: ^1.1.0 version: 1.1.0(monaco-editor@0.49.0) vite-plugin-svgr: specifier: ^4.2.0 - version: 4.2.0(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) + version: 4.2.0(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1)) packages: "@actions/github@5.1.1": @@ -1580,16 +1580,16 @@ packages: "@types/react": optional: true - "@mui/core-downloads-tracker@5.15.21": + "@mui/core-downloads-tracker@5.16.0": resolution: { - integrity: sha512-dp9lXBaJZzJYeJfQY3Ow4Rb49QaCEdkl2KKYscdQHQm6bMJ+l4XPY3Cd9PCeeJTsHPIDJ60lzXbeRgs6sx/rpw==, + integrity: sha512-8SLffXYPRVpcZx5QzxNE8fytTqzp+IuU3deZbQWg/vSaTlDpR5YVrQ4qQtXTi5cRdhOufV5INylmwlKK+//nPw==, } - "@mui/icons-material@5.15.21": + "@mui/icons-material@5.16.0": resolution: { - integrity: sha512-yqkq1MbdkmX5ZHyvZTBuAaA6RkvoqkoAgwBSx9Oh0L0jAfj9T/Ih/NhMNjkl8PWVSonjfDUkKroBnjRyo/1M9Q==, + integrity: sha512-6ISoOhkp9w5gD0PEW9JklrcbyARDkFWNTBdwXZ1Oy5IGlyu9B0zG0hnUIe4H17IaF1Vgj6C8VI+v4tkSdK0veg==, } engines: { node: ">=12.0.0" } peerDependencies: @@ -1621,10 +1621,10 @@ packages: "@types/react": optional: true - "@mui/material@5.15.21": + "@mui/material@5.16.0": resolution: { - integrity: sha512-nTyCcgduKwHqiuQ/B03EQUa+utSMzn2sQp0QAibsnYe4tvc3zkMbO0amKpl48vhABIY3IvT6w9615BFIgMt0YA==, + integrity: sha512-DbR1NckTLpjt9Zut9EGQ70th86HfN0BYQgyYro6aXQrNfjzSwe3BJS1AyBQ5mJ7TdL6YVRqohfukxj9JlqZZUg==, } engines: { node: ">=12.0.0" } peerDependencies: @@ -1641,10 +1641,10 @@ packages: "@types/react": optional: true - "@mui/private-theming@5.15.20": + "@mui/private-theming@5.16.0": resolution: { - integrity: sha512-BK8F94AIqSrnaPYXf2KAOjGZJgWfvqAVQ2gVR3EryvQFtuBnG6RwodxrCvd3B48VuMy6Wsk897+lQMUxJyk+6g==, + integrity: sha512-sYpubkO1MZOnxNyVOClrPNOTs0MfuRVVnAvCeMaOaXt6GimgQbnUcshYv2pSr6PFj+Mqzdff/FYOBceK8u5QgA==, } engines: { node: ">=12.0.0" } peerDependencies: @@ -1670,10 +1670,10 @@ packages: "@emotion/styled": optional: true - "@mui/system@5.15.20": + "@mui/system@5.16.0": resolution: { - integrity: sha512-LoMq4IlAAhxzL2VNUDBTQxAb4chnBe8JvRINVNDiMtHE2PiPOoHlhOPutSxEbaL5mkECPVWSv6p8JEV+uykwIA==, + integrity: sha512-9YbkC2m3+pNumAvubYv+ijLtog6puJ0fJ6rYfzfLCM47pWrw3m+30nXNM8zMgDaKL6vpfWJcCXm+LPaWBpy7sw==, } engines: { node: ">=12.0.0" } peerDependencies: @@ -1700,10 +1700,10 @@ packages: "@types/react": optional: true - "@mui/utils@5.15.20": + "@mui/utils@5.16.0": resolution: { - integrity: sha512-mAbYx0sovrnpAu1zHc3MDIhPqL8RPVC5W5xcO1b7PiSCJPtckIZmBkp8hefamAvUiAV8gpfMOM6Zb+eSisbI2A==, + integrity: sha512-kLLi5J1xY+mwtUlMb8Ubdxf4qFAA1+U7WPBvjM/qQ4CIwLCohNb0sHo1oYPufjSIH/Z9+dhVxD7dJlfGjd1AVA==, } engines: { node: ">=12.0.0" } peerDependencies: @@ -1713,10 +1713,10 @@ packages: "@types/react": optional: true - "@mui/x-data-grid@7.8.0": + "@mui/x-data-grid@7.9.0": resolution: { - integrity: sha512-X3t6EVSZ28vVKY9NfqKcClchw2o/KmHsywybp1tNFevIJiwjZSp7NDJ091GyTqMgyDt1Dy5z2hGxoTDUYYfeGg==, + integrity: sha512-RkrVD+tfcR/h3j2p2uqohxA00C5tCJIV5gb5+2ap8XdM0Y8XMF81bB8UADWenU5W83UTErWvtU7n4gCl7hJO9g==, } engines: { node: ">=14.0.0" } peerDependencies: @@ -1724,6 +1724,15 @@ packages: react: ^17.0.0 || ^18.0.0 react-dom: ^17.0.0 || ^18.0.0 + "@mui/x-internals@7.9.0": + resolution: + { + integrity: sha512-RJRrM6moaDZ8S11gDt8OKVclKm2v9khpIyLkpenNze+tT4dQYoU3liW5P2t31hA4Na/T6JQKNosB4qmB2TYfZw==, + } + engines: { node: ">=14.0.0" } + peerDependencies: + react: ^17.0.0 || ^18.0.0 + "@mui/x-tree-view@6.0.0-alpha.1": resolution: { @@ -2268,10 +2277,10 @@ packages: integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==, } - "@types/node@20.14.9": + "@types/node@20.14.10": resolution: { - integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==, + integrity: sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==, } "@types/parse-json@4.0.2": @@ -2740,10 +2749,10 @@ packages: integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==, } - electron-to-chromium@1.4.816: + electron-to-chromium@1.4.818: resolution: { - integrity: sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==, + integrity: sha512-eGvIk2V0dGImV9gWLq8fDfTTsCAeMDwZqEPMr+jMInxZdnp9Us8UpovYpRCf9NQ7VOFgrN2doNSgvISbsbNpxA==, } end-of-stream@1.4.4: @@ -5587,7 +5596,7 @@ snapshots: "@babel/runtime": 7.24.7 "@floating-ui/react-dom": 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) - "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) "@popperjs/core": 2.11.8 clsx: 2.1.1 prop-types: 15.8.1 @@ -5601,7 +5610,7 @@ snapshots: "@babel/runtime": 7.24.7 "@floating-ui/react-dom": 2.1.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) - "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) "@popperjs/core": 2.11.8 clsx: 2.1.1 prop-types: 15.8.1 @@ -5610,25 +5619,25 @@ snapshots: optionalDependencies: "@types/react": 18.3.3 - "@mui/core-downloads-tracker@5.15.21": {} + "@mui/core-downloads-tracker@5.16.0": {} - "@mui/icons-material@5.15.21(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)": + "@mui/icons-material@5.16.0(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 - "@mui/material": 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/material": 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 optionalDependencies: "@types/react": 18.3.3 - "@mui/lab@5.0.0-alpha.149(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@mui/lab@5.0.0-alpha.149(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 "@mui/base": 5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/material": 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/system": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + "@mui/material": 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/system": 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) - "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) - "@mui/x-tree-view": 6.0.0-alpha.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) + "@mui/x-tree-view": 6.0.0-alpha.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: 2.1.1 prop-types: 15.8.1 react: 18.3.1 @@ -5638,14 +5647,14 @@ snapshots: "@emotion/styled": 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@types/react": 18.3.3 - "@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 "@mui/base": 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/core-downloads-tracker": 5.15.21 - "@mui/system": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + "@mui/core-downloads-tracker": 5.16.0 + "@mui/system": 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) - "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) "@types/react-transition-group": 4.4.10 clsx: 2.1.1 csstype: 3.1.3 @@ -5659,10 +5668,10 @@ snapshots: "@emotion/styled": 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@types/react": 18.3.3 - "@mui/private-theming@5.15.20(@types/react@18.3.3)(react@18.3.1)": + "@mui/private-theming@5.16.0(@types/react@18.3.3)(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 - "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) prop-types: 15.8.1 react: 18.3.1 optionalDependencies: @@ -5679,13 +5688,13 @@ snapshots: "@emotion/react": 11.11.4(@types/react@18.3.3)(react@18.3.1) "@emotion/styled": 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) - "@mui/system@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)": + "@mui/system@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 - "@mui/private-theming": 5.15.20(@types/react@18.3.3)(react@18.3.1) + "@mui/private-theming": 5.16.0(@types/react@18.3.3)(react@18.3.1) "@mui/styled-engine": 5.15.14(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(react@18.3.1) "@mui/types": 7.2.14(@types/react@18.3.3) - "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) clsx: 2.1.1 csstype: 3.1.3 prop-types: 15.8.1 @@ -5699,7 +5708,7 @@ snapshots: optionalDependencies: "@types/react": 18.3.3 - "@mui/utils@5.15.20(@types/react@18.3.3)(react@18.3.1)": + "@mui/utils@5.16.0(@types/react@18.3.3)(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 "@types/prop-types": 15.7.12 @@ -5709,12 +5718,13 @@ snapshots: optionalDependencies: "@types/react": 18.3.3 - "@mui/x-data-grid@7.8.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@mui/x-data-grid@7.9.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 - "@mui/material": 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/system": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) - "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) + "@mui/material": 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/system": 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) + "@mui/x-internals": 7.9.0(@types/react@18.3.3)(react@18.3.1) clsx: 2.1.1 prop-types: 15.8.1 react: 18.3.1 @@ -5725,15 +5735,23 @@ snapshots: - "@emotion/styled" - "@types/react" - "@mui/x-tree-view@6.0.0-alpha.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": + "@mui/x-internals@7.9.0(@types/react@18.3.3)(react@18.3.1)": + dependencies: + "@babel/runtime": 7.24.7 + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) + react: 18.3.1 + transitivePeerDependencies: + - "@types/react" + + "@mui/x-tree-view@6.0.0-alpha.1(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@mui/base@5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/material@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mui/system@5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)": dependencies: "@babel/runtime": 7.24.7 "@emotion/react": 11.11.4(@types/react@18.3.3)(react@18.3.1) "@emotion/styled": 11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) "@mui/base": 5.0.0-beta.20(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/material": 5.15.21(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - "@mui/system": 5.15.20(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) - "@mui/utils": 5.15.20(@types/react@18.3.3)(react@18.3.1) + "@mui/material": 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + "@mui/system": 5.16.0(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@emotion/styled@11.11.5(@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1))(@types/react@18.3.3)(react@18.3.1) + "@mui/utils": 5.16.0(@types/react@18.3.3)(react@18.3.1) "@types/react-transition-group": 4.4.10 clsx: 2.1.1 prop-types: 15.8.1 @@ -6019,7 +6037,7 @@ snapshots: "@types/fs-extra@9.0.13": dependencies: - "@types/node": 20.14.9 + "@types/node": 20.14.10 "@types/hast@3.0.4": dependencies: @@ -6043,7 +6061,7 @@ snapshots: "@types/ms@0.7.34": {} - "@types/node@20.14.9": + "@types/node@20.14.10": dependencies: undici-types: 5.26.5 @@ -6070,7 +6088,7 @@ snapshots: "@ungap/structured-clone@1.2.0": {} - "@vitejs/plugin-legacy@5.4.1(terser@5.31.1)(vite@5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))": + "@vitejs/plugin-legacy@5.4.1(terser@5.31.1)(vite@5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1))": dependencies: "@babel/core": 7.24.7 "@babel/preset-env": 7.24.7(@babel/core@7.24.7) @@ -6081,18 +6099,18 @@ snapshots: regenerator-runtime: 0.14.1 systemjs: 6.15.1 terser: 5.31.1 - vite: 5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) + vite: 5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - supports-color - "@vitejs/plugin-react@4.3.1(vite@5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))": + "@vitejs/plugin-react@4.3.1(vite@5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1))": dependencies: "@babel/core": 7.24.7 "@babel/plugin-transform-react-jsx-self": 7.24.7(@babel/core@7.24.7) "@babel/plugin-transform-react-jsx-source": 7.24.7(@babel/core@7.24.7) "@types/babel__core": 7.20.5 react-refresh: 0.14.2 - vite: 5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) + vite: 5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - supports-color @@ -6188,7 +6206,7 @@ snapshots: browserslist@4.23.1: dependencies: caniuse-lite: 1.0.30001640 - electron-to-chromium: 1.4.816 + electron-to-chromium: 1.4.818 node-releases: 2.0.14 update-browserslist-db: 1.1.0(browserslist@4.23.1) @@ -6321,7 +6339,7 @@ snapshots: no-case: 3.0.4 tslib: 2.6.3 - electron-to-chromium@1.4.816: {} + electron-to-chromium@1.4.818: {} end-of-stream@1.4.4: dependencies: @@ -7393,24 +7411,24 @@ snapshots: dependencies: monaco-editor: 0.49.0 - vite-plugin-svgr@4.2.0(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)): + vite-plugin-svgr@4.2.0(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1)): dependencies: "@rollup/pluginutils": 5.1.0(rollup@4.18.0) "@svgr/core": 8.1.0(typescript@5.5.3) "@svgr/plugin-jsx": 8.1.0(@svgr/core@8.1.0(typescript@5.5.3)) - vite: 5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) + vite: 5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - rollup - supports-color - typescript - vite@5.3.3(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1): + vite@5.3.3(@types/node@20.14.10)(sass@1.77.6)(terser@5.31.1): dependencies: esbuild: 0.21.5 postcss: 8.4.39 rollup: 4.18.0 optionalDependencies: - "@types/node": 20.14.9 + "@types/node": 20.14.10 fsevents: 2.3.3 sass: 1.77.6 terser: 5.31.1 diff --git a/clash-verge-rev/src-tauri/Cargo.lock b/clash-verge-rev/src-tauri/Cargo.lock index c11de2b0f5..12db319125 100644 --- a/clash-verge-rev/src-tauri/Cargo.lock +++ b/clash-verge-rev/src-tauri/Cargo.lock @@ -99,7 +99,7 @@ dependencies = [ "clipboard-win", "core-graphics 0.23.2", "image 0.25.1", - "log 0.4.21", + "log 0.4.22", "objc2", "objc2-app-kit", "objc2-foundation", @@ -203,7 +203,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-lite 1.13.0", - "log 0.4.21", + "log 0.4.22", "parking", "polling 2.8.0", "rustix 0.37.27", @@ -307,7 +307,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -342,7 +342,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -433,9 +433,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block" @@ -489,7 +489,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b6fb81ca0f301f33aff7401e2ffab37dc9e0e4a1cf0ccf6b34f4d9e60aa0682" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "boa_interner", "boa_macros", "indexmap 2.2.6", @@ -504,7 +504,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "600e4e4a65b26efcef08a7b1cf2899d3845a32e82e067ee3b75eaf7e413ff31c" dependencies = [ "arrayvec", - "bitflags 2.5.0", + "bitflags 2.6.0", "boa_ast", "boa_gc", "boa_interner", @@ -578,7 +578,7 @@ checksum = "6be9c93793b60dac381af475b98634d4b451e28336e72218cad9a20176218dbc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "synstructure", ] @@ -588,7 +588,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e8592556849f0619ed142ce2b3a19086769314a8d657f93a5765d06dbce4818" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "boa_ast", "boa_interner", "boa_macros", @@ -661,7 +661,7 @@ checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -715,9 +715,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.99" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" [[package]] name = "cesu8" @@ -767,6 +767,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.38" @@ -779,12 +785,12 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "clash-verge" -version = "1.7.2" +version = "1.7.3" dependencies = [ "anyhow", "auto-launch", @@ -794,11 +800,11 @@ dependencies = [ "delay_timer", "dirs 5.0.1", "dunce", - "log 0.4.21", + "log 0.4.22", "log4rs", "nanoid", "once_cell", - "open 5.1.4", + "open 5.2.0", "parking_lot", "percent-encoding", "port_scanner", @@ -896,7 +902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1064,7 +1070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1074,7 +1080,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1098,7 +1104,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1109,7 +1115,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1137,7 +1143,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c7397f8c48906dd9b5afc75001368c979418e5dff5575998a831eb2319b424e" dependencies = [ - "lazy_static 1.4.0", + "lazy_static 1.5.0", "pathsearch", "rand 0.8.5", "shared_library", @@ -1159,7 +1165,7 @@ dependencies = [ "dashmap", "event-listener 5.3.0", "futures", - "log 0.4.21", + "log 0.4.22", "lru", "once_cell", "rs-snowflake", @@ -1199,7 +1205,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1212,7 +1218,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1310,13 +1316,13 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1325,7 +1331,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.3", + "libloading 0.8.4", ] [[package]] @@ -1357,9 +1363,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "embed-resource" @@ -1414,7 +1420,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1589,7 +1595,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1707,7 +1713,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -1843,7 +1849,7 @@ checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" dependencies = [ "cc", "libc", - "log 0.4.21", + "log 0.4.22", "rustversion", "windows 0.48.0", ] @@ -1985,7 +1991,7 @@ checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick 1.1.3", "bstr", - "log 0.4.21", + "log 0.4.22", "regex-automata 0.4.7", "regex-syntax 0.8.4", ] @@ -2203,7 +2209,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" dependencies = [ - "log 0.4.21", + "log 0.4.22", "mac", "markup5ever", "proc-macro2", @@ -2317,9 +2323,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "c4fe55fb7a772d59a5ff1dfbff4fe0258d19b89fec4b233e75d35d5d2316badc" dependencies = [ "bytes", "futures-channel", @@ -2343,7 +2349,7 @@ checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.3.1", + "hyper 1.4.0", "hyper-util", "rustls", "rustls-pki-types", @@ -2374,7 +2380,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.0", "hyper-util", "native-tls", "tokio", @@ -2384,16 +2390,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.3.1", + "hyper 1.4.0", "pin-project-lite", "socket2 0.5.7", "tokio", @@ -2516,9 +2522,9 @@ checksum = "e3744fecc0df9ce19999cdaf1f9f3a48c253431ce1d67ef499128fe9d0b607ab" [[package]] name = "icu_properties" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8173ba888885d250016e957b8ebfd5a65cdb690123d8833a19f6833f9c2b579" +checksum = "db9e559598096627aeca8cdfb98138a70eb4078025f8d1d5f2416a361241f756" dependencies = [ "displaydoc", "icu_collections", @@ -2560,7 +2566,7 @@ checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -2587,7 +2593,7 @@ checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ "crossbeam-deque", "globset", - "log 0.4.21", + "log 0.4.22", "memchr", "regex-automata 0.4.7", "same-file", @@ -2678,7 +2684,7 @@ dependencies = [ "bitflags 1.3.2", "cc", "handlebars", - "lazy_static 1.4.0", + "lazy_static 1.5.0", "libc", "nix 0.23.2", "serde", @@ -2794,7 +2800,7 @@ dependencies = [ "cesu8", "combine", "jni-sys", - "log 0.4.21", + "log 0.4.22", "thiserror", "walkdir", ] @@ -2852,9 +2858,9 @@ checksum = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libappindicator" @@ -2866,7 +2872,7 @@ dependencies = [ "gtk", "gtk-sys", "libappindicator-sys", - "log 0.4.21", + "log 0.4.22", ] [[package]] @@ -2898,12 +2904,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2912,16 +2918,10 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", ] -[[package]] -name = "line-wrap" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" - [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -2956,14 +2956,14 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" dependencies = [ - "log 0.4.21", + "log 0.4.22", ] [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" dependencies = [ "serde", ] @@ -2987,7 +2987,7 @@ dependencies = [ "fnv", "humantime", "libc", - "log 0.4.21", + "log 0.4.22", "log-mdc", "once_cell", "parking_lot", @@ -3060,7 +3060,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" dependencies = [ - "log 0.4.21", + "log 0.4.22", "phf 0.10.1", "phf_codegen 0.10.0", "string_cache", @@ -3130,9 +3130,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -3182,7 +3182,7 @@ dependencies = [ "futures-util", "http 0.2.12", "httparse", - "log 0.4.21", + "log 0.4.22", "memchr", "mime", "spin", @@ -3205,7 +3205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ "libc", - "log 0.4.21", + "log 0.4.22", "openssl", "openssl-probe", "openssl-sys", @@ -3280,9 +3280,21 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", - "cfg_aliases", + "cfg_aliases 0.1.1", + "libc", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if", + "cfg_aliases 0.2.1", "libc", "memoffset 0.9.1", ] @@ -3319,7 +3331,7 @@ version = "4.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5312f837191c317644f313f7b2b39f9cb1496570c74f7c17152dd3961219551f" dependencies = [ - "log 0.4.21", + "log 0.4.22", "mac-notification-sys", "serde", "tauri-winrt-notification", @@ -3347,9 +3359,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -3440,7 +3452,7 @@ dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3495,7 +3507,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "libc", "objc2", @@ -3511,7 +3523,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-foundation", @@ -3541,7 +3553,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "libc", "objc2", @@ -3553,7 +3565,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-foundation", @@ -3565,7 +3577,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-foundation", @@ -3592,9 +3604,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] @@ -3623,9 +3635,9 @@ dependencies = [ [[package]] name = "open" -version = "5.1.4" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ca541f22b1c46d4bb9801014f234758ab4297e7870b904b6a8415b980a7388" +checksum = "9d2c909a3fce3bd80efef4cd1c6c056bd9376a8fe06fcfdbebaf32cb485a7e37" dependencies = [ "is-wsl", "libc", @@ -3638,7 +3650,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "foreign-types 0.3.2", "libc", @@ -3655,7 +3667,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3768,7 +3780,7 @@ dependencies = [ "libc", "redox_syscall 0.5.2", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3807,9 +3819,9 @@ checksum = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" [[package]] name = "pest" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -3940,7 +3952,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -3987,7 +3999,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4021,14 +4033,13 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "indexmap 2.2.6", - "line-wrap", - "quick-xml", + "quick-xml 0.32.0", "serde", "time", ] @@ -4057,7 +4068,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "libc", - "log 0.4.21", + "log 0.4.22", "pin-project-lite", "windows-sys 0.48.0", ] @@ -4164,9 +4175,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4186,6 +4197,24 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick-xml" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f24d770aeca0eacb81ac29dfbc55ebcc09312fdd1f8bbecdc7e4a84e000e3b4" +dependencies = [ + "memchr", +] + [[package]] name = "quinn" version = "0.11.2" @@ -4364,7 +4393,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -4472,7 +4501,7 @@ dependencies = [ "hyper-tls 0.5.0", "ipnet", "js-sys", - "log 0.4.21", + "log 0.4.22", "mime", "native-tls", "once_cell", @@ -4511,13 +4540,13 @@ dependencies = [ "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.0", "hyper-rustls", "hyper-tls 0.6.0", "hyper-util", "ipnet", "js-sys", - "log 0.4.21", + "log 0.4.22", "mime", "native-tls", "once_cell", @@ -4556,8 +4585,8 @@ dependencies = [ "gobject-sys", "gtk-sys", "js-sys", - "lazy_static 1.4.0", - "log 0.4.21", + "lazy_static 1.5.0", + "log 0.4.22", "objc", "objc-foundation", "objc_id", @@ -4651,7 +4680,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys 0.4.14", @@ -4699,9 +4728,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" dependencies = [ "ring", "rustls-pki-types", @@ -4762,7 +4791,7 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -4789,7 +4818,7 @@ dependencies = [ "cssparser", "derive_more", "fxhash", - "log 0.4.21", + "log 0.4.22", "matches", "phf 0.8.0", "phf_codegen 0.8.0", @@ -4838,7 +4867,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" dependencies = [ - "pest 2.7.10", + "pest 2.7.11", ] [[package]] @@ -4868,14 +4897,14 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "indexmap 2.2.6", "itoa 1.0.11", @@ -4891,7 +4920,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -4917,9 +4946,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "e73139bc5ec2d45e6c5fd85be5a46949c1c39a4c18e56915f5eb4c12f975e377" dependencies = [ "base64 0.22.1", "chrono", @@ -4935,14 +4964,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "b80d3d6b56b64335c0180e5ffde23b3c5e08c14c585b51a15bd0e95393f46703" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5031,7 +5060,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ - "lazy_static 1.4.0", + "lazy_static 1.5.0", ] [[package]] @@ -5050,7 +5079,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a9e7e0f2bfae24d8a5b5a66c5b257a83c7412304311512a0c054cd5e619da11" dependencies = [ - "lazy_static 1.4.0", + "lazy_static 1.5.0", "libc", ] @@ -5232,9 +5261,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "subtle" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0208408ba0c3df17ed26eb06992cb1a1268d41b2c0e12e65203fbe3972cee5" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -5249,9 +5278,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -5278,7 +5307,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5303,7 +5332,7 @@ source = "git+https://github.com/zzzgydi/sysproxy-rs?branch=main#bd912f90ae7f20b dependencies = [ "interfaces", "iptools", - "log 0.4.21", + "log 0.4.22", "thiserror", "windows 0.52.0", "winreg 0.52.0", @@ -5384,10 +5413,10 @@ dependencies = [ "image 0.24.9", "instant", "jni", - "lazy_static 1.4.0", + "lazy_static 1.5.0", "libappindicator", "libc", - "log 0.4.21", + "log 0.4.22", "ndk", "ndk-context", "ndk-sys", @@ -5442,9 +5471,9 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e3b2c32de5bf5bed15a376064286643862b84e4e091d093f7bcdf1fda4b9758" +checksum = "336bc661a3f3250853fa83c6e5245449ed1c26dce5dcb28bdee7efedf6278806" dependencies = [ "anyhow", "base64 0.21.7", @@ -5620,7 +5649,7 @@ dependencies = [ "infer 0.13.0", "json-patch", "kuchikiki", - "log 0.4.21", + "log 0.4.22", "memchr", "phf 0.11.2", "proc-macro2", @@ -5651,7 +5680,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f89f5fb70d6f62381f5d9b2ba9008196150b40b75f3068eb24faeddf1c686871" dependencies = [ - "quick-xml", + "quick-xml 0.31.0", "windows 0.56.0", "windows-version", ] @@ -5713,9 +5742,9 @@ dependencies = [ "cfg-if", "filedescriptor", "hex", - "lazy_static 1.4.0", + "lazy_static 1.5.0", "libc", - "log 0.4.21", + "log 0.4.22", "memmem", "num-derive", "num-traits", @@ -5762,7 +5791,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5781,7 +5810,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" dependencies = [ - "lazy_static 1.4.0", + "lazy_static 1.5.0", ] [[package]] @@ -5851,9 +5880,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "ce6b6a2fb3a985e99cebfaefa9faa3024743da73304ca1c683a36429613d3d22" dependencies = [ "tinyvec_macros", ] @@ -5891,7 +5920,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -5922,7 +5951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", - "log 0.4.21", + "log 0.4.22", "tokio", "tungstenite", ] @@ -6052,7 +6081,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log 0.4.21", + "log 0.4.22", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -6066,7 +6095,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -6085,7 +6114,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "log 0.4.21", + "log 0.4.22", "once_cell", "tracing-core", ] @@ -6139,7 +6168,7 @@ dependencies = [ "data-encoding", "http 1.1.0", "httparse", - "log 0.4.21", + "log 0.4.22", "rand 0.8.5", "sha1", "thiserror", @@ -6261,7 +6290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" dependencies = [ "libc", - "log 0.4.21", + "log 0.4.22", ] [[package]] @@ -6296,9 +6325,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" dependencies = [ "getrandom 0.2.15", ] @@ -6399,7 +6428,7 @@ dependencies = [ "headers", "http 0.2.12", "hyper 0.14.29", - "log 0.4.21", + "log 0.4.22", "mime", "mime_guess", "multer", @@ -6445,11 +6474,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", - "log 0.4.21", + "log 0.4.22", "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-shared", ] @@ -6483,7 +6512,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6509,9 +6538,9 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34e9e6b6d4a2bb4e7e69433e0b35c7923b95d4dc8503a84d25ec917a4bbfdf07" +checksum = "269c04f203640d0da2092d1b8d89a2d081714ae3ac2f1b53e99f205740517198" dependencies = [ "cc", "downcast-rs", @@ -6523,11 +6552,11 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.3" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e63801c85358a431f986cffa74ba9599ff571fc5774ac113ed3b490c19a1133" +checksum = "08bd0f46c069d3382a36c8666c1b9ccef32b8b04f41667ca1fef06a1adcc2982" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "rustix 0.38.34", "wayland-backend", "wayland-scanner", @@ -6539,7 +6568,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -6551,7 +6580,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6560,23 +6589,23 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67da50b9f80159dec0ea4c11c13e24ef9e7574bd6ce24b01860a175010cea565" +checksum = "edf466fc49a4feb65a511ca403fec3601494d0dee85dbf37fff6fa0dd4eec3b6" dependencies = [ "proc-macro2", - "quick-xml", + "quick-xml 0.34.0", "quote", ] [[package]] name = "wayland-sys" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "105b1842da6554f91526c14a2a2172897b7f745a805d62af4ce698706be79c12" +checksum = "4a6754825230fa5b27bafaa28c30b3c9e72c55530581220cef401fa422c0fae7" dependencies = [ "dlib", - "log 0.4.21", + "log 0.4.22", "pkg-config", ] @@ -6788,7 +6817,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core 0.52.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6798,7 +6827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" dependencies = [ "windows-core 0.56.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6817,7 +6846,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6829,7 +6858,7 @@ dependencies = [ "windows-implement 0.56.0", "windows-interface", "windows-result", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6850,7 +6879,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -6861,7 +6890,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -6876,7 +6905,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6909,7 +6938,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6929,18 +6958,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -6955,7 +6984,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6998aa457c9ba8ff2fb9f13e9d2a930dabcea28f1d0ab94d687d8b3654844515" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6972,9 +7001,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -7002,9 +7031,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -7032,15 +7061,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -7068,9 +7097,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -7098,9 +7127,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -7116,9 +7145,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -7146,9 +7175,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -7205,7 +7234,7 @@ checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" dependencies = [ "derive-new", "libc", - "log 0.4.21", + "log 0.4.22", "nix 0.28.0", "os_pipe", "tempfile", @@ -7249,7 +7278,7 @@ dependencies = [ "http 0.2.12", "kuchikiki", "libc", - "log 0.4.21", + "log 0.4.22", "objc", "objc_id", "once_cell", @@ -7352,15 +7381,15 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "synstructure", ] [[package]] name = "zbus" -version = "4.3.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23915fcb26e7a9a9dc05fd93a9870d336d6d032cd7e8cebf1c5c37666489fdd5" +checksum = "851238c133804e0aa888edf4a0229481c753544ca12a60fd1c3230c8a500fe40" dependencies = [ "async-broadcast", "async-executor", @@ -7378,7 +7407,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix 0.28.0", + "nix 0.29.0", "ordered-stream", "rand 0.8.5", "serde", @@ -7396,14 +7425,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.3.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bcca0b586d2f8589da32347b4784ba424c4891ed86aa5b50d5e88f6b2c4f5d" +checksum = "8d5a3f12c20bd473be3194af6b49d50d7bb804ef3192dc70eddedb26b85d9da7" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "zvariant_utils", ] @@ -7420,22 +7449,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -7455,7 +7484,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "synstructure", ] @@ -7467,9 +7496,9 @@ checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zerovec" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ "yoke", "zerofrom", @@ -7478,13 +7507,13 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] [[package]] @@ -7500,9 +7529,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa6d31a02fbfb602bfde791de7fedeb9c2c18115b3d00f3a36e489f46ffbbc7" +checksum = "1724a2b330760dc7d2a8402d841119dc869ef120b139d29862d6980e9c75bfc9" dependencies = [ "endi", "enumflags2", @@ -7513,14 +7542,14 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642bf1b6b6d527988b3e8193d20969d53700a36eac734d21ae6639db168701c8" +checksum = "55025a7a518ad14518fb243559c058a2e5b848b015e31f1d90414f36e3317859" dependencies = [ "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", "zvariant_utils", ] @@ -7532,5 +7561,5 @@ checksum = "fc242db087efc22bd9ade7aa7809e4ba828132edc312871584a6b4391bdf8786" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.68", ] diff --git a/clash-verge-rev/src-tauri/Cargo.toml b/clash-verge-rev/src-tauri/Cargo.toml index 0171e52cef..32a320c903 100644 --- a/clash-verge-rev/src-tauri/Cargo.toml +++ b/clash-verge-rev/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clash-verge" -version = "1.7.2" +version = "1.7.3" description = "clash verge" authors = ["zzzgydi", "wonfen", "MystiPanda"] license = "GPL-3.0-only" diff --git a/clash-verge-rev/src-tauri/tauri.conf.json b/clash-verge-rev/src-tauri/tauri.conf.json index c33c989c34..ad5b936570 100644 --- a/clash-verge-rev/src-tauri/tauri.conf.json +++ b/clash-verge-rev/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "../node_modules/@tauri-apps/cli/schema.json", "package": { "productName": "Clash Verge", - "version": "1.7.2" + "version": "1.7.3" }, "build": { "distDir": "../dist", diff --git a/clash-verge-rev/src/components/profile/group-item.tsx b/clash-verge-rev/src/components/profile/group-item.tsx index 7bf18cf567..79d67f66a4 100644 --- a/clash-verge-rev/src/components/profile/group-item.tsx +++ b/clash-verge-rev/src/components/profile/group-item.tsx @@ -137,7 +137,7 @@ export const GroupItem = (props: Props) => { ); }; -const StyledPrimary = styled("span")` +const StyledPrimary = styled("div")` font-size: 15px; font-weight: 700; line-height: 1.5; diff --git a/clash-verge-rev/src/components/profile/groups-editor-viewer.tsx b/clash-verge-rev/src/components/profile/groups-editor-viewer.tsx index 8f6557d44c..5a59e09848 100644 --- a/clash-verge-rev/src/components/profile/groups-editor-viewer.tsx +++ b/clash-verge-rev/src/components/profile/groups-editor-viewer.tsx @@ -78,10 +78,18 @@ export const GroupsEditorViewer = (props: Props) => { const [appendSeq, setAppendSeq] = useState([]); const [deleteSeq, setDeleteSeq] = useState([]); + const filteredPrependSeq = useMemo( + () => prependSeq.filter((group) => match(group.name)), + [prependSeq, match] + ); const filteredGroupList = useMemo( () => groupList.filter((group) => match(group.name)), [groupList, match] ); + const filteredAppendSeq = useMemo( + () => appendSeq.filter((group) => match(group.name)), + [appendSeq, match] + ); const sensors = useSensors( useSensor(PointerSensor), @@ -376,6 +384,7 @@ export const GroupsEditorViewer = (props: Props) => { }} multiple options={proxyPolicyList} + disableCloseOnSelect onChange={(_, value) => value && field.onChange(value)} renderInput={(params) => } /> @@ -393,6 +402,7 @@ export const GroupsEditorViewer = (props: Props) => { sx={{ width: "calc(100% - 150px)" }} multiple options={proxyProviderList} + disableCloseOnSelect onChange={(_, value) => value && field.onChange(value)} renderInput={(params) => } /> @@ -541,23 +551,33 @@ export const GroupsEditorViewer = (props: Props) => { { @@ -576,7 +596,6 @@ export const GroupsEditorViewer = (props: Props) => { { @@ -705,13 +724,13 @@ export const GroupsEditorViewer = (props: Props) => { style={{ height: "calc(100% - 24px)", marginTop: "8px" }} totalCount={ filteredGroupList.length + - (prependSeq.length > 0 ? 1 : 0) + - (appendSeq.length > 0 ? 1 : 0) + (filteredPrependSeq.length > 0 ? 1 : 0) + + (filteredAppendSeq.length > 0 ? 1 : 0) } increaseViewportBy={256} itemContent={(index) => { - let shift = prependSeq.length > 0 ? 1 : 0; - if (prependSeq.length > 0 && index === 0) { + let shift = filteredPrependSeq.length > 0 ? 1 : 0; + if (filteredPrependSeq.length > 0 && index === 0) { return ( { onDragEnd={onPrependDragEnd} > { + items={filteredPrependSeq.map((x) => { return x.name; })} > - {prependSeq.map((item, index) => { + {filteredPrependSeq.map((item, index) => { return ( { onDragEnd={onAppendDragEnd} > { + items={filteredAppendSeq.map((x) => { return x.name; })} > - {appendSeq.map((item, index) => { + {filteredAppendSeq.map((item, index) => { return ( { const [appendSeq, setAppendSeq] = useState([]); const [deleteSeq, setDeleteSeq] = useState([]); + const filteredPrependSeq = useMemo( + () => prependSeq.filter((proxy) => match(proxy.name)), + [prependSeq, match] + ); const filteredProxyList = useMemo( () => proxyList.filter((proxy) => match(proxy.name)), [proxyList, match] ); + const filteredAppendSeq = useMemo( + () => appendSeq.filter((proxy) => match(proxy.name)), + [appendSeq, match] + ); const sensors = useSensors( useSensor(PointerSensor), @@ -119,7 +127,31 @@ export const ProxiesEditorViewer = (props: Props) => { } } }; - + const handleParse = () => { + let proxies = [] as IProxyConfig[]; + let names: string[] = []; + let uris = ""; + try { + uris = atob(proxyUri); + } catch { + uris = proxyUri; + } + uris + .trim() + .split("\n") + .forEach((uri) => { + try { + let proxy = parseUri(uri.trim()); + if (!names.includes(proxy.name)) { + proxies.push(proxy); + names.push(proxy.name); + } + } catch (err: any) { + Notice.error(err.message || err.toString()); + } + }); + return proxies; + }; const fetchProfile = async () => { let data = await readProfileFile(profileUid); @@ -228,7 +260,6 @@ export const ProxiesEditorViewer = (props: Props) => { placeholder={t("Use newlines for multiple uri")} fullWidth rows={9} - sx={{ height: "100px" }} multiline size="small" onChange={(e) => setProxyUri(e.target.value)} @@ -240,18 +271,7 @@ export const ProxiesEditorViewer = (props: Props) => { fullWidth variant="contained" onClick={() => { - let proxies = [] as IProxyConfig[]; - proxyUri - .trim() - .split("\n") - .forEach((uri) => { - try { - let proxy = parseUri(uri.trim()); - proxies.push(proxy); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }); + let proxies = handleParse(); setPrependSeq([...prependSeq, ...proxies]); }} > @@ -263,18 +283,7 @@ export const ProxiesEditorViewer = (props: Props) => { fullWidth variant="contained" onClick={() => { - let proxies = [] as IProxyConfig[]; - proxyUri - .trim() - .split("\n") - .forEach((uri) => { - try { - let proxy = parseUri(uri.trim()); - proxies.push(proxy); - } catch (err: any) { - Notice.error(err.message || err.toString()); - } - }); + let proxies = handleParse(); setAppendSeq([...appendSeq, ...proxies]); }} > @@ -297,13 +306,13 @@ export const ProxiesEditorViewer = (props: Props) => { style={{ height: "calc(100% - 24px)", marginTop: "8px" }} totalCount={ filteredProxyList.length + - (prependSeq.length > 0 ? 1 : 0) + - (appendSeq.length > 0 ? 1 : 0) + (filteredPrependSeq.length > 0 ? 1 : 0) + + (filteredAppendSeq.length > 0 ? 1 : 0) } increaseViewportBy={256} itemContent={(index) => { - let shift = prependSeq.length > 0 ? 1 : 0; - if (prependSeq.length > 0 && index === 0) { + let shift = filteredPrependSeq.length > 0 ? 1 : 0; + if (filteredPrependSeq.length > 0 && index === 0) { return ( { onDragEnd={onPrependDragEnd} > { + items={filteredPrependSeq.map((x) => { return x.name; })} > - {prependSeq.map((item, index) => { + {filteredPrependSeq.map((item, index) => { return ( { onDragEnd={onAppendDragEnd} > { + items={filteredAppendSeq.map((x) => { return x.name; })} > - {appendSeq.map((item, index) => { + {filteredAppendSeq.map((item, index) => { return ( { ); }; -const StyledPrimary = styled("span")` +const StyledPrimary = styled("div")` font-size: 15px; font-weight: 700; line-height: 1.5; diff --git a/clash-verge-rev/src/components/profile/rule-item.tsx b/clash-verge-rev/src/components/profile/rule-item.tsx index 44e1478951..dfff9ef8a7 100644 --- a/clash-verge-rev/src/components/profile/rule-item.tsx +++ b/clash-verge-rev/src/components/profile/rule-item.tsx @@ -18,7 +18,12 @@ interface Props { export const RuleItem = (props: Props) => { let { type, ruleRaw, onDelete } = props; const sortable = type === "prepend" || type === "append"; - const rule = ruleRaw.replace(",no-resolve", "").split(","); + const rule = ruleRaw.replace(",no-resolve", ""); + + const ruleType = rule.match(/^[^,]+/)?.[0] ?? ""; + const proxyPolicy = rule.match(/[^,]+$/)?.[0] ?? ""; + const ruleContent = rule.slice(ruleType.length + 1, -proxyPolicy.length - 1); + const { attributes, listeners, setNodeRef, transform, transition } = sortable ? useSortable({ id: ruleRaw }) : { @@ -56,7 +61,7 @@ export const RuleItem = (props: Props) => { - {rule.length === 3 ? rule[1] : "-"} + {ruleContent || "-"} } secondary={ @@ -70,10 +75,10 @@ export const RuleItem = (props: Props) => { }} > - {rule[0]} + {ruleType} - {rule.length === 3 ? rule[2] : rule[1]} + {proxyPolicy} } @@ -92,7 +97,7 @@ export const RuleItem = (props: Props) => { ); }; -const StyledPrimary = styled("span")` +const StyledPrimary = styled("div")` font-size: 15px; font-weight: 700; line-height: 1.5; diff --git a/clash-verge-rev/src/components/profile/rules-editor-viewer.tsx b/clash-verge-rev/src/components/profile/rules-editor-viewer.tsx index 99e20db5dc..e4cb130288 100644 --- a/clash-verge-rev/src/components/profile/rules-editor-viewer.tsx +++ b/clash-verge-rev/src/components/profile/rules-editor-viewer.tsx @@ -254,10 +254,18 @@ export const RulesEditorViewer = (props: Props) => { const [appendSeq, setAppendSeq] = useState([]); const [deleteSeq, setDeleteSeq] = useState([]); + const filteredPrependSeq = useMemo( + () => prependSeq.filter((rule) => match(rule)), + [prependSeq, match] + ); const filteredRuleList = useMemo( () => ruleList.filter((rule) => match(rule)), [ruleList, match] ); + const filteredAppendSeq = useMemo( + () => appendSeq.filter((rule) => match(rule)), + [appendSeq, match] + ); const sensors = useSensors( useSensor(PointerSensor), @@ -573,13 +581,13 @@ export const RulesEditorViewer = (props: Props) => { style={{ height: "calc(100% - 24px)", marginTop: "8px" }} totalCount={ filteredRuleList.length + - (prependSeq.length > 0 ? 1 : 0) + - (appendSeq.length > 0 ? 1 : 0) + (filteredPrependSeq.length > 0 ? 1 : 0) + + (filteredAppendSeq.length > 0 ? 1 : 0) } increaseViewportBy={256} itemContent={(index) => { - let shift = prependSeq.length > 0 ? 1 : 0; - if (prependSeq.length > 0 && index === 0) { + let shift = filteredPrependSeq.length > 0 ? 1 : 0; + if (filteredPrependSeq.length > 0 && index === 0) { return ( { onDragEnd={onPrependDragEnd} > { + items={filteredPrependSeq.map((x) => { return x; })} > - {prependSeq.map((item, index) => { + {filteredPrependSeq.map((item, index) => { return ( { onDragEnd={onAppendDragEnd} > { + items={filteredAppendSeq.map((x) => { return x; })} > - {appendSeq.map((item, index) => { + {filteredAppendSeq.map((item, index) => { return ( ((props, ref) => { let validReg; if (getSystem() === "windows") { validReg = - /^((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){1,3}\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\*|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+|localhost|)(;((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){1,3}\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\*|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+|localhost|))*;?$/; + /^((\*\.)?([a-zA-Z0-9-]+\.?)+(local|test|example|invalid|localhost|onion|([a-zA-Z]{2,}))|(\d{1,3}\.){1,3}\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\*|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+|localhost|)(;((\*\.)?([a-zA-Z0-9-]+\.?)+(local|test|example|invalid|localhost|onion|([a-zA-Z]{2,}))|(\d{1,3}\.){1,3}\d{1,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\d{1,3}\.\*|\d{1,3}\.\*|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+|localhost|))*;?$/; } else { validReg = - /^((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){1,3}\d{1,3}(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+(\/\d{1,3})?|localhost|)(,((\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}|(\d{1,3}\.){1,3}\d{1,3}(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+(\/\d{1,3})?|localhost|))*,?$/; + /^((\*\.)?([a-zA-Z0-9-]+\.?)+(local|test|example|invalid|localhost|onion|([a-zA-Z]{2,}))|(\d{1,3}\.){1,3}\d{1,3}(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+(\/\d{1,3})?|localhost|)(,((\*\.)?([a-zA-Z0-9-]+\.?)+(local|test|example|invalid|localhost|onion|([a-zA-Z]{2,}))|(\d{1,3}\.){1,3}\d{1,3}(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\d{1,3}\.\*(\/\d{1,2}|\/3[0-2])?|\d{1,3}\.\*(\/3[0-2])?|([a-fA-F0-9:]+:+)+[a-fA-F0-9]+(\/\d{1,3})?|localhost|))*,?$/; } const [open, setOpen] = useState(false); diff --git a/clash-verge-rev/src/services/types.d.ts b/clash-verge-rev/src/services/types.d.ts index e2e47c7c72..3c1c357663 100644 --- a/clash-verge-rev/src/services/types.d.ts +++ b/clash-verge-rev/src/services/types.d.ts @@ -223,7 +223,7 @@ interface IProxyGroupConfig { filter?: string; "exclude-filter"?: string; "exclude-type"?: string; - "expected-status"?: number; + "expected-status"?: string; hidden?: boolean; icon?: string; } @@ -243,7 +243,7 @@ interface HttpOptions { method?: string; path?: string[]; headers?: { - [key: string]: string; + [key: string]: string[]; }; } @@ -262,7 +262,38 @@ interface RealityOptions { } type NetworkType = "ws" | "http" | "h2" | "grpc"; - +type CipherType = + | "none" + | "auto" + | "dummy" + | "aes-128-gcm" + | "aes-192-gcm" + | "aes-256-gcm" + | "lea-128-gcm" + | "lea-192-gcm" + | "lea-256-gcm" + | "aes-128-gcm-siv" + | "aes-256-gcm-siv" + | "2022-blake3-aes-128-gcm" + | "2022-blake3-aes-256-gcm" + | "aes-128-cfb" + | "aes-192-cfb" + | "aes-256-cfb" + | "aes-128-ctr" + | "aes-192-ctr" + | "aes-256-ctr" + | "chacha20" + | "chacha20-ietf" + | "chacha20-ietf-poly1305" + | "2022-blake3-chacha20-poly1305" + | "rabbit128-poly1305" + | "xchacha20-ietf-poly1305" + | "xchacha20" + | "aegis-128l" + | "aegis-256" + | "aez-384" + | "deoxys-ii-256-128" + | "rc4-md5"; // base interface IProxyBaseConfig { tfo?: boolean; @@ -294,7 +325,9 @@ interface IProxyHttpConfig extends IProxyBaseConfig { sni?: string; "skip-cert-verify"?: boolean; fingerprint?: string; - headers?: {}; + headers?: { + [key: string]: string; + }; } // socks5 interface IProxySocks5Config extends IProxyBaseConfig { @@ -399,7 +432,9 @@ interface IProxyVlessConfig extends IProxyBaseConfig { "grpc-opts"?: GrpcOptions; "ws-opts"?: WsOptions; "ws-path"?: string; - "ws-headers"?: {}; + "ws-headers"?: { + [key: string]: string; + }; "skip-cert-verify"?: boolean; fingerprint?: string; servername?: string; @@ -413,7 +448,7 @@ interface IProxyVmessConfig extends IProxyBaseConfig { port?: number; uuid?: string; alterId?: number; - cipher?: string; + cipher?: CipherType; udp?: boolean; network?: NetworkType; tls?: boolean; @@ -516,7 +551,7 @@ interface IProxyShadowsocksConfig extends IProxyBaseConfig { server?: string; port?: number; password?: string; - cipher?: string; + cipher?: CipherType; udp?: boolean; plugin?: "obfs" | "v2ray-plugin" | "shadow-tls" | "restls"; "plugin-opts"?: { @@ -526,7 +561,9 @@ interface IProxyShadowsocksConfig extends IProxyBaseConfig { path?: string; tls?: string; fingerprint?: string; - headers?: {}; + headers?: { + [key: string]: string; + }; "skip-cert-verify"?: boolean; version?: number; mux?: boolean; @@ -546,7 +583,7 @@ interface IProxyshadowsocksRConfig extends IProxyBaseConfig { server?: string; port?: number; password?: string; - cipher?: string; + cipher?: CipherType; obfs?: string; "obfs-param"?: string; protocol?: string; diff --git a/clash-verge-rev/src/utils/uri-parser.ts b/clash-verge-rev/src/utils/uri-parser.ts index ea9d0c1880..6d6131e54c 100644 --- a/clash-verge-rev/src/utils/uri-parser.ts +++ b/clash-verge-rev/src/utils/uri-parser.ts @@ -80,10 +80,83 @@ function decodeBase64OrOriginal(str: string): string { } } +function getCipher(str: string | undefined) { + switch (str) { + case "none": + return "none"; + case "auto": + return "auto"; + case "dummy": + return "dummy"; + case "aes-128-gcm": + return "aes-128-gcm"; + case "aes-192-gcm": + return "aes-192-gcm"; + case "aes-256-gcm": + return "aes-256-gcm"; + case "lea-128-gcm": + return "lea-128-gcm"; + case "lea-192-gcm": + return "lea-192-gcm"; + case "lea-256-gcm": + return "lea-256-gcm"; + case "aes-128-gcm-siv": + return "aes-128-gcm-siv"; + case "aes-256-gcm-siv": + return "aes-256-gcm-siv"; + case "2022-blake3-aes-128-gcm": + return "2022-blake3-aes-128-gcm"; + case "2022-blake3-aes-256-gcm": + return "2022-blake3-aes-256-gcm"; + case "aes-128-cfb": + return "aes-128-cfb"; + case "aes-192-cfb": + return "aes-192-cfb"; + case "aes-256-cfb": + return "aes-256-cfb"; + case "aes-128-ctr": + return "aes-128-ctr"; + case "aes-192-ctr": + return "aes-192-ctr"; + case "aes-256-ctr": + return "aes-256-ctr"; + case "chacha20": + return "chacha20"; + case "chacha20-poly1305": + return "chacha20-ietf-poly1305"; + case "chacha20-ietf": + return "chacha20-ietf"; + case "chacha20-ietf-poly1305": + return "chacha20-ietf-poly1305"; + case "2022-blake3-chacha20-poly1305": + return "2022-blake3-chacha20-poly1305"; + case "rabbit128-poly1305": + return "rabbit128-poly1305"; + case "xchacha20-ietf-poly1305": + return "xchacha20-ietf-poly1305"; + case "xchacha20": + return "xchacha20"; + case "aegis-128l": + return "aegis-128l"; + case "aegis-256": + return "aegis-256"; + case "aez-384": + return "aez-384"; + case "deoxys-ii-256-128": + return "deoxys-ii-256-128"; + case "rc4-md5": + return "rc4-md5"; + case undefined: + return "none"; + default: + return "auto"; + } +} + function URI_SS(line: string): IProxyShadowsocksConfig { // parse url let content = line.split("ss://")[1]; - content = decodeBase64OrOriginal(content); + const proxy: IProxyShadowsocksConfig = { name: decodeURIComponent(line.split("#")[1]).trim(), type: "ss", @@ -125,7 +198,7 @@ function URI_SS(line: string): IProxyShadowsocksConfig { `${serverAndPort?.substring(portIdx + 1)}`.match(/\d+/)?.[0] ?? "" ); const userInfo = userInfoStr.match(/(^.*?):(.*$)/); - proxy.cipher = userInfo?.[1]; + proxy.cipher = getCipher(userInfo?.[1]); proxy.password = userInfo?.[2]; // handle obfs @@ -172,7 +245,7 @@ function URI_SS(line: string): IProxyShadowsocksConfig { function URI_SSR(line: string): IProxyshadowsocksRConfig { line = decodeBase64OrOriginal(line.split("ssr://")[1]); - line = decodeBase64OrOriginal(line); + // handle IPV6 & IPV4 format let splitIdx = line.indexOf(":origin"); if (splitIdx === -1) { @@ -194,7 +267,7 @@ function URI_SSR(line: string): IProxyshadowsocksRConfig { server, port, protocol: params[0], - cipher: params[1], + cipher: getCipher(params[1]), obfs: params[2], password: decodeBase64OrOriginal(params[3]), }; @@ -243,7 +316,7 @@ function URI_VMESS(line: string): IProxyVmessConfig { type: "vmess", server: partitions[1], port: parseInt(partitions[2], 10), - cipher: getIfNotBlank(partitions[3], "auto"), + cipher: getCipher(getIfNotBlank(partitions[3], "auto")), uuid: partitions[4].match(/^"(.*)"$/)?.[1] || "", tls: params.obfs === "wss", udp: getIfPresent(params["udp-relay"]), @@ -320,7 +393,7 @@ function URI_VMESS(line: string): IProxyVmessConfig { type: "vmess", server, port, - cipher: getIfPresent(params.scy, "auto"), + cipher: getCipher(getIfPresent(params.scy, "auto")), uuid: params.id, tls: ["tls", true, 1, "1"].includes(params.tls), "skip-cert-verify": isPresent(params.verify_cert) @@ -411,7 +484,6 @@ function URI_VMESS(line: string): IProxyVmessConfig { function URI_VLESS(line: string): IProxyVlessConfig { line = line.split("vless://")[1]; - line = decodeBase64OrOriginal(line); let isShadowrocket; let parsed = /^(.*?)@(.*?):(\d+)\/?(\?(.*?))?(?:#(.*?))?$/.exec(line)!; if (!parsed) { @@ -578,7 +650,6 @@ function URI_Trojan(line: string): IProxyTrojanConfig { function URI_Hysteria2(line: string): IProxyHysteria2Config { line = line.split(/(hysteria2|hy2):\/\//)[2]; - line = decodeBase64OrOriginal(line); // eslint-disable-next-line no-unused-vars let [__, password, server, ___, port, ____, addons = "", name] = /^(.*?)@(.*?)(:(\d+))?\/?(\?(.*?))?(?:#(.*?))?$/.exec(line) || []; @@ -627,7 +698,6 @@ function URI_Hysteria2(line: string): IProxyHysteria2Config { function URI_Hysteria(line: string): IProxyHysteriaConfig { line = line.split(/(hysteria|hy):\/\//)[2]; - line = decodeBase64OrOriginal(line); let [__, server, ___, port, ____, addons = "", name] = /^(.*?)(:(\d+))?\/?(\?(.*?))?(?:#(.*?))?$/.exec(line)!; let portNum = parseInt(`${port}`, 10); @@ -723,7 +793,7 @@ function URI_Hysteria(line: string): IProxyHysteriaConfig { function URI_TUIC(line: string): IProxyTuicConfig { line = line.split(/tuic:\/\//)[1]; - line = decodeBase64OrOriginal(line); + let [__, uuid, password, server, ___, port, ____, addons = "", name] = /^(.*?):(.*?)@(.*?)(:(\d+))?\/?(\?(.*?))?(?:#(.*?))?$/.exec(line) || []; @@ -803,7 +873,6 @@ function URI_TUIC(line: string): IProxyTuicConfig { function URI_Wireguard(line: string): IProxyWireguardConfig { line = line.split(/(wireguard|wg):\/\//)[2]; - line = decodeBase64OrOriginal(line); let [__, ___, privateKey, server, ____, port, _____, addons = "", name] = /^((.*?)@)?(.*?)(:(\d+))?\/?(\?(.*?))?(?:#(.*?))?$/.exec(line)!; @@ -886,7 +955,6 @@ function URI_Wireguard(line: string): IProxyWireguardConfig { function URI_HTTP(line: string): IProxyHttpConfig { line = line.split(/(http|https):\/\//)[2]; - line = decodeBase64OrOriginal(line); let [__, ___, auth, server, ____, port, _____, addons = "", name] = /^((.*?)@)?(.*?)(:(\d+))?\/?(\?(.*?))?(?:#(.*?))?$/.exec(line)!; @@ -951,7 +1019,6 @@ function URI_HTTP(line: string): IProxyHttpConfig { function URI_SOCKS(line: string): IProxySocks5Config { line = line.split(/socks5:\/\//)[1]; - line = decodeBase64OrOriginal(line); let [__, ___, auth, server, ____, port, _____, addons = "", name] = /^((.*?)@)?(.*?)(:(\d+))?\/?(\?(.*?))?(?:#(.*?))?$/.exec(line)!; diff --git a/geoip/lib/common.go b/geoip/lib/common.go new file mode 100644 index 0000000000..81d8a2283b --- /dev/null +++ b/geoip/lib/common.go @@ -0,0 +1,21 @@ +package lib + +import ( + "fmt" + "io" + "net/http" +) + +func getRemoteURLContent(url string) ([]byte, error) { + resp, err := http.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("failed to get remote content -> %s: %s", url, resp.Status) + } + + return io.ReadAll(resp.Body) +} diff --git a/geoip/lib/container.go b/geoip/lib/container.go new file mode 100644 index 0000000000..7427d85194 --- /dev/null +++ b/geoip/lib/container.go @@ -0,0 +1,183 @@ +package lib + +import ( + "fmt" + "strings" + + "go4.org/netipx" +) + +type Container interface { + GetEntry(name string) (*Entry, bool) + Add(entry *Entry, opts ...IgnoreIPOption) error + Remove(entry *Entry, rCase CaseRemove, opts ...IgnoreIPOption) error + Loop() <-chan *Entry +} + +type container struct { + entries map[string]*Entry +} + +func NewContainer() Container { + return &container{ + entries: make(map[string]*Entry), + } +} + +func (c *container) isValid() bool { + return c.entries != nil +} + +func (c *container) GetEntry(name string) (*Entry, bool) { + if !c.isValid() { + return nil, false + } + val, ok := c.entries[strings.ToUpper(strings.TrimSpace(name))] + if !ok { + return nil, false + } + return val, true +} + +func (c *container) Loop() <-chan *Entry { + ch := make(chan *Entry, 300) + go func() { + for _, val := range c.entries { + ch <- val + } + close(ch) + }() + return ch +} + +func (c *container) Add(entry *Entry, opts ...IgnoreIPOption) error { + var ignoreIPType IPType + for _, opt := range opts { + if opt != nil { + ignoreIPType = opt() + } + } + + name := entry.GetName() + val, found := c.GetEntry(name) + + switch found { + case true: + var ipv4set, ipv6set *netipx.IPSet + var err4, err6 error + if entry.hasIPv4Builder() { + ipv4set, err4 = entry.ipv4Builder.IPSet() + if err4 != nil { + return err4 + } + } + if entry.hasIPv6Builder() { + ipv6set, err6 = entry.ipv6Builder.IPSet() + if err6 != nil { + return err6 + } + } + switch ignoreIPType { + case IPv4: + if !val.hasIPv6Builder() { + val.ipv6Builder = new(netipx.IPSetBuilder) + } + val.ipv6Builder.AddSet(ipv6set) + case IPv6: + if !val.hasIPv4Builder() { + val.ipv4Builder = new(netipx.IPSetBuilder) + } + val.ipv4Builder.AddSet(ipv4set) + default: + if !val.hasIPv4Builder() { + val.ipv4Builder = new(netipx.IPSetBuilder) + } + if !val.hasIPv6Builder() { + val.ipv6Builder = new(netipx.IPSetBuilder) + } + val.ipv4Builder.AddSet(ipv4set) + val.ipv6Builder.AddSet(ipv6set) + } + + case false: + switch ignoreIPType { + case IPv4: + entry.ipv4Builder = nil + case IPv6: + entry.ipv6Builder = nil + } + c.entries[name] = entry + } + + return nil +} + +func (c *container) Remove(entry *Entry, rCase CaseRemove, opts ...IgnoreIPOption) error { + name := entry.GetName() + val, found := c.GetEntry(name) + if !found { + return fmt.Errorf("entry %s not found", name) + } + + var ignoreIPType IPType + for _, opt := range opts { + if opt != nil { + ignoreIPType = opt() + } + } + + switch rCase { + case CaseRemovePrefix: + var ipv4set, ipv6set *netipx.IPSet + var err4, err6 error + if entry.hasIPv4Builder() { + ipv4set, err4 = entry.ipv4Builder.IPSet() + if err4 != nil { + return err4 + } + } + if entry.hasIPv6Builder() { + ipv6set, err6 = entry.ipv6Builder.IPSet() + if err6 != nil { + return err6 + } + } + + switch ignoreIPType { + case IPv4: + if !val.hasIPv6Builder() { + val.ipv6Builder = new(netipx.IPSetBuilder) + } + val.ipv6Builder.RemoveSet(ipv6set) + case IPv6: + if !val.hasIPv4Builder() { + val.ipv4Builder = new(netipx.IPSetBuilder) + } + val.ipv4Builder.RemoveSet(ipv4set) + default: + if !val.hasIPv4Builder() { + val.ipv4Builder = new(netipx.IPSetBuilder) + } + if !val.hasIPv6Builder() { + val.ipv6Builder = new(netipx.IPSetBuilder) + } + val.ipv4Builder.RemoveSet(ipv4set) + val.ipv6Builder.RemoveSet(ipv6set) + } + + case CaseRemoveEntry: + switch ignoreIPType { + case IPv4: + val.ipv6Builder = nil + case IPv6: + val.ipv4Builder = nil + default: + delete(c.entries, name) + } + + default: + return fmt.Errorf("unknown remove case %d", rCase) + } + + return nil +} diff --git a/geoip/lib/func.go b/geoip/lib/converter.go similarity index 79% rename from geoip/lib/func.go rename to geoip/lib/converter.go index c1ce55919f..e660efb73d 100644 --- a/geoip/lib/func.go +++ b/geoip/lib/converter.go @@ -2,8 +2,6 @@ package lib import ( "fmt" - "io" - "net/http" "sort" "strings" ) @@ -54,17 +52,3 @@ func RegisterOutputConverter(name string, c OutputConverter) error { outputConverterMap[name] = c return nil } - -func getRemoteURLContent(url string) ([]byte, error) { - resp, err := http.Get(url) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("failed to get remote content -> %s: %s", url, resp.Status) - } - - return io.ReadAll(resp.Body) -} diff --git a/geoip/lib/entry.go b/geoip/lib/entry.go new file mode 100644 index 0000000000..311e89cb02 --- /dev/null +++ b/geoip/lib/entry.go @@ -0,0 +1,328 @@ +package lib + +import ( + "fmt" + "net" + "net/netip" + "strings" + "sync" + + "go4.org/netipx" +) + +type Entry struct { + name string + mu *sync.Mutex + ipv4Builder *netipx.IPSetBuilder + ipv6Builder *netipx.IPSetBuilder +} + +func NewEntry(name string) *Entry { + return &Entry{ + name: strings.ToUpper(strings.TrimSpace(name)), + mu: new(sync.Mutex), + ipv4Builder: new(netipx.IPSetBuilder), + ipv6Builder: new(netipx.IPSetBuilder), + } +} + +func (e *Entry) GetName() string { + return e.name +} + +func (e *Entry) hasIPv4Builder() bool { + return e.ipv4Builder != nil +} + +func (e *Entry) hasIPv6Builder() bool { + return e.ipv6Builder != nil +} + +func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) { + switch src := src.(type) { + case net.IP: + ip, ok := netipx.FromStdIP(src) + if !ok { + return nil, "", ErrInvalidIP + } + ip = ip.Unmap() + switch { + case ip.Is4(): + prefix := netip.PrefixFrom(ip, 32) + return &prefix, IPv4, nil + case ip.Is6(): + prefix := netip.PrefixFrom(ip, 128) + return &prefix, IPv6, nil + default: + return nil, "", ErrInvalidIPLength + } + + case *net.IPNet: + prefix, ok := netipx.FromStdIPNet(src) + if !ok { + return nil, "", ErrInvalidIPNet + } + ip := prefix.Addr().Unmap() + switch { + case ip.Is4(): + return &prefix, IPv4, nil + case ip.Is6(): + return &prefix, IPv6, nil + default: + return nil, "", ErrInvalidIPLength + } + + case netip.Addr: + src = src.Unmap() + switch { + case src.Is4(): + prefix := netip.PrefixFrom(src, 32) + return &prefix, IPv4, nil + case src.Is6(): + prefix := netip.PrefixFrom(src, 128) + return &prefix, IPv6, nil + default: + return nil, "", ErrInvalidIPLength + } + + case *netip.Addr: + *src = (*src).Unmap() + switch { + case src.Is4(): + prefix := netip.PrefixFrom(*src, 32) + return &prefix, IPv4, nil + case src.Is6(): + prefix := netip.PrefixFrom(*src, 128) + return &prefix, IPv6, nil + default: + return nil, "", ErrInvalidIPLength + } + + case netip.Prefix: + ip := src.Addr() + switch { + case ip.Is4(): + prefix, err := ip.Prefix(src.Bits()) + if err != nil { + return nil, "", ErrInvalidPrefix + } + return &prefix, IPv4, nil + case ip.Is4In6(): + ip = ip.Unmap() + bits := src.Bits() + if bits < 96 { + return nil, "", ErrInvalidPrefix + } + prefix, err := ip.Prefix(bits - 96) + if err != nil { + return nil, "", ErrInvalidPrefix + } + return &prefix, IPv4, nil + case ip.Is6(): + prefix, err := ip.Prefix(src.Bits()) + if err != nil { + return nil, "", ErrInvalidPrefix + } + return &prefix, IPv6, nil + default: + return nil, "", ErrInvalidIPLength + } + + case *netip.Prefix: + ip := src.Addr() + switch { + case ip.Is4(): + prefix, err := ip.Prefix(src.Bits()) + if err != nil { + return nil, "", ErrInvalidPrefix + } + return &prefix, IPv4, nil + case ip.Is4In6(): + ip = ip.Unmap() + bits := src.Bits() + if bits < 96 { + return nil, "", ErrInvalidPrefix + } + prefix, err := ip.Prefix(bits - 96) + if err != nil { + return nil, "", ErrInvalidPrefix + } + return &prefix, IPv4, nil + case ip.Is6(): + prefix, err := ip.Prefix(src.Bits()) + if err != nil { + return nil, "", ErrInvalidPrefix + } + return &prefix, IPv6, nil + default: + return nil, "", ErrInvalidIPLength + } + + case string: + src, _, _ = strings.Cut(src, "#") + src, _, _ = strings.Cut(src, "//") + src, _, _ = strings.Cut(src, "/*") + src = strings.TrimSpace(src) + if src == "" { + return nil, "", ErrCommentLine + } + + switch strings.Contains(src, "/") { + case true: // src is CIDR notation + ip, network, err := net.ParseCIDR(src) + if err != nil { + return nil, "", ErrInvalidCIDR + } + addr, ok := netipx.FromStdIP(ip) + if !ok { + return nil, "", ErrInvalidIP + } + if addr.Unmap().Is4() && strings.Contains(network.String(), "::") { // src is invalid IPv4-mapped IPv6 address + return nil, "", ErrInvalidCIDR + } + prefix, ok := netipx.FromStdIPNet(network) + if !ok { + return nil, "", ErrInvalidIPNet + } + + addr = prefix.Addr().Unmap() + switch { + case addr.Is4(): + return &prefix, IPv4, nil + case addr.Is6(): + return &prefix, IPv6, nil + default: + return nil, "", ErrInvalidIPLength + } + + case false: // src is IP address + ip, err := netip.ParseAddr(src) + if err != nil { + return nil, "", ErrInvalidIP + } + ip = ip.Unmap() + switch { + case ip.Is4(): + prefix := netip.PrefixFrom(ip, 32) + return &prefix, IPv4, nil + case ip.Is6(): + prefix := netip.PrefixFrom(ip, 128) + return &prefix, IPv6, nil + default: + return nil, "", ErrInvalidIPLength + } + } + } + + return nil, "", ErrInvalidPrefixType +} + +func (e *Entry) add(prefix *netip.Prefix, ipType IPType) error { + e.mu.Lock() + defer e.mu.Unlock() + + switch ipType { + case IPv4: + if !e.hasIPv4Builder() { + e.ipv4Builder = new(netipx.IPSetBuilder) + } + e.ipv4Builder.AddPrefix(*prefix) + case IPv6: + if !e.hasIPv6Builder() { + e.ipv6Builder = new(netipx.IPSetBuilder) + } + e.ipv6Builder.AddPrefix(*prefix) + default: + return ErrInvalidIPType + } + + return nil +} + +func (e *Entry) remove(prefix *netip.Prefix, ipType IPType) error { + e.mu.Lock() + defer e.mu.Unlock() + + switch ipType { + case IPv4: + if e.hasIPv4Builder() { + e.ipv4Builder.RemovePrefix(*prefix) + } + case IPv6: + if e.hasIPv6Builder() { + e.ipv6Builder.RemovePrefix(*prefix) + } + default: + return ErrInvalidIPType + } + + return nil +} + +func (e *Entry) AddPrefix(cidr any) error { + prefix, ipType, err := e.processPrefix(cidr) + if err != nil && err != ErrCommentLine { + return err + } + if err := e.add(prefix, ipType); err != nil { + return err + } + return nil +} + +func (e *Entry) RemovePrefix(cidr string) error { + prefix, ipType, err := e.processPrefix(cidr) + if err != nil && err != ErrCommentLine { + return err + } + if err := e.remove(prefix, ipType); err != nil { + return err + } + return nil +} + +func (e *Entry) MarshalText(opts ...IgnoreIPOption) ([]string, error) { + var ignoreIPType IPType + for _, opt := range opts { + if opt != nil { + ignoreIPType = opt() + } + } + disableIPv4, disableIPv6 := false, false + switch ignoreIPType { + case IPv4: + disableIPv4 = true + case IPv6: + disableIPv6 = true + } + + prefixSet := make([]string, 0, 1024) + + if !disableIPv4 && e.hasIPv4Builder() { + ipv4set, err := e.ipv4Builder.IPSet() + if err != nil { + return nil, err + } + prefixes := ipv4set.Prefixes() + for _, prefix := range prefixes { + prefixSet = append(prefixSet, prefix.String()) + } + } + + if !disableIPv6 && e.hasIPv6Builder() { + ipv6set, err := e.ipv6Builder.IPSet() + if err != nil { + return nil, err + } + prefixes := ipv6set.Prefixes() + for _, prefix := range prefixes { + prefixSet = append(prefixSet, prefix.String()) + } + } + + if len(prefixSet) > 0 { + return prefixSet, nil + } + + return nil, fmt.Errorf("entry %s has no prefix", e.GetName()) +} diff --git a/geoip/lib/error.go b/geoip/lib/error.go index 1b8e4518b9..80dcc736fd 100644 --- a/geoip/lib/error.go +++ b/geoip/lib/error.go @@ -10,6 +10,8 @@ var ( ErrInvalidIP = errors.New("invalid IP address") ErrInvalidIPLength = errors.New("invalid IP address length") ErrInvalidIPNet = errors.New("invalid IPNet address") + ErrInvalidCIDR = errors.New("invalid CIDR") + ErrInvalidPrefix = errors.New("invalid prefix") ErrInvalidPrefixType = errors.New("invalid prefix type") ErrCommentLine = errors.New("comment line") ) diff --git a/geoip/lib/lib.go b/geoip/lib/lib.go index 430a39f345..691708ff75 100644 --- a/geoip/lib/lib.go +++ b/geoip/lib/lib.go @@ -1,16 +1,5 @@ package lib -import ( - "fmt" - "log" - "net" - "net/netip" - "strings" - "sync" - - "go4.org/netipx" -) - const ( ActionAdd Action = "add" ActionRemove Action = "remove" @@ -18,6 +7,9 @@ const ( IPv4 IPType = "ipv4" IPv6 IPType = "ipv6" + + CaseRemovePrefix CaseRemove = 0 + CaseRemoveEntry CaseRemove = 1 ) var ActionsRegistry = map[Action]bool{ @@ -30,6 +22,8 @@ type Action string type IPType string +type CaseRemove int + type Typer interface { GetType() string } @@ -56,280 +50,6 @@ type OutputConverter interface { Output(Container) error } -type Entry struct { - name string - mu *sync.Mutex - ipv4Builder *netipx.IPSetBuilder - ipv6Builder *netipx.IPSetBuilder -} - -func NewEntry(name string) *Entry { - return &Entry{ - name: strings.ToUpper(strings.TrimSpace(name)), - mu: new(sync.Mutex), - ipv4Builder: new(netipx.IPSetBuilder), - ipv6Builder: new(netipx.IPSetBuilder), - } -} - -func (e *Entry) GetName() string { - return e.name -} - -func (e *Entry) hasIPv4Builder() bool { - return e.ipv4Builder != nil -} - -func (e *Entry) hasIPv6Builder() bool { - return e.ipv6Builder != nil -} - -func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) { - switch src := src.(type) { - case net.IP: - ip, ok := netipx.FromStdIP(src) - if !ok { - return nil, "", ErrInvalidIP - } - switch { - case ip.Is4(): - prefix := netip.PrefixFrom(ip, 32) - return &prefix, IPv4, nil - case ip.Is6(): - prefix := netip.PrefixFrom(ip, 128) - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case *net.IPNet: - prefix, ok := netipx.FromStdIPNet(src) - if !ok { - return nil, "", ErrInvalidIPNet - } - ip := prefix.Addr() - switch { - case ip.Is4(): - return &prefix, IPv4, nil - case ip.Is6(): - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case netip.Addr: - switch { - case src.Is4(): - prefix := netip.PrefixFrom(src, 32) - return &prefix, IPv4, nil - case src.Is6(): - prefix := netip.PrefixFrom(src, 128) - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case *netip.Addr: - switch { - case src.Is4(): - prefix := netip.PrefixFrom(*src, 32) - return &prefix, IPv4, nil - case src.Is6(): - prefix := netip.PrefixFrom(*src, 128) - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case netip.Prefix: - ip := src.Addr() - switch { - case ip.Is4(): - return &src, IPv4, nil - case ip.Is6(): - return &src, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case *netip.Prefix: - ip := src.Addr() - switch { - case ip.Is4(): - return src, IPv4, nil - case ip.Is6(): - return src, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case string: - src, _, _ = strings.Cut(src, "#") - src, _, _ = strings.Cut(src, "//") - src, _, _ = strings.Cut(src, "/*") - src = strings.TrimSpace(src) - if src == "" { - return nil, "", ErrCommentLine - } - - _, network, err := net.ParseCIDR(src) - switch err { - case nil: - prefix, err2 := netip.ParsePrefix(network.String()) - if err2 != nil { - return nil, "", ErrInvalidIPNet - } - ip := prefix.Addr() - switch { - case ip.Is4(): - return &prefix, IPv4, nil - case ip.Is6(): - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - default: - ip, err := netip.ParseAddr(src) - if err != nil { - return nil, "", err - } - switch { - case ip.Is4(): - prefix := netip.PrefixFrom(ip, 32) - return &prefix, IPv4, nil - case ip.Is4In6(): - _, network, err2 := net.ParseCIDR(src + "/128") - if err2 != nil { - return nil, "", ErrInvalidIPNet - } - prefix, err3 := netip.ParsePrefix(network.String()) - if err3 != nil { - return nil, "", ErrInvalidIPNet - } - return &prefix, IPv4, nil - case ip.Is6(): - prefix := netip.PrefixFrom(ip, 128) - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - } - } - - return nil, "", ErrInvalidPrefixType -} - -func (e *Entry) add(prefix *netip.Prefix, ipType IPType) error { - e.mu.Lock() - defer e.mu.Unlock() - - switch ipType { - case IPv4: - if !e.hasIPv4Builder() { - e.ipv4Builder = new(netipx.IPSetBuilder) - } - e.ipv4Builder.AddPrefix(*prefix) - case IPv6: - if !e.hasIPv6Builder() { - e.ipv6Builder = new(netipx.IPSetBuilder) - } - e.ipv6Builder.AddPrefix(*prefix) - default: - return ErrInvalidIPType - } - - return nil -} - -func (e *Entry) remove(prefix *netip.Prefix, ipType IPType) error { - e.mu.Lock() - defer e.mu.Unlock() - - switch ipType { - case IPv4: - if e.hasIPv4Builder() { - e.ipv4Builder.RemovePrefix(*prefix) - } - case IPv6: - if e.hasIPv6Builder() { - e.ipv6Builder.RemovePrefix(*prefix) - } - default: - return ErrInvalidIPType - } - - return nil -} - -func (e *Entry) AddPrefix(cidr any) error { - prefix, ipType, err := e.processPrefix(cidr) - if err != nil && err != ErrCommentLine { - return err - } - if err := e.add(prefix, ipType); err != nil { - return err - } - return nil -} - -func (e *Entry) RemovePrefix(cidr string) error { - prefix, ipType, err := e.processPrefix(cidr) - if err != nil && err != ErrCommentLine { - return err - } - if err := e.remove(prefix, ipType); err != nil { - return err - } - return nil -} - -func (e *Entry) MarshalText(opts ...IgnoreIPOption) ([]string, error) { - var ignoreIPType IPType - for _, opt := range opts { - if opt != nil { - ignoreIPType = opt() - } - } - disableIPv4, disableIPv6 := false, false - switch ignoreIPType { - case IPv4: - disableIPv4 = true - case IPv6: - disableIPv6 = true - } - - prefixSet := make([]string, 0, 1024) - - if !disableIPv4 && e.hasIPv4Builder() { - ipv4set, err := e.ipv4Builder.IPSet() - if err != nil { - return nil, err - } - prefixes := ipv4set.Prefixes() - for _, prefix := range prefixes { - prefixSet = append(prefixSet, prefix.String()) - } - } - - if !disableIPv6 && e.hasIPv6Builder() { - ipv6set, err := e.ipv6Builder.IPSet() - if err != nil { - return nil, err - } - prefixes := ipv6set.Prefixes() - for _, prefix := range prefixes { - prefixSet = append(prefixSet, prefix.String()) - } - } - - if len(prefixSet) > 0 { - return prefixSet, nil - } - - return nil, fmt.Errorf("entry %s has no prefix", e.GetName()) -} - type IgnoreIPOption func() IPType func IgnoreIPv4() IPType { @@ -339,138 +59,3 @@ func IgnoreIPv4() IPType { func IgnoreIPv6() IPType { return IPv6 } - -type Container interface { - GetEntry(name string) (*Entry, bool) - Add(entry *Entry, opts ...IgnoreIPOption) error - Remove(name string, opts ...IgnoreIPOption) - Loop() <-chan *Entry -} - -type container struct { - entries *sync.Map // map[name]*Entry -} - -func NewContainer() Container { - return &container{ - entries: new(sync.Map), - } -} - -func (c *container) isValid() bool { - if c == nil || c.entries == nil { - return false - } - return true -} - -func (c *container) GetEntry(name string) (*Entry, bool) { - if !c.isValid() { - return nil, false - } - val, ok := c.entries.Load(strings.ToUpper(strings.TrimSpace(name))) - if !ok { - return nil, false - } - return val.(*Entry), true -} - -func (c *container) Loop() <-chan *Entry { - ch := make(chan *Entry, 300) - go func() { - c.entries.Range(func(key, value any) bool { - ch <- value.(*Entry) - return true - }) - close(ch) - }() - return ch -} - -func (c *container) Add(entry *Entry, opts ...IgnoreIPOption) error { - var ignoreIPType IPType - for _, opt := range opts { - if opt != nil { - ignoreIPType = opt() - } - } - - name := entry.GetName() - val, found := c.GetEntry(name) - switch found { - case true: - var ipv4set, ipv6set *netipx.IPSet - var err4, err6 error - if entry.hasIPv4Builder() { - ipv4set, err4 = entry.ipv4Builder.IPSet() - if err4 != nil { - return err4 - } - } - if entry.hasIPv6Builder() { - ipv6set, err6 = entry.ipv6Builder.IPSet() - if err6 != nil { - return err6 - } - } - switch ignoreIPType { - case IPv4: - if !val.hasIPv6Builder() { - val.ipv6Builder = new(netipx.IPSetBuilder) - } - val.ipv6Builder.AddSet(ipv6set) - case IPv6: - if !val.hasIPv4Builder() { - val.ipv4Builder = new(netipx.IPSetBuilder) - } - val.ipv4Builder.AddSet(ipv4set) - default: - if !val.hasIPv4Builder() { - val.ipv4Builder = new(netipx.IPSetBuilder) - } - if !val.hasIPv6Builder() { - val.ipv6Builder = new(netipx.IPSetBuilder) - } - val.ipv4Builder.AddSet(ipv4set) - val.ipv6Builder.AddSet(ipv6set) - } - c.entries.Store(name, val) - - case false: - switch ignoreIPType { - case IPv4: - entry.ipv4Builder = nil - case IPv6: - entry.ipv6Builder = nil - } - c.entries.Store(name, entry) - } - - return nil -} - -func (c *container) Remove(name string, opts ...IgnoreIPOption) { - val, found := c.GetEntry(name) - if !found { - log.Printf("failed to remove non-existent entry %s", name) - return - } - - var ignoreIPType IPType - for _, opt := range opts { - if opt != nil { - ignoreIPType = opt() - } - } - - switch ignoreIPType { - case IPv4: - val.ipv6Builder = nil - c.entries.Store(name, val) - case IPv6: - val.ipv4Builder = nil - c.entries.Store(name, val) - default: - c.entries.Delete(name) - } -} diff --git a/geoip/plugin/maxmind/country_csv.go b/geoip/plugin/maxmind/country_csv.go index 4608f12162..aea07a7313 100644 --- a/geoip/plugin/maxmind/country_csv.go +++ b/geoip/plugin/maxmind/country_csv.go @@ -4,6 +4,7 @@ import ( "encoding/csv" "encoding/json" "errors" + "fmt" "os" "path/filepath" "strings" @@ -113,6 +114,10 @@ func (g *geoLite2CountryCSV) Input(container lib.Container) (lib.Container, erro } } + if len(entries) == 0 { + return nil, fmt.Errorf("❌ [type %s | action %s] no entry is generated", typeCountryCSV, g.Action) + } + var ignoreIPType lib.IgnoreIPOption switch g.OnlyIPType { case lib.IPv4: @@ -121,14 +126,16 @@ func (g *geoLite2CountryCSV) Input(container lib.Container) (lib.Container, erro ignoreIPType = lib.IgnoreIPv4 } - for name, entry := range entries { + for _, entry := range entries { switch g.Action { case lib.ActionAdd: if err := container.Add(entry, ignoreIPType); err != nil { return nil, err } case lib.ActionRemove: - container.Remove(name, ignoreIPType) + if err := container.Remove(entry, lib.CaseRemovePrefix, ignoreIPType); err != nil { + return nil, err + } default: return nil, lib.ErrUnknownAction } @@ -193,10 +200,8 @@ func (g *geoLite2CountryCSV) process(file string, ccMap map[string]string, entri for _, line := range lines[1:] { ccID := strings.TrimSpace(line[1]) if countryCode, found := ccMap[ccID]; found { - if len(wantList) > 0 { - if _, found := wantList[countryCode]; !found { - continue - } + if len(wantList) > 0 && !wantList[countryCode] { + continue } cidrStr := strings.ToLower(strings.TrimSpace(line[0])) entry, found := entries[countryCode] diff --git a/geoip/plugin/maxmind/mmdb_in.go b/geoip/plugin/maxmind/mmdb_in.go index eef4c7d68a..0c94a12c25 100644 --- a/geoip/plugin/maxmind/mmdb_in.go +++ b/geoip/plugin/maxmind/mmdb_in.go @@ -107,7 +107,7 @@ func (g *maxmindMMDBIn) Input(container lib.Container) (lib.Container, error) { } if len(entries) == 0 { - return nil, fmt.Errorf("❌ [type %s | action %s] no entry is newly generated", typeMaxmindMMDBIn, g.Action) + return nil, fmt.Errorf("❌ [type %s | action %s] no entry is generated", typeMaxmindMMDBIn, g.Action) } var ignoreIPType lib.IgnoreIPOption @@ -138,7 +138,11 @@ func (g *maxmindMMDBIn) Input(container lib.Container) (lib.Container, error) { return nil, err } case lib.ActionRemove: - container.Remove(name, ignoreIPType) + if err := container.Remove(entry, lib.CaseRemovePrefix, ignoreIPType); err != nil { + return nil, err + } + default: + return nil, lib.ErrUnknownAction } } @@ -197,23 +201,14 @@ func (g *maxmindMMDBIn) generateEntries(entries map[string]*lib.Entry) error { continue } - var entry *lib.Entry name := strings.ToUpper(record.Country.IsoCode) - if theEntry, found := entries[name]; found { - entry = theEntry - } else { + entry, found := entries[name] + if !found { entry = lib.NewEntry(name) } - switch g.Action { - case lib.ActionAdd: - if err := entry.AddPrefix(subnet); err != nil { - return err - } - case lib.ActionRemove: - if err := entry.RemovePrefix(subnet.String()); err != nil { - return err - } + if err := entry.AddPrefix(subnet); err != nil { + return err } entries[name] = entry diff --git a/geoip/plugin/plaintext/text_in.go b/geoip/plugin/plaintext/text_in.go index 246a4ac10f..0180e52c08 100644 --- a/geoip/plugin/plaintext/text_in.go +++ b/geoip/plugin/plaintext/text_in.go @@ -106,7 +106,7 @@ func (t *textIn) Input(container lib.Container) (lib.Container, error) { } if len(entries) == 0 { - return nil, fmt.Errorf("type %s | action %s no entry are generated", t.Type, t.Action) + return nil, fmt.Errorf("type %s | action %s no entry is generated", t.Type, t.Action) } for _, entry := range entries { @@ -116,7 +116,11 @@ func (t *textIn) Input(container lib.Container) (lib.Container, error) { return nil, err } case lib.ActionRemove: - container.Remove(entry.GetName(), ignoreIPType) + if err := container.Remove(entry, lib.CaseRemovePrefix, ignoreIPType); err != nil { + return nil, err + } + default: + return nil, lib.ErrUnknownAction } } diff --git a/geoip/plugin/singbox/srs_in.go b/geoip/plugin/singbox/srs_in.go index 343fd4ca66..44812cb82e 100644 --- a/geoip/plugin/singbox/srs_in.go +++ b/geoip/plugin/singbox/srs_in.go @@ -114,7 +114,7 @@ func (s *srsIn) Input(container lib.Container) (lib.Container, error) { } if len(entries) == 0 { - return nil, fmt.Errorf("type %s | action %s no entry are generated", s.Type, s.Action) + return nil, fmt.Errorf("type %s | action %s no entry is generated", s.Type, s.Action) } for _, entry := range entries { @@ -124,7 +124,11 @@ func (s *srsIn) Input(container lib.Container) (lib.Container, error) { return nil, err } case lib.ActionRemove: - container.Remove(entry.GetName(), ignoreIPType) + if err := container.Remove(entry, lib.CaseRemovePrefix, ignoreIPType); err != nil { + return nil, err + } + default: + return nil, lib.ErrUnknownAction } } @@ -200,10 +204,9 @@ func (s *srsIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry) } func (s *srsIn) generateEntries(name string, reader io.Reader, entries map[string]*lib.Entry) error { - entry := lib.NewEntry(name) - if theEntry, found := entries[entry.GetName()]; found { - fmt.Printf("⚠️ [type %s | action %s] found duplicated entry: %s. Process anyway\n", typeSRSIn, s.Action, name) - entry = theEntry + entry, found := entries[name] + if !found { + entry = lib.NewEntry(name) } plainRuleSet, err := srs.Read(reader, true) @@ -213,20 +216,12 @@ func (s *srsIn) generateEntries(name string, reader io.Reader, entries map[strin for _, rule := range plainRuleSet.Rules { for _, cidrStr := range rule.DefaultOptions.IPCIDR { - switch s.Action { - case lib.ActionAdd: - if err := entry.AddPrefix(cidrStr); err != nil { - return err - } - case lib.ActionRemove: - if err := entry.RemovePrefix(cidrStr); err != nil { - return err - } + if err := entry.AddPrefix(cidrStr); err != nil { + return err } } } - entries[entry.GetName()] = entry - + entries[name] = entry return nil } diff --git a/geoip/plugin/special/cutter.go b/geoip/plugin/special/cutter.go index c5543c2b99..d14e286d0e 100644 --- a/geoip/plugin/special/cutter.go +++ b/geoip/plugin/special/cutter.go @@ -89,7 +89,9 @@ func (c *cutter) Input(container lib.Container) (lib.Container, error) { if len(wantList) > 0 && !wantList[name] { continue } - container.Remove(name, ignoreIPType) + if err := container.Remove(entry, lib.CaseRemoveEntry, ignoreIPType); err != nil { + return nil, err + } } return container, nil diff --git a/geoip/plugin/special/private.go b/geoip/plugin/special/private.go index a3907aee7c..ec81acd15a 100644 --- a/geoip/plugin/special/private.go +++ b/geoip/plugin/special/private.go @@ -85,7 +85,9 @@ func (p *private) Input(container lib.Container) (lib.Container, error) { return nil, err } case lib.ActionRemove: - container.Remove(entryNamePrivate) + if err := container.Remove(entry, lib.CaseRemovePrefix); err != nil { + return nil, err + } default: return nil, lib.ErrUnknownAction } diff --git a/geoip/plugin/special/stdin.go b/geoip/plugin/special/stdin.go index 1f59c1fea6..4f56d75623 100644 --- a/geoip/plugin/special/stdin.go +++ b/geoip/plugin/special/stdin.go @@ -3,6 +3,7 @@ package special import ( "bufio" "encoding/json" + "fmt" "os" "strings" @@ -35,6 +36,10 @@ func newStdin(action lib.Action, data json.RawMessage) (lib.InputConverter, erro } } + if tmp.Name == "" { + return nil, fmt.Errorf("type %s | action %s missing name", typeStdin, action) + } + return &stdin{ Type: typeStdin, Action: action, @@ -81,15 +86,8 @@ func (s *stdin) Input(container lib.Container) (lib.Container, error) { continue } - switch s.Action { - case lib.ActionAdd: - if err := entry.AddPrefix(line); err != nil { - continue - } - case lib.ActionRemove: - if err := entry.RemovePrefix(line); err != nil { - continue - } + if err := entry.AddPrefix(line); err != nil { + continue } } @@ -105,8 +103,17 @@ func (s *stdin) Input(container lib.Container) (lib.Container, error) { ignoreIPType = lib.IgnoreIPv4 } - if err := container.Add(entry, ignoreIPType); err != nil { - return nil, err + switch s.Action { + case lib.ActionAdd: + if err := container.Add(entry, ignoreIPType); err != nil { + return nil, err + } + case lib.ActionRemove: + if err := container.Remove(entry, lib.CaseRemovePrefix, ignoreIPType); err != nil { + return nil, err + } + default: + return nil, lib.ErrUnknownAction } return container, nil diff --git a/geoip/plugin/special/stdout.go b/geoip/plugin/special/stdout.go index 736d642f48..9437e59770 100644 --- a/geoip/plugin/special/stdout.go +++ b/geoip/plugin/special/stdout.go @@ -74,31 +74,17 @@ func (s *stdout) Output(container lib.Container) error { } } - switch len(wantList) { - case 0: - for entry := range container.Loop() { - cidrList, err := s.generateCIDRList(entry) - if err != nil { - continue - } - for _, cidr := range cidrList { - io.WriteString(os.Stdout, cidr+"\n") - } + for entry := range container.Loop() { + if len(wantList) > 0 && !wantList[entry.GetName()] { + continue } - default: - for name := range wantList { - entry, found := container.GetEntry(name) - if !found { - continue - } - cidrList, err := s.generateCIDRList(entry) - if err != nil { - continue - } - for _, cidr := range cidrList { - io.WriteString(os.Stdout, cidr+"\n") - } + cidrList, err := s.generateCIDRList(entry) + if err != nil { + continue + } + for _, cidr := range cidrList { + io.WriteString(os.Stdout, cidr+"\n") } } diff --git a/geoip/plugin/special/test.go b/geoip/plugin/special/test.go index 9a19004fca..cf83ed83ce 100644 --- a/geoip/plugin/special/test.go +++ b/geoip/plugin/special/test.go @@ -65,7 +65,9 @@ func (t *test) Input(container lib.Container) (lib.Container, error) { return nil, err } case lib.ActionRemove: - container.Remove(entryNameTest) + if err := container.Remove(entry, lib.CaseRemovePrefix); err != nil { + return nil, err + } default: return nil, lib.ErrUnknownAction } diff --git a/geoip/plugin/v2ray/dat_in.go b/geoip/plugin/v2ray/dat_in.go index 65b9a67456..5baf32f20a 100644 --- a/geoip/plugin/v2ray/dat_in.go +++ b/geoip/plugin/v2ray/dat_in.go @@ -92,7 +92,7 @@ func (g *geoIPDatIn) Input(container lib.Container) (lib.Container, error) { } if len(entries) == 0 { - return nil, fmt.Errorf("❌ [type %s | action %s] no entry is newly generated", typeGeoIPdatIn, g.Action) + return nil, fmt.Errorf("❌ [type %s | action %s] no entry is generated", typeGeoIPdatIn, g.Action) } var ignoreIPType lib.IgnoreIPOption @@ -123,7 +123,11 @@ func (g *geoIPDatIn) Input(container lib.Container) (lib.Container, error) { return nil, err } case lib.ActionRemove: - container.Remove(name, ignoreIPType) + if err := container.Remove(entry, lib.CaseRemovePrefix, ignoreIPType); err != nil { + return nil, err + } + default: + return nil, lib.ErrUnknownAction } } @@ -174,26 +178,16 @@ func (g *geoIPDatIn) generateEntries(reader io.Reader, entries map[string]*lib.E } for _, geoip := range geoipList.Entry { - var entry *lib.Entry name := geoip.CountryCode - if theEntry, found := entries[name]; found { - fmt.Printf("⚠️ [type %s | action %s] found duplicated entry: %s. Process anyway\n", typeGeoIPdatIn, g.Action, name) - entry = theEntry - } else { + entry, found := entries[name] + if !found { entry = lib.NewEntry(name) } for _, v2rayCIDR := range geoip.Cidr { ipStr := net.IP(v2rayCIDR.GetIp()).String() + "/" + fmt.Sprint(v2rayCIDR.GetPrefix()) - switch g.Action { - case lib.ActionAdd: - if err := entry.AddPrefix(ipStr); err != nil { - return err - } - case lib.ActionRemove: - if err := entry.RemovePrefix(ipStr); err != nil { - return err - } + if err := entry.AddPrefix(ipStr); err != nil { + return err } } diff --git a/geoip/plugin/v2ray/dat_out.go b/geoip/plugin/v2ray/dat_out.go index 345b85ce79..46e3baa2f0 100644 --- a/geoip/plugin/v2ray/dat_out.go +++ b/geoip/plugin/v2ray/dat_out.go @@ -155,10 +155,10 @@ func (g *geoIPDatOut) Output(container lib.Container) error { } } - // Sort to make reproducible builds - g.sort(geoIPList) - if !g.OneFilePerList && updated { + // Sort to make reproducible builds + g.sort(geoIPList) + geoIPBytes, err := proto.Marshal(geoIPList) if err != nil { return err diff --git a/lede/package/base-files/files/bin/config_generate b/lede/package/base-files/files/bin/config_generate index 4c83b49f72..a9ca4d5b26 100755 --- a/lede/package/base-files/files/bin/config_generate +++ b/lede/package/base-files/files/bin/config_generate @@ -305,10 +305,10 @@ generate_static_system() { set system.ntp='timeserver' set system.ntp.enabled='1' set system.ntp.enable_server='1' - add_list system.ntp.server='ntp.aliyun.com' - add_list system.ntp.server='time1.cloud.tencent.com' - add_list system.ntp.server='time.ustc.edu.cn' - add_list system.ntp.server='cn.pool.ntp.org' + add_list system.ntp.server='time.apple.com' + add_list system.ntp.server='time.google.com' + add_list system.ntp.server='time.windows.com' + add_list system.ntp.server='time.cloudflare.com' EOF if json_is_a system object; then diff --git a/lede/package/lean/default-settings/files/zzz-default-settings b/lede/package/lean/default-settings/files/zzz-default-settings index 13177d8c5d..1d820559e3 100755 --- a/lede/package/lean/default-settings/files/zzz-default-settings +++ b/lede/package/lean/default-settings/files/zzz-default-settings @@ -3,8 +3,16 @@ uci set luci.main.lang=zh_cn uci commit luci -uci set system.@system[0].timezone=CST-8 -uci set system.@system[0].zonename=Asia/Shanghai +uci -q batch <<-EOF + set system.@system[0].timezone='CST-8' + set system.@system[0].zonename='Asia/Shanghai' + + delete system.ntp.server + add_list system.ntp.server='ntp1.aliyun.com' + add_list system.ntp.server='ntp.tencent.com' + add_list system.ntp.server='ntp.ntsc.ac.cn' + add_list system.ntp.server='time.ustc.edu.cn' +EOF uci commit system uci set fstab.@global[0].anon_mount=1 @@ -28,9 +36,7 @@ sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/usb_printer.lua sed -i 's/\"services\"/\"nas\"/g' /usr/lib/lua/luci/controller/xunlei.lua sed -i 's/services/nas/g' /usr/lib/lua/luci/view/minidlna_status.htm -#ln -sf /sbin/ip /usr/bin/ip - -sed -i 's#downloads.openwrt.org#mirrors.cloud.tencent.com/lede#g' /etc/opkg/distfeeds.conf +sed -i 's#downloads.openwrt.org#mirrors.tencent.com/lede#g' /etc/opkg/distfeeds.conf sed -i 's/root::0:0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow sed -i 's/root:::0:99999:7:::/root:$1$V4UetPzk$CYXluq4wUazHjmCDBCqXF.:0:0:99999:7:::/g' /etc/shadow @@ -40,12 +46,6 @@ sed -i '/openwrt_luci/ { s/snapshots/releases\/18.06.9/g; }' /etc/opkg/distfeed sed -i '/check_signature/d' /etc/opkg.conf sed -i '/REDIRECT --to-ports 53/d' /etc/firewall.user -#echo 'iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53' >> /etc/firewall.user -#echo 'iptables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53' >> /etc/firewall.user -#echo '[ -n "$(command -v ip6tables)" ] && ip6tables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53' >> /etc/firewall.user -#echo '[ -n "$(command -v ip6tables)" ] && ip6tables -t nat -A PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports 53' >> /etc/firewall.user - -#echo 'iptables -A OUTPUT -m string --string "api.installer.xiaomi.cn" --algo bm --to 65535 -j DROP' >> /etc/firewall.user sed -i '/option disabled/d' /etc/config/wireless sed -i '/set wireless.radio${devidx}.disabled/d' /lib/wifi/mac80211.sh @@ -58,11 +58,7 @@ echo "DISTRIB_DESCRIPTION='OpenWrt '" >> /etc/openwrt_release sed -i '/log-facility/d' /etc/dnsmasq.conf echo "log-facility=/dev/null" >> /etc/dnsmasq.conf -if [ -f /www/luci-static/resources/luci.js ]; then - sed -i 's/ifname/device/g' /etc/config/network -else - sed -i 's/device/ifname/g' /etc/config/network -fi +#ln -sf /sbin/ip /usr/bin/ip rm -rf /tmp/luci-modulecache/ rm -f /tmp/luci-indexcache diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-360v6.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-360v6.dts index e8872c86f7..30c5ab88a0 100644 --- a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-360v6.dts +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6000-360v6.dts @@ -184,25 +184,25 @@ &dp1 { status = "okay"; phy-handle = <&qca8075_0>; - label = "wan"; + label = "lan1"; }; &dp2 { status = "okay"; phy-handle = <&qca8075_1>; - label = "lan1"; + label = "lan2"; }; &dp3 { status = "okay"; phy-handle = <&qca8075_2>; - label = "lan2"; + label = "lan3"; }; &dp4 { status = "okay"; phy-handle = <&qca8075_3>; - label = "lan3"; + label = "wan"; }; &wifi { diff --git a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6010-re-cs-02.dts b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6010-re-cs-02.dts index a7ec1be5f4..b5f97cb424 100644 --- a/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6010-re-cs-02.dts +++ b/lede/target/linux/qualcommax/files/arch/arm64/boot/dts/qcom/ipq6010-re-cs-02.dts @@ -271,6 +271,5 @@ &wifi { status = "okay"; - qcom,ath11k-calibration-variant = "JDC-AX1800-Pro"; - qcom,ath11k-fw-memory-mode = <1>; + qcom,ath11k-calibration-variant = "JDC-AX6600"; }; diff --git a/openwrt-packages/adguardhome/Makefile b/openwrt-packages/adguardhome/Makefile index f30b58dd29..fdcfea33df 100644 --- a/openwrt-packages/adguardhome/Makefile +++ b/openwrt-packages/adguardhome/Makefile @@ -12,6 +12,7 @@ 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:=de6d99c4420d131b76e5d22b58ac91159e74e5783f02ada8b2f993f353e254f9 +PKG_BUILD_DIR:=$(BUILD_DIR)/AdGuardHome-$(PKG_VERSION) PKG_LICENSE:=GPL-3.0-only PKG_LICENSE_FILES:=LICENSE.txt @@ -57,17 +58,13 @@ 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:=af9ae57b55a09a0aaf7c9a69a46734827443f98135d4c4b176874de3f9a449d8 + HASH:=af9ae57b55a09a0aaf7c9a69a46734827443f98135d4c4b176874de3f9a449d8 endef define Build/Prepare $(call Build/Prepare/Default) - if [ -d "$(BUILD_DIR)/AdGuardHome-$(PKG_VERSION)" ]; then \ - mv "$(BUILD_DIR)/AdGuardHome-$(PKG_VERSION)/"* "$(BUILD_DIR)/adguardhome-$(PKG_VERSION)/"; \ - fi gzip -dc $(DL_DIR)/$(FRONTEND_FILE) | $(HOST_TAR) -C $(PKG_BUILD_DIR)/ $(TAR_OPTIONS) - ( cd "$(BUILD_DIR)/adguardhome-$(PKG_VERSION)"; go mod tidy ) endef define Package/adguardhome/install diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/iptables.sh b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/iptables.sh index b718166b30..93ec84c125 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/iptables.sh @@ -1111,7 +1111,7 @@ add_firewall_rule() { $ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW") -o lo -j RETURN insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW) -m mark --mark 1 -j RETURN" - [ $(config_t_get global dns_redirect) == "1" ] && { + [ $(config_t_get global dns_redirect "0") = "1" ] && { $ipt_m -A PSW -p udp --dport 53 -j RETURN $ip6t_m -A PSW -p udp --dport 53 -j RETURN $ipt_n -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "PSW_DNS_Hijack" 2>/dev/null diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/nftables.sh b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/nftables.sh index ca75f6904b..690c9eeeed 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/nftables.sh +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/nftables.sh @@ -1152,7 +1152,7 @@ add_firewall_rule() { nft "add rule inet fw4 mangle_output oif lo counter return comment \"PSW_OUTPUT_MANGLE\"" nft "add rule inet fw4 mangle_output meta mark 1 counter return comment \"PSW_OUTPUT_MANGLE\"" - [ $(config_t_get global dns_redirect) == "1" ] && { + [ $(config_t_get global dns_redirect "0") = "1" ] && { nft "add rule inet fw4 PSW_MANGLE ip protocol udp udp dport 53 counter return" nft "add rule inet fw4 PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter return" nft insert rule inet fw4 dstnat position 0 tcp dport 53 counter redirect to :53 comment \"PSW_DNS_Hijack\" 2>/dev/null diff --git a/shadowsocks-rust/crates/shadowsocks/src/relay/tcprelay/aead.rs b/shadowsocks-rust/crates/shadowsocks/src/relay/tcprelay/aead.rs index 4d0c7fc882..1d4e5a22b9 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/relay/tcprelay/aead.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/relay/tcprelay/aead.rs @@ -1,6 +1,6 @@ //! AEAD packet I/O facilities //! -//! AEAD protocol is defined in . +//! AEAD protocol is defined in . //! //! ```plain //! TCP request (before encryption) @@ -305,7 +305,7 @@ impl DecryptedReader { }; if plen > MAX_PACKET_SIZE { - // https://shadowsocks.org/en/spec/AEAD-Ciphers.html + // https://shadowsocks.org/doc/aead.html // // AEAD TCP protocol have reserved the higher two bits for future use return Err(ProtocolError::DataTooLong(plen)); diff --git a/shadowsocks-rust/src/service/local.rs b/shadowsocks-rust/src/service/local.rs index 78a0f86281..1eca5668c5 100644 --- a/shadowsocks-rust/src/service/local.rs +++ b/shadowsocks-rust/src/service/local.rs @@ -181,7 +181,7 @@ pub fn define_command_line_options(mut app: Command) -> Command { .action(ArgAction::Set) .value_hint(ValueHint::CommandName) .requires("SERVER_ADDR") - .help("SIP003 (https://shadowsocks.org/guide/sip003.html) plugin"), + .help("SIP003 (https://shadowsocks.org/doc/sip003.html) plugin"), ) .arg( Arg::new("PLUGIN_MODE") @@ -206,7 +206,7 @@ pub fn define_command_line_options(mut app: Command) -> Command { .action(ArgAction::Set) .value_hint(ValueHint::Url) .value_parser(vparser::parse_server_url) - .help("Server address in SIP002 (https://shadowsocks.org/guide/sip002.html) URL"), + .help("Server address in SIP002 (https://shadowsocks.org/doc/sip002.html) URL"), ) .group(ArgGroup::new("SERVER_CONFIG") .arg("SERVER_ADDR").arg("SERVER_URL").multiple(true)) diff --git a/shadowsocks-rust/src/service/manager.rs b/shadowsocks-rust/src/service/manager.rs index 0d44a8fad9..aac9d86d8d 100644 --- a/shadowsocks-rust/src/service/manager.rs +++ b/shadowsocks-rust/src/service/manager.rs @@ -93,7 +93,7 @@ pub fn define_command_line_options(mut app: Command) -> Command { .num_args(1) .action(ArgAction::Set) .value_hint(ValueHint::CommandName) - .help("Default SIP003 (https://shadowsocks.org/guide/sip003.html) plugin"), + .help("Default SIP003 (https://shadowsocks.org/doc/sip003.html) plugin"), ) .arg( Arg::new("PLUGIN_MODE") diff --git a/shadowsocks-rust/src/service/server.rs b/shadowsocks-rust/src/service/server.rs index bdb01262c2..1585c6446f 100644 --- a/shadowsocks-rust/src/service/server.rs +++ b/shadowsocks-rust/src/service/server.rs @@ -121,7 +121,7 @@ pub fn define_command_line_options(mut app: Command) -> Command { .action(ArgAction::Set) .value_hint(ValueHint::CommandName) .requires("SERVER_ADDR") - .help("SIP003 (https://shadowsocks.org/guide/sip003.html) plugin"), + .help("SIP003 (https://shadowsocks.org/doc/sip003.html) plugin"), ) .arg( Arg::new("PLUGIN_MODE") @@ -494,7 +494,7 @@ pub fn create(matches: &ArgMatches) -> Result<(Runtime, impl Future Result { match ServerConfig::from_url(v) { Ok(t) => Ok(t), - Err(..) => Err("should be SIP002 (https://shadowsocks.org/guide/sip002.html) format".to_owned()), + Err(..) => Err("should be SIP002 (https://shadowsocks.org/doc/sip002.html) format".to_owned()), } } diff --git a/small/luci-app-passwall/root/usr/share/passwall/iptables.sh b/small/luci-app-passwall/root/usr/share/passwall/iptables.sh index b718166b30..93ec84c125 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/iptables.sh +++ b/small/luci-app-passwall/root/usr/share/passwall/iptables.sh @@ -1111,7 +1111,7 @@ add_firewall_rule() { $ip6t_m -I OUTPUT $(comment "mangle-OUTPUT-PSW") -o lo -j RETURN insert_rule_before "$ip6t_m" "OUTPUT" "mwan3" "$(comment mangle-OUTPUT-PSW) -m mark --mark 1 -j RETURN" - [ $(config_t_get global dns_redirect) == "1" ] && { + [ $(config_t_get global dns_redirect "0") = "1" ] && { $ipt_m -A PSW -p udp --dport 53 -j RETURN $ip6t_m -A PSW -p udp --dport 53 -j RETURN $ipt_n -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 -m comment --comment "PSW_DNS_Hijack" 2>/dev/null diff --git a/small/luci-app-passwall/root/usr/share/passwall/nftables.sh b/small/luci-app-passwall/root/usr/share/passwall/nftables.sh index ca75f6904b..690c9eeeed 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/nftables.sh +++ b/small/luci-app-passwall/root/usr/share/passwall/nftables.sh @@ -1152,7 +1152,7 @@ add_firewall_rule() { nft "add rule inet fw4 mangle_output oif lo counter return comment \"PSW_OUTPUT_MANGLE\"" nft "add rule inet fw4 mangle_output meta mark 1 counter return comment \"PSW_OUTPUT_MANGLE\"" - [ $(config_t_get global dns_redirect) == "1" ] && { + [ $(config_t_get global dns_redirect "0") = "1" ] && { nft "add rule inet fw4 PSW_MANGLE ip protocol udp udp dport 53 counter return" nft "add rule inet fw4 PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter return" nft insert rule inet fw4 dstnat position 0 tcp dport 53 counter redirect to :53 comment \"PSW_DNS_Hijack\" 2>/dev/null diff --git a/v2rayu/Build/appdmg.sh b/v2rayu/Build/appdmg.sh index cbda668a97..11c58ec2f1 100755 --- a/v2rayu/Build/appdmg.sh +++ b/v2rayu/Build/appdmg.sh @@ -35,8 +35,6 @@ do echo "appdmg V2rayU-64.dmg" rm -f V2rayU-64.dmg appdmg appdmg.json "V2rayU-64.dmg" - #rm -fr release/V2rayU.app - ./sign_update "V2rayU-64.dmg" break ;; @@ -48,8 +46,6 @@ do echo "appdmg V2rayU-arm64.dmg" rm -f V2rayU-arm64.dmg appdmg appdmg.json "V2rayU-arm64.dmg" - #rm -fr release/V2rayU.app - ./sign_update "V2rayU-64.dmg" break ;; diff --git a/v2rayu/Build/build.plist b/v2rayu/Build/build.plist index 30596a7a27..e49f5ec64b 100644 --- a/v2rayu/Build/build.plist +++ b/v2rayu/Build/build.plist @@ -1,10 +1,10 @@ - - - - - compileBitcode - - method - development - - + + + + + method + + development + + + diff --git a/v2rayu/Build/publish.sh b/v2rayu/Build/publish.sh deleted file mode 100755 index 2a4f2be30b..0000000000 --- a/v2rayu/Build/publish.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -# publish.sh -# V2rayU -# -# Created by yanue on 2019/7/18. -# Copyright © 2019 yanue. All rights reserved. - -read -p "请输入版本描述: " release_note -#pushRelease ${release_note} -generateAppcast ${release_note} - -echo "Done" diff --git a/v2rayu/Build/release.sh b/v2rayu/Build/release.sh index 86935e6d41..7cb0643297 100755 --- a/v2rayu/Build/release.sh +++ b/v2rayu/Build/release.sh @@ -13,26 +13,60 @@ APP_TITLE="${APP_NAME} - V${APP_Version}" AppCastDir=$HOME/swift/appcast function updatePlistVersion() { + echo "Updating plist version..." buildString=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${BASE_DIR}/V2rayU/${INFOPLIST_FILE}") - /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildString" "${BASE_DIR}/V2rayU/${INFOPLIST_FILE}" + if [ $? -eq 0 ]; then + /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildString" "${BASE_DIR}/V2rayU/${INFOPLIST_FILE}" + if [ $? -ne 0 ]; then + echo "Error: Failed to set CFBundleVersion" + exit 1 + fi + else + echo "Error: Failed to read CFBundleShortVersionString" + exit 1 + fi } function build() { - echo "Building V2rayU."${APP_Version} + echo "Building V2rayU version ${APP_Version}" + echo "Cleaning up old archive & app..." rm -rf ${V2rayU_ARCHIVE} ${V2rayU_RELEASE} + if [ $? -ne 0 ]; then + echo "Error: Failed to clean up old archive & app" + exit 1 + fi echo "Building archive... please wait a minute" xcodebuild -workspace ${BASE_DIR}/V2rayU.xcworkspace -config Release -scheme V2rayU -archivePath ${V2rayU_ARCHIVE} archive + if [ $? -ne 0 ]; then + echo "Error: Failed to build archive" + exit 1 + fi echo "Exporting archive..." xcodebuild -archivePath ${V2rayU_ARCHIVE} -exportArchive -exportPath ${V2rayU_RELEASE} -exportOptionsPlist ./build.plist + if [ $? -ne 0 ]; then + echo "Error: Failed to export archive" + exit 1 + fi echo "Cleaning up archive..." rm -rf ${V2rayU_ARCHIVE} + if [ $? -ne 0 ]; then + echo "Error: Failed to clean up archive" + exit 1 + fi + echo "Setting permissions for resources..." chmod -R 755 "${V2rayU_RELEASE}/${APP_NAME}.app/Contents/Resources/v2ray-core" chmod -R 755 "${V2rayU_RELEASE}/${APP_NAME}.app/Contents/Resources/unzip.sh" + if [ $? -ne 0 ]; then + echo "Error: Failed to set permissions for resources" + exit 1 + fi + + echo "Build and export completed successfully." } function createDmg() { @@ -209,9 +243,6 @@ function createDmgByAppdmg() { echo ${BUILD_DIR}/appdmg.json appdmg appdmg.json ${DMG_FINAL} - # appcast sign update - ${AppCastDir}/bin/sign_update ${DMG_FINAL} - # umount "/Volumes/${APP_NAME}" } @@ -256,7 +287,7 @@ function makeDmg() { } - - +#makeDmg +createDmgByAppdmg echo 'done' diff --git a/v2rayu/Build/sign.sh b/v2rayu/Build/sign.sh deleted file mode 100755 index 85f56bbe20..0000000000 --- a/v2rayu/Build/sign.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -# sign.sh -# V2rayU -# -# Created by yanue on 2023/8/1. -# Copyright © 2023 yanue. All rights reserved. -set -ex - -TOKEN=$1 -release_id=$2 - -echo "token $TOKEN, release ${RELEASE_ID}" - -curl -X "PATCH" "https://api.appcenter.ms/v0.1/apps/yanue/V2rayU/releases/${release_id}" \ - -H "X-API-Token: $TOKEN" \ - -H 'Content-Type: application/json; charset=utf-8' \ - -d '{ - "release_notes": "test", - "metadata": { - "ed_signature": "PW8pDnr5VZkmC93gZjUDlHI8gkJSspPoDU3DdhsMkps" - } -}' diff --git a/v2rayu/Build/sign_update b/v2rayu/Build/sign_update deleted file mode 100755 index 2814c1609d6a89cfa17f11c527edd394b7ed5e1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303168 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 c70h8P>k`K94O!ItpnvAav zGMKMG&!4a!w)5Bz*6%SHzaSp_$On&i$k#=991!L9`v5-j`ikT}Y%+dHX^)a`h-m$p z$=I(0^7`Cl{F=hQBHs`Z@SVx{Acdbc8NWezn{y`P{0`t>nC z^ zWj)4Cw3dy}TR)NUtnBoUWn*KJ*3(JPJNt3`(x{c|**p7x({*O~N3N`0zYXvoSd;L7 z$bnyx9$$5H`mm~VtsMAkLk+?@cR0b zRrB+PR()F^SM>+hU1o!a){Da&!Gm}1j&;1w2FwRo-fOf2pSHw-k2E{*DQ1o@HnV&e ztiQy2>G>=#10USozz^^4!3TBr;QL|z5HXtLja+=0F7-j{c#DCbWAWh4qgno0l&xsA z9&$Wuo$yND`V~w-<+DiVq^Q)W#`ie>us4KQWZ!GqZ+NeUuhkm4|wNv6lybDa^oMj@0wNr?C8mAdbHl z@4&Ad$MLIsIPg=j?)y8|i=IgF;2-tZ^N$92@RI`!{F*S1U(-j==l5axHz5CVHv^xk z_uw;Ap0u7qx%P6tmDXM~2Q%<_A$opoqyxXUFUwEs%kk$>zQk0l$CT%-KgVb*yMzAv zxRuslfQNHVmEEBqU8;x&vrd&$kp2eZ#vwd>oX9_s^{t!@y5Lk1FG7C4i2w3V>V_Zn zkcIKC{2X+7saRu%JU<8M`Hv7*j5HsmthBB~*u@Z*&jbIJ2-_j$cc~A`g|IcC`(>O5 zf1|GhzXS0rQm~d=k+&Xeww0fQHWNHPN?C55mHMdl$#VPi1^fWZzn}WJ z^|%0Y{K3?v)?Wn}?=E$j^)aMBo?2#oVT{479m}*@p4=uvJJ!qm(-@}Ji^=UHej1}U zcS~kkeVE)jqFb`3c^KfIliNlNOZGNLApMlF9U>yedYC^)`VC_PBCt+m+)IJ9Mqy>G`fuu zW7YbxBn&SXb$Rw0UE^%t>R~N6`9850t|N>nl3Y&^rl+ zuADPki|Z_PF;&7kOWp7)VV$LJOckxOD9>`#SmM!_#$hck7X7ufuZ(fw-PYevV;wyR z{p=u}$@s}&gE?5}XPs@;Sc?vFGa1{%CS$J=z9FKwx5@Y(>~WC4$>@&o(6%PyWrPO> znv5Qlt_%5wh_E2|=#zqanT!Ss4CZh|&g9}Z@9tfv(`=DZp?_7~@&_eQacAv)@bpmu^hE8(PClY@>&RQfuA70>* z0DX9YM+)?@0p(19KD-g03VrNBf0zJ$_)t3N!w2ccK_6dGI_Sff!l4gegpY?l{-AK^ z!w=yPLLdFm7bZX#ttlOJ(HiLzpo=!pMQfBJ0lH`dT_ivkZJ>(;=wTxCuuA#vu%D6u zJ+vhr&_i4B7y>=KgKYR13mbI zM-KGh4<7TOhcxu*InYA@!Y4rw6YyShpa+i9K@S|#UBJp_Ti2Xv7OJ@kMca-oMF(8C3+lgxk~f~EI06?z#) z=VPFUaN+?ygo8&u^iT#KxzIx|gr`FfZjdz>dI%(b&_f{j{<#UURhJ{MZ!sEsfe*!26>;9y>%*AZTj;C2CdF5My2y(U9T>oWHdw>I zhVjGI7#IEvgzt>So*w!aAz%F-O-yb z$Nr_RQvk*(*w?~XB&V|r#uA`sovhVpJ0GEMt?q8BbwargV;?rCBlaRYyMopiv|7-5 zgVu}B=^Ow$4ZjIGu!2W9`eRqDIj#X6=DXI5XhRpVpL7&qm5W>;zdP@Mv`?ci%1ceN z&SM>{4iDw6x3UhE7tzL#E(+j#g=_eu5ia~C>{Z6*535?ka@I>2YaU(XjlC%y*_EJAn?PGPrsxIN~;u`on7V5D#<-`Xs((|8mcjC`?b;LM^Yh%#ORyuqI+){oL(hrmpQ+CeWZf&* zg4P`}uEidqC*&*};>7Pm8XAxJznr&z2kT$?G{T)V@nv1N<*j$nI8=55d=|Do7GsxA z8m{szY~MlfIqU4iUqRZ}208H_gBF=}~N zgiV4TbSzhS@dc*}9mZX2QcJDN5FU`S%$kJqS+Nd&5p^vIVK1UT&O`c%2i=+RH)wOK!Mk$&YHK3W21D097JKkE)bR^J z8h&+dayal6&>xj?2+FYv z_(u}H68L%K)f!{9AjsDP`|63%Q6kG&lZ5$|Yvn75&mV8K1}^6K1B?cG_U4}j4+iry zhVc{l`Z1&**cRyKJaiMx`Uv&2C-Og!I)57dO>nBodK&hK>PsO07Uewlb)8Wki}213 z$SV~tK+vC8Wi|Si@{X8mBA*)AvbQtz{M-2~zhL|ZAwBMrRz~1`RE^N{*GG8pHK=Pv zoWHe@Ghj}n;a}t&bdIk{*YIu{H|rYKr*aMI_!`tp$~O;uuA_Y6(EW*c zZ$6xBZ4KuFFb5RluXA3Nso-;J+!NM0&=2(uMbbQU4eU`g=?-!mxz?2@06&1a(L)7# z{x*0o(6p_*9cQY&UC8pAS=37gKI-T@IA^d4X9M2BS)lfKXPd@9XZ;>LsID_i`$`6L zoTrf2#3GKr13sHH?JGa&!a}cl)ISZs1NLMU^t?6_b{V?f5vk$BAlDAeZwyF39CkSv z`)R>wA3G7ACxwsf=Z$%mp)xV`Y3oj;O9Y&Nb%U;eCyy_+I;A{nePaAdYd^HZeW0C> zbS0=yGscxz!^W3c&Y`k5=3m<|*P=20Czva3!8xFE$mWK5R5kE&oE33Jy)MU` zsyq;V3~W`k0Bd*`)H9u#!eN6k_ecP&!(1#R*$9S5D0{#$lt)XMQ&A$NtIk`i`FJnB+UVx`yuEijKCZ*IGj{L$Qw*kIkT$%Mc z&XQzsjIrbGgsKcj#<&z?5A4SqL&h4+8G6RZV%`>lyw_k}li!LlPV&Y6G3GLP0gN%T zJ@$<;cggF7ePhgBa=S6c>>iA9cwKx|ZV34!s&e}<#>ssd<9YP8xeqYLDT5fJGv;Ku zvE(OK$N4%GFt|WQr+Y4e|zBc^V zQj@%%N7`99!%IBA#@T(+mva4Iz7u-8;61GOi|3T<<6KYB9uDa)c$QW;$5?@LtxU;* z0c^?p1Gtid12iRv25j{hv}3c=z#YMEOxXnuQ`QsX=DZV@nmqRd-(a7nMo0GuAzuv1 z4SpBUCu6);7R+)&+I-ehv-bC+8+NoFab)|*qerGKomi8|x?86$O{;me}^h2=qdh1k{sU@BlFjnor>aLxst54b9e^JFQr-c=-^qVi-A;Px>%Fg2+#f1)9 z;cmgs!3!!nJ#b<}Y{H2nu`ixDvYZWH-G%X7jq`}Mc%Q`;k1=}dag2{S&&3twPnuD= z;W(?Y#+FtdiQQCrJyvf&PJS~$*naK`Zsv8Bhs@A#2J0zdcF9|-)kwpd1EUB?=%BS6DF@EQ1h27aF% z>CA<#KF1m)IhRx{Wmv1W^^%H?jMmx_G|Oik-O!2QtQn<8k96F06y?%GPS@2dSUu#_ z+Bzdm3+>LVxSVBIPhvP*XXrK)y3K@c!#M{@pU@FxZK_WL z+>{Z-fv z^`4V#1B-Fzoorx7_<{|rV;gK>JZ#u1*tTGIoplv#8=awWhRs?9yWd& zk4m(wI^oWsUbId5?M%jzuu}$ z!^u_Kon<(oYP&o7U8H%%6Mds#{YN8_x{ft#7H<=&(;N-o2#$gZ5WR*JN+Y zhij#K1Z`_hzo0D}igIKu!=52v4ri}YffIZN=TYb^%orJefh$`_d&}^(weYdecm}X< zjlAdRZM%3=qz#v8&_5AR-1U-p`U?1f23*V|TE<_{l+6+H(3D*S-xA1m24O!UAKG`^ zk9|ma-#Is~vAzlW&Kg~leP_Af8H;*H=UI{r?933V5diUZ;Qy z6>zcw4pYDe1$-6XFlgYffOjh3bqcsp0VgZqFa>N-z*q5If(HHyc&7qhr+^C;aIyjp zQ@{oVd^K9ZUjgq_!0Qxnp#n};z+n;`ZWQl%UL7XhJ-r&H735FG-`3S)T=WSp91{Eo z;Byju9dNA#Uj?jp6w_P={DKsI0q{E#{0rcf5_}FY?lB2G&j9W#!QTUZSc1O=yh(z; z0(??}zX0scinJ#I_mJRE0cT6_QNYhj@F#%3m*9^8x539ls4Ry7&y(N-fbk75AsqLx z{1}Z0{{!#<34RmsV-mav@aqzcb83E{NbswGad%tb^9tZLxO7N)l><(Y;BA2OC3q{~ z?GpSvU=K+@n*hg3@H2q3CHP6exVtIv+yK}p!LV(9W(i&kc)A4RoSNS{30?_!mjtf> zTq(i06Xo}_1TO~6;ot?yyZ~@_37!ksEW!BRh~Eqeo(cGI2`&JaI zI1l9arvzsLZl`PfZ)K=Kc<`!(2d_hTP;}vOk$k9Ecp$R)a853a#<48}-(rcALzx@( z_4S0r4UH`*$j{E0&WvgR$7WAv%*FJ7hmOo=NcSC_;joy#fx%sXxS?k8@3+BDgk)|a zzY>YxJGkU`7Zwe{RF+5juVLT4)}_9t>mfG%yMD}@BL>wUiXF)G8Sx@}=EV{9BL==u zKWk72W=xr>es+wW*;;g}-f?vZv+(B|^)9O)XCea*GW%|fV3s}}%)WQStA2rPe*L7S z@yxt0HZbF|+t+WI!ZT|gjH|!$(|c^3>t5!gtE=w(I^>=D3o{1Pcda+p4|)BKJ0+j( zW@ZO0x}$MARe!C|$okaE59_N|-l}gMmR0}u7kln_rsXo`6VI^@MUxoqs{`)5(ro-llGyc@8^)u)5?D<|cW{K_!d+O2!<~4_JneeFt>m6f1tLLUpuOD;4 ztNzQp1NCuF{mOXt$glq?bq3ofer3JqRA;8o6t+H@EoVDF-M-#X{uUekV0C@=$=giu ztzpbj+vs|I$d&r!kyn^^PbJlRuC4w57`pC9EW0p#og`_fD5Ii5l9t&bMTtrw4TOxg z5)}~=87(at86{hZs3bI0q-AA%geWTssVLRCzxN+_e>m?s&$;G(plD)5k2bktbIT1x z|5wJIl_pS_o)KjWW%uw3~9 z|BS9;GP%KJkV9|nJhau#Myq=+yS#EXPI`5-JjX)XsM$~IhdHU|C1S|94Crl)Wdlp( zAg`;*^}8NpZs1QA@7aK5?@kyWydg#_T_#Xtt`_Nu zd}I2<46!+SA77Ykf&Ciq`RLnH^nA`<>IpTVgtOjs?G}Ujtae<~nTFE`tl0xIeOx#+ z4|d^WNxEesRBJ!NWo;)fxH5{eRcuLYw4h=B>^Ijh(1QOAQ|`T28`Zt3Ea8(LD&p5; zhDJCX)=flrbQM)SDQBzaZ4?x0XR!q(#&~(+62Eaknlh)U@tcaTY5l-qls8;K!0{}$ zWR478&eUQLCH_LSwSu|kx#HfP9EOAMp<)w)pR*Rhd-NOrNiqN3O1%ji6DYe1BR6 z6?Q#k-*h9P5%6dBkJ5jP;c+VWp}Mq}XInqRiTy@{=FnVrbm< zhL7e2l?&)>xDpfbCM z?B{NAwDrr8)Mb4*nQQQm_bjMvz9m0+-Grtc{)IacTS)&xCNuAzNK2-=Ft$z~S{@n{ z(QO8e;RR@)`I%l!KaIwfx3G0_AFr?Qp(i5!JX}5x&$<$Ez`6vL0|6{Dpq!%GM_~DS zMI8OToykeqk{q}#6fR5QhevEcPL~U>eEpP`ZvV>_gkRB-tyjp`SQfi>-Q-_u z4$yy^`snGE!qdZOshezAQ@>U1IV84nvghSOVh znY(r){VeE#Z1qDrK12p4k#Sg8@5nmeuAv1|;Ew z^-IHX#c|knDuQaft}$b40YTUh!=L&6A*EMF^ygR;VjOgMsYo-~u6%~GxiNG?qMekF zb7;I@%6GmtM6k$6%1x-kl%q!w(037Ke>-SvRW_X;I>>+5tU;pO0d`aL16n<&Gb_J| zv`*miJv%d*w3^oA%~y5WiVf_0GH&ucw|sO zFRmuglHqAsH*FMjmkHs@x@nZgce0j-p|nMgvrDr!)9E)od|&W5%Igb4MVSv)&K2XU zZFOL(EloFuDUi_biIA__4@utzG(o-*W8%54=pRA1XRVyHCIt8*R+ga+ZSUAeNLdRB% zOh@Unpq@um|5qIG^-Ji~seCfqxgWN}jL_LwK@Za3GVQBXH2PaL(tOXtdUqe5ME}8T zS2;ABUWHFb9X?Kejn9+9$#u3c^@+_VL9Yd;{>?||3Hs*X zuY;QLGW|6|400guF^k&>uSZjLui#wV#h;*d7Js@D6~7O2bKg8j3|HkkVi)L|(K}QN z!cF^KTllUIuW9YyF)Y%cUI3=Ivfvb3x|bb*LG^{`?5yM&%dTQ(uLisNP=TtHHnFL9 z2S{S)M7B}dj`Sxq;_{iJRA2Rlb-X5cEDpgZkw|DthA>0cj17S*+)O)$E*hp{`mP=n z3BompC5BSYUQxR5YX*heZEX53L%fd*#82g`m>O!!6X#sOs~$sM6DAC0Jq6}plY!0Y zn`vTUG^ut3@m<*)@bCC-b|vd5eh!X6mvk0R?e&L}>@29sMUa<3&~JOZ7UyT*z?>7~ zY0hXV`btsk+Wzh2d{3Ho*YCr^cPHR5s){1QFH*PgHP}TB$237uiV5w4&i?5%7v^2GIc0B`!W35xn9keFMhQT= zzR62g-k*k1D#5JjojDGFyoRIpe$egeWX&H%sq~{Kv#8dBbC5Z+{PCJpM=CPkeYvo3 z9>aFbdqX~N=5k|dAobPaL- z8mm@nQ08-v=jpYLtaFJMQB9d=;e2%%%;u{;>rIpODhRt*F^|n?^1YLDOd=l-s}J zeKOvdQ((rulNPC4l3MRzEA>j~4jCVtHWh0Lj zsilKIjhL&JCvHF8%&W%S#`=;{UgfKW&wnJD?ZOD^qA^rxv5~Ap1CSo;f=-82ia2bJ z3khblO}2=p&mTh$?tvuSRUjBxbBsdr3V83^a0*PsGst@66|p0cL#Vv^}>M!ix>~ zF2mLIL)?_NR`^r*u)8#}HJv^+JYnNhCnLV*ITv*sO6t7^f&mu$$*8v-`I$cOHkiXE zW_*WDstljhCM!^gkFb;*xs+CDM1R-jG)r6nh)?l*S9M1OFQkvmjHfyL^0MhT z)2mCh7yN0F;#~g1y#o6(lPI=vDC&o?1^I-AqVh zl0Pl8Jwp+LGm#%P1|8~QTxm=P^|p%AsfkwQ-8OY;02#|Ca0B5uojek{-e*G7)w zNqc0mdQuB>alcP`@%vfj`H^(3J%!P6f%z%6gj;Bgpnt>T87@}P2;WU?-n~iKbuyM8 z%P*(t@&{1!UYaULR`VUgZs;fspbyFW>8r_RT6M+-R|_7qs4?m^=FuUn4=SbKBPOwX z-k-58Z8X18b)9B*ou+NpTj2Gkk>$>!_n$zW*c?8P zQbLu^li@tBg)GO;V1BDhr#%H>!dlN_XYsk`M2%Xq#%Re0q!dulN{I5197{rfbIP2(vP1oH>5uu2l-wn~EB(~Q69;vO7f!>(;IMaL$ zMndOEtUCuIOEu~KlU#OlYC1hOYG4C5-a{r$jn|5P#_MA%>AsZ;e3I`oT~&^;%X}E0 za6^FWe7K~_GMcpBk1IWs#h|}4mw$Z$yHit8`cIB_D=BiD7IT!0Jx-MikJ1OpPJAfz z!M}U=*u|Z0=(?gnm9>U6UQwE#*3m)4*`a8wcOW*Qk}kh&#}7|Yj++%wUowLjiP4Yy z7diTpAi2gL9{#EIqWQ6h5_Xgh<)|D5=)fn+RKQew)9 z-$-k13-|i|ke*v*k>At9#-g}7jhO#28wZ6H=hZ6@X(C$kd&7o zFOSd29W3Jht!Hq`B%KnySK`8}%lu2vF9hYd3HazZI%>Fz>-$}TPvbA9@8d>t8)|s| z8VPDme#%{C^hmdJ5wDVrM!1$WpF4RHPA9!ML!o0HKfrphEO)HhVoEF zK`QM6h2}{KN(cVk7wx8Fb+%aK+DW5jtNF_LBPco2pGPPb38sBoQ1QH*G}^(8 zD)Ro(jk(I~bh#I*1$%Q;TQqhmICG(p70{^hq|Y}Oko_qg4Ajk}_PQ<%Jodq}OB<1R z+lnMAZD`z@PcT=y!iqu|m8|&5dxh#~X>b+U-QSC69bfpi&5r9G`h|jo1|CrRpU+Qq3~I@!H$!I!(;N_7(kA7hspWqJnR`a6;ETA(aOe|?7x3j z$lUXmLSH_Ea`Q-1iaP{R5mO}Ay~kZiaM??L=~8JkyBlPSDe=z89QmFCMiubc>(!v^ z;=#0Phmn(wG;>Zn0Fg1aP}t-NgRluywmKhAMkceWpVJ}QW`($OGpWXM6720PU}O9a zmNC89R)37`y!{aha!p)*iVxa54zW#UeyCXeljfg4NGo*Zy9sh7;aW)OYG~nML4@s7+Vw4 zX#K@pzCz7PteOM<&PptN0Owl2#jrfI| zS?<&lsEOMP3fSNuO;nB8&ZfWEi|{Ewcv{mI68kDe|29n|pP7d#ZTEKk5nDx-WvA)i zyFuJmO~e=@PnuB|OIAT+*@$BYX_asj4g40Q7sqR}Zxs*eS#2H*7ji+kRXW;rvgrN& zW=Kg*qqp}21(cj$wBjx!OHXT>i8!+Tr9m6@&SJVx3q3t8!jhcwF=1R3i+of>)h1db zE^;1*vLD%t+TZB7Zoonxy+m!sHtrI#f=-`*A>b$sve{;=q%Dea-)Lim_a^GFl_9bi zpemlhItolNd3H1(r9T`Y(gIDbNELzF@^I@HCslLKTPEaEwyraKFUd&qm zlYJP~O@Bidk=NFhWO(cbKSJB#7t}#w##tCVQHaw;Wr92H3_l{SK(Yl#F;=jLs(Qb$ zwnwQ{B;UfF1URa?;TtWw9E2yX>v^zsDV^61#RPGC+BWA0+xvJO_@?2!+UYi}z9qq9 zpTD55mKRWv=0e3$CwYry15T-~VF?X2RQ^zy_H->Ik{(M#Aii`W+bbr@PX1>>fy$IQ96xb(SN z+9o=TJ_*budo4e%BR37h54~e?cE?F1M~WYwoI<}&hm-w}UgWy@;oz??wC7eai}f-f z8-)axp?itCzun-kiVD$UaGKBU-%n39t|B1sHq8D;a*KxzbYt~jTwdZ0g_Y`DSwE9f zj5d?v_BW)cDUS>ZJ2ZFyBU4j>rZb87m(`9KUU~={d`@Dc!vtO`aT41TcEF@;9r>4j zr7=QdXj+mJqPK0L84nJyu)Xq>6mEorTY~7?)8!a-bP9Ed?BKVK*h8Ro@W+caDWxNp znx;BXU34PCuf(Hv^kr7)Vu8@f*LkUw9QOEsq6KX>6maVeS>2Bz^9z6Z&S{poW+#Mu zby3uN@Cf!+Yf|E)Lo8xzGnwz5LuE?^=Rv~@k0(Ww(}FH0CYMAreM(vDi^<4u$>-Z+ zzM#MEK68{Tppw{aFzN|G>2+7ACk-JD*Aaa6qE8f2&fw2FJi`csV~K;6Z5%ZgI5%e^fuL!iAhY_`rXG zLV5+pv>`;)7a(8eF0a1}GK(FL_=n$VN%>RSvRWH^rB(6scReI;CBtpxGm<#=6;9V? zkk*FzxSO{b`IpPs_89>r;#>gV{Ak*^*OvmCUqP(v04a^%fwVMLuD)Om{dtf>)=^D# z_jeO(6L4?C#S3_rP7aQ|HN=CSf3$Q=9iFdPM4eM_vU%@YP`0m=#xLujM9mj0phcK8 z-a2AU_gM;ye$RW-vgpsl4}9vmcT_j#H2e141d|o)xn$=HEd5$f{flSd+_-ZTqcah+ zySH&6!Tnk#)5~Vor&Hux6)rLQ3H_M9fS(;3h2DF@JgPt&Nymqh!o@`t*83jr>KC!$ ziZVOfbqS7Ezu3bOLRfaP5ASA5L*mtSc56~DRS0y~S>Y3lpLso_})pbX0-B|4d(g3L~n#S5*F+8 z*d}Gts#!rto&}S_T@PM5e>kOAd=O}!D~UD)v%yoJVYfMejWyAS|A}ijY`q*&HSdHIyj>#WA( z09A5GJ%UGh^6b!rx%B&lA)JSKQnl(mp7eP-tO|GXe=ToGNb4n2wx5UhGvq1tnIdew z3Rv{)57=fHz}-t8<7iPlp z^y1a4#U!1s0*iG~OxdUgKf*slO2rgCJ{tU!-wgV7*qV9yyWtjp!iIe@Bd3gZ_GfZ7 ze1BW>jXB3*bWaBv$8)h=^CaId`w<#Tf*VQM7_|JVX}l-bj0 z(>e4ydIJoW2sq2Z$6QS@1d;ze!wwm7Xb;xVXa6s>E8`p+D`th@DNelm+g!R*+r#Wq z=F{&@W7*^k9a_v6pt1cJlIFT{@rSn5Vx)%RA2uk8aAzy0>(eORSiVET63K<`v~s}% znpKw%mlPG4?|H~3ZkS3BtP@yE?^n{x*2K+1D{>V5%wD)(p!KRFX#b5pWI1#SP5$9R zYnF_JPJKUlL>BW46pf1{q@ar)~TBy7va zIc-@Ucla0OWyB&}d@RZj=`0hQ{G^J|_55hY-@8iTOSGVHx zie&zbm688AfyYp5i4_73;6ufE+|l%7pZ6A__EtSPw@On+q%}8q-A^id0VH&?jiee} z_?H7!xZ%Ey|7jS4xqesq9-CU~)40p4R?el}ij(ozl$D>bOV{G*e#Zf3*jq~Ye3s8i@)n`m0cB$ies1D)HRd}@F+H9yvY z^{Oklr@WgG9f`@09w9j27ad<-Qz!P*0^MuSHt!&h ze_{OZ=Mz-qG>e(7GoWHgExz|(A59olN?-LJ!m{WUYfkeK;FVWc)aDPi`9AhPQpWd{ z>1=;XB#JYSGWpp1l&P|bEbCI~SHya};!YT*F&pRXb!nMk;`OS%*629x$eivhrFXt{ ztgqY(@|LwM`}|%yyhGqU4K~oNH^ZPE7LV0wbEwD3guWVG;n&apMrcPX0;VWYdcqO7 zs8_?cWe8tB{W}~#{h;){#kBFtDyAks7K3a4<6RH+=*sWWXv-Q(4YRu8_Q`{6ww&es zh!s}%^mErO$070VB4y6|i`K3EO#k=*y;`?`4Ie2=S8S6|TYZZHpA2Cr1sPzC^0yoUkWpr&zFBF@bJWEzI5}bIcj`io1&o+%cCN%K2~xN|{G^wx^{) zf4hx=bx$#=(;e-oCasxr@OHRJVJla%;KpCL;#omXJ`vP9t(pZj6bk6al0|`TiHHpeB&S??D*7(iE0>NS@Jl=!`YnhG<`wW=ca5oe zsKDnDaN@UT&)tjEu2o}V&YHx8%Is@1&v=za_{uwY&9Jn>_+ z3O{mL3%+0>j*SN{kw$40ltLsu;*qlENQ^(+!gx7MMLAv$pSG zSEh}HQRD%(xulbx#3t}Wf$qZoOW-TUWl-u!ExI~uDXq>Iqi4fTkz|N0jo&3i{eGY5 zsM2wKoG;Dg6{aF0_de;r8joiI&(NqofYh5d>^@>?`CD-oZ6@$Ym;B~`ESyMfggIBA z{U7Z6irCL^7u*!&p9-hEpjJ~wHcM+f{_SoGLw~M zxcvG%zbF!fVI27Tzz6ojeMwQ?klrcOGo^_ZNLgOUg&KQkh*=H4due4FED+?)IyL!;N@rL+ab&~GCgEP~7-|pg zz}c>2xFGt1Mj7AZA=$4;Vt+QNRyJcz{A*-L@4>r7=Oj5%$RsZ}6T;_q|1T znJY>DaK^;e>6l@XPl|I(c&}wM$qLOU2LDO}%vGxnSShx2WUmmd)vi4E<_(zjE z-wD%&*Nv2LyMYV0OXJSbw*np;NZzZ$xn0X&K~_qNt5}v(Sknf!F;EWQp3lQBmrk0u z!-Fe%4N}nDJ}&w@h0g9fLFeOdLhaTIGH*Ob#oMmp+>>|`aSg%&FG+z;ugg~|>e8ol zjvqf2(W_QQ*Ov`KySxWSNFElyRW^ShN7$ihC7O*cP-r{wuGg6_q=md>;X~qNoktI@O&_wx;v^Vto$t|_qxHr$c%M4Y=!dR31%xU z$ZR*t!=?H)9X*mmdJ+nFBdE_`vN(f4oglXR^A6;16y$4v`=U&cZ7%g&M~5=L;O3B1 zlyNbaE&Lfok(=+a?MwP;{|jx}@FtLIRNL6u)+f|h@P|xKj-flDae|<}EQxGe%O9II z;+v@@IjX*-AMaw&cs7)D-!I}1`z8cZISM;WQourj_*UBypX$oWpR zHjA*r6ft~J*JS_P(@{7qgU-H%zoc988Hc@pX-AjMTf?kTzc8O5Dw>O5e!+CBC6)OB~#&?Gr(-)_c ze8cfMq&rK2o4*@@JdZrs2fo0~{5!m2WH;$~`f-iUrBHE^;=?w((~+#7*y8&VeZl2; zb#N0dOJ2vWXDX0Uy-BB6_#u1sQGQw45ARwdF*WKcHtt!9%%`H1WU-koFv}ARTXLoS zLN%m$X%1U9{|=u1C&a}zp2W$_(Pa2Nmt4nr)4L__$lCY=EX{w?neqd)s&PI>^cz!A zZ5BQ?k7VnQ-65UX$FS?NJbZ^I@}Iqzu~hvWOv?f>=F}m2cchE1{rp8k0#8!gnI%kc zB@5Orm{gOp>B6dwY*V%f=4o0BJpAjlP{3E_=H%nj&&->}*au*ifu^7E|hXmQ-NwnN|HT#=7 ziIn_DFw2((^w*=8<(ACC>>@i{+L;`ke3fTutkC+j76V!?D|QG3sBn z($3%Suvx5wve%cRr#S(8M^7d9)#E5|#b=oDd$`}_EO@T)1bzGOJLwjDM9H`9e0yLL zeSKAkg`-U|)oUjywPeEW-W1jz8%Rg;UO_+}>A2!UN_rWFQum2$L5?7=*7t@7=(S`(T={T7WW3S=ePJ!tQ=qG{a{l<0Df-9Dm-*x5m zhOQLkvec2_zn7*Tp2t(R32t{mfl?QpUZ#U##=Ug^!9BRCO~SHIPvGgWgsC+}(YWRhyuN82iOun3!N)W3 zOQ0i#Y2Bv~J6VLixrcu<3~+JN5kwZ}V#x8|WG3weu`TD3qW+V4g||~#Zz1z~^Z+VL z`UOS(4tNVZtkHZ5{mk^EedpwH)4PwK9W|X2ug9U}?G6mcOlR9KF2>ANi{bX>HT5A5 zi9h5}boe8VAGkti7i2T-qhly)$zrxZtq3>Y$&%ygWV+?}g7#l8fQ4Znl^n95L4J;B zzOo@x3pI%B(IXj7{Pl7vGH%>QGk>qeH!n5xLk{A##WGfc##@M&pNM(iqFGVk7%Qvi{ zVod|yv%(t_n;P-qlr_mUy&}nGY=w%_iZ&a^z`G=BhGvlzR9r z9T9g&^x+Wl*W6E|1!uv@EEzHHPthp`?{C`%r^0%cpEi ziY`8xsngq=dbA)xLOGhG`(K{gU&kD2XjKK$bvtcZoRiaGMPa5by&mUA*_ki+p zd+2XkEIreZ#D(;GJWs&q->tt*lSB#-Qni~b1-iY7ryi4>mJ250z~xFtptVyNnsOC5 zJ-nV9EKG)B^JeDuC?C9F2fO(@jcl&o=hj2^(QRuZTJ2y=YnJ=+{&~7^_~yg=!*|jg z%`&dFvlEdS31r?k6$caiS_Yjp?sW8-6OIhcLStVA{HD$0 z(Mq$BEO>c9HU0p3-2MWiQZW*eDPps}RAG}sHB+_PPsP%5Jf-UyF3$8~UC%;csgOe} zHr)_l@`?O}*GlS%lBWeP6YyNpl~l*Pg>;iFJLYl$t`oBH`dTnP1g*pEw%hcmwT2vK z+#~e~r%C3a1*xhe@`$+uxUsJhCa;7sNq-lABk49$t7;-9+4i9ZdUk!tVye!SWZVau^e)dQ2Hj1YSk%`kedUkyrYgwd6 zp7Sqq|Dg$3k)8&be+RL}ZVMZ%-w4~S#WcfP3lh3+xUTVyzNQVM+mDHut{?yKs0};* zwbLc}{TP&8$5bH!Ps=DKxp^wpRp|=)K0eU4PNm^K*%+5A#{Zq_7x1z1krx74^()kJSenc2D1}6S7zMTq!#nUJTc>M}F289c?4$$z zeFDtoB8iLR&G^&n?R4UvHfqZ=sr7Ot7dnvx*UUUNS!@d3-f050jp5`yMbIaS2_T6( zXIN9mL`-+RLCJq_((2$6?mH+CL*p)1-#VUVy}CsXM%`2-*+lz_o{>VZE$h0fMSHhz zfz!t!_|(~mNb4iC#yNpjY#l-qE>5GJ)dJk#wu{I2C&7B)Fi&opO!Y$+vzsLw;n^~d zCb=KMk&z+n?)+xjUHpJ24mpT*>nkxgGLxjAd+-f0*{~e@h>Z#<#I~LY8u`Tln=c)q zw7_a;pLmYz&Ayo8=gzkkt7A`l1uYT1OtVuO$m{Dl6und9^M39^!mo{pSXD-MT{E%D z_yNAJnTpWpQWQSF&VFk4V2pJ?Khvv9&&?GmPSF#`i(^>2(Js1`I-UQ=Zqh;ZaX8uX z6i#7__}>0&kjOEnuywr@WfBKyrjl&GQ~3t#3JK;+C=wk=^fjcrK6`@*sCmz_h~^<7E(i#b;^y#<3uODWGh zMxcR6;j3!`no~YdgQj9aB))bXe#Plu#D|gOgX_k@r z@Az7ZRZ_>*ag&%=uPVA;-KKD_C!|>L2-~ukB0j{6C{djzD~;ndw(GI^VjZ8N@QOAI zhNv8vRZL&^*sf z2rZ7H%F>H$?7dptn!1HZ{vM8exXy|{*wCtBx%6bkCQ?g{z=esPwCMXCK7Qp%%siXV z|CI?-@u46#JFS(XcjqDePck%uqy%{;LxdDM^2=9+sr!5hj$JuL<`IQlWMwk`UQ48& z^$SRP*+Nomw87W=qp0Lf1teznbGbF`2-+vh?i>PK-3~MVVSnkO?{&6kMKCtZ_(C@kW$gG)ZZ^r!dJ2m=l^vNXzm$_WV{!UN zR`PiW7U!Mho)1OorK=C+D!f6v%zrRhzXuY5zI6HZN(7sF^IwU@RDB@`;R};U@yk|B zm=`I?U4@bSmAmA9Tb9kXm!toVw$bNU!4UNaqj;~22nmah+x&tEz-0YM!4$+LqRWo`S22!9`FGVbONY)q&*6!l;LLb50Y%Z$HM9!U?A0wC7v0e z`R<`?*DrNw>rdt~cb>ybq>e9fG)2zmX!^TG0dDy#5WG#38f_B!yrr5b(KmB_6p!JR4n9p{v( zKRREKO5NcFtY-Ht^ej!}LxlPu`8tzlzL6AkpsVehpHIq9j^XXpuyeO0uW2g;L3KaBzxqPUjq3D=oB8qD4DeC?%yug-V-BrJ{W& z(I%mVn(I3_ujT!Izuxc9@6X>K=YBlybKNs@&D_^KXU=`kJ#$^xbb;-0&g9XUUoa|o z74V*2f!|q9)HJUbXtH@G9O;Mi&Eu*6t)DpQXCy{VxR0U}W2x7SPq4Y%iI`0>f|*yh zfcM=ru)B2%8|UbQx=t=Elst#gnM24sG6_|##DVlm6&00C2$&>i}`>Xb0$F4kIgt^>}wF+Go{x`Bcbc}sbo@1 zEZBr>CGpE$!DaSX46ojWT7Da#Vq*uetB)d^8+=hTTpd<8$ia3~b(~@m2A6|UVVH6$ zF4XHnnw2)foh6&#TjL8HraglQE0#jW&zWTM)nz!nb5G(wL;*`D8<1&&HSm7IJJ25G zi=_iZq~B%s9bBJDy~EZ+NRk13P(Fz!!hPUKZ(vT>44C*K1@$e@(Ap)BpJZ!2%( z;TwZ7Joh!a@%6~?rmm>&&c4I4mEdb+6lm2Xm*Ep*7_;r1*0 zz;Do5Oj)H%o&^*E$@D<=joDCqrG@%BuVQvJ4fxu71)ht$jE}Y*0`-X9G=b@7%-qe! z8TW@_3JIhOB#wB0SttqaHVQ7P1`)f_zBoUI&0l8M!kooPWM29yIO_P3lq4R;z09Vl z_Jj$3`P~&W7EsiyTT4ww9)No8K)T}WP7st?;9{RN9B`O|FvkoF0{WoM+7?(cK8EZ} z&B5c!-|?5nZg9KOl^!l}N8KSK$-Fz6pjkKwRvb@)+Z76s{^lMyjOHQ7;2b*Vzr@^r zE#Q(i6D7LG!Of|HxOpTpJ^FHTbk;R&^7&2YWAD0Rtl41b_W9q+vTHC^lL~NxT*LlranT zlYY2l$6M^b{TT_an+wlK7~Z%_z(;O9(HS!WKD^nDhgu%s8K=&`nfeu;?%j-E21npa z(JXr5nmo+Y)x_)R5y+VxKwgaxM((u~`ocT_-fK-DCh>hBNZyNPJ^BD|YgR)Do2MF? z^%;how}EMU*<3TnAI%YAlMY8PfNJ);JjWfOJaw@rU) z_3;p_D#CZBk091NzK!?XaFzBE!iQT*zKCedp9!|8G*AwIa3(daaMG1VP?~sC7nsCO4Qt{a9plNImQKpKp-Z~ko-u%Rn z3opnK+ozC`uY((c*5EGo9lFH8A3k`$re?x4w3jrHZ9m6i><~3l@7f5Sc0Gwt)f9BL zw!-4dcWgby6OS<80Yb@B`be(}t~k32e9F&3prIEqPbv7K`$KxfHWVwXTu|?M1?;Wd zLI)IehqSydL}`u>KFgT}d+)!+YpYFQx$kpKD0oNLEr`MJ?2pvwnL18T&&H~-0#JXg zO)shDKqXyG;)n2Hi_>kq_xTNsEni9N#w~_J#oqW+^*d^AwLqn)dSsey1^sz%0dkuJYK@SciI0TcOG5gy%xhPbntjITO0dj56^z+Lg}nv z62ra;KUQ`m^Ng;dx!HUO5PgPcr9NcJIRdk{4+7`M`4wP9kr;2?ne7A-_xZ!==XxXi}Jji*}?@ z&*fv#Icg$yH5&$6!*$>~c09j?cS^9A*os|Jwler7FO> zh&u2in)JiA`RFol!tnFC2!PP#bud+6xozmc#JEy>Mf=G0vM; zh()%Kv37hoynWU{uE;BZZqyj6urm&ICT7$9s{^sTrYp?JQG!QTtx#Fs5+n=6_#?Oz zyj#*8)B0Y4{`rH+%PBu`k@`p)Z>Eb!RNj)v^g-A(aSGg8B7`*|aq#$CfBdw516b_| zVsqU^@HG4g4$_UHC3dbbVDS?=wNDzJWj3Ibul<6M>3fJ;$q=|d@dD}n*$Xy3R)z^) z71(9^X^gF2h@zVtN#qG@bXa==UTvNSk!~SamY@&*oloH{ZX9;!>VfZ-19-DO1uV)o z;;L^gAa}4UsC>_d^&Khbl=Q+`w_bu*tO@o!+aESm-6P-M|G;Xy0W|k)Jbu1qLe{zH zgIexms@-4%Uj?-=VsK}y6ip`zla*1AcOE*18{>2rRhVRJg}Ze4=u|I{Zwy+0W_ivyuD3-+Qtbp6b6G%7CX~=#QkK9y!+|uF&dK-OVP^lh0 zp5TsJu?^^$qzm(OdeaCtuVBk`&*rCB;K;qUxcSg;IH%SPo}}%^?7`oNpGptde={5& zFh6*Wi;j^%`4Bk%m4hwJru4qkaMJ8zkCPf*36J{?CaxY&K6_O_*9rcZ>EQ%wD@W3C zN3Y-+i+pgjyaR`imeHeAbzyCv`*hQiVo;hr9kOn6QNQ9Y`Oq{5`VW4CotN6fn9cRfCNj@|KTMrJkD4ls!8ymb5c#M@*w|q< z5j9Uly3LI^bz{zaKhGh)FRS6Bi6IT%v=5{2=#cKJXKUhfK9=ZjuhHs&{Fi6cDdrTEE zdwXZxRi}=dhh@R|=)T~R7l-en<1y#1KQ=5Zg6spgpj5X!Z7ma4D5V2nvBY3_NtTP$m*w~@sw90HQM6~@e7GQCR13X(H!Q(D-;bwCM^}bk$%W)7bFWAa_U#X)ym-V;X2jK1J zDY$j2JZ5=5gdGK|@IdSo_~Nn(kKdn;Hy!rUi&^`j>%MEWKbC@(gBLk4H3&ESI$Jdhbjx@+`1(T}I*&^g>qIa#_znHGjE|Et$HU4m>!HK$Sr|KI zH~P#@hUziN(8=HkxUlbD@!9X-VYvcqUj4>9g_f|r?{s3oY}h@^Tfd*DVC=vT#KhVa zTXJ@wLY^+X-{(!ekN$?McAofZ-be`OcMmKIL^$GoCpdWYJN61&gKtj_feZV6XcPA_ zoS)?fmwf_o-sdjVbSd*sL%29HMGmenUW|##PeA1W(?e=u-kF*gZ9R}nmvL>jAzDtFM^q0!z&kl+WY&~bcxqJw9P6ruDfyamBbdLrMmCS=lUjolyqS$e$}_fxs6w<2e_>h= z5qi%bf)T3s$(hKzSow4royGfz8T?+TbAXRtAD^T3dkF}7G*YG7-k^P2k;{1hW7F$MLOWE2{uO#|pXechbu@7#tH9Wc90J?q!c)@5Y zgfXY8f=ngq^&}o|S|7nJ#muhxH}iQG6b-k|^TD)O0j3W%po4=ppmOL{<`bs|e@#A1 za`_@yFCR`8IIV{sJFk$rhQGkHMuUv${sBe~F2s-Ju^{JHMoT_l!wGENK3V@A6hAgW z`IpMDcFb`)wpV+OX_r> zyX3RreJ_NnY8`=hXZ4_PVFI?O2$9G4h8BlIaG}>r)RbrX{@zuvE#(>wJEQ?W*gNd_ zVr4u|gXmZVD_HX21f2Fu0fX>fbmjSu`_i#mzC7b7@2Y&RGGJ%E~5t!^YQ*DD0U*-y&555Xc9T1)B-o}8q?6_ z&QNt?4&-!fh5fCP4<`3#<8R0yojp&p4Mau|pM^~@qad54%)QFCl?s9WzB%x`+Jt=n{sGtInBw4` zr8v3r0jY6g-|3?&nGJhBUTyis#usd^gu4PAvd+QE_$9bDgoB^+v#=q=1LGgP!F5TW zpkU1w;%b(FGY@8Bv9lIFQ#*lbDi@irlX6UawH1sSk1`C7Vvm6B1g)5U*S)d$wNW0M zyKaWvvmWEFJ8`t7rZ0@#*@D?-`B*oa=|-$w!StRQh|=|9n8cX|_v$j>LdgIU{-6Og zC%>R$hSs3tX#q{@>WL3rR^y|~<*>3(0$tJJH!KeAfqfrN1IHI*Y3->=V4HoOnh0K? z63+=;4}E|QnzPX0T{LWpeMKgI^MKzYpJJWkKrq_WomT7GflZtSUBANz2JE^|D~9(+ zg{trLSFQ^4_b`CgGpEak43y~a7eC>JXeFSbB3qxxBOX3marRv|`qtziR(u5Vz^n@6 zBe$aP`bBV0Go^}Kt)Y7c`)=iU!HN#fdiH zKav;(E`^@{ige=^UyK^V)>QpNV1uAP&ENDBK0F!;KW=QoalRVx_4Qt;{a%BUvwL80 zqY-)pd!uc1BXN7B0>fPN@#pPKd}z{>UeIRaNr5?Vr|O}Gmj~_FR|T)Wdq^9%moQzg zPjG)_SMasGjcOL(v35l?@$TgWw@OXu^upC};^|tlp}P;1>L<{GqfbHLzX7*S%E0@^ zlWC7+Q%E*&r^nqsqv|RTd~=ocMUFZ~MGQuf@jJ|TyA$vCRtC`!G2SkZgDa2IP!j7y zuRVN<(_a20za=NJ=3xj{E&qmR!e=ty#hsw8-$e4sa}_R0UPDW>Ub1&rAhiBpo@NuIi6=WTRSK}w)vV8^M_I?_9 zwL1>(+VaWc1CPP}^#OA3;s#XhI180-B|!LvokYz{5Be+)CD{+hqVMl=*b$$F-;Qsi z+ij;p%|t)STR8y+Ix>CN+~wFgM2k+l8ich(2%+qIUQ}%l3B}BR>+XFtS8+CFKrmA6h|~hYvGqJxyT=v4B;E<$S!UKj`47WTlwA5P{9G6g){J?u{H5l zHNj52I8Y9A!12syXVTzO7?BoEjprA$t@HMyfS&=o-G@@g2k&A0qg$Bmmx4npMI^Vf z9_)XfCaXQxq4~n^bVKKGJeISDPWiq8KC*YXh1Pd8ur$N;MnxDj&W!MGxI;`z87KxT z;ncNO$Z-wC2RQ@LIBqKPw=SmwkHg?`Z5sVCL5Q6m9VeYn`@-iwo#>%k&*0MAc<^`p zgm1ih6St>B@O9BO^0*`#r{{IT1gqO{{EjDW{xuRqX7kDK!rhqkU^k{QJtfoAb4kyV zVoV;mfZQbrALi*}rb!L#ddt>i`fEY+^FG9i*=f5hx(rsAU!vm(H8P{#7H*vWiB{$1 z*m>Y~GI@e494(%JiOgSZU|J(omzlu?t!dP?xEQ+2m(a95VpzH1I}vz~!||WGkhmA| zxNvVMS)^aY{21J(uBRNZ?At4%X5Jan@905dm=`?ib{|(e^TB^_2=;W1#v{j1lVuwe z*c_`HeW0p>exC=D-J7a$S*!()#(QXy_>t}!%k(UVG{S{~W@bNY3jQ9`@yN}IG{tx< zmVP)7CRZ9^mi~R(=X@j-yxR`e)6-$@#Wd1f83l{RzJYu-2UwM*L^a}f;xMgX9Cc$n zoZUPf3*zeF!^uMWcwGTb9p%RSiNA%y-z{MLRvGUno+mMlT6pl?LORp15Lce=g}TSL z;OI5Kp~QIrXs`{%mYV~t-0MYqy*mdNTM*+IF`XuK17GEFbo2urZhFQc*Zg&0 z=Urv0RBi%~*?L>~p&ERo&gR3Ldquo#yIFU*kTF`0Q zTr&M>3OeqkG_m3v)aa&C&WJ#`u4_!n8^=LT_G$b%RR{-m_Jbv=8tI? z?%&=M^IvITvt}wTa2f#LvzhZ&z~}YOV4^q_`4#)A z`JLZj@z4(ZIDke5Hy|on13#=AMXnkQ!c)e5$clSjIC4x399_g?{>z=IO=BH4jR~gC zdS6j)F0<>)@x*nLl0Y-G4-N|IP6lbDg7w=7YP=x;k`8Vr5&cu)c&BL6X-{{U!>z{H zevx3S(}mQW9t*wD57UQT#7XO3K)1XGz`$ z7_Kdu2qS-+K;o6BaDUH57#q!_r`2QOVB{gZd3+tl4?Ts4Rc@fw@lDL$Bjpoe7L&C1mbMp`QQ7I3ueqk`} z0^5mg&KpdhXG_XN%hxW z+GF|HPq1I@EGiu=hMi$gP?)d?LtJoIin0Q&-{WZzr(on2?Mw48`J`pJ>m!mmo!HFqygQ4f7Yb zj+%9xh8A-qaMJuBtj#E=(=!LatvNy*D69nct>NU@t0|b1^cbs4T~Nb`*)ux7hgaj4 z(#}SS@HJ&W2|1O3nJbmaBHLx~+H(kL3GD<|FK!^w%&+KS4SO)Ql_2-%Q2fEGg#$M` z0{_Yrcu0HGtT(@5zy?3)5kW)PwgC;sc@A8kh zkE04#CnUq(UYEg4b0VDdzX&ZUZ_&R{lRcMi<9oMna5`9zgjtk=(wA4vem5M~Z;t}I za<*O;5J93*9vu{mAzbYWF6q__w!3VD2R>{LbZiP*P-nW#Z5!}|CSj;sI`Yny6W6sv zz#P5NLHR7)YZ*X_GLx`sL=PHcQv(lv&Znz4&cu}?bD{8DC6;L+U;KST*iG=Etmwf%m`+9oQL`gUvb;gjpThs23B((5zF|cP_*eKF#&z- zJEV|UuKo;1FP{PbHx;;SPa}DA)Ev@k*OL=WZ{03+HW|R}2}xS}=sM=x%S$U7v{O33 zkh6<$lDHbZGq2)?if5R&vj=KfFN6nak5SIR0_V9T)6r`J&@=EIvjt@Pq2v?H>AZyL z22gZ+0Bd!DDVQF(7`S`>D)cZ2M!jviSvv4I*E4+X& z*Iz{k^={Z~`iXYy(jEHTUqCD7n_*5$GWsnY1-&kY5#0iZw~UTc?|s8j zKk@^ab@~%Nxkqq59S+q>0hj@A;OQqX=1ck}lo|Wd+hxA^{rqgofA50(CpLikLLq+p zc7_HkEP~pAYVy?U7hZdzfq6}}c)$KV2%0b83}$=B9dC>)j_jn72BR^eR+WC8^8kGI zJSFn-@6q3JE_EGK4IQf9QB%#AxWFuesIMfLeeWZf)$hi$;vU%PZ4QhY0YoG^fQnPz z;H}w>u%>bv`EkSyrbd0Ek@8(|del{1z0e<%>z|XbVrP6=Z%-bS97Il$AsPnfV8C1l z8c}-!FAlDyz29o%i(gmSx7=jB#>U)nK}8_=%%RmotD*9iB`r~Y4F|MdzyiC`xM7bb zWadwWey=2ScUdi5lq_XFjaQ+@_ykg_Ga769>%#~8lW1v{Ob>Qv-+n{|ON?{Tq@syt z-Q~df$zx#<^EF(PG@hK9S_o&?Z>E-Z%P{?B3g&J-53AqZq_P?OgTw)_+H-l0f%8M+VexYS~ww{PfO z|LN#r+Ywfr34}xaGEgmJK91|zg#?zI#AQ|o$o{xe2+7O>vd@M2OPE0Hjbkt;ztwHTZ*hu%G)@ka7YlRiwo|WwWsoiyh@T&S#T92Ru{q}5IBd%kSb1;-%=Y+2vh8DV z?~j|57@xq!jx$IL(;E%2uEXu0PT}*VtLW6y0JKVp!~nBQbYc2lk{wm}Nxv(#Thj$K zn(K+z!VP%qX9JY?Hpfw?a>=M(=kX?6&oh`>!QPYIY17_nJTp&%?t}M$GF#tw9b^Hj zo;i4gI|FX$Os8pfrD*y39E`v112dBh;qA;On6$Bo=yn(aVJ*F3P0D-7h~9`vlG}Kt z<_w-LO28?~6xXSL#Y1!IkYjxgn@+~l7iM%9`Wy%Fczc5K@)E%EM>nip zs|rmvi|CW+a-8J*gjB3rgBwn{;i$e{piz`a?jCi-T_?BT*|+kzZi_A~s;<|5yZ>s@vA4ZaL^ZCFV&Ldr` zQ=wyr6_6OR9V_G&VMSF2<^}d8?-tF#+g)Fh-+tAgm%5qwuVL@GTWn1`H4hb6t%2Qk z3Ai9*JDzAbjC~5lxMAcotcZJ!OZ(YDf&Lou)xI;#VVnBBJCp*w%z99>CA)A`-V<~= z^&9od&og_!#o)KKFT`&uf?Gd_P!qq^SUzGk+T2}%zn1sHr!neymCZkga=S1+?qp)o zF%VCF^r3xwGo3{ZrW+dM0yi$aB_+8JVVGqj-p+T1OoK@zZ7|>j<@H$FISHToyd?|! z2%(S{hL&Z_uj8_@MDER17~yyqwx&AayAu3I%NBU>{hUyZGi zU%|J7Q%O&|p?LgFI&8|j2v3VC8G3s(zMI=jY?wY^&rS7k$j%L;yT8M^B6-NSsD{_q zJ=vOl2A=%-433<8PTp7?LbIihNw`WS=8a(U35h!}>A5?6xLXFp)%KH?>8oII({;+Z zuZivt4#0Mu&iKP{8O(W_fa#C*XnD#cwD#CU?#L6Uj+;%EIWNRlI|#ZlKO@I?mf=|~ zBYYu$kG$Pdgfo~e;V_RxoU+J+daG@L$R2%(w#Gy3+p84U*PCFK$r9-2cn2P4Hq)c~ zs$uLM9tk_wgy|!mkzw2z%vALO?+5cS!U3r3#P=9|l=<^G*aDm(DYW^r5$@09)0g(= zP-FcPvYqX-7LhxgDCKN}opXaAOC=pQsA@y=l@oY#?+D_ltpn-X)N#?TZlG1^%KSX7 z2Q`iBWcw{Awl|g`bXu4QF}+UF(jh%iLD&y_=_KI2_Y!JqJPD(-Lon^B4|uwDrSFD! zfc@*1(V1+YspaO@^k#np9C>*m`DvPgt2YGGhxbJAu45WKm^vH<2H#-)ig;WxxfFHY zbOGr56<@Ed!0#g;(I)xR5c+E>x!rpd-Wu}_?_bry=)uNd^5_QYt&62!r?BV9yF?sr zSPIS(Eu!%HJSwJC!T4FnVB!9^_{;q|zRL6?$MSdMS6&|ZarFzVvc5^Ejv*LmiZRlH z!sXXz>7qooN5PC?_(pIVD&B2n`y_S5&uce{-@GTMVCQ2|wH~?m)9|re_)znb1 z6%6!D$V!7!SQ`^YYs2HPq38&$|M&&mmVKl{U#27f)N5RnQwQ;1H}-N9mQF!}a&A2vo@r!%$p zVA!BFWXAoopmgyfU0BTO_c;hNo@7Jl<8-q7&>+Y)+(AxOb-_+M+5U*ryy3P#lJVOI zgK|SYwF$Sz>bHyF`fxtPRUM~iLnCl}kL~Do&;msp#H8-BF&-Ip5mV$ma7$bY^{tr# zVU;HI{2HduQQDt6ns9L6howLl7r@k0JxO%G!C2qFBc1W&0e1A*LZ|l$$Fx1E)LQd7 zRw|j3#P}d6E8IfD^X9@zjnx>%{PXsVb)ly^TfvjP2jN@FRh+MvM4XS_!Ur9iso|`C zxX-W@^~WmWinu#e68Hf85~h)P&ywJhc3*OMdI!9gXM(yOH{p;l2f8SDfn8%C624+C z3`{+W3ESplOT0eyT&sXr->1;%R1c;@w1e#GtOXA9)M)57z{0m@;bNy;%-MVwJ}>VF zwGWn(iEn~n++GE8RWKS2T%3vco)SLktcAPRUB&xu=cwx{ci0tMO&V6k;n3Bp;56R_ zPtTZ3j+Neky^~Wg)vgE*k1in1_YULzuM5cR*}c)yT0kYK!y$c09~|RKVcuOa30}-$ z>sVI7h9n%VI{*f;b;*ubB4As=eb}llp-omMc;Yvo7#_O|=>clYhsq6D zlJ|=&8nYBPjyn%y&qjk%!&@#LF#^I%lVPQ{Ke{4wegNz|>z z#Z1p~cUFIV@S`UP&vnFUtLkuSWdk;+*u#UU49M)9hZ?)P!xN{wgcCL$8wcj$IFoVA zPWc}GoO~D8AN&lv3%6ko4W|AByF#L4H7;0Zg5AcKL)OFV_@ne8d1;%5c5ew?swaXL z-{6_=H37A-@Wany#g;qY z0xfCM1H1IEMD_R@U2TK*Mz|aad z&+E4mXRSR!tCAOE{DIS_jsM<C z9nB6<;qd_tUc7?On>OH~;il-E84hP*C@wh`jCQZB*WtM_1-Ul1&DG-;1v&c;WoXxiV=~g@3b~i9gR|u4pxM?$V5Yq| z+_?m(y*+7Mk_DxNK&XX& zLP&=l^9!w7vLCM)5It~d53O6Ty#6R?P|nbYsfKH$#GskI_bvRY8RzG`(i`LP7%O@pk#)dtq@adavEhoP>^-#x0MFOE6 z@mkS6;dqsE(JCXIHz%;-(h}tvf;Ef2O1z6i$F?xXn#W$mn0CLWo2mG0$0j}A9ZCI; zi}$A1@4m>}QB|qyViq^KsP1G%!n&)wE_UPYJRDh?uB;O-r$1XTqSjzV)dBvYm6ECD zEmnok4(851>8`fo$?BgG*)M}WyG^%9RW&|g5O&olYtq1$)RH0cxm8{3imol2eZF`@ z*2IP`udeE5Dy2-`m{}oMF8^wJzzszqzpGO4uwm-I4DZ>mQaU|E@4DVxvw?j^ej0vx z&abc$PA~H|@9Lpq=Kdn!=sFLv5;yC3r1?3ec@fn)pC*sIUK~5Ybh-Mf5u)Tk`Fh9n zn)4ZCly$+hpx#*nle@AS}Xnr?Luv}%&?svhLd&{5p>V7T@I&sC;f z8}sj;GZv=JQ!OdGm#=YgpO$;J)$~rGWBYIWu>PfEq{EObhaIm^7UY@)%(;FgPr2{7 zn`^BqryhFbEUpZQbh)w9Yj6JX2MvOeA-|5-d4FEMLE>lF%SI5eKT4GSC0#wLWaYmKvLMQ0~qQ0nX|;ze*ITy48RTX!q%q1-@YQ&XdH!?fpf zqqTWrZBDpE5XO=40yv?e(b^&|Cr~>`BnZ=%gmAT|aiar5I6VGHroGg5Xd8&N%~?i^ zf4Y$e%fZryh_yqx{9s8)Yw1SDW~?NRM4QJC2n`S9inWDOaX9=yZDF{7C@-Kjlk^T^ zAxAVnlsldq=+1=aNWw+jiG%)D!4Qc=C?0QUDCIK{iUjkx0g{mdQE(fVotvAB+d%CZ ze2#x;8wQ+!0Ipcfs{at{uSPYljL1^R;;r?Qo$s6J8(| zOPDa?kpY6RVSneB-mkUh0wGt#VB`mDi=)L7ZkTomN3881DhQa*ZYvdoHOjxh3Rc!G zZXR~F1GQ%h!iTU{W48|AhK8~nt$eLgbH$R@wrp#c);NaMKeUgwYbci^W;w#!>n35l zwrg{OTbu6h;(}COt9DcZxqKcsaHO^khd)H39n6)qmM;FQcou4J{y)o@%qk%Gvs-Al zmot(h6pmns1)kt#7mz_sSTV4kSBv*zp4df!sh_j)XH_Ae8U~eDQergT+R`m#|XB zEdi3oGww)^bv$_s~E?GJNWja7Chk*R1At1-h$CM<)fxrlmcVwpM zxuc*@Ino90hVLQf?>LEkB9sPgIo$022W;+4*HGwjGSW{cz~2y_@WkOOa&$*P^-vMrYV*miAWZ@q64JN@k2)3w=k z+u>Meh)`!2Z32#{r(VnbB8U8TRWz9 z+SYly(vB`Wm0OE%&F9L_5suQjwxP!&=63x;{zt}tlEI8+Yn9=bS9@83t(~^@nA4Yqoj1DlqN~(PAScj(i2j8K}t)d^pTWSN$D3U{UxQH7Prf*E~VO1Izmbt7q+KA zlhPU~JuId9QhHfR%cRsyn%`DRU8Qucl!i#DL`q|%G(k#JrF5T^=1OUSl$JV*Vk7p;RMY0 z4G5X<8ywCN1;TWZFv&77Iy8`_g!}vY^Z0>W5yUtosayKGSWmU_wQ;m^clXutb#}Mq zNH`$Ql~1ztoo{1rEf9oqIeZUMI2S}QB&jEhb>{|HNhBhxfB-=_UjnU+(kNGvKq3eb zg#J^UySu~Rqusfp2wnj9k0_f^j#&IJfyrDxSHuf&W$}>$Rt4#8+_;i(5x-5yBn?Yn z9kI2G=S)_U6D(av?C$OiF=fA*nSAR(q;c*JVo%rB0vH3&`Hu_tg<_|G_JG*P%-5C| zAmIu498t8pL?Ge>b8VdX(p2NozBU5Bgclqx2p3z4M4W$M8Dq;0;)I7v+$AC&KX?jX z!W9Vxp`6wtXG(7=HvV5sVxuu0+$f1lxI`G1}wDXEtg>nyEIzV*_E>^az z8?;5)2t-_a*2IBrwSXAcB+dVWd$Ncl4B-WcAx1k%>woatazv3lcK?$0c4}>@-v5i8 zCl+!f0U@md_i1fKqfvj!WzyOg7!)ySR9YHI`X6Qel@VfUNK)Vb!8*ld8c))C&wl@d z$;E#jmvx*7t_{RI`l~wq|3{Wtt~QVaV)&1$7>)MzZLQ589dJx2mme$%v9fXJ`APzU zSZ4)sr~fmT6Q`9=^*{KGjeP?I{0Oc{;_PlG5(z{ef;JK@9%VPmSLiMnWi!ggJ=nfA zx8{H39zDa&ai)=J5HFO=t~_~?5LZr{Xzn4cvbEJn`@iHG=j$)x1qO3H1b?CBE--a= zXC>K0x7~2)KWA;P%c%cIY;SZUBM~=H~KWoMcgso2*_Uv;P7>{j7!1^yX z28~NQ!%SaEn`pECOXT*C1W{i}k)|EQo}TPg0gfB!Gq8U1tZjEtFBe?DKO zO&-!-fcyWK0?eG<+bb*0EBvRtqsRD$Ghq0EytW5xXmYqjJkumtB#4Y={kg5lv;N@ur}vy0Cp1(L zz>#px0ysiW08bKaWgQ*GI&|w}ryZSKX@29eYyi>vf@5+CIU;WBbHF`J5NZ>`W#bLs zaoi|j>(h`Q?C#Hm|GPZCR<`0%M!u7c# zYDjlWUxEL;0N*wsTQQj<;Ip9(h`;=q6ebRK=knPw2E;%9j1+O%;7Z)a86)>cAtJ7X z!(NVzakU)lZ|!gAwvw#{QLWKQ{}$cew_8(E|CZ7^OtIy%))GXwCZ+wA)c!DT&*k=) z1X=%$;}3Ci|6&M?=5xY$0X7_Q8v^-%rEpu{EPpHY!e2?jTuIvtXC^0lS!UQ^V!njlTtwS?5aB3~^(ZBGrhTwC> zVvp7bS!?R6zfyU89vfq^G4fy7)%=zEw`TeB_t-yx`0-bym@Bd6O8-C7P7@>lXRC$t z=ko=T{QrP@^?zmg;}%JOaYXV$Lp?&+znRsc^&q~`0pxtcLRbgn282tvz9C#r>u`Qx zSZlx0m18{eaM`Dg8Q8@u74ri58l@V!Mq+7cs~-4@Jd$&DFqa6mLsiu+)z#Hi`wlfz zFHiKKIQg}Nc&b&4gkje7g3I;{Fw4s%Fn$__P?2O2g=uh+krla z@*T<%lpj*oP_})Jl%GPm0p&fEn^8VRxjkj~zNG$+lueO@Jt?Qf5bj2~m~vlMegMfI zKzR=3B+6xRBwt0jSv+9_{Y_2Y55tHFHydeO!9A1)))x?PI(<=hsI?88?#8hGcbOCn{x=iNZDZo z;b3IDd|?RvzjD1OPobPd`FqNG$_{T4eF3neogh3%c_!r{cS-&nEN`DLoWD1OVKsk=`amu49pQ1dM z@_EWjDPN(yoAOP{rzzj3d=nYkDD)!jacoYwF6AJ~tthJ~yHm~s_5pdn2hKxaA$YYA z1P!jxl*n;1a0>V?l9tEs$P+%o6y*D~Z7B#HB#ikTz|PkuJ4B9#4=JObJrC+qJ!7U1 zA#$jh=%tK$9KOQ5AgX7~^hLM=2^Uzulu^%~H@Q^L7|Ub()9m2`64Of=_3Zhyn(7%_ z^td9`OBnU+c_y?X{$tGacZl3lzm!qWo__e=(Pfa)1D zeHd52l(GH~p+Q*o3#w<#^l+Ms2{{@*q>Os@{60eUjG11;>7|VNwxOi{4o<}XjG6vC zrTEEp!Hmon;E|KkSLGiLe-BDd(J zjC$5zc}(?;nO=ImVf&?wde*ksLvo-xzI<4;V;Sih7}&-zc7 zsGc#?yAZkM_@#_`*57h!L)y=n>2;i5%BW}kvv;YUG1EWC>7|T%)}M23OX_FL^wRS^ z8a7H9^{oHrNA--Ez9(0|lu^(6i&0e1nCYeUS*xG*FY~FMaZUBCKl%mLGk%)B49dIE zW5dO796LBy%y;9sJI9$EFXMP0$KP^n*REoHz8nwZ_&tt~ar}^DkMbYx64P}Elu^HjzMqv)J!7VS z+V#%f@6J*^W2TR_B@IBv%jOFq8qd2{kQP18VZ%{pBroU6GV*OG^ zJ$v80NA--EelU@XXHGP1lrrks`)O@A(tgHFzY$j;;R5wiM!jhO$!kLOjIlf(zY7>9 zWYoJLKte`6d;e`s^^7qe^@BP8Ng4I*ec6rb88f}~e8c*sT;2881@@z6XNpS{noqa8qdp1@ z6Vo$p0_8i}m5*m&es$+_D=05LpPhlNozHAMXA*4>W7Zx`9kDr<_DC6zhmHTtqI$+m zZ-8+^OvvaDDOcD2LazNERndMn-qZ}7htEUCtbXP{R=7mFgKYy&bMVVtOf~ zo{eXDQ9Wae-j35t81-!YE0pRPGkrX+K*9z3k8uo?$Mb=WXJLMI{u~J9HMk?1l7Ow9 z4{ZExFXW>?8RPz8lei6cfsF0JGMI27t=|^7kqzm6U|tK6%g0-=Ujf@;6q_XcUZkAK z@kbn&a@+vKQoS3;i5wSjyocjQ9LK={!6r+4XLG!oaBXOom^N_v*EoK@R>l4430w42 zIWFY*0LNc(e46769G7uyZzs0LQvZt_M{qob<3f&iaD0JdCm5Fke_HCx;dm^^(>dP8 z@wXh`=J+AUHc+#){jrn7(PiFA#zW8_Y{OBgzK{W{eZki{ri=CvvPI3|=D1#PKAK-{bfTj*oNv1IPC`c7Sh6 zdcJhwIELdCj^E^X3dajMUeEDSj<0b1fUxEJ&Vj}b2O9yF3uXoz2{sCBG}xP9Z-M23 z<%5j_8xJ-CY$Dhsu(!dcf=vUP4mJa9F4%mq1z-!o-UnL(_A%H-u+PE10NVt%8EgyK zR%lgFeFk<2?EjO$@CtDelvaK#SBk%t zbD@M!jlX+J`Ti<_D^cT^J5Kl1XgjOrtp{I~$JtpERc>?5V(YklQBn0#byaA}qt2>| zr?W1!ez=lIx+-LUJBH5ce*Z-DoK<}^o;zYNGc5mVSRG3Ld_Y}g)n5;#6ZchR5S^GS ziJl`|qp&%#sOTgJ;1dJ7aSMcViwhFWjjL8;>L8;A!E~gQG-^!}MJHzdmGHSLg%Dqk zdDTXjiv_9+8yAoNFGZG%yZ$%D^WnZNG3z3*h;9&e7 zm*pF+1zVQqRug4eUZ_HNCEd)&RnpBCr;%V*8sSPa`4CFF*=p>h^*pIx%A+MKO?Sep zSe)uIG!y1W!F(PFd4}LoH8e+yM~rdelE_lLad>+hAtY6qV}NK>t#>d)BpbDnTC)+0 zl3;7IG<==(f|Q}*rntD5E9rwE^jL#x>kxU7s-rk0sWZh78 zIPSx?o@9~Z%4B`6R-@D#R9QJ%yu6KA#ZZ+_=_OY0GZdc7 zi8}EBE6v^UuGDKxjM0)-Lje5C#Loj^dKKxb8lh9I9H<&mKB0ikm+?afqkEMYxG%>2 zCIs}#QKxH72?5FCQW=-*pMrCmOu2Cp7>*CK-r`gJv9_n|R~d{m1H{@H zxvMWeLp-@8-+4{l{Aa%!Pj9iNKlz1v`UuJtE#7kA6ZQa~Dvd^5sx$P%$qG#I5LbqZ zQ{lu_W0ttc$blOaXoeaywW%;EY&hJ608RR2oaQC2Lx#9CW|69lIdEmAYLy0WgEtgZ z8hi=*C^gBjGswvhTOch0N=wN=0pd^Q5 zR4cQ!njAG|sFhGmtjn0D^7r;p;-eV06Ce*T3#wuE4$OUnW1{)uq!{RzX?*3Kk)#<@-sH8hldFCwXlH)wu^4>!= z#VbycpHPQ zO0jQ9J5N}snv)Mt&i-NIo=7hy>S+Rcc2W`Fs<>2|AwHwYy7l?zFvqXFZhklY#b#8x zM~ho4Jm~#k)*zcOXuzgd%ta?u?pX}4T+$aho;4~6-CUg(CkMl9MuVUjuF6)V=yfnb z$*53gD}qwIvWKUq4f8c;`lSS^gMxJ#0lI*o5nhl|GZpcQIOt@j>$IMx^i(e&ouXIH zP@P5r)7@bXpjLxjcB5ye9{+zquBB+QScXnIQ%J5kPm)8x-_t6-cT{)~dH;LfN3GRfu@#lO4dSnOm7c7s|Ax08 z>;?U^U3R&rUiH7k;rpOfzYoYgbvB49cBCtHW~=O}%U$#Gw<>a<{Rg||RrYif;6GL9 zvlVnWKw->QD})rSr}`i2>ca0iFlu2kDp;3YH#C{n<*9Oqiu9euQI=;skdykXju0xs zBa{vbJ=1X`aV*KGen#IXRD?%sb+C#IKRv64h+|=-F@JrGEKb-7v9OImS-MJw>X4BERk48OlJ~7>+QIpxrw2^m9vZnvM z~EWfq%>^NwAK3`tRFn-m#sysH>KCNJvwZ~{v+2m>! zX5_Te9~7jn~@5%nu*3#?)kJ@fN#T^Go{a`V^jDQ9ojn?dAQStn3@wropO(uDMR? z*+1O6dwWIKlV9Z@I#$@Me{g~O(y6OPy}11L$Ua-0zIWsB!7cJVbdzVmCt+jG9Z7(afgiT)M*KfF^pUS34t1`Dc z8Ga@5;u|aaT`S%d{p4k*3$0Rm5rN#h39kiA!E4s6ArDZAIN7m}_ucZXfjof+YO4#B@UGkZd4frm+D zO!vSafk%WWuo#p!!M_SsfLcN1AqsKl-Rr}lXTzcUc)NRbbZ~v@{%mY)$lb}lx#aGY z1A7<(X1P1L*goUClh2Lq&Or@Zr$t8hX#Yn$r>#c=doJ1eR`ABUzwUDF?U?8bjjJ~O zYuSfA`*ofZvcBo)RvWtZZ+tdGF|+f&xV0@V&t2}mKy|rVaSbx(n_Xr^f2?)P$(>@~ zZ^^oW(Zlk0?r;5p$NjGZKWf?g!NjNS;)E(_nbVFaO>)VojEle2(qs(j`^~sVrnz~3 zG0h6w4*PXY-X|Ld>-YVfQf&9_i4*CzF@x=&jNUkU1P3nJcmX~n#l4(HY@mWLcH zsN?p+D;qODOmkkMeOn#AqjY`0%WGX%#Tj1Tm}HYT{?)L>lYVp36gF!*ulv-zPKVM8 zoNjjP?D$F2gwm@sCzNh3Yr8*etNu`Ep=)q#o%2b1cZ4`}a9KDYN|Z#T+q zeqVKC``PC_J{hK)v~5nFdVPuJ=D@ClBO-pU{bsLwH@fX=+QvKK*1a+Dn=>1jH}`pX z|LnNlD`rKG`lXSs)slqBxaFU38~sY;D+TRur(IXveDwN)1GxbYzE=I#x>o7wuJu~| z)M=`siQ=P;-Y2sL#ol;d(OR8w@%r2;4U_j|79IOxVPWlkA=|ecOx*Fo)S}Ct{p%D& zs(&1RCg#VoGh2pDz417;#kfI=v0>R`*92{yb2a1I-bqW1_MU%~cXK8Hh&w>so__@s8u-l%DlJUh+o(Iowe|7WvGcYoKie@a2gY(;W| zMP)7Ded3>F-X347IMcYp@(yjk|Db2=>jl0Aqi0?gJbzkx@la5Yr+xo_H~-4qhrQBv z3@jUSB(P5M3SV`*OWm4`z1n-$m^baS$GC0E|GWEtn*Q}ql`7ZC&-))OakcrfXK6_D zloPL|g?Pq(6WZn1))Q7v9sl;Lj*AyJIRD+~pZjI3%gY-u?XAXZmR@hueBqSyU2kPB zT=6({TZ8A;c&WvIk@j$R3bAAbUXefb0R;1F{EX56B*n zJs^8P_JHgG*#oi%WDm$5kUb!KK=y#_0oenx2V@V(9*{jCdqDPp>;c&WvIk@j$R3bA zAbUXefb0R;1F{EX56B*nJs^8P_JHgG*#oi%WDm$5kUb!KK=y#_0oenx2V@V(9{8{J G!2benq6# 10.24.0' pod 'FirebaseCrashlytics' - pod 'Alamofire' - pod 'SwiftyJSON' + pod 'SwiftyJSON'/ # master branch pod 'Preferences', :git => 'https://github.com/sindresorhus/Preferences.git' pod 'QRCoder' @@ -21,11 +20,11 @@ target 'V2rayU' do end -# fix libarclite_macosx.a need min deploy target 10.14 +# fix libarclite_macosx.a need min deploy target 11.0 post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| - config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '10.14' + config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '11.0' end end end diff --git a/v2rayu/Podfile.lock b/v2rayu/Podfile.lock index 177acccf5d..3eb133ccf5 100644 --- a/v2rayu/Podfile.lock +++ b/v2rayu/Podfile.lock @@ -1,5 +1,4 @@ PODS: - - Alamofire (4.8.2) - FirebaseAnalytics (10.24.0): - FirebaseAnalytics/AdIdSupport (= 10.24.0) - FirebaseCore (~> 10.0) @@ -112,26 +111,22 @@ PODS: - PromisesSwift (2.4.0): - PromisesObjC (= 2.4.0) - QRCoder (1.1.0) - - Sparkle (2.6.2) - Swifter (1.4.7) - SwiftyJSON (5.0.0) - Yams (5.0.6) DEPENDENCIES: - - Alamofire - FirebaseAnalytics (~> 10.24.0) - FirebaseCrashlytics - MASShortcut - Preferences (from `https://github.com/sindresorhus/Preferences.git`) - QRCoder - - Sparkle (~> 2.0) - Swifter - SwiftyJSON - Yams SPEC REPOS: https://github.com/CocoaPods/Specs.git: - - Alamofire - FirebaseAnalytics - FirebaseCore - FirebaseCoreExtension @@ -148,7 +143,6 @@ SPEC REPOS: - PromisesObjC - PromisesSwift - QRCoder - - Sparkle - Swifter - SwiftyJSON - Yams @@ -163,7 +157,6 @@ CHECKOUT OPTIONS: :git: https://github.com/sindresorhus/Preferences.git SPEC CHECKSUMS: - Alamofire: ae5c501addb7afdbb13687d7f2f722c78734c2d3 FirebaseAnalytics: b5efc493eb0f40ec560b04a472e3e1a15d39ca13 FirebaseCore: 11dc8a16dfb7c5e3c3f45ba0e191a33ac4f50894 FirebaseCoreExtension: af5fd85e817ea9d19f9a2659a376cf9cf99f03c0 @@ -181,11 +174,10 @@ SPEC CHECKSUMS: PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851 QRCoder: cbd2bee531cc86d286df7942334cfed94c803ae4 - Sparkle: a62c7dc4f410ced73beb2169cf1d3cc3f028a295 Swifter: 2327ef5d872c638aebab79646ce494af508b0c8f SwiftyJSON: 36413e04c44ee145039d332b4f4e2d3e8d6c4db7 Yams: e10dae147f517ed57ecae37c5e8681bdf8fcab65 -PODFILE CHECKSUM: 071aabe40b11d56fb50a9b83f6ed47079838bdee +PODFILE CHECKSUM: d61ad825ad5d61b2b98237544e21946c9babe3a0 COCOAPODS: 1.15.2 diff --git a/v2rayu/V2rayU.xcodeproj/project.pbxproj b/v2rayu/V2rayU.xcodeproj/project.pbxproj index 5dc3a9e413..1ab46b93f8 100755 --- a/v2rayu/V2rayU.xcodeproj/project.pbxproj +++ b/v2rayu/V2rayU.xcodeproj/project.pbxproj @@ -25,7 +25,6 @@ 664EB377216C9A5F00B6AE0D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664EB376216C9A5F00B6AE0D /* Assets.xcassets */; }; 664EB392216CA9E800B6AE0D /* ConfigWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664EB390216CA9E800B6AE0D /* ConfigWindow.swift */; }; 6662C20B240EA782000AF6CD /* PreferenceDns.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6662C209240EA782000AF6CD /* PreferenceDns.xib */; }; - 667029CA21AF8E7A0079EF41 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 667029C921AF8E7A0079EF41 /* Sparkle.framework */; }; 667029D321AFB86E0079EF41 /* QrcodeWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 667029D121AFB86E0079EF41 /* QrcodeWindow.xib */; }; 66784AFC2170486D00AD307F /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66784AFB2170486D00AD307F /* Util.swift */; }; 667ECE722A9A05EC009B00EC /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 667ECE712A9A05EC009B00EC /* main.swift */; }; @@ -110,15 +109,11 @@ 6608D9DD2182C92D00A0E0DD /* v2rayOutbound.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = v2rayOutbound.swift; sourceTree = ""; }; 6608D9E12182C9C100A0E0DD /* v2rayStream.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = v2rayStream.swift; sourceTree = ""; }; 660D0E59216E0158000C2922 /* V2rayServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = V2rayServer.swift; sourceTree = ""; usesTabs = 0; wrapsLines = 0; }; - 66107B8722DEDBE4002FFB60 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; 66107B8922DEE445002FFB60 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 6618372823E9BF1A000F7410 /* ToastWindow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ToastWindow.swift; sourceTree = ""; }; 6618372D23E9BF73000F7410 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ToastWindow.xib; sourceTree = ""; }; 66193A8523EE45B200289B6A /* PreferenceRouting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceRouting.swift; sourceTree = ""; }; 66193A8823EE46BC00289B6A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = V2rayU/Base.lproj/PreferenceRouting.xib; sourceTree = SOURCE_ROOT; }; - 66193A9323EF1EF600289B6A /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "../zh-Hans.lproj/PreferenceRouting.strings"; sourceTree = ""; }; - 66193A9523EF1EFA00289B6A /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "../zh-HK.lproj/PreferenceRouting.strings"; sourceTree = ""; }; - 6625848D2AB745E700DFDC1E /* sign.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = sign.sh; sourceTree = ""; }; 6625848E2AB746D500DFDC1E /* appdmg.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = appdmg.sh; sourceTree = ""; }; 662F0ACE2AB720C700884C17 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = ../en.lproj/PreferenceGeneral.strings; sourceTree = ""; }; 663F040525ED4B2C00687600 /* V2rayLaunch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = V2rayLaunch.swift; sourceTree = ""; }; @@ -126,19 +121,17 @@ 664B95DD217062A500DBC941 /* Alamofire */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Alamofire; path = Pods/Alamofire; sourceTree = ""; }; 664BAC462C2DB0E100654FB7 /* V2rayRouting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = V2rayRouting.swift; sourceTree = ""; }; 664BAC482C314CD600654FB7 /* AppVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersion.swift; sourceTree = ""; }; + 664BAC4F2C394AA000654FB7 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "../zh-Hans.lproj/PreferenceRouting.strings"; sourceTree = ""; }; 664EB371216C9A5E00B6AE0D /* V2rayU.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = V2rayU.app; sourceTree = BUILT_PRODUCTS_DIR; }; 664EB374216C9A5E00B6AE0D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 664EB376216C9A5F00B6AE0D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 664EB379216C9A5F00B6AE0D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 664EB37B216C9A5F00B6AE0D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 664EB390216CA9E800B6AE0D /* ConfigWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigWindow.swift; sourceTree = ""; }; - 664FC05321A70C4300048FE3 /* build.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = build.plist; sourceTree = ""; }; - 6653C20422E0A2B700754D66 /* publish.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = publish.sh; sourceTree = ""; }; 665DC9BA22A542F90062337B /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 6662C20A240EA782000AF6CD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = V2rayU/Base.lproj/PreferenceDns.xib; sourceTree = SOURCE_ROOT; }; 6662C20C240EA794000AF6CD /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "../zh-Hans.lproj/PreferenceDns.strings"; sourceTree = ""; }; 6662C20D240EA797000AF6CD /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "../zh-HK.lproj/PreferenceDns.strings"; sourceTree = ""; }; - 667029C921AF8E7A0079EF41 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = "../../Downloads/Sparkle-1.21.0/Sparkle.framework"; sourceTree = ""; }; 667029D221AFB86E0079EF41 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/QrcodeWindow.xib; sourceTree = ""; }; 66784AFB2170486D00AD307F /* Util.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = ""; }; 667ECE6F2A9A05EB009B00EC /* V2rayUTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = V2rayUTool; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -154,7 +147,9 @@ 669A73AC233776B900807CF9 /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "../zh-HK.lproj/PreferenceGeneral.strings"; sourceTree = ""; }; 669A73AD233776B900807CF9 /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "../zh-HK.lproj/PreferencePac.strings"; sourceTree = ""; }; 669A73AE233776B900807CF9 /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "../zh-HK.lproj/PreferenceSubscription.strings"; sourceTree = ""; }; - 669A73AF233776B900807CF9 /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "zh-HK.lproj/Localizable.strings"; sourceTree = ""; }; + 66A358662C39517B00914A25 /* zh-HK */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-HK"; path = "zh-HK.lproj/Localizable.strings"; sourceTree = ""; }; + 66A358672C39517F00914A25 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; + 66A358682C3959AE00914A25 /* build.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = build.plist; sourceTree = ""; }; 66A5CE4521706B5A009B08B2 /* Pods_V2rayU.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Pods_V2rayU.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 66A77BE2268225790097A126 /* v2ray-core */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "v2ray-core"; path = "Build/v2ray-core"; sourceTree = ""; }; 66ACB19F21757D5B005B5881 /* MainMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMenu.swift; sourceTree = ""; }; @@ -205,7 +200,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 667029CA21AF8E7A0079EF41 /* Sparkle.framework in Frameworks */, 66973EB721797719001FEA1E /* ServiceManagement.framework in Frameworks */, F260898E336CFA5EAB07ADC9 /* Pods_V2rayU.framework in Frameworks */, ); @@ -313,12 +307,10 @@ 66FEAD44217D75D7009DECF9 /* Build */ = { isa = PBXGroup; children = ( + 66A358682C3959AE00914A25 /* build.plist */, 6625848E2AB746D500DFDC1E /* appdmg.sh */, - 6625848D2AB745E700DFDC1E /* sign.sh */, - 664FC05321A70C4300048FE3 /* build.plist */, 66FEAD45217D75FC009DECF9 /* release.sh */, 6D6DFD93CE866018306A090E /* pac */, - 6653C20422E0A2B700754D66 /* publish.sh */, 6D6DF927AC79EEF7378C192A /* appdmg.json */, ); path = Build; @@ -360,7 +352,6 @@ children = ( 665DC9BA22A542F90062337B /* AppKit.framework */, 664666A021CBD6C60094F0B7 /* libPods-V2rayUTool.a */, - 667029C921AF8E7A0079EF41 /* Sparkle.framework */, 66973EB621797719001FEA1E /* ServiceManagement.framework */, 66A5CE4521706B5A009B08B2 /* Pods_V2rayU.framework */, 664B95DD217062A500DBC941 /* Alamofire */, @@ -595,9 +586,9 @@ 66107B8822DEDBE4002FFB60 /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( - 66107B8722DEDBE4002FFB60 /* zh-Hans */, 66107B8922DEE445002FFB60 /* en */, - 669A73AF233776B900807CF9 /* zh-HK */, + 66A358662C39517B00914A25 /* zh-HK */, + 66A358672C39517F00914A25 /* zh-Hans */, ); name = Localizable.strings; sourceTree = ""; @@ -614,8 +605,7 @@ isa = PBXVariantGroup; children = ( 66193A8823EE46BC00289B6A /* Base */, - 66193A9323EF1EF600289B6A /* zh-Hans */, - 66193A9523EF1EFA00289B6A /* zh-HK */, + 664BAC4F2C394AA000654FB7 /* zh-Hans */, ); name = PreferenceRouting.xib; sourceTree = ""; @@ -844,14 +834,15 @@ buildSettings = { ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 4.0.0; + CURRENT_PROJECT_VERSION = 4.2.0; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = RJYEH6TCJD; ENABLE_ONLY_ACTIVE_RESOURCES = YES; INFOPLIST_FILE = V2rayU/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = V2rayU; @@ -860,7 +851,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 4.0.0; + MARKETING_VERSION = 4.2.0; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = net.yanue.V2rayU; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -878,14 +869,15 @@ buildSettings = { ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 4.0.0; + CURRENT_PROJECT_VERSION = 4.2.0; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = RJYEH6TCJD; ENABLE_ONLY_ACTIVE_RESOURCES = YES; INFOPLIST_FILE = V2rayU/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = V2rayU; @@ -894,7 +886,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 4.0.0; + MARKETING_VERSION = 4.2.0; ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = net.yanue.V2rayU; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -912,8 +904,9 @@ ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = RJYEH6TCJD; ENABLE_HARDENED_RUNTIME = YES; MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -927,8 +920,9 @@ ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = RJYEH6TCJD; ENABLE_HARDENED_RUNTIME = YES; MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/v2rayu/V2rayU/AppVersion.swift b/v2rayu/V2rayU/AppVersion.swift index ea0b929490..c4a040c67c 100644 --- a/v2rayu/V2rayU/AppVersion.swift +++ b/v2rayu/V2rayU/AppVersion.swift @@ -45,6 +45,16 @@ struct GithubAsset: Codable { } } +struct GithubError: Codable { + let message: String + let documentationUrl: String + + enum CodingKeys: String, CodingKey { + case message + case documentationUrl = "documentation_url" + } +} + let V2rayUpdater = AppCheckController() // AppCheckController - 检查新版本页面 @@ -169,22 +179,46 @@ class AppCheckController: NSWindowController { } } } catch { - print("Error decoding JSON: \(error)") - DispatchQueue.main.async { - // update progress text - self.bindData.progressText = "Check failed: \(error)" - var title = "Check failed!" - var toast = "\(error)" - if isMainland { - title = "检查失败" - toast = "\(error)"; + // 可能请求太频繁了 + do { + let decoder = JSONDecoder() + + // try decode data + let data: GithubError = try decoder.decode(GithubError.self, from: data) + DispatchQueue.main.async { + // update progress text + self.bindData.progressText = "Check failed: \(error)" + var title = "Check failed!" + if isMainland { + title = "检查失败" + } + var toast = "\(data.message)\n\(data.documentationUrl)"; + // open dialog + alertDialog(title: title, message: toast) + // sleep 2s + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + // close window + self.closeWindow() + } } - // open dialog - alertDialog(title: title, message: toast) - // sleep 2s - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - // close window - self.closeWindow() + } catch { + print("Error decoding JSON: \(error)") + DispatchQueue.main.async { + // update progress text + self.bindData.progressText = "Check failed: \(error)" + var title = "Check failed!" + var toast = "\(error)" + if isMainland { + title = "检查失败" + toast = "\(error)"; + } + // open dialog + alertDialog(title: title, message: toast) + // sleep 2s + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + // close window + self.closeWindow() + } } } } @@ -258,7 +292,7 @@ class AppVersionController: NSWindowController { let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 500, height: 300), styleMask: [.titled, .closable, .resizable], backing: .buffered, defer: false) - window.title = "Software Update" + window.title = "V2rayU Update" window.contentView = contentView super.init(window: window) @@ -272,19 +306,37 @@ class AppVersionController: NSWindowController { } func show(release: GithubRelease) { - bindData.title = "A new version of V2rayU is available!" - bindData.description = "V2rayU \(appVersion) is now available—you have \(release.tagName). Would you like to download it now?" - bindData.releaseNotes = release.name + "\n" + release.body - self.release = release - print("bindData.releaseNotes", bindData.releaseNotes) - // bring window to front - window?.orderFrontRegardless() - // center position - window?.center() - // make window key - window?.makeKeyAndOrderFront(nil) - // activate app - NSApp.activate(ignoringOtherApps: true) + DispatchQueue.main.async { + self.release = release + if isMainland { + self.bindData.title = "A new version of V2rayU is available!" + if release.prerelease{ + self.bindData.description = "V2rayU \(release.tagName) preview is now available, you have \(appVersion). Would you like to download it now?" + } else { + self.bindData.description = "V2rayU \(release.tagName) is now available, you have \(appVersion). Would you like to download it now?" + } + self.bindData.releaseNotes = release.name + "\n" + release.body + } else { + self.bindData.title = "V2rayU 有新版本上线了!" + if release.prerelease { + self.bindData.description = "V2rayU 已上线 \(release.tagName) 预览版,您有的版本 \(appVersion) —,需要立即下载吗?" + } else { + self.bindData.description = "V2rayU 已上线 \(release.tagName),您有的版本 \(appVersion) —,需要立即下载吗?" + } + self.bindData.releaseNotes = release.name + "\n" + release.body + self.bindData.releaseNodesTitle = "更新日志" + self.bindData.skipVersion = "跳过此版本" + self.bindData.installUpdate = "安装此版本" + } + // bring window to front + self.window?.orderFrontRegardless() + // center position + self.window?.center() + // make window key + self.window?.makeKeyAndOrderFront(nil) + // activate app + NSApp.activate(ignoringOtherApps: true) + } } required init?(coder: NSCoder) { @@ -309,10 +361,10 @@ class AppVersionController: NSWindowController { func skipAction() { print("Skip action") - // UserDefaults 记录是否跳过版本更新 - UserDefaults.standard.set(release.tagName, forKey: "skipAppVersion") - // 关闭窗口 DispatchQueue.main.async { + // UserDefaults 记录是否跳过版本更新 + UserDefaults.standard.set(self.release.tagName, forKey: "skipAppVersion") + // 关闭窗口 self.window?.close() } } @@ -320,8 +372,10 @@ class AppVersionController: NSWindowController { class BindData: ObservableObject { @Published var title = "A new version of V2rayU App is available!" @Published var description = "" - @Published var releaseNotes = """ - """ + @Published var releaseNotes = "" + @Published var releaseNodesTitle = "Release Notes:" + @Published var skipVersion = "Skip This Version!" + @Published var installUpdate = "Install Update!" } struct ContentView: View { @@ -347,7 +401,7 @@ class AppVersionController: NSWindowController { Text(bindData.description) .padding(.trailing, 20) - Text("Release Notes:") + Text(bindData.releaseNodesTitle) .font(.headline) .bold() .padding(.top, 20) @@ -364,22 +418,25 @@ class AppVersionController: NSWindowController { Spacer(minLength: 20) // 右边 margin 40 } + + HStack { + Button(bindData.skipVersion) { + skipAction() + } + + Spacer() + + Button(bindData.installUpdate) { + installAction() + } + .padding(.trailing, 20) + .keyboardShortcut(.defaultAction) + } + .padding(.top,20) + .padding(.bottom,20) } } - HStack { - Button("Skip This Version") { - skipAction() - } - - Spacer() - - Button("Install Update") { - installAction() - } - .keyboardShortcut(.defaultAction) - } - .padding(20) } .frame(width: 500, height: 300) } diff --git a/v2rayu/V2rayU/Base.lproj/PreferenceDns.xib b/v2rayu/V2rayU/Base.lproj/PreferenceDns.xib index 154c84255d..aeeb67d413 100755 --- a/v2rayu/V2rayU/Base.lproj/PreferenceDns.xib +++ b/v2rayu/V2rayU/Base.lproj/PreferenceDns.xib @@ -1,8 +1,8 @@ - + - + @@ -51,7 +51,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -91,7 +91,7 @@ - + diff --git a/v2rayu/V2rayU/Info.plist b/v2rayu/V2rayU/Info.plist index 2fca0a39bb..ea56de5ddb 100644 --- a/v2rayu/V2rayU/Info.plist +++ b/v2rayu/V2rayU/Info.plist @@ -4,14 +4,14 @@ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIconFile - AppIcon - CFBundleGetInfoString - CFBundleDisplayName + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleGetInfoString + + CFBundleIconFile + AppIcon CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion diff --git a/v2rayu/V2rayU/Ping.swift b/v2rayu/V2rayU/Ping.swift index 456f2ca663..d2b18d1625 100644 --- a/v2rayu/V2rayU/Ping.swift +++ b/v2rayu/V2rayU/Ping.swift @@ -6,8 +6,6 @@ // Copyright © 2019 yanue. All rights reserved. // -import SwiftyJSON - // ping and choose fastest v2ray var inPing = false var inPingCurrent = false diff --git a/v2rayu/V2rayU/Preference/PreferenceSubscription.swift b/v2rayu/V2rayU/Preference/PreferenceSubscription.swift index 214b8afdcd..86b0e42bbd 100644 --- a/v2rayu/V2rayU/Preference/PreferenceSubscription.swift +++ b/v2rayu/V2rayU/Preference/PreferenceSubscription.swift @@ -8,7 +8,6 @@ import Cocoa import Preferences -import SwiftyJSON final class PreferenceSubscribeViewController: NSViewController, PreferencePane, NSTabViewDelegate { let preferencePaneIdentifier = PreferencePane.Identifier.subscribeTab diff --git a/v2rayu/V2rayU/V2rayLaunch.swift b/v2rayu/V2rayU/V2rayLaunch.swift index ee7ff2f109..47ba283b73 100644 --- a/v2rayu/V2rayU/V2rayLaunch.swift +++ b/v2rayu/V2rayU/V2rayLaunch.swift @@ -9,7 +9,6 @@ import Cocoa import SystemConfiguration import Swifter -import Alamofire let LAUNCH_AGENT_NAME = "yanue.v2rayu.v2ray-core" let AppResourcesPath = Bundle.main.bundlePath + "/Contents/Resources" diff --git a/v2rayu/V2rayU/V2rayServer.swift b/v2rayu/V2rayU/V2rayServer.swift index b627da81c6..d714cfc21a 100644 --- a/v2rayu/V2rayU/V2rayServer.swift +++ b/v2rayu/V2rayU/V2rayServer.swift @@ -7,7 +7,6 @@ // import Cocoa -import SwiftyJSON // ----- v2ray server manager ----- class V2rayServer: NSObject { diff --git a/v2rayu/V2rayU/V2raySubscription.swift b/v2rayu/V2rayU/V2raySubscription.swift index e0d9add155..4052aca74c 100644 --- a/v2rayu/V2rayU/V2raySubscription.swift +++ b/v2rayu/V2rayU/V2raySubscription.swift @@ -7,7 +7,6 @@ // import Cocoa -import SwiftyJSON import Yams // ----- v2ray subscribe manager ----- diff --git a/v2rayu/V2rayU/en.lproj/Localizable.strings b/v2rayu/V2rayU/en.lproj/Localizable.strings index 7c264b2ac6..1da9de2959 100644 --- a/v2rayu/V2rayU/en.lproj/Localizable.strings +++ b/v2rayu/V2rayU/en.lproj/Localizable.strings @@ -5,4 +5,3 @@ Created by yanue on 2019/7/17. Copyright © 2019 yanue. All rights reserved. */ -// Localizable App Name是App在英语环境环境下显示的名称 diff --git a/v2rayu/V2rayU/zh-HK.lproj/Localizable.strings b/v2rayu/V2rayU/zh-HK.lproj/Localizable.strings index 7c264b2ac6..1da9de2959 100644 --- a/v2rayu/V2rayU/zh-HK.lproj/Localizable.strings +++ b/v2rayu/V2rayU/zh-HK.lproj/Localizable.strings @@ -5,4 +5,3 @@ Created by yanue on 2019/7/17. Copyright © 2019 yanue. All rights reserved. */ -// Localizable App Name是App在英语环境环境下显示的名称 diff --git a/v2rayu/V2rayU/zh-HK.lproj/PreferenceRouting.strings b/v2rayu/V2rayU/zh-HK.lproj/PreferenceRouting.strings index 40cc57ce04..aea250a4b8 100644 --- a/v2rayu/V2rayU/zh-HK.lproj/PreferenceRouting.strings +++ b/v2rayu/V2rayU/zh-HK.lproj/PreferenceRouting.strings @@ -1,45 +1,45 @@ -/* Class = "NSTextFieldCell"; title = "Domain Strategy:"; ObjectID = "22k-l7-G7a"; */ -"22k-l7-G7a.title" = "域名策略:"; +/* Class = "NSTextFieldCell"; title = "Block:"; ObjectID = "0Cd-bg-07K"; */ +"0Cd-bg-07K.title" = "Block:"; -/* Class = "NSMenuItem"; title = "Bypassing LAN and mainland address"; ObjectID = "3qq-dt-TS9"; */ -"3qq-dt-TS9.title" = "绕过局域网和大陆地址"; +/* Class = "NSMenuItem"; title = "IPOnDemand"; ObjectID = "2ST-s0-RrI"; */ +"2ST-s0-RrI.title" = "IPOnDemand"; -/* Class = "NSTextFieldCell"; title = "Routing Rule:"; ObjectID = "4rB-9k-291"; */ -"4rB-9k-291.title" = "路由模式:"; +/* Class = "NSTextFieldCell"; title = "Direct:"; ObjectID = "3hZ-qS-PUG"; */ +"3hZ-qS-PUG.title" = "Direct:"; /* Class = "NSButtonCell"; title = "save"; ObjectID = "8g2-Nj-m07"; */ -"8g2-Nj-m07.title" = "保存"; +"8g2-Nj-m07.title" = "save"; -/* Class = "NSMenuItem"; title = "IPIfNonMatch"; ObjectID = "92h-JU-wqn"; */ -"92h-JU-wqn.title" = "IPIfNonMatch"; +/* Class = "NSTextFieldCell"; title = "Rouing Rules"; ObjectID = "E4W-rN-0eq"; */ +"E4W-rN-0eq.title" = "Rouing Rules"; -/* Class = "NSMenuItem"; title = "Bypassing the LAN Address"; ObjectID = "CoE-cp-7fn"; */ -"CoE-cp-7fn.title" = "绕过局域网地址"; +/* Class = "NSTextFieldCell"; title = "Custom Rule Name"; ObjectID = "Ecy-wl-v5i"; */ +"Ecy-wl-v5i.title" = "Custom Rule Name"; -/* Class = "NSMenuItem"; title = "Bypassing mainland address"; ObjectID = "EaD-tR-ldB"; */ -"EaD-tR-ldB.title" = "绕过大陆地址"; +/* Class = "NSTextFieldCell"; title = "Routing Rule:"; ObjectID = "J2T-Pf-s5D"; */ +"J2T-Pf-s5D.title" = "Routing Rule:"; -/* Class = "NSMenuItem"; title = "IPOnDemand"; ObjectID = "Js7-cb-bWa"; */ -"Js7-cb-bWa.title" = "IPOnDemand"; +/* Class = "NSMenuItem"; title = "AsIs"; ObjectID = "Kl2-gr-bsh"; */ +"Kl2-gr-bsh.title" = "AsIs"; -/* Class = "NSMenuItem"; title = "AsIs"; ObjectID = "LX1-ye-51i"; */ -"LX1-ye-51i.title" = "AsIs"; +/* Class = "NSTextFieldCell"; title = "Custom Rule JSON Text"; ObjectID = "Q0v-Ic-TRt"; */ +"Q0v-Ic-TRt.title" = "Custom Rule JSON Text"; -/* Class = "NSButtonCell"; title = "load default"; ObjectID = "RSN-g5-vmP"; */ -"RSN-g5-vmP.title" = "load default"; +/* Class = "NSTextFieldCell"; title = "Domain Strategy:"; ObjectID = "Qp3-K0-xA9"; */ +"Qp3-K0-xA9.title" = "Domain Strategy:"; -/* Class = "NSTextFieldCell"; title = "* Set the rules line by line: domain or ip"; ObjectID = "ccq-gn-C6Z"; */ -"ccq-gn-C6Z.title" = "*按行设置域名或ip"; +/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "YQ1-7i-YOl"; */ +"YQ1-7i-YOl.title" = "Text Cell"; -/* Class = "NSTabViewItem"; label = "Block"; ObjectID = "nsT-BW-R2Z"; */ -"nsT-BW-R2Z.label" = "阻止ip或域名"; +/* Class = "NSTextFieldCell"; title = "Proxy:"; ObjectID = "cfS-8I-8Au"; */ +"cfS-8I-8Au.title" = "Proxy:"; -/* Class = "NSTabViewItem"; label = "Proxy"; ObjectID = "pnL-Z8-fIK"; */ -"pnL-Z8-fIK.label" = "代理ip或域名"; +/* Class = "NSMenuItem"; title = "IPIfNonMatch"; ObjectID = "dSb-GT-n2n"; */ +"dSb-GT-n2n.title" = "IPIfNonMatch"; -/* Class = "NSTabViewItem"; label = "Direct"; ObjectID = "yc0-Po-cG1"; */ -"yc0-Po-cG1.label" = "直连ip或域名"; +/* Class = "NSTextFieldCell"; title = "like: { \"domainStrategy\": \"IPOnDemand\", \"rules\": []}"; ObjectID = "ejH-X7-8Fb"; */ +"ejH-X7-8Fb.title" = "like: { \"domainStrategy\": \"IPOnDemand\", \"rules\": []}"; -/* Class = "NSMenuItem"; title = "Global"; ObjectID = "zLf-pT-xlm"; */ -"zLf-pT-xlm.title" = "全局"; +/* Class = "NSTextFieldCell"; title = "* Set the rules line by line: domain or ip"; ObjectID = "ymo-ds-No9"; */ +"ymo-ds-No9.title" = "* Set the rules line by line: domain or ip"; diff --git a/v2rayu/V2rayU/zh-Hans.lproj/PreferenceRouting.strings b/v2rayu/V2rayU/zh-Hans.lproj/PreferenceRouting.strings index 40cc57ce04..cbbf840748 100644 --- a/v2rayu/V2rayU/zh-Hans.lproj/PreferenceRouting.strings +++ b/v2rayu/V2rayU/zh-Hans.lproj/PreferenceRouting.strings @@ -1,45 +1,45 @@ -/* Class = "NSTextFieldCell"; title = "Domain Strategy:"; ObjectID = "22k-l7-G7a"; */ -"22k-l7-G7a.title" = "域名策略:"; +/* Class = "NSTextFieldCell"; title = "Block:"; ObjectID = "0Cd-bg-07K"; */ +"0Cd-bg-07K.title" = "阻止ip或域名:"; -/* Class = "NSMenuItem"; title = "Bypassing LAN and mainland address"; ObjectID = "3qq-dt-TS9"; */ -"3qq-dt-TS9.title" = "绕过局域网和大陆地址"; +/* Class = "NSMenuItem"; title = "IPOnDemand"; ObjectID = "2ST-s0-RrI"; */ +"2ST-s0-RrI.title" = "IPOnDemand"; -/* Class = "NSTextFieldCell"; title = "Routing Rule:"; ObjectID = "4rB-9k-291"; */ -"4rB-9k-291.title" = "路由模式:"; +/* Class = "NSTextFieldCell"; title = "Direct:"; ObjectID = "3hZ-qS-PUG"; */ +"3hZ-qS-PUG.title" = "直连ip或域名:"; /* Class = "NSButtonCell"; title = "save"; ObjectID = "8g2-Nj-m07"; */ "8g2-Nj-m07.title" = "保存"; -/* Class = "NSMenuItem"; title = "IPIfNonMatch"; ObjectID = "92h-JU-wqn"; */ -"92h-JU-wqn.title" = "IPIfNonMatch"; +/* Class = "NSTextFieldCell"; title = "Rouing Rules"; ObjectID = "E4W-rN-0eq"; */ +"E4W-rN-0eq.title" = "路由规则列表"; -/* Class = "NSMenuItem"; title = "Bypassing the LAN Address"; ObjectID = "CoE-cp-7fn"; */ -"CoE-cp-7fn.title" = "绕过局域网地址"; +/* Class = "NSTextFieldCell"; title = "Custom Rule Name"; ObjectID = "Ecy-wl-v5i"; */ +"Ecy-wl-v5i.title" = "自定义路由名称"; -/* Class = "NSMenuItem"; title = "Bypassing mainland address"; ObjectID = "EaD-tR-ldB"; */ -"EaD-tR-ldB.title" = "绕过大陆地址"; +/* Class = "NSTextFieldCell"; title = "Routing Rule:"; ObjectID = "J2T-Pf-s5D"; */ +"J2T-Pf-s5D.title" = "路由规则:"; -/* Class = "NSMenuItem"; title = "IPOnDemand"; ObjectID = "Js7-cb-bWa"; */ -"Js7-cb-bWa.title" = "IPOnDemand"; +/* Class = "NSMenuItem"; title = "AsIs"; ObjectID = "Kl2-gr-bsh"; */ +"Kl2-gr-bsh.title" = "AsIs"; -/* Class = "NSMenuItem"; title = "AsIs"; ObjectID = "LX1-ye-51i"; */ -"LX1-ye-51i.title" = "AsIs"; +/* Class = "NSTextFieldCell"; title = "Custom Rule JSON Text"; ObjectID = "Q0v-Ic-TRt"; */ +"Q0v-Ic-TRt.title" = "自定义路由 json 内容"; -/* Class = "NSButtonCell"; title = "load default"; ObjectID = "RSN-g5-vmP"; */ -"RSN-g5-vmP.title" = "load default"; +/* Class = "NSTextFieldCell"; title = "Domain Strategy:"; ObjectID = "Qp3-K0-xA9"; */ +"Qp3-K0-xA9.title" = "域名策略:"; -/* Class = "NSTextFieldCell"; title = "* Set the rules line by line: domain or ip"; ObjectID = "ccq-gn-C6Z"; */ -"ccq-gn-C6Z.title" = "*按行设置域名或ip"; +/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "YQ1-7i-YOl"; */ +"YQ1-7i-YOl.title" = ""; -/* Class = "NSTabViewItem"; label = "Block"; ObjectID = "nsT-BW-R2Z"; */ -"nsT-BW-R2Z.label" = "阻止ip或域名"; +/* Class = "NSTextFieldCell"; title = "Proxy:"; ObjectID = "cfS-8I-8Au"; */ +"cfS-8I-8Au.title" = "代理ip或域名:"; -/* Class = "NSTabViewItem"; label = "Proxy"; ObjectID = "pnL-Z8-fIK"; */ -"pnL-Z8-fIK.label" = "代理ip或域名"; +/* Class = "NSMenuItem"; title = "IPIfNonMatch"; ObjectID = "dSb-GT-n2n"; */ +"dSb-GT-n2n.title" = "IPIfNonMatch"; -/* Class = "NSTabViewItem"; label = "Direct"; ObjectID = "yc0-Po-cG1"; */ -"yc0-Po-cG1.label" = "直连ip或域名"; +/* Class = "NSTextFieldCell"; title = "like: { \"domainStrategy\": \"IPOnDemand\", \"rules\": []}"; ObjectID = "ejH-X7-8Fb"; */ +"ejH-X7-8Fb.title" = "例如: { \"domainStrategy\": \"IPOnDemand\", \"rules\": []}"; -/* Class = "NSMenuItem"; title = "Global"; ObjectID = "zLf-pT-xlm"; */ -"zLf-pT-xlm.title" = "全局"; +/* Class = "NSTextFieldCell"; title = "* Set the rules line by line: domain or ip"; ObjectID = "ymo-ds-No9"; */ +"ymo-ds-No9.title" = "* 按行设置域名或ip"; diff --git a/xray-core/go.mod b/xray-core/go.mod index 31b32a8d4e..4de34e82e0 100644 --- a/xray-core/go.mod +++ b/xray-core/go.mod @@ -25,7 +25,7 @@ require ( golang.org/x/crypto v0.24.0 golang.org/x/net v0.26.0 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.21.0 + golang.org/x/sys v0.22.0 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 diff --git a/xray-core/go.sum b/xray-core/go.sum index 60e11526c4..ab32e8d78e 100644 --- a/xray-core/go.sum +++ b/xray-core/go.sum @@ -226,8 +226,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/youtube-dl/youtube_dl/extractor/yandexmusic.py b/youtube-dl/youtube_dl/extractor/yandexmusic.py index 84969f8e11..55d4fb5a01 100644 --- a/youtube-dl/youtube_dl/extractor/yandexmusic.py +++ b/youtube-dl/youtube_dl/extractor/yandexmusic.py @@ -120,6 +120,7 @@ class YandexMusicTrackIE(YandexMusicBaseIE): download_data = self._download_json( 'https://music.yandex.ru/api/v2.1/handlers/track/%s:%s/web-album_track-track-track-main/download/m' % (track_id, album_id), track_id, 'Downloading track location url JSON', + query={'hq': 1}, headers={'X-Retpath-Y': url}) fd_data = self._download_json( diff --git a/yt-dlp/yt_dlp/extractor/_extractors.py b/yt-dlp/yt_dlp/extractor/_extractors.py index 7f6507defd..34dea79ef9 100644 --- a/yt-dlp/yt_dlp/extractor/_extractors.py +++ b/yt-dlp/yt_dlp/extractor/_extractors.py @@ -2324,6 +2324,7 @@ from .vidio import ( ) from .vidlii import VidLiiIE from .vidly import VidlyIE +from .vidyard import VidyardIE from .viewlift import ( ViewLiftEmbedIE, ViewLiftIE, diff --git a/yt-dlp/yt_dlp/extractor/abematv.py b/yt-dlp/yt_dlp/extractor/abematv.py index 293a6c40e0..9471df1da9 100644 --- a/yt-dlp/yt_dlp/extractor/abematv.py +++ b/yt-dlp/yt_dlp/extractor/abematv.py @@ -368,6 +368,7 @@ class AbemaTVIE(AbemaTVBaseIE): info['episode_number'] = epis if epis < 2000 else None is_live, m3u8_url = False, None + availability = 'public' if video_type == 'now-on-air': is_live = True channel_url = 'https://api.abema.io/v1/channels' @@ -389,6 +390,7 @@ class AbemaTVIE(AbemaTVBaseIE): if 3 not in ondemand_types: # cannot acquire decryption key for these streams self.report_warning('This is a premium-only stream') + availability = 'premium_only' info.update(traverse_obj(api_response, { 'series': ('series', 'title'), 'season': ('season', 'name'), @@ -408,6 +410,7 @@ class AbemaTVIE(AbemaTVBaseIE): headers=headers) if not traverse_obj(api_response, ('slot', 'flags', 'timeshiftFree'), default=False): self.report_warning('This is a premium-only stream') + availability = 'premium_only' m3u8_url = f'https://vod-abematv.akamaized.net/slot/{video_id}/playlist.m3u8' else: @@ -425,6 +428,7 @@ class AbemaTVIE(AbemaTVBaseIE): 'description': description, 'formats': formats, 'is_live': is_live, + 'availability': availability, }) return info diff --git a/yt-dlp/yt_dlp/extractor/cellebrite.py b/yt-dlp/yt_dlp/extractor/cellebrite.py index e90365a8be..54367c4d52 100644 --- a/yt-dlp/yt_dlp/extractor/cellebrite.py +++ b/yt-dlp/yt_dlp/extractor/cellebrite.py @@ -1,63 +1,50 @@ -from .common import InfoExtractor -from ..utils import traverse_obj +from .vidyard import VidyardBaseIE, VidyardIE +from ..utils import ExtractorError, make_archive_id, url_basename -class CellebriteIE(InfoExtractor): +class CellebriteIE(VidyardBaseIE): _VALID_URL = r'https?://cellebrite\.com/(?:\w+)?/(?P[\w-]+)' _TESTS = [{ 'url': 'https://cellebrite.com/en/collect-data-from-android-devices-with-cellebrite-ufed/', 'info_dict': { - 'id': '16025876', + 'id': 'ZqmUss3dQfEMGpauambPuH', + 'display_id': '16025876', 'ext': 'mp4', - 'description': 'md5:174571cb97083fd1d457d75c684f4e2b', - 'thumbnail': 'https://cellebrite.com/wp-content/uploads/2021/05/Chat-Capture-1024x559.png', 'title': 'Ask the Expert: Chat Capture - Collect Data from Android Devices in Cellebrite UFED', - 'duration': 455, - 'tags': [], + 'description': 'md5:dee48fe12bbae5c01fe6a053f7676da4', + 'thumbnail': 'https://cellebrite.com/wp-content/uploads/2021/05/Chat-Capture-1024x559.png', + 'duration': 455.979, + '_old_archive_ids': ['cellebrite 16025876'], }, }, { 'url': 'https://cellebrite.com/en/how-to-lawfully-collect-the-maximum-amount-of-data-from-android-devices/', 'info_dict': { - 'id': '29018255', + 'id': 'QV1U8a2yzcxigw7VFnqKyg', + 'display_id': '29018255', 'ext': 'mp4', - 'duration': 134, - 'tags': [], - 'description': 'md5:e9a3d124c7287b0b07bad2547061cacf', + 'title': 'How to Lawfully Collect the Maximum Amount of Data From Android Devices', + 'description': 'md5:0e943a9ac14c374d5d74faed634d773c', 'thumbnail': 'https://cellebrite.com/wp-content/uploads/2022/07/How-to-Lawfully-Collect-the-Maximum-Amount-of-Data-From-Android-Devices.png', - 'title': 'Android Extractions Explained', + 'duration': 134.315, + '_old_archive_ids': ['cellebrite 29018255'], }, }] - def _get_formats_and_subtitles(self, json_data, display_id): - formats = [{'url': url} for url in traverse_obj(json_data, ('mp4', ..., 'url')) or []] - subtitles = {} - - for url in traverse_obj(json_data, ('hls', ..., 'url')) or []: - fmt, sub = self._extract_m3u8_formats_and_subtitles( - url, display_id, ext='mp4', headers={'Referer': 'https://play.vidyard.com/'}) - formats.extend(fmt) - self._merge_subtitles(sub, target=subtitles) - - return formats, subtitles - def _real_extract(self, url): - display_id = self._match_id(url) - webpage = self._download_webpage(url, display_id) + slug = self._match_id(url) + webpage = self._download_webpage(url, slug) + vidyard_url = next(VidyardIE._extract_embed_urls(url, webpage), None) + if not vidyard_url: + raise ExtractorError('No Vidyard video embeds found on page') - player_uuid = self._search_regex( - r']*\bdata-uuid\s*=\s*"([^"\?]+)', webpage, 'player UUID') - json_data = self._download_json( - f'https://play.vidyard.com/player/{player_uuid}.json', display_id)['payload']['chapters'][0] + video_id = url_basename(vidyard_url) + info = self._process_video_json(self._fetch_video_json(video_id)['chapters'][0], video_id) + if info.get('display_id'): + info['_old_archive_ids'] = [make_archive_id(self, info['display_id'])] + if thumbnail := self._og_search_thumbnail(webpage, default=None): + info.setdefault('thumbnails', []).append({'url': thumbnail}) - formats, subtitles = self._get_formats_and_subtitles(json_data['sources'], display_id) return { - 'id': str(json_data['videoId']), - 'title': json_data.get('name') or self._og_search_title(webpage), - 'formats': formats, - 'subtitles': subtitles, - 'description': json_data.get('description') or self._og_search_description(webpage), - 'duration': json_data.get('seconds'), - 'tags': json_data.get('tags'), - 'thumbnail': self._og_search_thumbnail(webpage), - 'http_headers': {'Referer': 'https://play.vidyard.com/'}, + 'description': self._og_search_description(webpage, default=None), + **info, } diff --git a/yt-dlp/yt_dlp/extractor/chzzk.py b/yt-dlp/yt_dlp/extractor/chzzk.py index 420fe0514b..e0b9980afd 100644 --- a/yt-dlp/yt_dlp/extractor/chzzk.py +++ b/yt-dlp/yt_dlp/extractor/chzzk.py @@ -36,7 +36,7 @@ class CHZZKLiveIE(InfoExtractor): def _real_extract(self, url): channel_id = self._match_id(url) live_detail = self._download_json( - f'https://api.chzzk.naver.com/service/v2/channels/{channel_id}/live-detail', channel_id, + f'https://api.chzzk.naver.com/service/v3/channels/{channel_id}/live-detail', channel_id, note='Downloading channel info', errnote='Unable to download channel info')['content'] if live_detail.get('status') == 'CLOSE': @@ -106,12 +106,45 @@ class CHZZKVideoIE(InfoExtractor): 'upload_date': '20231219', 'view_count': int, }, + 'skip': 'Replay video is expired', + }, { + # Manually uploaded video + 'url': 'https://chzzk.naver.com/video/1980', + 'info_dict': { + 'id': '1980', + 'ext': 'mp4', + 'title': '※시청주의※한번보면 잊기 힘든 영상', + 'channel': '라디유radiyu', + 'channel_id': '68f895c59a1043bc5019b5e08c83a5c5', + 'channel_is_verified': False, + 'thumbnail': r're:^https?://.*\.jpg$', + 'duration': 95, + 'timestamp': 1703102631.722, + 'upload_date': '20231220', + 'view_count': int, + }, + }, { + # Partner channel replay video + 'url': 'https://chzzk.naver.com/video/2458', + 'info_dict': { + 'id': '2458', + 'ext': 'mp4', + 'title': '첫 방송', + 'channel': '강지', + 'channel_id': 'b5ed5db484d04faf4d150aedd362f34b', + 'channel_is_verified': True, + 'thumbnail': r're:^https?://.*\.jpg$', + 'duration': 4433, + 'timestamp': 1703307460.214, + 'upload_date': '20231223', + 'view_count': int, + }, }] def _real_extract(self, url): video_id = self._match_id(url) video_meta = self._download_json( - f'https://api.chzzk.naver.com/service/v2/videos/{video_id}', video_id, + f'https://api.chzzk.naver.com/service/v3/videos/{video_id}', video_id, note='Downloading video info', errnote='Unable to download video info')['content'] formats, subtitles = self._extract_mpd_formats_and_subtitles( f'https://apis.naver.com/neonplayer/vodplay/v1/playback/{video_meta["videoId"]}', video_id, diff --git a/yt-dlp/yt_dlp/extractor/swearnet.py b/yt-dlp/yt_dlp/extractor/swearnet.py index b4835c5adc..2d6fb3eb47 100644 --- a/yt-dlp/yt_dlp/extractor/swearnet.py +++ b/yt-dlp/yt_dlp/extractor/swearnet.py @@ -1,55 +1,31 @@ -from .common import InfoExtractor -from ..utils import ExtractorError, int_or_none, traverse_obj +from .vidyard import VidyardBaseIE +from ..utils import ExtractorError, int_or_none, make_archive_id -class SwearnetEpisodeIE(InfoExtractor): +class SwearnetEpisodeIE(VidyardBaseIE): _VALID_URL = r'https?://www\.swearnet\.com/shows/(?P[\w-]+)/seasons/(?P\d+)/episodes/(?P\d+)' _TESTS = [{ 'url': 'https://www.swearnet.com/shows/gettin-learnt-with-ricky/seasons/1/episodes/1', 'info_dict': { - 'id': '232819', + 'id': 'wicK2EOzjOdxkUXGDIgcPw', + 'display_id': '232819', 'ext': 'mp4', 'episode_number': 1, 'episode': 'Episode 1', 'duration': 719, - 'description': 'md5:c48ef71440ce466284c07085cd7bd761', + 'description': r're:Are you drunk and high and craving a grilled cheese sandwich.+', 'season': 'Season 1', 'title': 'Episode 1 - Grilled Cheese Sammich', 'season_number': 1, - 'thumbnail': 'https://cdn.vidyard.com/thumbnails/232819/_RX04IKIq60a2V6rIRqq_Q_small.jpg', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/custom/0dd74f9b-388a-452e-b570-b407fb64435b_small.jpg', + 'tags': ['Getting Learnt with Ricky', 'drunk', 'grilled cheese', 'high'], + '_old_archive_ids': ['swearnetepisode 232819'], }, }] - def _get_formats_and_subtitle(self, video_source, video_id): - video_source = video_source or {} - formats, subtitles = [], {} - for key, value in video_source.items(): - if key == 'hls': - for video_hls in value: - fmts, subs = self._extract_m3u8_formats_and_subtitles(video_hls.get('url'), video_id) - formats.extend(fmts) - self._merge_subtitles(subs, target=subtitles) - else: - formats.extend({ - 'url': video_mp4.get('url'), - 'ext': 'mp4', - } for video_mp4 in value) - - return formats, subtitles - - def _get_direct_subtitle(self, caption_json): - subs = {} - for caption in caption_json: - subs.setdefault(caption.get('language') or 'und', []).append({ - 'url': caption.get('vttUrl'), - 'name': caption.get('name'), - }) - - return subs - def _real_extract(self, url): - display_id, season_number, episode_number = self._match_valid_url(url).group('id', 'season_num', 'episode_num') - webpage = self._download_webpage(url, display_id) + slug, season_number, episode_number = self._match_valid_url(url).group('id', 'season_num', 'episode_num') + webpage = self._download_webpage(url, slug) try: external_id = self._search_regex(r'externalid\s*=\s*"([^"]+)', webpage, 'externalid') @@ -58,22 +34,12 @@ class SwearnetEpisodeIE(InfoExtractor): self.raise_login_required() raise - json_data = self._download_json( - f'https://play.vidyard.com/player/{external_id}.json', display_id)['payload']['chapters'][0] - - formats, subtitles = self._get_formats_and_subtitle(json_data['sources'], display_id) - self._merge_subtitles(self._get_direct_subtitle(json_data.get('captions')), target=subtitles) + info = self._process_video_json(self._fetch_video_json(external_id)['chapters'][0], external_id) + if info.get('display_id'): + info['_old_archive_ids'] = [make_archive_id(self, info['display_id'])] return { - 'id': str(json_data['videoId']), - 'title': json_data.get('name') or self._html_search_meta(['og:title', 'twitter:title'], webpage), - 'description': (json_data.get('description') - or self._html_search_meta(['og:description', 'twitter:description'], webpage)), - 'duration': int_or_none(json_data.get('seconds')), - 'formats': formats, - 'subtitles': subtitles, + **info, 'season_number': int_or_none(season_number), 'episode_number': int_or_none(episode_number), - 'thumbnails': [{'url': thumbnail_url} - for thumbnail_url in traverse_obj(json_data, ('thumbnailUrls', ...))], } diff --git a/yt-dlp/yt_dlp/extractor/vidyard.py b/yt-dlp/yt_dlp/extractor/vidyard.py new file mode 100644 index 0000000000..20a54b1618 --- /dev/null +++ b/yt-dlp/yt_dlp/extractor/vidyard.py @@ -0,0 +1,426 @@ +import functools +import re + +from .common import InfoExtractor +from ..utils import ( + extract_attributes, + float_or_none, + int_or_none, + join_nonempty, + mimetype2ext, + parse_resolution, + str_or_none, + unescapeHTML, + url_or_none, +) +from ..utils.traversal import traverse_obj + + +class VidyardBaseIE(InfoExtractor): + _HEADERS = {'Referer': 'https://play.vidyard.com/'} + + def _get_formats_and_subtitles(self, sources, video_id): + formats, subtitles = [], {} + + def add_hls_fmts_and_subs(m3u8_url): + fmts, subs = self._extract_m3u8_formats_and_subtitles( + m3u8_url, video_id, 'mp4', m3u8_id='hls', headers=self._HEADERS, fatal=False) + formats.extend(fmts) + self._merge_subtitles(subs, target=subtitles) + + hls_list = isinstance(sources, dict) and sources.pop('hls', None) + if master_m3u8_url := traverse_obj( + hls_list, (lambda _, v: v['profile'] == 'auto', 'url', {url_or_none}, any)): + add_hls_fmts_and_subs(master_m3u8_url) + if not formats: # These are duplicate and unnecesary requests if we got 'auto' hls fmts + for variant_m3u8_url in traverse_obj(hls_list, (..., 'url', {url_or_none})): + add_hls_fmts_and_subs(variant_m3u8_url) + + for source_type, source_list in traverse_obj(sources, ({dict.items}, ...)): + for source in traverse_obj(source_list, lambda _, v: url_or_none(v['url'])): + profile = source.get('profile') + formats.append({ + 'url': source['url'], + 'ext': mimetype2ext(source.get('mimeType'), default=None), + 'format_id': join_nonempty('http', source_type, profile), + **parse_resolution(profile), + }) + + self._remove_duplicate_formats(formats) + return formats, subtitles + + def _get_direct_subtitles(self, caption_json): + subs = {} + for caption in traverse_obj(caption_json, lambda _, v: url_or_none(v['vttUrl'])): + subs.setdefault(caption.get('language') or 'und', []).append({ + 'url': caption['vttUrl'], + 'name': caption.get('name'), + }) + + return subs + + def _fetch_video_json(self, video_id): + return self._download_json( + f'https://play.vidyard.com/player/{video_id}.json', video_id)['payload'] + + def _process_video_json(self, json_data, video_id): + formats, subtitles = self._get_formats_and_subtitles(json_data['sources'], video_id) + self._merge_subtitles(self._get_direct_subtitles(json_data.get('captions')), target=subtitles) + + return { + **traverse_obj(json_data, { + 'id': ('facadeUuid', {str}), + 'display_id': ('videoId', {int}, {str_or_none}), + 'title': ('name', {str}), + 'description': ('description', {str}, {unescapeHTML}, {lambda x: x or None}), + 'duration': (( + ('milliseconds', {functools.partial(float_or_none, scale=1000)}), + ('seconds', {int_or_none})), any), + 'thumbnails': ('thumbnailUrls', ('small', 'normal'), {'url': {url_or_none}}), + 'tags': ('tags', ..., 'name', {str}), + }), + 'formats': formats, + 'subtitles': subtitles, + 'http_headers': self._HEADERS, + } + + +class VidyardIE(VidyardBaseIE): + _VALID_URL = [ + r'https?://[\w-]+(?:\.hubs)?\.vidyard\.com/watch/(?P[\w-]+)', + r'https?://(?:embed|share)\.vidyard\.com/share/(?P[\w-]+)', + r'https?://play\.vidyard\.com/(?:player/)?(?P[\w-]+)', + ] + _EMBED_REGEX = [r']* src=["\'](?P(?:https?:)?//play\.vidyard\.com/[\w-]+)'] + _TESTS = [{ + 'url': 'https://vyexample03.hubs.vidyard.com/watch/oTDMPlUv--51Th455G5u7Q', + 'info_dict': { + 'id': 'oTDMPlUv--51Th455G5u7Q', + 'display_id': '50347', + 'ext': 'mp4', + 'title': 'Homepage Video', + 'description': 'Look I changed the description.', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/50347/OUPa5LTKV46849sLYngMqQ_small.jpg', + 'duration': 99, + 'tags': ['these', 'are', 'all', 'tags'], + }, + }, { + 'url': 'https://share.vidyard.com/watch/PaQzDAT1h8JqB8ivEu2j6Y?', + 'info_dict': { + 'id': 'PaQzDAT1h8JqB8ivEu2j6Y', + 'display_id': '9281024', + 'ext': 'mp4', + 'title': 'Inline Embed', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/spacer.gif', + 'duration': 41.186, + }, + }, { + 'url': 'https://embed.vidyard.com/share/oTDMPlUv--51Th455G5u7Q', + 'info_dict': { + 'id': 'oTDMPlUv--51Th455G5u7Q', + 'display_id': '50347', + 'ext': 'mp4', + 'title': 'Homepage Video', + 'description': 'Look I changed the description.', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/50347/OUPa5LTKV46849sLYngMqQ_small.jpg', + 'duration': 99, + 'tags': ['these', 'are', 'all', 'tags'], + }, + }, { + # First video from playlist below + 'url': 'https://embed.vidyard.com/share/SyStyHtYujcBHe5PkZc5DL', + 'info_dict': { + 'id': 'SyStyHtYujcBHe5PkZc5DL', + 'display_id': '41974005', + 'ext': 'mp4', + 'title': 'Prepare the Frame and Track for Palm Beach Polysatin Shutters With BiFold Track', + 'description': r're:In this video, you will learn how to prepare the frame.+', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/41974005/IJw7oCaJcF1h7WWu3OVZ8A_small.png', + 'duration': 258.666, + }, + }, { + # Playlist + 'url': 'https://thelink.hubs.vidyard.com/watch/pwu7pCYWSwAnPxs8nDoFrE', + 'info_dict': { + 'id': 'pwu7pCYWSwAnPxs8nDoFrE', + 'title': 'PLAYLIST - Palm Beach Shutters- Bi-Fold Track System Installation', + 'entries': [{ + 'id': 'SyStyHtYujcBHe5PkZc5DL', + 'display_id': '41974005', + 'ext': 'mp4', + 'title': 'Prepare the Frame and Track for Palm Beach Polysatin Shutters With BiFold Track', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/41974005/IJw7oCaJcF1h7WWu3OVZ8A_small.png', + 'duration': 258.666, + }, { + 'id': '1Fw4B84jZTXLXWqkE71RiM', + 'display_id': '5861113', + 'ext': 'mp4', + 'title': 'Palm Beach - Bi-Fold Track System "Frame Installation"', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/5861113/29CJ54s5g1_aP38zkKLHew_small.jpg', + 'duration': 167.858, + }, { + 'id': 'DqP3wBvLXSpxrcqpT5kEeo', + 'display_id': '41976334', + 'ext': 'mp4', + 'title': 'Install the Track for Palm Beach Polysatin Shutters With BiFold Track', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/5861090/RwG2VaTylUa6KhSTED1r1Q_small.png', + 'duration': 94.229, + }, { + 'id': 'opfybfxpzQArxqtQYB6oBU', + 'display_id': '41976364', + 'ext': 'mp4', + 'title': 'Install the Panel for Palm Beach Polysatin Shutters With BiFold Track', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/5860926/JIOaJR08dM4QgXi_iQ2zGA_small.png', + 'duration': 191.467, + }, { + 'id': 'rWrXvkbTNNaNqD6189HJya', + 'display_id': '41976382', + 'ext': 'mp4', + 'title': 'Adjust the Panels for Palm Beach Polysatin Shutters With BiFold Track', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/5860687/CwHxBv4UudAhOh43FVB4tw_small.png', + 'duration': 138.155, + }, { + 'id': 'eYPTB521MZ9TPEArSethQ5', + 'display_id': '41976409', + 'ext': 'mp4', + 'title': 'Assemble and Install the Valance for Palm Beach Polysatin Shutters With BiFold Track', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/5861425/0y68qlMU4O5VKU7bJ8i_AA_small.png', + 'duration': 148.224, + }], + }, + 'playlist_count': 6, + }, { + # Non hubs.vidyard.com playlist + 'url': 'https://salesforce.vidyard.com/watch/d4vqPjs7Q5EzVEis5QT3jd', + 'info_dict': { + 'id': 'd4vqPjs7Q5EzVEis5QT3jd', + 'title': 'How To: Service Cloud: Import External Content in Lightning Knowledge', + 'entries': [{ + 'id': 'mcjDpSZir2iSttbvFkx6Rv', + 'display_id': '29479036', + 'ext': 'mp4', + 'title': 'Welcome to this Expert Coaching Series', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/ouyQi9WuwyiOupChUWNmjQ/7170d3485ba602e012df05_small.jpg', + 'duration': 38.205, + }, { + 'id': '84bPYwpg243G6xYEfJdYw9', + 'display_id': '21820704', + 'ext': 'mp4', + 'title': 'Chapter 1 - Title + Agenda', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/HFPN0ZgQq4Ow8BghGcQSow/bfaa30123c8f6601e7d7f2_small.jpg', + 'duration': 98.016, + }, { + 'id': 'nP17fMuvA66buVHUrzqjTi', + 'display_id': '21820707', + 'ext': 'mp4', + 'title': 'Chapter 2 - Import Options', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/rGRIF5nFjPI9OOA2qJ_Dbg/86a8d02bfec9a566845dd4_small.jpg', + 'duration': 199.136, + }, { + 'id': 'm54EcwXdpA5gDBH5rgCYoV', + 'display_id': '21820710', + 'ext': 'mp4', + 'title': 'Chapter 3 - Importing Article Translations', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/IVX4XR8zpSsiNIHx45kz-A/1ccbf8a29a33856d06b3ed_small.jpg', + 'duration': 184.352, + }, { + 'id': 'j4nzS42oq4hE9oRV73w3eQ', + 'display_id': '21820716', + 'ext': 'mp4', + 'title': 'Chapter 4 - Best Practices', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/BtrRrQpRDLbA4AT95YQyog/1f1e6b8e7fdc3fa95ec8d3_small.jpg', + 'duration': 296.960, + }, { + 'id': 'y28PYfW5pftvers9PXzisC', + 'display_id': '21820727', + 'ext': 'mp4', + 'title': 'Chapter 5 - Migration Steps', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/K2CdQOXDfLcrVTF60r0bdw/a09239ada28b6ffce12b1f_small.jpg', + 'duration': 620.640, + }, { + 'id': 'YWU1eQxYvhj29SjYoPw5jH', + 'display_id': '21820733', + 'ext': 'mp4', + 'title': 'Chapter 6 - Demo', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/rsmhP-cO8dAa8ilvFGCX0g/7911ef415167cd14032068_small.jpg', + 'duration': 631.456, + }, { + 'id': 'nmEvVqpwdJUgb74zKsLGxn', + 'display_id': '29479037', + 'ext': 'mp4', + 'title': 'Schedule Your Follow-Up', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/Rtwc7X4PEkF4Ae5kHi-Jvw/174ebed3f34227b1ffa1d0_small.jpg', + 'duration': 33.608, + }], + }, + 'playlist_count': 8, + }, { + # URL of iframe embed src + 'url': 'https://play.vidyard.com/iDqTwWGrd36vaLuaCY3nTs.html', + 'info_dict': { + 'id': 'iDqTwWGrd36vaLuaCY3nTs', + 'display_id': '9281009', + 'ext': 'mp4', + 'title': 'Lightbox Embed', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/spacer.gif', + 'duration': 39.035, + }, + }, { + # Player JSON URL + 'url': 'https://play.vidyard.com/player/7GAApnNNbcZZ46k6JqJQSh.json?disable_analytics=0', + 'info_dict': { + 'id': '7GAApnNNbcZZ46k6JqJQSh', + 'display_id': '820026', + 'ext': 'mp4', + 'title': 'The Art of Storytelling: How to Deliver Your Brand Story with Content & Social', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/MhbE-5sEFQu4x3fI6FkNlA/41eb5717c557cd19456910_small.jpg', + 'duration': 2153.013, + 'tags': ['Summit2017'], + }, + }, { + 'url': 'http://share.vidyard.com/share/diYeo6YR2yiGgL8odvS8Ri', + 'only_matching': True, + }, { + 'url': 'https://play.vidyard.com/FFlz3ZpxhIfKQ1fd9DAryA', + 'only_matching': True, + }, { + 'url': 'https://play.vidyard.com/qhMAu5A76GZVrFzOPgSf9A/type/standalone', + 'only_matching': True, + }] + _WEBPAGE_TESTS = [{ + # URL containing inline/lightbox embedded video + 'url': 'https://resources.altium.com/p/2-the-extreme-importance-of-pc-board-stack-up', + 'info_dict': { + 'id': 'GDx1oXrFWj4XHbipfoXaMn', + 'display_id': '3225198', + 'ext': 'mp4', + 'title': 'The Extreme Importance of PC Board Stack Up', + 'thumbnail': 'https://cdn.vidyard.com/thumbnails/73_Q3_hBexWX7Og1sae6cg/9998fa4faec921439e2c04_small.jpg', + 'duration': 3422.742, + }, + }, { + #