Update On Mon Jul 15 20:32:26 CEST 2024

This commit is contained in:
github-action[bot]
2024-07-15 20:32:26 +02:00
parent 5375a8745d
commit bdc5abca14
57 changed files with 1214 additions and 1210 deletions

1
.github/update.log vendored
View File

@@ -703,3 +703,4 @@ Update On Thu Jul 11 20:30:51 CEST 2024
Update On Fri Jul 12 20:34:05 CEST 2024 Update On Fri Jul 12 20:34:05 CEST 2024
Update On Sat Jul 13 20:28:46 CEST 2024 Update On Sat Jul 13 20:28:46 CEST 2024
Update On Sun Jul 14 20:40:18 CEST 2024 Update On Sun Jul 14 20:40:18 CEST 2024
Update On Mon Jul 15 20:32:15 CEST 2024

View File

@@ -69,7 +69,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
} }
if groupOption.IncludeAllProviders { if groupOption.IncludeAllProviders {
groupOption.Use = append(groupOption.Use, AllProviders...) groupOption.Use = AllProviders
} }
if groupOption.IncludeAllProxies { if groupOption.IncludeAllProxies {
if groupOption.Filter != "" { if groupOption.Filter != "" {

View File

@@ -1779,9 +1779,9 @@ dependencies = [
[[package]] [[package]]
name = "fast_image_resize" name = "fast_image_resize"
version = "4.0.0" version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02abb58c39fa9b20678cedabab49e6c4f6ecb7480d7cb5711496b9289184a875" checksum = "89a06940fe3bab6e93dc275bb8a67cc833b70f4078124e7e7f7352f5c8470e63"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"document-features", "document-features",

View File

@@ -108,7 +108,7 @@
}, },
"windows": [], "windows": [],
"security": { "security": {
"csp": "script-src 'unsafe-eval' 'self'; default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self'; img-src data: 'self' https:;" "csp": "script-src 'unsafe-eval' 'self'; default-src 'self' blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' http: https:;"
} }
} }
} }

View File

@@ -258,12 +258,23 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
submit-to-winget: submit-to-winget:
runs-on: windows-latest runs-on: ubuntu-latest
needs: [release-update] needs: [release-update]
steps: steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get Version
run: |
sudo apt-get update
sudo apt-get install jq
echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
- name: Submit to Winget - name: Submit to Winget
uses: vedantmgoyal9/winget-releaser@main uses: vedantmgoyal9/winget-releaser@main
with: with:
identifier: ClashVergeRev.ClashVergeRev identifier: ClashVergeRev.ClashVergeRev
version: ${{env.VERSION}}
release-tag: v${{env.VERSION}}
installers-regex: '_(arm64|x64|x86)-setup\.exe$' installers-regex: '_(arm64|x64|x86)-setup\.exe$'
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.WINGET_TOKEN }}

View File

@@ -1,3 +1,28 @@
## v1.7.5
### Features
- 展示局域网 IP 地址信息
- 在设置页面直接复制环境变量
- 优化服务模式安装逻辑
### Performance
- 优化切换订阅速度
- 优化更改端口速度
### Bugs Fixes
- 调整 MacOS 托盘图标大小
- Trojan URI 解析错误
- 卡片拖动显示层级错误
- 代理绕过格式检查错误
- MacOS 下编辑器最大化失败
- MacOS 服务安装失败
- 更改窗口大小导致闪退的问题
---
## v1.7.3 ## v1.7.3
### Features ### Features

View File

@@ -1,6 +1,6 @@
{ {
"name": "clash-verge", "name": "clash-verge",
"version": "1.7.3", "version": "1.7.5",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
"scripts": { "scripts": {
"dev": "tauri dev", "dev": "tauri dev",

View File

@@ -790,7 +790,7 @@ dependencies = [
[[package]] [[package]]
name = "clash-verge" name = "clash-verge"
version = "1.7.3" version = "1.7.5"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"auto-launch", "auto-launch",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "clash-verge" name = "clash-verge"
version = "1.7.3" version = "1.7.5"
description = "clash verge" description = "clash verge"
authors = ["zzzgydi", "wonfen", "MystiPanda"] authors = ["zzzgydi", "wonfen", "MystiPanda"]
license = "GPL-3.0-only" license = "GPL-3.0-only"

View File

@@ -191,11 +191,15 @@ pub fn init_config() -> Result<()> {
/// after tauri setup /// after tauri setup
pub fn init_resources() -> Result<()> { pub fn init_resources() -> Result<()> {
let app_dir = dirs::app_home_dir()?; let app_dir = dirs::app_home_dir()?;
let test_dir = app_dir.join("test");
let res_dir = dirs::app_resources_dir()?; let res_dir = dirs::app_resources_dir()?;
if !app_dir.exists() { if !app_dir.exists() {
let _ = fs::create_dir_all(&app_dir); let _ = fs::create_dir_all(&app_dir);
} }
if !test_dir.exists() {
let _ = fs::create_dir_all(&test_dir);
}
if !res_dir.exists() { if !res_dir.exists() {
let _ = fs::create_dir_all(&res_dir); let _ = fs::create_dir_all(&res_dir);
} }
@@ -210,9 +214,10 @@ pub fn init_resources() -> Result<()> {
for file in file_list.iter() { for file in file_list.iter() {
let src_path = res_dir.join(file); let src_path = res_dir.join(file);
let dest_path = app_dir.join(file); let dest_path = app_dir.join(file);
let test_dest_path = test_dir.join(file);
let handle_copy = || { let handle_copy = |dest: &PathBuf| {
match fs::copy(&src_path, &dest_path) { match fs::copy(&src_path, dest) {
Ok(_) => log::debug!(target: "app", "resources copied '{file}'"), Ok(_) => log::debug!(target: "app", "resources copied '{file}'"),
Err(err) => { Err(err) => {
log::error!(target: "app", "failed to copy resources '{file}', {err}") log::error!(target: "app", "failed to copy resources '{file}', {err}")
@@ -220,8 +225,11 @@ pub fn init_resources() -> Result<()> {
}; };
}; };
if src_path.exists() && !test_dest_path.exists() {
handle_copy(&test_dest_path);
}
if src_path.exists() && !dest_path.exists() { if src_path.exists() && !dest_path.exists() {
handle_copy(); handle_copy(&dest_path);
continue; continue;
} }
@@ -231,14 +239,14 @@ pub fn init_resources() -> Result<()> {
match (src_modified, dest_modified) { match (src_modified, dest_modified) {
(Ok(src_modified), Ok(dest_modified)) => { (Ok(src_modified), Ok(dest_modified)) => {
if src_modified > dest_modified { if src_modified > dest_modified {
handle_copy(); handle_copy(&dest_path);
} else { } else {
log::debug!(target: "app", "skipping resource copy '{file}'"); log::debug!(target: "app", "skipping resource copy '{file}'");
} }
} }
_ => { _ => {
log::debug!(target: "app", "failed to get modified '{file}'"); log::debug!(target: "app", "failed to get modified '{file}'");
handle_copy(); handle_copy(&dest_path);
} }
}; };
} }

View File

@@ -2,7 +2,7 @@
"$schema": "../node_modules/@tauri-apps/cli/schema.json", "$schema": "../node_modules/@tauri-apps/cli/schema.json",
"package": { "package": {
"productName": "Clash Verge", "productName": "Clash Verge",
"version": "1.7.3" "version": "1.7.5"
}, },
"build": { "build": {
"distDir": "../dist", "distDir": "../dist",

View File

@@ -11,6 +11,7 @@ export const Switch = styled((props: SwitchProps) => (
width: 42, width: 42,
height: 26, height: 26,
padding: 0, padding: 0,
marginRight: 1,
"& .MuiSwitch-switchBase": { "& .MuiSwitch-switchBase": {
padding: 0, padding: 0,
margin: 2, margin: 2,

View File

@@ -49,9 +49,8 @@ export const NetworkInterfaceViewer = forwardRef<DialogRef>((props, ref) => {
</Box> </Box>
} }
contentSx={{ width: 450, maxHeight: 330 }} contentSx={{ width: 450, maxHeight: 330 }}
okBtn={t("Save")} disableOk
cancelBtn={t("Cancel")} cancelBtn={t("Close")}
onClose={() => setOpen(false)}
onCancel={() => setOpen(false)} onCancel={() => setOpen(false)}
> >
{networkInterfaces.map((item) => ( {networkInterfaces.map((item) => (

View File

@@ -0,0 +1,97 @@
import { KeyedMutator } from "swr";
import { useState } from "react";
import { useLockFn } from "ahooks";
import { useTranslation } from "react-i18next";
import { installService, uninstallService } from "@/services/cmds";
import { Notice } from "@/components/base";
import { LoadingButton } from "@mui/lab";
interface Props {
status: "active" | "installed" | "unknown" | "uninstall";
mutate: KeyedMutator<"active" | "installed" | "unknown" | "uninstall">;
patchVerge: (value: Partial<IVergeConfig>) => Promise<void>;
onChangeData: (patch: Partial<IVergeConfig>) => void;
}
export const ServiceSwitcher = (props: Props) => {
const { status, mutate, patchVerge, onChangeData } = props;
const isActive = status === "active";
const isInstalled = status === "installed";
const isUninstall = status === "uninstall" || status === "unknown";
const { t } = useTranslation();
const [serviceLoading, setServiceLoading] = useState(false);
const [uninstallServiceLoaing, setUninstallServiceLoading] = useState(false);
const onInstallOrEnableService = useLockFn(async () => {
setServiceLoading(true);
try {
if (isUninstall) {
// install service
await installService();
await mutate();
setTimeout(() => {
mutate();
}, 2000);
Notice.success(t("Service Installed Successfully"));
setServiceLoading(false);
} else {
// enable or disable service
await patchVerge({ enable_service_mode: !isActive });
onChangeData({ enable_service_mode: !isActive });
await mutate();
setTimeout(() => {
mutate();
}, 2000);
setServiceLoading(false);
}
} catch (err: any) {
await mutate();
Notice.error(err.message || err.toString());
setServiceLoading(false);
}
});
const onUninstallService = useLockFn(async () => {
setUninstallServiceLoading(true);
try {
await uninstallService();
await mutate();
setTimeout(() => {
mutate();
}, 2000);
Notice.success(t("Service Uninstalled Successfully"));
setUninstallServiceLoading(false);
} catch (err: any) {
await mutate();
Notice.error(err.message || err.toString());
setUninstallServiceLoading(false);
}
});
return (
<>
<LoadingButton
size="small"
variant={isUninstall ? "outlined" : "contained"}
onClick={onInstallOrEnableService}
loading={serviceLoading}
>
{isActive ? t("Disable") : isInstalled ? t("Enable") : t("Install")}
</LoadingButton>
{isInstalled && (
<LoadingButton
size="small"
variant="outlined"
color="error"
sx={{ ml: 1 }}
onClick={onUninstallService}
loading={uninstallServiceLoaing}
>
{t("Uninstall")}
</LoadingButton>
)}
</>
);
};

View File

@@ -1,129 +0,0 @@
import useSWR from "swr";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useLockFn } from "ahooks";
import { useTranslation } from "react-i18next";
import { Button, Stack, Typography } from "@mui/material";
import {
checkService,
installService,
uninstallService,
patchVergeConfig,
} from "@/services/cmds";
import { BaseDialog, DialogRef, Notice } from "@/components/base";
interface Props {
enable: boolean;
}
export const ServiceViewer = forwardRef<DialogRef, Props>((props, ref) => {
const { enable } = props;
const { t } = useTranslation();
const [open, setOpen] = useState(false);
const { data: status, mutate: mutateCheck } = useSWR(
"checkService",
checkService,
{
revalidateIfStale: false,
shouldRetryOnError: false,
focusThrottleInterval: 36e5, // 1 hour
}
);
useImperativeHandle(ref, () => ({
open: () => setOpen(true),
close: () => setOpen(false),
}));
const state = status != null ? status : "pending";
const onInstall = useLockFn(async () => {
try {
await installService();
await mutateCheck();
setOpen(false);
setTimeout(() => {
mutateCheck();
}, 2000);
Notice.success(t("Service Installed Successfully"));
} catch (err: any) {
mutateCheck();
Notice.error(err.message || err.toString());
}
});
const onUninstall = useLockFn(async () => {
try {
if (enable) {
await patchVergeConfig({ enable_service_mode: false });
}
await uninstallService();
mutateCheck();
setOpen(false);
Notice.success(t("Service Uninstalled Successfully"));
} catch (err: any) {
mutateCheck();
Notice.error(err.message || err.toString());
}
});
// fix unhandled error of the service mode
const onDisable = useLockFn(async () => {
try {
await patchVergeConfig({ enable_service_mode: false });
mutateCheck();
setOpen(false);
} catch (err: any) {
mutateCheck();
Notice.error(err.message || err.toString());
}
});
return (
<BaseDialog
open={open}
title={t("Service Mode")}
contentSx={{ width: 360, userSelect: "text" }}
disableFooter
onClose={() => setOpen(false)}
>
<Typography>
{t("Current State")}: {t(state)}
</Typography>
{(state === "unknown" || state === "uninstall") && (
<Typography>
{t(
"Information: Please make sure that the Clash Verge Service is installed and enabled"
)}
</Typography>
)}
<Stack
direction="row"
spacing={1}
sx={{ mt: 4, justifyContent: "flex-end" }}
>
{state === "uninstall" && enable && (
<Button variant="contained" onClick={onDisable}>
{t("Disable Service Mode")}
</Button>
)}
{state === "uninstall" && (
<Button variant="contained" onClick={onInstall}>
{t("Install")}
</Button>
)}
{(state === "active" || state === "installed") && (
<Button variant="outlined" onClick={onUninstall}>
{t("Uninstall")}
</Button>
)}
</Stack>
</BaseDialog>
);
});

View File

@@ -1,13 +1,13 @@
import useSWR from "swr"; import useSWR from "swr";
import { useRef } from "react"; import { useRef } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { PrivacyTipRounded, SettingsRounded } from "@mui/icons-material"; import { SettingsRounded } from "@mui/icons-material";
import { checkService } from "@/services/cmds"; import { checkService } from "@/services/cmds";
import { useVerge } from "@/hooks/use-verge"; import { useVerge } from "@/hooks/use-verge";
import { DialogRef, Switch } from "@/components/base"; import { DialogRef, Notice, Switch } from "@/components/base";
import { SettingList, SettingItem } from "./mods/setting-comp"; import { SettingList, SettingItem } from "./mods/setting-comp";
import { GuardState } from "./mods/guard-state"; import { GuardState } from "./mods/guard-state";
import { ServiceViewer } from "./mods/service-viewer"; import { ServiceSwitcher } from "./mods/service-switcher";
import { SysproxyViewer } from "./mods/sysproxy-viewer"; import { SysproxyViewer } from "./mods/sysproxy-viewer";
import { TunViewer } from "./mods/tun-viewer"; import { TunViewer } from "./mods/tun-viewer";
import { TooltipIcon } from "@/components/base/base-tooltip-icon"; import { TooltipIcon } from "@/components/base/base-tooltip-icon";
@@ -20,22 +20,23 @@ const SettingSystem = ({ onError }: Props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { verge, mutateVerge, patchVerge } = useVerge(); const { verge, mutateVerge, patchVerge } = useVerge();
// service mode // service mode
const { data: serviceStatus } = useSWR("checkService", checkService, { const { data: serviceStatus, mutate: mutateServiceStatus } = useSWR(
revalidateIfStale: false, "checkService",
shouldRetryOnError: false, checkService,
focusThrottleInterval: 36e5, // 1 hour {
}); revalidateIfStale: false,
shouldRetryOnError: false,
focusThrottleInterval: 36e5, // 1 hour
}
);
const serviceRef = useRef<DialogRef>(null);
const sysproxyRef = useRef<DialogRef>(null); const sysproxyRef = useRef<DialogRef>(null);
const tunRef = useRef<DialogRef>(null); const tunRef = useRef<DialogRef>(null);
const { const {
enable_tun_mode, enable_tun_mode,
enable_auto_launch, enable_auto_launch,
enable_service_mode,
enable_silent_start, enable_silent_start,
enable_system_proxy, enable_system_proxy,
} = verge ?? {}; } = verge ?? {};
@@ -49,7 +50,6 @@ const SettingSystem = ({ onError }: Props) => {
<SettingList title={t("System Setting")}> <SettingList title={t("System Setting")}>
<SysproxyViewer ref={sysproxyRef} /> <SysproxyViewer ref={sysproxyRef} />
<TunViewer ref={tunRef} /> <TunViewer ref={tunRef} />
<ServiceViewer ref={serviceRef} enable={!!enable_service_mode} />
<SettingItem <SettingItem
label={t("Tun Mode")} label={t("Tun Mode")}
@@ -66,38 +66,33 @@ const SettingSystem = ({ onError }: Props) => {
valueProps="checked" valueProps="checked"
onCatch={onError} onCatch={onError}
onFormat={onSwitchFormat} onFormat={onSwitchFormat}
onChange={(e) => onChangeData({ enable_tun_mode: e })} onChange={(e) => {
onGuard={(e) => patchVerge({ enable_tun_mode: e })} if (serviceStatus !== "active") {
onChangeData({ enable_tun_mode: false });
} else {
onChangeData({ enable_tun_mode: e });
}
}}
onGuard={(e) => {
if (serviceStatus !== "active" && e) {
Notice.error(t("Please Enable Service Mode"));
return Promise.resolve();
} else {
return patchVerge({ enable_tun_mode: e });
}
}}
> >
<Switch edge="end" /> <Switch edge="end" />
</GuardState> </GuardState>
</SettingItem> </SettingItem>
<SettingItem <SettingItem label={t("Service Mode")}>
label={t("Service Mode")} <ServiceSwitcher
extra={ status={serviceStatus ?? "unknown"}
<TooltipIcon mutate={mutateServiceStatus}
title={t("Service Mode Info")} patchVerge={patchVerge}
icon={PrivacyTipRounded} onChangeData={onChangeData}
onClick={() => serviceRef.current?.open()} />
/>
}
>
<GuardState
value={enable_service_mode ?? false}
valueProps="checked"
onCatch={onError}
onFormat={onSwitchFormat}
onChange={(e) => onChangeData({ enable_service_mode: e })}
onGuard={(e) => patchVerge({ enable_service_mode: e })}
>
<Switch
edge="end"
disabled={
serviceStatus !== "active" && serviceStatus !== "installed"
}
/>
</GuardState>
</SettingItem> </SettingItem>
<SettingItem <SettingItem

View File

@@ -266,7 +266,7 @@
"Restart": "Restart", "Restart": "Restart",
"Release Version": "Release Version", "Release Version": "Release Version",
"Alpha Version": "Alpha Version", "Alpha Version": "Alpha Version",
"Tun mode requires": "Tun mode requires", "Please Enable Service Mode": "Please Install and Enable Service Mode First",
"Grant": "Grant", "Grant": "Grant",
"Open UWP tool": "Open UWP tool", "Open UWP tool": "Open UWP tool",
"Open UWP tool Info": "Since Windows 8, UWP apps (such as Microsoft Store) are restricted from directly accessing local host network services, and this tool can be used to bypass this restriction", "Open UWP tool Info": "Since Windows 8, UWP apps (such as Microsoft Store) are restricted from directly accessing local host network services, and this tool can be used to bypass this restriction",

View File

@@ -261,7 +261,7 @@
"Restart": "راه‌اندازی مجدد", "Restart": "راه‌اندازی مجدد",
"Release Version": "نسخه نهایی", "Release Version": "نسخه نهایی",
"Alpha Version": "نسخه آلفا", "Alpha Version": "نسخه آلفا",
"Tun mode requires": "Tun mode نیاز دارد", "Please Install and Enable Service Mode First": "لطفاً ابتدا حالت سرویس را نصب و فعال کنید",
"Grant": "اعطا", "Grant": "اعطا",
"Open UWP tool": "باز کردن ابزار UWP", "Open UWP tool": "باز کردن ابزار UWP",
"Open UWP tool Info": "از ویندوز 8 به بعد، برنامه‌های UWP (مانند Microsoft Store) از دسترسی مستقیم به خدمات شبکه محلی محدود شده‌اند و این ابزار می‌تواند برای دور زدن این محدودیت استفاده شود", "Open UWP tool Info": "از ویندوز 8 به بعد، برنامه‌های UWP (مانند Microsoft Store) از دسترسی مستقیم به خدمات شبکه محلی محدود شده‌اند و این ابزار می‌تواند برای دور زدن این محدودیت استفاده شود",

View File

@@ -264,7 +264,7 @@
"Restart": "Перезапуск", "Restart": "Перезапуск",
"Release Version": "Официальная версия", "Release Version": "Официальная версия",
"Alpha Version": "Альфа-версия", "Alpha Version": "Альфа-версия",
"Tun mode requires": "Требуется Режим туннеля", "Please Enable Service Mode": "Пожалуйста, сначала установите и включите режим обслуживания",
"Grant": "Предоставить", "Grant": "Предоставить",
"Open UWP tool": "Открыть UWP инструмент", "Open UWP tool": "Открыть UWP инструмент",
"Open UWP tool Info": "С Windows 8 приложения UWP (такие как Microsoft Store) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение", "Open UWP tool Info": "С Windows 8 приложения UWP (такие как Microsoft Store) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение",

View File

@@ -266,7 +266,7 @@
"Restart": "重启内核", "Restart": "重启内核",
"Release Version": "正式版", "Release Version": "正式版",
"Alpha Version": "预览版", "Alpha Version": "预览版",
"Tun mode requires": "如需启用 Tun 模式需要授权", "Please Enable Service Mode": "请先安装并启用服务模式",
"Grant": "授权", "Grant": "授权",
"Open UWP tool": "UWP 工具", "Open UWP tool": "UWP 工具",
"Open UWP tool Info": "Windows 8开始限制 UWP 应用(如微软商店)直接访问本地主机的网络服务,使用此工具可绕过该限制", "Open UWP tool Info": "Windows 8开始限制 UWP 应用(如微软商店)直接访问本地主机的网络服务,使用此工具可绕过该限制",

View File

@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=lua PKG_NAME:=lua
PKG_VERSION:=5.1.5 PKG_VERSION:=5.1.5
PKG_RELEASE:=10 PKG_RELEASE:=11
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://www.lua.org/ftp/ \ PKG_SOURCE_URL:=https://www.lua.org/ftp/ \

View File

@@ -8,7 +8,6 @@ Including it allows multiple lua versions to coexist.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
--- ---
diff --git a/Makefile b/Makefile
--- a/Makefile --- a/Makefile
+++ b/Makefile +++ b/Makefile
@@ -41,10 +41,10 @@ RANLIB= ranlib @@ -41,10 +41,10 @@ RANLIB= ranlib
@@ -42,7 +41,7 @@ rename to doc/luac5.1.1
diff --git a/src/Makefile b/src/Makefile diff --git a/src/Makefile b/src/Makefile
--- a/src/Makefile --- a/src/Makefile
+++ b/src/Makefile +++ b/src/Makefile
@@ -29,10 +29,10 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ @@ -29,10 +29,10 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ld
LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
lstrlib.o loadlib.o linit.o lstrlib.o loadlib.o linit.o

View File

@@ -1,8 +1,6 @@
diff --git a/src/lnum.c b/src/lnum.c
index 1456b6a2ed23..b0632b04c2b7 100644
--- a/src/lnum.c --- a/src/lnum.c
+++ b/src/lnum.c +++ b/src/lnum.c
@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) { @@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lu
#else #else
return 0; /* Reject the number */ return 0; /* Reject the number */
#endif #endif
@@ -11,7 +9,7 @@ index 1456b6a2ed23..b0632b04c2b7 100644
} }
} else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) { } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */ return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */
@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Integer ib ) { @@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Inte
return 0; return 0;
} }
@@ -25,8 +23,6 @@ index 1456b6a2ed23..b0632b04c2b7 100644
+ return (unsigned LUA_INTEGER)v; + return (unsigned LUA_INTEGER)v;
+} +}
+#endif +#endif
diff --git a/src/lnum_config.h b/src/lnum_config.h
index 19d7a4231a49..1092eead6629 100644
--- a/src/lnum_config.h --- a/src/lnum_config.h
+++ b/src/lnum_config.h +++ b/src/lnum_config.h
@@ -141,7 +141,12 @@ @@ -141,7 +141,12 @@
@@ -43,6 +39,3 @@ index 19d7a4231a49..1092eead6629 100644
#endif #endif
#ifndef LUA_INTEGER_MIN #ifndef LUA_INTEGER_MIN
# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */ # define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */
--
1.9.1

View File

@@ -10,7 +10,7 @@
#if defined(LUA_USE_MACOSX) #if defined(LUA_USE_MACOSX)
--- a/src/Makefile --- a/src/Makefile
+++ b/src/Makefile +++ b/src/Makefile
@@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@ LIBS= -lm $(MYLIBS)
MYCFLAGS= MYCFLAGS=
MYLDFLAGS= MYLDFLAGS=
MYLIBS= MYLIBS=
@@ -18,7 +18,7 @@
# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
@@ -75,7 +76,7 @@ @@ -75,7 +76,7 @@ echo:
@echo "MYLIBS = $(MYLIBS)" @echo "MYLIBS = $(MYLIBS)"
# convenience targets for popular platforms # convenience targets for popular platforms
@@ -27,7 +27,7 @@
none: none:
@echo "Please choose a platform:" @echo "Please choose a platform:"
@echo " $(PLATS)" @echo " $(PLATS)"
@@ -90,16 +91,16 @@ @@ -90,16 +91,16 @@ bsd:
$(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E"
freebsd: freebsd:

View File

@@ -0,0 +1,19 @@
From: Enrico Tassi <gareuselesinge@debian.org>
Date: Tue, 26 Aug 2014 16:20:55 +0200
Subject: Fix stack overflow in vararg functions
---
src/ldo.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId fu
CallInfo *ci;
StkId st, base;
Proto *p = cl->p;
- luaD_checkstack(L, p->maxstacksize);
+ luaD_checkstack(L, p->maxstacksize + p->numparams);
func = restorestack(L, funcr);
if (!p->is_vararg) { /* no varargs? */
base = func + 1;

View File

@@ -8,7 +8,6 @@ Including it allows multiple lua versions to coexist.
Signed-off-by: Rafał Miłecki <rafal@milecki.pl> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
--- ---
diff --git a/Makefile b/Makefile
--- a/Makefile --- a/Makefile
+++ b/Makefile +++ b/Makefile
@@ -41,10 +41,10 @@ RANLIB= ranlib @@ -41,10 +41,10 @@ RANLIB= ranlib
@@ -42,7 +41,7 @@ rename to doc/luac5.1.1
diff --git a/src/Makefile b/src/Makefile diff --git a/src/Makefile b/src/Makefile
--- a/src/Makefile --- a/src/Makefile
+++ b/src/Makefile +++ b/src/Makefile
@@ -29,10 +29,10 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ @@ -29,10 +29,10 @@ CORE_O= lapi.o lcode.o ldebug.o ldo.o ld
LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \
lstrlib.o loadlib.o linit.o lstrlib.o loadlib.o linit.o

View File

@@ -1,8 +1,6 @@
diff --git a/src/lnum.c b/src/lnum.c
index 1456b6a2ed23..b0632b04c2b7 100644
--- a/src/lnum.c --- a/src/lnum.c
+++ b/src/lnum.c +++ b/src/lnum.c
@@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lua_Integer *res, char **endptr_ref) { @@ -127,6 +127,8 @@ static int luaO_str2i (const char *s, lu
#else #else
return 0; /* Reject the number */ return 0; /* Reject the number */
#endif #endif
@@ -11,7 +9,7 @@ index 1456b6a2ed23..b0632b04c2b7 100644
} }
} else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) { } else if ((v > LUA_INTEGER_MAX) || (*endptr && (!isspace(*endptr)))) {
return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */ return TK_NUMBER; /* not in signed range, or has '.', 'e' etc. trailing */
@@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Integer ib ) { @@ -310,3 +312,13 @@ int try_unmint( lua_Integer *r, lua_Inte
return 0; return 0;
} }
@@ -25,8 +23,6 @@ index 1456b6a2ed23..b0632b04c2b7 100644
+ return (unsigned LUA_INTEGER)v; + return (unsigned LUA_INTEGER)v;
+} +}
+#endif +#endif
diff --git a/src/lnum_config.h b/src/lnum_config.h
index 19d7a4231a49..1092eead6629 100644
--- a/src/lnum_config.h --- a/src/lnum_config.h
+++ b/src/lnum_config.h +++ b/src/lnum_config.h
@@ -141,7 +141,12 @@ @@ -141,7 +141,12 @@
@@ -43,6 +39,3 @@ index 19d7a4231a49..1092eead6629 100644
#endif #endif
#ifndef LUA_INTEGER_MIN #ifndef LUA_INTEGER_MIN
# define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */ # define LUA_INTEGER_MIN (-LUA_INTEGER_MAX -1) /* -2^16|32 */
--
1.9.1

View File

@@ -0,0 +1,19 @@
From: Enrico Tassi <gareuselesinge@debian.org>
Date: Tue, 26 Aug 2014 16:20:55 +0200
Subject: Fix stack overflow in vararg functions
---
src/ldo.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -274,7 +274,7 @@ int luaD_precall (lua_State *L, StkId fu
CallInfo *ci;
StkId st, base;
Proto *p = cl->p;
- luaD_checkstack(L, p->maxstacksize);
+ luaD_checkstack(L, p->maxstacksize + p->numparams);
func = restorestack(L, funcr);
if (!p->is_vararg) { /* no varargs? */
base = func + 1;

View File

@@ -88,10 +88,10 @@ type BBRSender struct {
currentRoundTripEnd int64 currentRoundTripEnd int64
// Tracks the maximum bandwidth over the multiple recent round-trips. // Tracks the maximum bandwidth over the multiple recent round-trips.
maxBandwidth WindowedFilter[uint64] maxBandwidth WindowedFilter[int64]
// Tracks the maximum number of bytes acked faster than the sending rate. // Tracks the maximum number of bytes acked faster than the sending rate.
maxAckHeight WindowedFilter[uint64] maxAckHeight WindowedFilter[int64]
// The time this aggregation started and the number of bytes acked during it. // The time this aggregation started and the number of bytes acked during it.
aggregationEpochStartTime time.Time aggregationEpochStartTime time.Time
@@ -158,7 +158,7 @@ type BBRSender struct {
isAtFullBandwidth bool isAtFullBandwidth bool
// Number of rounds during which there was no significant bandwidth increase. // Number of rounds during which there was no significant bandwidth increase.
roundsWithoutBandwidthGain uint64 roundsWithoutBandwidthGain int64
// The bandwidth compared to which the increase is measured. // The bandwidth compared to which the increase is measured.
bandwidthAtLastRound int64 bandwidthAtLastRound int64
@@ -234,7 +234,7 @@ func (b *BBRSender) IsProbingForMoreBandwidth() bool {
return b.mode == modeProbeBW return b.mode == modeProbeBW
} }
func (b *BBRSender) AdjustNetworkParameters(bandwidth uint64, rtt time.Duration) { func (b *BBRSender) AdjustNetworkParameters(bandwidth int64, rtt time.Duration) {
if bandwidth > 0 { if bandwidth > 0 {
b.maxBandwidth.Update(bandwidth, b.roundTripCount) b.maxBandwidth.Update(bandwidth, b.roundTripCount)
} }
@@ -276,8 +276,7 @@ func (b *BBRSender) PacingRate(bytesInFlight int64) int64 {
} }
func (b *BBRSender) BandwidthEstimate() int64 { func (b *BBRSender) BandwidthEstimate() int64 {
// Implementation here return b.maxBandwidth.GetBest()
return 0
} }
func (b *BBRSender) GetCongestionWindow() int64 { func (b *BBRSender) GetCongestionWindow() int64 {
@@ -286,7 +285,6 @@ func (b *BBRSender) GetCongestionWindow() int64 {
} }
func (b *BBRSender) GetSlowStartThreshold() int64 { func (b *BBRSender) GetSlowStartThreshold() int64 {
// Implementation here
return 0 return 0
} }
@@ -299,8 +297,10 @@ func (b *BBRSender) NumStartupRTTs() int64 {
} }
func (b *BBRSender) GetMinRTT() time.Duration { func (b *BBRSender) GetMinRTT() time.Duration {
// Implementation here if b.minRTT != 0 {
return 0 return b.minRTT
}
return b.rttStats.SmoothedRTT()
} }
func (b *BBRSender) IsAtFullBandwidth() bool { func (b *BBRSender) IsAtFullBandwidth() bool {

View File

@@ -69,7 +69,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
} }
if groupOption.IncludeAllProviders { if groupOption.IncludeAllProviders {
groupOption.Use = append(groupOption.Use, AllProviders...) groupOption.Use = AllProviders
} }
if groupOption.IncludeAllProxies { if groupOption.IncludeAllProxies {
if groupOption.Filter != "" { if groupOption.Filter != "" {

View File

@@ -740,8 +740,7 @@ return view.extend({
so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'), so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'),
_('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' + _('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' +
'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.<br/>' + 'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.'));
'Can be overrides by <code>rules.[].client_subnet</code>. Will overrides <code>dns.client_subnet</code>.'));
so.datatype = 'or(cidr, ipaddr)'; so.datatype = 'or(cidr, ipaddr)';
/* DNS servers end */ /* DNS servers end */
@@ -949,8 +948,7 @@ return view.extend({
so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'), so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'),
_('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' + _('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' +
'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.<br/>' + 'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.'));
'Will overrides <code>dns.client_subnet</code> and <code>servers.[].client_subnet</code>.'));
so.datatype = 'or(cidr, ipaddr)'; so.datatype = 'or(cidr, ipaddr)';
/* DNS rules end */ /* DNS rules end */
/* Custom routing settings end */ /* Custom routing settings end */

View File

@@ -479,8 +479,7 @@ return view.extend({
o = s.option(form.Value, 'tls_sni', _('TLS SNI'), o = s.option(form.Value, 'tls_sni', _('TLS SNI'),
_('Used to verify the hostname on the returned certificates unless insecure is given.')); _('Used to verify the hostname on the returned certificates unless insecure is given.'));
o.depends({'tls': '1', 'tls_reality': '0'}); o.depends('tls', '1');
o.depends({'tls': '1', 'tls_reality': null});
o.modalonly = true; o.modalonly = true;
o = s.option(form.DynamicList, 'tls_alpn', _('TLS ALPN'), o = s.option(form.DynamicList, 'tls_alpn', _('TLS ALPN'),

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -40,14 +40,15 @@ chain input {
iifname {{ tun_name }} counter accept comment "!{{ cfgname }}: accept tun input" iifname {{ tun_name }} counter accept comment "!{{ cfgname }}: accept tun input"
{% endif %} {% endif %}
{% {%
uci.foreach(cfgname, 'server', (s) => { if (auto_firewall === '1')
if (s.enabled !== '1') uci.foreach(cfgname, 'server', (s) => {
return; if (s.enabled !== '1')
return;
let proto = s.network || '{ tcp, udp }'; let proto = s.network || '{ tcp, udp }';
printf(' meta l4proto %s th dport %s counter accept comment "!%s: accept server %s"\n', printf(' meta l4proto %s th dport %s counter accept comment "!%s: accept server %s"\n',
proto, s.port, cfgname, s['.name']); proto, s.port, cfgname, s['.name']);
}); });
%} %}
} }
{% endif %} {% endif %}

View File

@@ -740,8 +740,7 @@ return view.extend({
so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'), so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'),
_('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' + _('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' +
'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.<br/>' + 'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.'));
'Can be overrides by <code>rules.[].client_subnet</code>. Will overrides <code>dns.client_subnet</code>.'));
so.datatype = 'or(cidr, ipaddr)'; so.datatype = 'or(cidr, ipaddr)';
/* DNS servers end */ /* DNS servers end */
@@ -949,8 +948,7 @@ return view.extend({
so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'), so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'),
_('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' + _('Append a <code>edns0-subnet</code> OPT extra record with the specified IP prefix to every query by default.<br/>' +
'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.<br/>' + 'If value is an IP address instead of prefix, <code>/32</code> or <code>/128</code> will be appended automatically.'));
'Will overrides <code>dns.client_subnet</code> and <code>servers.[].client_subnet</code>.'));
so.datatype = 'or(cidr, ipaddr)'; so.datatype = 'or(cidr, ipaddr)';
/* DNS rules end */ /* DNS rules end */
/* Custom routing settings end */ /* Custom routing settings end */

View File

@@ -479,8 +479,7 @@ return view.extend({
o = s.option(form.Value, 'tls_sni', _('TLS SNI'), o = s.option(form.Value, 'tls_sni', _('TLS SNI'),
_('Used to verify the hostname on the returned certificates unless insecure is given.')); _('Used to verify the hostname on the returned certificates unless insecure is given.'));
o.depends({'tls': '1', 'tls_reality': '0'}); o.depends('tls', '1');
o.depends({'tls': '1', 'tls_reality': null});
o.modalonly = true; o.modalonly = true;
o = s.option(form.DynamicList, 'tls_alpn', _('TLS ALPN'), o = s.option(form.DynamicList, 'tls_alpn', _('TLS ALPN'),

File diff suppressed because it is too large Load Diff

View File

@@ -40,14 +40,15 @@ chain input {
iifname {{ tun_name }} counter accept comment "!{{ cfgname }}: accept tun input" iifname {{ tun_name }} counter accept comment "!{{ cfgname }}: accept tun input"
{% endif %} {% endif %}
{% {%
uci.foreach(cfgname, 'server', (s) => { if (auto_firewall === '1')
if (s.enabled !== '1') uci.foreach(cfgname, 'server', (s) => {
return; if (s.enabled !== '1')
return;
let proto = s.network || '{ tcp, udp }'; let proto = s.network || '{ tcp, udp }';
printf(' meta l4proto %s th dport %s counter accept comment "!%s: accept server %s"\n', printf(' meta l4proto %s th dport %s counter accept comment "!%s: accept server %s"\n',
proto, s.port, cfgname, s['.name']); proto, s.port, cfgname, s['.name']);
}); });
%} %}
} }
{% endif %} {% endif %}

View File

@@ -916,7 +916,8 @@ add_firewall_rule() {
WAN_IP=$(get_wan_ip) WAN_IP=$(get_wan_ip)
if [ -n "${WAN_IP}" ]; then if [ -n "${WAN_IP}" ]; then
[ -n "${is_tproxy}" ] && nft "add rule inet fw4 PSW_MANGLE ip daddr ${WAN_IP} counter return comment \"WAN_IP_RETURN\"" || nft "add rule inet fw4 PSW_NAT ip daddr ${WAN_IP} counter return comment \"WAN_IP_RETURN\"" nft "add rule inet fw4 PSW_MANGLE ip daddr ${WAN_IP} counter return comment \"WAN_IP_RETURN\""
[ -z "${is_tproxy}" ] && nft "add rule inet fw4 PSW_NAT ip daddr ${WAN_IP} counter return comment \"WAN_IP_RETURN\""
fi fi
unset WAN_IP unset WAN_IP

View File

@@ -308,9 +308,9 @@ dependencies = [
[[package]] [[package]]
name = "blake3" name = "blake3"
version = "1.5.2" version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d08263faac5cde2a4d52b513dadb80846023aade56fcd8fc99ba73ba8050e92" checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210"
dependencies = [ dependencies = [
"arrayref", "arrayref",
"arrayvec", "arrayvec",

View File

@@ -30,13 +30,13 @@ define Download/geosite
HASH:=dbaba085b1de1b8b875f3db78fb367aef080f24993af01abe21f4d4ba99048be HASH:=dbaba085b1de1b8b875f3db78fb367aef080f24993af01abe21f4d4ba99048be
endef endef
GEOSITE_IRAN_VER:=202407080029 GEOSITE_IRAN_VER:=202407150030
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER) GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
define Download/geosite-ir define Download/geosite-ir
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/ URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
URL_FILE:=iran.dat URL_FILE:=iran.dat
FILE:=$(GEOSITE_IRAN_FILE) FILE:=$(GEOSITE_IRAN_FILE)
HASH:=d3c6bd7daab2c720c4c9796c3b31ee7328273cc52b9ff6621e63c5e0513f9a49 HASH:=73f55b3bc7ae33c63a9eb5ae11be288d9500b89ffa824584a57eb89cbc84a8d6
endef endef
define Package/v2ray-geodata/template define Package/v2ray-geodata/template

View File

@@ -78,6 +78,9 @@ jobs:
# Include amd64 on all platforms. # Include amd64 on all platforms.
goos: [windows, freebsd, openbsd, linux, darwin] goos: [windows, freebsd, openbsd, linux, darwin]
goarch: [amd64, 386] goarch: [amd64, 386]
gotoolchain: [""]
patch-assetname: [""]
exclude: exclude:
# Exclude i386 on darwin # Exclude i386 on darwin
- goarch: 386 - goarch: 386
@@ -152,6 +155,16 @@ jobs:
goarch: arm goarch: arm
goarm: 7 goarm: 7
# END OPENBSD ARM # END OPENBSD ARM
# BEGIN Windows 7
- goos: windows
goarch: amd64
gotoolchain: 1.21.4
patch-assetname: win7-64
- goos: windows
goarch: 386
gotoolchain: 1.21.4
patch-assetname: win7-32
# END Windows 7
fail-fast: false fail-fast: false
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -164,16 +177,17 @@ jobs:
- name: Checkout codebase - name: Checkout codebase
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Show workflow information - name: Show workflow information
run: | run: |
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json) _NAME=${{ matrix.patch-assetname }}
[ -n "$_NAME" ] || _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME" echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version-file: go.mod go-version: ${{ matrix.gotoolchain || '1.22' }}
check-latest: true check-latest: true
- name: Get project dependencies - name: Get project dependencies

View File

@@ -32,7 +32,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version-file: go.mod go-version: '1.22'
check-latest: true check-latest: true
- name: Restore Cache - name: Restore Cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4

View File

@@ -27,8 +27,7 @@
- [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**) - [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**)
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray) - [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
- Web Panel - Web Panel
- [X-UI-English](https://github.com/NidukaAkalanka/x-ui-english), [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [X-UI](https://github.com/diditra/x-ui) - [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [Xray-UI](https://github.com/qist/xray-ui)
- [Xray-UI](https://github.com/qist/xray-ui), [X-UI](https://github.com/sing-web/x-ui)
- [Hiddify](https://github.com/hiddify/hiddify-config) - [Hiddify](https://github.com/hiddify/hiddify-config)
- [Marzban](https://github.com/Gozargah/Marzban) - [Marzban](https://github.com/Gozargah/Marzban)
- [Libertea](https://github.com/VZiChoushaDui/Libertea) - [Libertea](https://github.com/VZiChoushaDui/Libertea)
@@ -67,13 +66,10 @@
- [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray)) - [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
- Windows - Windows
- [v2rayN](https://github.com/2dust/v2rayN) - [v2rayN](https://github.com/2dust/v2rayN)
- [NekoRay](https://github.com/Matsuridayo/nekoray)
- [Furious](https://github.com/LorenEteval/Furious) - [Furious](https://github.com/LorenEteval/Furious)
- [HiddifyN](https://github.com/hiddify/HiddifyN)
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient) - [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
- Android - Android
- [v2rayNG](https://github.com/2dust/v2rayNG) - [v2rayNG](https://github.com/2dust/v2rayNG)
- [HiddifyNG](https://github.com/hiddify/HiddifyNG)
- [X-flutter](https://github.com/XTLS/X-flutter) - [X-flutter](https://github.com/XTLS/X-flutter)
- iOS & macOS arm64 - iOS & macOS arm64
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [FoXray](https://apps.apple.com/app/foxray/id6448898396)
@@ -85,7 +81,6 @@
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [FoXray](https://apps.apple.com/app/foxray/id6448898396)
- Linux - Linux
- [v2rayA](https://github.com/v2rayA/v2rayA) - [v2rayA](https://github.com/v2rayA/v2rayA)
- [NekoRay](https://github.com/Matsuridayo/nekoray)
- [Furious](https://github.com/LorenEteval/Furious) - [Furious](https://github.com/LorenEteval/Furious)
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX... ## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
@@ -98,21 +93,15 @@
- [XTLS/libXray](https://github.com/XTLS/libXray) - [XTLS/libXray](https://github.com/XTLS/libXray)
- [xtlsapi](https://github.com/hiddify/xtlsapi) - [xtlsapi](https://github.com/hiddify/xtlsapi)
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite) - [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
- [XrayKit](https://github.com/arror/XrayKit)
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python) - [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
- [xray-api](https://github.com/XVGuardian/xray-api) - [xray-api](https://github.com/XVGuardian/xray-api)
- [XrayR](https://github.com/XrayR-project/XrayR) - [XrayR](https://github.com/XrayR-project/XrayR)
- [XrayR-release](https://github.com/XrayR-project/XrayR-release) - [XrayR-release](https://github.com/XrayR-project/XrayR-release)
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board) - [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
- [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta) - [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta)
- [Clash Verge](https://github.com/zzzgydi/clash-verge)
- [clashN](https://github.com/2dust/clashN) - [clashN](https://github.com/2dust/clashN)
- [Clash Meta for Android](https://github.com/MetaCubeX/ClashMetaForAndroid) - [Clash Meta for Android](https://github.com/MetaCubeX/ClashMetaForAndroid)
- [meta_for_ios](https://t.me/meta_for_ios)
- [sing-box](https://github.com/SagerNet/sing-box) - [sing-box](https://github.com/SagerNet/sing-box)
- [installReality](https://github.com/BoxXt/installReality)
- [sbox-reality](https://github.com/Misaka-blog/sbox-reality)
- [sing-box-for-ios](https://github.com/SagerNet/sing-box-for-ios)
## Contributing ## Contributing

View File

@@ -151,7 +151,7 @@ func LogInfo(ctx context.Context, msg ...interface{}) {
} }
func LogInfoInner(ctx context.Context, inner error, msg ...interface{}) { func LogInfoInner(ctx context.Context, inner error, msg ...interface{}) {
doLog(ctx, inner, log.Severity_Debug, msg...) doLog(ctx, inner, log.Severity_Info, msg...)
} }
func LogWarning(ctx context.Context, msg ...interface{}) { func LogWarning(ctx context.Context, msg ...interface{}) {
@@ -159,7 +159,7 @@ func LogWarning(ctx context.Context, msg ...interface{}) {
} }
func LogWarningInner(ctx context.Context, inner error, msg ...interface{}) { func LogWarningInner(ctx context.Context, inner error, msg ...interface{}) {
doLog(ctx, inner, log.Severity_Debug, msg...) doLog(ctx, inner, log.Severity_Warning, msg...)
} }
func LogError(ctx context.Context, msg ...interface{}) { func LogError(ctx context.Context, msg ...interface{}) {
@@ -167,7 +167,7 @@ func LogError(ctx context.Context, msg ...interface{}) {
} }
func LogErrorInner(ctx context.Context, inner error, msg ...interface{}) { func LogErrorInner(ctx context.Context, inner error, msg ...interface{}) {
doLog(ctx, inner, log.Severity_Debug, msg...) doLog(ctx, inner, log.Severity_Error, msg...)
} }
func doLog(ctx context.Context, inner error, severity log.Severity, msg ...interface{}) { func doLog(ctx context.Context, inner error, severity log.Severity, msg ...interface{}) {

View File

@@ -21,7 +21,7 @@ import (
var ( var (
Version_x byte = 1 Version_x byte = 1
Version_y byte = 8 Version_y byte = 8
Version_z byte = 17 Version_z byte = 18
) )
var ( var (

View File

@@ -1,6 +1,6 @@
module github.com/xtls/xray-core module github.com/xtls/xray-core
go 1.22 go 1.21.4
require ( require (
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0

View File

@@ -17,7 +17,7 @@ More details are at [Latest Release Page](https://github.com/Chilledheart/yass/r
- GTK3 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-gtk3.el8.x86_64.1.11.4.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-gtk3-ubuntu-16.04-xenial_amd64.1.11.4.deb) (minimum requirement: centos 8 or ubuntu 16.04) - GTK3 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-gtk3.el8.x86_64.1.11.4.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-gtk3-ubuntu-16.04-xenial_amd64.1.11.4.deb) (minimum requirement: centos 8 or ubuntu 16.04)
- Qt5 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-qt5.el8.x86_64.1.11.4.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-qt5-ubuntu-16.04-xenial_amd64.1.11.4.deb) (minimum requirement: centos 8 or ubuntu 16.04) - Qt5 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-qt5.el8.x86_64.1.11.4.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-qt5-ubuntu-16.04-xenial_amd64.1.11.4.deb) (minimum requirement: centos 8 or ubuntu 16.04)
- GTK4 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-gtk4.lp155.x86_64.1.11.4.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-gtk4-ubuntu-22.04-jammy_amd64.1.11.4.deb) (minimum requirement: opensuse leap 15.5, centos 9 or ubuntu 22.04) - GTK4 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-gtk4.lp155.x86_64.1.11.4.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-gtk4-ubuntu-22.04-jammy_amd64.1.11.4.deb) (minimum requirement: opensuse leap 15.5, centos 9 or ubuntu 22.04)
- Qt6 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-qt6.lp155.x86_64.1.11.4.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-qt6-ubuntu-22.04-jammy_amd64.1.11.4.deb) (minimum requirement: opensuse leap 15.5 or ubuntu 22.04) - Qt6 [download rpm](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-qt6.lp155.x86_64.1.11.4.rpm) or [download deb](https://github.com/Chilledheart/yass/releases/download/1.11.4/yass-qt6-ubuntu-22.04-jammy_amd64.1.11.4.deb) (minimum requirement: opensuse leap 15.5, centos 9 with epel or ubuntu 22.04)
[![aur yass-proxy-gtk3](https://img.shields.io/aur/version/yass-proxy-gtk3)](https://aur.archlinux.org/packages/yass-proxy-gtk3) [![aur yass-proxy-gtk3](https://img.shields.io/aur/version/yass-proxy-gtk3)](https://aur.archlinux.org/packages/yass-proxy-gtk3)
[![aur yass-proxy-qt5](https://img.shields.io/aur/version/yass-proxy-qt5)](https://aur.archlinux.org/packages/yass-proxy-qt5) [![aur yass-proxy-qt5](https://img.shields.io/aur/version/yass-proxy-qt5)](https://aur.archlinux.org/packages/yass-proxy-qt5)

View File

@@ -1859,6 +1859,9 @@ The following extractors use this feature:
#### bilibili #### bilibili
* `prefer_multi_flv`: Prefer extracting flv formats over mp4 for older videos that still provide legacy formats * `prefer_multi_flv`: Prefer extracting flv formats over mp4 for older videos that still provide legacy formats
#### digitalconcerthall
* `prefer_combined_hls`: Prefer extracting combined/pre-merged video and audio HLS formats. This will exclude 4K/HEVC video and lossless/FLAC audio formats, which are only available as split video/audio HLS formats
**Note**: These options may be changed/removed in the future without concern for backward compatibility **Note**: These options may be changed/removed in the future without concern for backward compatibility
<!-- MANPAGE: MOVE "INSTALLATION" SECTION HERE --> <!-- MANPAGE: MOVE "INSTALLATION" SECTION HERE -->

View File

@@ -929,6 +929,11 @@ class TestUtil(unittest.TestCase):
'acodec': 'none', 'acodec': 'none',
'dynamic_range': 'DV', 'dynamic_range': 'DV',
}) })
self.assertEqual(parse_codecs('fLaC'), {
'vcodec': 'none',
'acodec': 'flac',
'dynamic_range': None,
})
self.assertEqual(parse_codecs('theora, vorbis'), { self.assertEqual(parse_codecs('theora, vorbis'), {
'vcodec': 'theora', 'vcodec': 'theora',
'acodec': 'vorbis', 'acodec': 'vorbis',

View File

@@ -1,6 +1,8 @@
from .common import InfoExtractor from .common import InfoExtractor
from ..networking.exceptions import HTTPError
from ..utils import ( from ..utils import (
ExtractorError, ExtractorError,
parse_codecs,
try_get, try_get,
url_or_none, url_or_none,
urlencode_postdata, urlencode_postdata,
@@ -12,6 +14,7 @@ class DigitalConcertHallIE(InfoExtractor):
IE_DESC = 'DigitalConcertHall extractor' IE_DESC = 'DigitalConcertHall extractor'
_VALID_URL = r'https?://(?:www\.)?digitalconcerthall\.com/(?P<language>[a-z]+)/(?P<type>film|concert|work)/(?P<id>[0-9]+)-?(?P<part>[0-9]+)?' _VALID_URL = r'https?://(?:www\.)?digitalconcerthall\.com/(?P<language>[a-z]+)/(?P<type>film|concert|work)/(?P<id>[0-9]+)-?(?P<part>[0-9]+)?'
_OAUTH_URL = 'https://api.digitalconcerthall.com/v2/oauth2/token' _OAUTH_URL = 'https://api.digitalconcerthall.com/v2/oauth2/token'
_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15'
_ACCESS_TOKEN = None _ACCESS_TOKEN = None
_NETRC_MACHINE = 'digitalconcerthall' _NETRC_MACHINE = 'digitalconcerthall'
_TESTS = [{ _TESTS = [{
@@ -68,33 +71,42 @@ class DigitalConcertHallIE(InfoExtractor):
}] }]
def _perform_login(self, username, password): def _perform_login(self, username, password):
token_response = self._download_json( login_token = self._download_json(
self._OAUTH_URL, self._OAUTH_URL,
None, 'Obtaining token', errnote='Unable to obtain token', data=urlencode_postdata({ None, 'Obtaining token', errnote='Unable to obtain token', data=urlencode_postdata({
'affiliate': 'none', 'affiliate': 'none',
'grant_type': 'device', 'grant_type': 'device',
'device_vendor': 'unknown', 'device_vendor': 'unknown',
# device_model 'Safari' gets split streams of 4K/HEVC video and lossless/FLAC audio
'device_model': 'unknown' if self._configuration_arg('prefer_combined_hls') else 'Safari',
'app_id': 'dch.webapp', 'app_id': 'dch.webapp',
'app_version': '1.0.0', 'app_distributor': 'berlinphil',
'app_version': '1.84.0',
'client_secret': '2ySLN+2Fwb', 'client_secret': '2ySLN+2Fwb',
}), headers={ }), headers={
'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json',
}) 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
self._ACCESS_TOKEN = token_response['access_token'] 'User-Agent': self._USER_AGENT,
})['access_token']
try: try:
self._download_json( login_response = self._download_json(
self._OAUTH_URL, self._OAUTH_URL,
None, note='Logging in', errnote='Unable to login', data=urlencode_postdata({ None, note='Logging in', errnote='Unable to login', data=urlencode_postdata({
'grant_type': 'password', 'grant_type': 'password',
'username': username, 'username': username,
'password': password, 'password': password,
}), headers={ }), headers={
'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Referer': 'https://www.digitalconcerthall.com', 'Referer': 'https://www.digitalconcerthall.com',
'Authorization': f'Bearer {self._ACCESS_TOKEN}', 'Authorization': f'Bearer {login_token}',
'User-Agent': self._USER_AGENT,
}) })
except ExtractorError: except ExtractorError as error:
self.raise_login_required(msg='Login info incorrect') if isinstance(error.cause, HTTPError) and error.cause.status == 401:
raise ExtractorError('Invalid username or password', expected=True)
raise
self._ACCESS_TOKEN = login_response['access_token']
def _real_initialize(self): def _real_initialize(self):
if not self._ACCESS_TOKEN: if not self._ACCESS_TOKEN:
@@ -108,11 +120,15 @@ class DigitalConcertHallIE(InfoExtractor):
'Accept': 'application/json', 'Accept': 'application/json',
'Authorization': f'Bearer {self._ACCESS_TOKEN}', 'Authorization': f'Bearer {self._ACCESS_TOKEN}',
'Accept-Language': language, 'Accept-Language': language,
'User-Agent': self._USER_AGENT,
}) })
formats = [] formats = []
for m3u8_url in traverse_obj(stream_info, ('channel', ..., 'stream', ..., 'url', {url_or_none})): for m3u8_url in traverse_obj(stream_info, ('channel', ..., 'stream', ..., 'url', {url_or_none})):
formats.extend(self._extract_m3u8_formats(m3u8_url, video_id, 'mp4', fatal=False)) formats.extend(self._extract_m3u8_formats(m3u8_url, video_id, 'mp4', m3u8_id='hls', fatal=False))
for fmt in formats:
if fmt.get('format_note') and fmt.get('vcodec') == 'none':
fmt.update(parse_codecs(fmt['format_note']))
yield { yield {
'id': video_id, 'id': video_id,
@@ -140,13 +156,15 @@ class DigitalConcertHallIE(InfoExtractor):
f'https://api.digitalconcerthall.com/v2/{api_type}/{video_id}', video_id, headers={ f'https://api.digitalconcerthall.com/v2/{api_type}/{video_id}', video_id, headers={
'Accept': 'application/json', 'Accept': 'application/json',
'Accept-Language': language, 'Accept-Language': language,
'User-Agent': self._USER_AGENT,
'Authorization': f'Bearer {self._ACCESS_TOKEN}',
}) })
album_artists = traverse_obj(vid_info, ('_links', 'artist', ..., 'name'))
videos = [vid_info] if type_ == 'film' else traverse_obj(vid_info, ('_embedded', ..., ...)) videos = [vid_info] if type_ == 'film' else traverse_obj(vid_info, ('_embedded', ..., ...))
if type_ == 'work': if type_ == 'work':
videos = [videos[int(part) - 1]] videos = [videos[int(part) - 1]]
album_artists = traverse_obj(vid_info, ('_links', 'artist', ..., 'name', {str}))
thumbnail = traverse_obj(vid_info, ( thumbnail = traverse_obj(vid_info, (
'image', ..., {self._proto_relative_url}, {url_or_none}, 'image', ..., {self._proto_relative_url}, {url_or_none},
{lambda x: x.format(width=0, height=0)}, any)) # NB: 0x0 is the original size {lambda x: x.format(width=0, height=0)}, any)) # NB: 0x0 is the original size

View File

@@ -43,6 +43,7 @@ from ..utils import (
xpath_text, xpath_text,
xpath_with_ns, xpath_with_ns,
) )
from ..utils._utils import _UnsafeExtensionError
class GenericIE(InfoExtractor): class GenericIE(InfoExtractor):
@@ -2446,9 +2447,13 @@ class GenericIE(InfoExtractor):
if not is_html(first_bytes): if not is_html(first_bytes):
self.report_warning( self.report_warning(
'URL could be a direct video link, returning it as such.') 'URL could be a direct video link, returning it as such.')
ext = determine_ext(url)
if ext not in _UnsafeExtensionError.ALLOWED_EXTENSIONS:
ext = 'unknown_video'
info_dict.update({ info_dict.update({
'direct': True, 'direct': True,
'url': url, 'url': url,
'ext': ext,
}) })
return info_dict return info_dict

View File

@@ -871,7 +871,7 @@ class SoundcloudUserPermalinkIE(SoundcloudPagedPlaylistBaseIE):
'id': '30909869', 'id': '30909869',
'title': 'neilcic', 'title': 'neilcic',
}, },
'playlist_mincount': 23, 'playlist_mincount': 22,
}] }]
def _real_extract(self, url): def _real_extract(self, url):
@@ -880,7 +880,7 @@ class SoundcloudUserPermalinkIE(SoundcloudPagedPlaylistBaseIE):
self._resolv_url(url), user_id, 'Downloading user info', headers=self._HEADERS) self._resolv_url(url), user_id, 'Downloading user info', headers=self._HEADERS)
return self._extract_playlist( return self._extract_playlist(
f'{self._API_V2_BASE}stream/users/{user["id"]}', str(user['id']), user.get('username')) f'{self._API_V2_BASE}users/{user["id"]}/tracks', str(user['id']), user.get('username'))
class SoundcloudTrackStationIE(SoundcloudPagedPlaylistBaseIE): class SoundcloudTrackStationIE(SoundcloudPagedPlaylistBaseIE):

View File

@@ -270,7 +270,7 @@ def build_innertube_clients():
THIRD_PARTY = { THIRD_PARTY = {
'embedUrl': 'https://www.youtube.com/', # Can be any valid URL 'embedUrl': 'https://www.youtube.com/', # Can be any valid URL
} }
BASE_CLIENTS = ('ios', 'android', 'web', 'tv', 'mweb') BASE_CLIENTS = ('ios', 'web', 'tv', 'mweb', 'android')
priority = qualities(BASE_CLIENTS[::-1]) priority = qualities(BASE_CLIENTS[::-1])
for client, ytcfg in tuple(INNERTUBE_CLIENTS.items()): for client, ytcfg in tuple(INNERTUBE_CLIENTS.items()):
@@ -3702,17 +3702,17 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
return pr_id return pr_id
def _extract_player_responses(self, clients, video_id, webpage, master_ytcfg, smuggled_data): def _extract_player_responses(self, clients, video_id, webpage, master_ytcfg, smuggled_data):
initial_pr = None initial_pr = ignore_initial_response = None
if webpage: if webpage:
experiments = traverse_obj(master_ytcfg, ( if 'web' in clients:
'WEB_PLAYER_CONTEXT_CONFIGS', ..., 'serializedExperimentIds', {str}, {lambda x: x.split(',')}, ..., {str})) experiments = traverse_obj(master_ytcfg, (
if all(x in experiments for x in self._POTOKEN_EXPERIMENTS): 'WEB_PLAYER_CONTEXT_CONFIGS', ..., 'serializedExperimentIds', {lambda x: x.split(',')}, ...))
self.report_warning( if all(x in experiments for x in self._POTOKEN_EXPERIMENTS):
'Webpage contains broken formats (poToken experiment detected). Ignoring initial player response') self.report_warning(
master_ytcfg = self._get_default_ytcfg() 'Webpage contains broken formats (poToken experiment detected). Ignoring initial player response')
else: ignore_initial_response = True
initial_pr = self._search_json( initial_pr = self._search_json(
self._YT_INITIAL_PLAYER_RESPONSE_RE, webpage, 'initial player response', video_id, fatal=False) self._YT_INITIAL_PLAYER_RESPONSE_RE, webpage, 'initial player response', video_id, fatal=False)
prs = [] prs = []
if initial_pr and not self._invalid_player_response(initial_pr, video_id): if initial_pr and not self._invalid_player_response(initial_pr, video_id):
@@ -3740,8 +3740,10 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
skipped_clients = {} skipped_clients = {}
while clients: while clients:
client, base_client, variant = _split_innertube_client(clients.pop()) client, base_client, variant = _split_innertube_client(clients.pop())
player_ytcfg = master_ytcfg if client == 'web' else {} player_ytcfg = {}
if 'configs' not in self._configuration_arg('player_skip') and client != 'web': if client == 'web':
player_ytcfg = self._get_default_ytcfg() if ignore_initial_response else master_ytcfg
elif 'configs' not in self._configuration_arg('player_skip'):
player_ytcfg = self._download_ytcfg(client, video_id) or player_ytcfg player_ytcfg = self._download_ytcfg(client, video_id) or player_ytcfg
player_url = player_url or self._extract_player_url(master_ytcfg, player_ytcfg, webpage=webpage) player_url = player_url or self._extract_player_url(master_ytcfg, player_ytcfg, webpage=webpage)
@@ -3754,7 +3756,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
player_url = self._download_player_url(video_id) player_url = self._download_player_url(video_id)
tried_iframe_fallback = True tried_iframe_fallback = True
pr = initial_pr if client == 'web' and initial_pr else None pr = initial_pr if client == 'web' and not ignore_initial_response else None
for retry in self.RetryManager(fatal=False): for retry in self.RetryManager(fatal=False):
try: try:
pr = pr or self._extract_player_response( pr = pr or self._extract_player_response(
@@ -3765,7 +3767,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
break break
experiments = traverse_obj(pr, ( experiments = traverse_obj(pr, (
'responseContext', 'serviceTrackingParams', lambda _, v: v['service'] == 'GFEEDBACK', 'responseContext', 'serviceTrackingParams', lambda _, v: v['service'] == 'GFEEDBACK',
'params', lambda _, v: v['key'] == 'e', 'value', {lambda x: x.split(',')}, ..., {str})) 'params', lambda _, v: v['key'] == 'e', 'value', {lambda x: x.split(',')}, ...))
if all(x in experiments for x in self._POTOKEN_EXPERIMENTS): if all(x in experiments for x in self._POTOKEN_EXPERIMENTS):
pr = None pr = None
retry.error = ExtractorError('API returned broken formats (poToken experiment detected)', expected=True) retry.error = ExtractorError('API returned broken formats (poToken experiment detected)', expected=True)

View File

@@ -2984,6 +2984,7 @@ def parse_codecs(codecs_str):
str.strip, codecs_str.strip().strip(',').split(',')))) str.strip, codecs_str.strip().strip(',').split(','))))
vcodec, acodec, scodec, hdr = None, None, None, None vcodec, acodec, scodec, hdr = None, None, None, None
for full_codec in split_codecs: for full_codec in split_codecs:
full_codec = re.sub(r'^([^.]+)', lambda m: m.group(1).lower(), full_codec)
parts = re.sub(r'0+(?=\d)', '', full_codec).split('.') parts = re.sub(r'0+(?=\d)', '', full_codec).split('.')
if parts[0] in ('avc1', 'avc2', 'avc3', 'avc4', 'vp9', 'vp8', 'hev1', 'hev2', if parts[0] in ('avc1', 'avc2', 'avc3', 'avc4', 'vp9', 'vp8', 'hev1', 'hev2',
'h263', 'h264', 'mp4v', 'hvc1', 'av1', 'theora', 'dvh1', 'dvhe'): 'h263', 'h264', 'mp4v', 'hvc1', 'av1', 'theora', 'dvh1', 'dvhe'):