mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
Update On Mon May 27 20:31:45 CEST 2024
This commit is contained in:
1
.github/update.log
vendored
1
.github/update.log
vendored
@@ -659,3 +659,4 @@ Update On Thu May 23 20:29:12 CEST 2024
|
||||
Update On Fri May 24 20:29:24 CEST 2024
|
||||
Update On Sat May 25 20:28:13 CEST 2024
|
||||
Update On Sun May 26 20:29:29 CEST 2024
|
||||
Update On Mon May 27 20:31:35 CEST 2024
|
||||
|
@@ -24,11 +24,12 @@
|
||||
"@nyanpasu/ui": "workspace:^",
|
||||
"@tauri-apps/api": "1.5.6",
|
||||
"ahooks": "3.8.0",
|
||||
"allotment": "1.20.2",
|
||||
"axios": "1.7.2",
|
||||
"dayjs": "1.11.11",
|
||||
"framer-motion": "11.2.6",
|
||||
"i18next": "23.11.5",
|
||||
"jotai": "2.8.1",
|
||||
"jotai": "2.8.2",
|
||||
"monaco-editor": "0.49.0",
|
||||
"mui-color-input": "2.0.3",
|
||||
"react": "18.3.1",
|
||||
@@ -55,6 +56,7 @@
|
||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||
"@typescript-eslint/parser": "7.10.0",
|
||||
"@vitejs/plugin-react": "4.3.0",
|
||||
"babel-plugin-react-compiler": "0.0.0-experimental-592953e-20240517",
|
||||
"sass": "1.77.2",
|
||||
"shiki": "1.6.0",
|
||||
"vite": "5.2.11",
|
||||
|
@@ -0,0 +1,128 @@
|
||||
import { Edit, Add } from "@mui/icons-material";
|
||||
import {
|
||||
ListItemButton,
|
||||
alpha,
|
||||
ListItemText,
|
||||
IconButton,
|
||||
ListItemIcon,
|
||||
useTheme,
|
||||
} from "@mui/material";
|
||||
import { Profile, useClash } from "@nyanpasu/interface";
|
||||
import { filterProfiles } from "../utils";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { memo } from "react";
|
||||
|
||||
const ChainItem = memo(function ChainItem({
|
||||
name,
|
||||
desc,
|
||||
selected,
|
||||
onClick,
|
||||
onChainEdit,
|
||||
}: {
|
||||
name?: string;
|
||||
desc?: string;
|
||||
selected?: boolean;
|
||||
onClick: () => void;
|
||||
onChainEdit: () => void;
|
||||
}) {
|
||||
const { palette } = useTheme();
|
||||
|
||||
return (
|
||||
<ListItemButton
|
||||
className="!mt-2 !mb-2"
|
||||
sx={{
|
||||
backgroundColor: selected
|
||||
? alpha(palette.primary.main, 0.3)
|
||||
: alpha(palette.secondary.main, 0.1),
|
||||
borderRadius: 4,
|
||||
|
||||
"&:hover": {
|
||||
backgroundColor: selected
|
||||
? alpha(palette.primary.main, 0.5)
|
||||
: undefined,
|
||||
},
|
||||
}}
|
||||
onClick={onClick}
|
||||
>
|
||||
<ListItemText primary={name} secondary={desc} />
|
||||
|
||||
<IconButton
|
||||
edge="end"
|
||||
color="primary"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
onChainEdit();
|
||||
}}
|
||||
>
|
||||
<Edit />
|
||||
</IconButton>
|
||||
</ListItemButton>
|
||||
);
|
||||
});
|
||||
|
||||
export interface SideChainProps {
|
||||
global?: boolean;
|
||||
profile?: Profile.Item;
|
||||
onChainEdit: (item?: Profile.Item) => void | Promise<void>;
|
||||
}
|
||||
|
||||
export const SideChain = ({ global, profile, onChainEdit }: SideChainProps) => {
|
||||
const { palette } = useTheme();
|
||||
|
||||
const { getProfiles, setProfilesConfig, setProfiles } = useClash();
|
||||
|
||||
const { scripts } = filterProfiles(getProfiles.data?.items);
|
||||
|
||||
const handleChainClick = useLockFn(async (uid: string) => {
|
||||
const chains = global
|
||||
? getProfiles.data?.chain ?? []
|
||||
: profile?.chains ?? [];
|
||||
|
||||
const updatedChains = chains.includes(uid)
|
||||
? chains.filter((chain) => chain !== uid)
|
||||
: [...chains, uid];
|
||||
|
||||
if (global) {
|
||||
await setProfilesConfig({ chain: updatedChains });
|
||||
} else {
|
||||
await setProfiles(uid, { chains: updatedChains });
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="!pl-2 !pr-2 overflow-auto h-full">
|
||||
{scripts?.map((item, index) => {
|
||||
const selected = global
|
||||
? getProfiles.data?.chain?.includes(item.uid)
|
||||
: profile?.chains?.includes(item.uid);
|
||||
|
||||
return (
|
||||
<ChainItem
|
||||
key={index}
|
||||
name={item.name}
|
||||
desc={item.desc}
|
||||
selected={selected}
|
||||
onClick={() => handleChainClick(item.uid)}
|
||||
onChainEdit={() => onChainEdit(item)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
<ListItemButton
|
||||
className="!mt-2 !mb-2"
|
||||
sx={{
|
||||
backgroundColor: alpha(palette.secondary.main, 0.1),
|
||||
borderRadius: 4,
|
||||
}}
|
||||
onClick={() => onChainEdit()}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Add color="primary" />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText primary="New Chian" />
|
||||
</ListItemButton>
|
||||
</div>
|
||||
);
|
||||
};
|
@@ -0,0 +1,77 @@
|
||||
import { RamenDining, Terminal } from "@mui/icons-material";
|
||||
import { Divider } from "@mui/material";
|
||||
import { useClash } from "@nyanpasu/interface";
|
||||
import { memo } from "react";
|
||||
import { isEmpty } from "lodash-es";
|
||||
import { VList } from "virtua";
|
||||
import { filterProfiles } from "../utils";
|
||||
import { classNames } from "@/utils";
|
||||
|
||||
const LogListItem = memo(function LogListItem({
|
||||
name,
|
||||
item,
|
||||
showDivider,
|
||||
}: {
|
||||
name?: string;
|
||||
item?: [string, string];
|
||||
showDivider?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{showDivider && <Divider />}
|
||||
|
||||
<div className="w-full font-mono break-all">
|
||||
<span className="text-red-500">[{name}]: </span>
|
||||
<span>{item}</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
export interface SideLogProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const SideLog = ({ className }: SideLogProps) => {
|
||||
const { getRuntimeLogs, getProfiles } = useClash();
|
||||
|
||||
const { scripts } = filterProfiles(getProfiles.data?.items);
|
||||
|
||||
return (
|
||||
<div className={classNames("w-full", className)}>
|
||||
<div className="p-2 pl-4 flex justify-between items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal />
|
||||
|
||||
<span>Console</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
<VList className="flex flex-col gap-2 p-2 overflow-auto select-text">
|
||||
{!isEmpty(getRuntimeLogs.data) ? (
|
||||
Object.entries(getRuntimeLogs.data).map(([uid, content]) => {
|
||||
return content.map((item, index) => {
|
||||
const name = scripts?.find((script) => script.uid === uid)?.name;
|
||||
|
||||
return (
|
||||
<LogListItem
|
||||
key={uid + index}
|
||||
name={name}
|
||||
item={item}
|
||||
showDivider={index !== 0}
|
||||
/>
|
||||
);
|
||||
});
|
||||
})
|
||||
) : (
|
||||
<div className="w-full h-full min-h-48 flex flex-col justify-center items-center">
|
||||
<RamenDining className="!size-10" />
|
||||
<p>No Log</p>
|
||||
</div>
|
||||
)}
|
||||
</VList>
|
||||
</div>
|
||||
);
|
||||
};
|
@@ -1,22 +1,12 @@
|
||||
import { Add, Close, Edit, RamenDining, Terminal } from "@mui/icons-material";
|
||||
import {
|
||||
Divider,
|
||||
ListItemButton,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
IconButton,
|
||||
List,
|
||||
useTheme,
|
||||
alpha,
|
||||
} from "@mui/material";
|
||||
import { Profile, useClash } from "@nyanpasu/interface";
|
||||
import { Close } from "@mui/icons-material";
|
||||
import { IconButton } from "@mui/material";
|
||||
import { Profile } from "@nyanpasu/interface";
|
||||
import { useState } from "react";
|
||||
import { filterProfiles } from "./utils";
|
||||
import { useLockFn } from "ahooks";
|
||||
import { Expand, ExpandMore } from "@nyanpasu/ui";
|
||||
import { isEmpty } from "lodash-es";
|
||||
import { ScriptDialog } from "./script-dialog";
|
||||
import { VList } from "virtua";
|
||||
import { SideLog } from "./modules/side-log";
|
||||
import { Allotment } from "allotment";
|
||||
import "allotment/dist/style.css";
|
||||
import { SideChain } from "./modules/side-chain";
|
||||
|
||||
export interface ProfileSideProps {
|
||||
profile?: Profile.Item;
|
||||
@@ -25,113 +15,45 @@ export interface ProfileSideProps {
|
||||
}
|
||||
|
||||
export const ProfileSide = ({ profile, global, onClose }: ProfileSideProps) => {
|
||||
const { palette } = useTheme();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const { getProfiles, setProfilesConfig, getRuntimeLogs, setProfiles } =
|
||||
useClash();
|
||||
|
||||
const { scripts } = filterProfiles(getProfiles.data?.items);
|
||||
|
||||
const handleChainClick = useLockFn(async (uid: string) => {
|
||||
const chains = global
|
||||
? getProfiles.data?.chain ?? []
|
||||
: profile?.chains ?? [];
|
||||
|
||||
const updatedChains = chains.includes(uid)
|
||||
? chains.filter((chain) => chain !== uid)
|
||||
: [...chains, uid];
|
||||
|
||||
if (global) {
|
||||
await setProfilesConfig({ chain: updatedChains });
|
||||
} else {
|
||||
await setProfiles(uid, { chains: updatedChains });
|
||||
}
|
||||
});
|
||||
|
||||
const [item, setItem] = useState<Profile.Item>();
|
||||
|
||||
const handleEditChain = async (item: Profile.Item) => {
|
||||
const handleEditChain = async (item?: Profile.Item) => {
|
||||
setItem(item);
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const [expand, setExpand] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="relative h-full">
|
||||
<div className="flex-col gap-2">
|
||||
<div className="p-4 pr-2 flex justify-between items-start">
|
||||
<div>
|
||||
<div className="text-xl font-bold">Proxy Chains</div>
|
||||
<>
|
||||
<div className="p-4 pr-2 flex justify-between items-start">
|
||||
<div>
|
||||
<div className="text-xl font-bold">Proxy Chains</div>
|
||||
|
||||
<div className="truncate">
|
||||
{global ? "Global Chain" : profile?.name}
|
||||
</div>
|
||||
<div className="truncate">
|
||||
{global ? "Global Chain" : profile?.name}
|
||||
</div>
|
||||
|
||||
<IconButton onClick={onClose}>
|
||||
<Close />
|
||||
</IconButton>
|
||||
</div>
|
||||
|
||||
<List className="!pl-2 !pr-2 overflow-auto" disablePadding>
|
||||
{scripts?.map((item, index) => {
|
||||
const selected = global
|
||||
? getProfiles.data?.chain?.includes(item.uid)
|
||||
: profile?.chains?.includes(item.uid);
|
||||
<IconButton onClick={onClose}>
|
||||
<Close />
|
||||
</IconButton>
|
||||
</div>
|
||||
|
||||
return (
|
||||
<ListItemButton
|
||||
key={index}
|
||||
className="!mt-2 !mb-2"
|
||||
sx={{
|
||||
backgroundColor: selected
|
||||
? alpha(palette.primary.main, 0.3)
|
||||
: alpha(palette.grey[100], 0.1),
|
||||
borderRadius: 4,
|
||||
<div style={{ height: "calc(100% - 84px)" }}>
|
||||
<Allotment vertical defaultSizes={[1, 0]}>
|
||||
<Allotment.Pane snap>
|
||||
<SideChain
|
||||
global={global}
|
||||
profile={profile}
|
||||
onChainEdit={handleEditChain}
|
||||
/>
|
||||
</Allotment.Pane>
|
||||
|
||||
"&:hover": {
|
||||
backgroundColor: selected
|
||||
? alpha(palette.primary.main, 0.5)
|
||||
: undefined,
|
||||
},
|
||||
}}
|
||||
onClick={() => handleChainClick(item.uid)}
|
||||
>
|
||||
<ListItemText primary={item.name} secondary={item.desc} />
|
||||
|
||||
<IconButton
|
||||
edge="end"
|
||||
color="primary"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
handleEditChain(item);
|
||||
}}
|
||||
>
|
||||
<Edit />
|
||||
</IconButton>
|
||||
</ListItemButton>
|
||||
);
|
||||
})}
|
||||
|
||||
<ListItemButton
|
||||
className="!mt-2!mb-2"
|
||||
sx={{
|
||||
backgroundColor: alpha(palette.grey[100], 0.1),
|
||||
borderRadius: 4,
|
||||
}}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Add color="primary" />
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText primary="New Chian" />
|
||||
</ListItemButton>
|
||||
</List>
|
||||
<Allotment.Pane minSize={40}>
|
||||
<SideLog className="h-full" />
|
||||
</Allotment.Pane>
|
||||
</Allotment>
|
||||
</div>
|
||||
|
||||
<ScriptDialog
|
||||
@@ -142,58 +64,7 @@ export const ProfileSide = ({ profile, global, onClose }: ProfileSideProps) => {
|
||||
setItem(undefined);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="absolute bottom-0 z-10 w-full">
|
||||
<Divider />
|
||||
|
||||
<div className="p-1 pl-4 flex justify-between items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<Terminal />
|
||||
|
||||
<span>Console</span>
|
||||
</div>
|
||||
|
||||
<ExpandMore
|
||||
size="small"
|
||||
reverse
|
||||
expand={expand}
|
||||
onClick={() => setExpand(!expand)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Expand open={expand}>
|
||||
<Divider />
|
||||
|
||||
<VList className="flex flex-col gap-2 p-2 overflow-auto min-h-48 max-h-48">
|
||||
{!isEmpty(getRuntimeLogs.data) ? (
|
||||
Object.entries(getRuntimeLogs.data).map(([uid, content]) => {
|
||||
return content.map((item, index) => {
|
||||
const name = scripts?.find(
|
||||
(script) => script.uid === uid,
|
||||
)?.name;
|
||||
|
||||
return (
|
||||
<>
|
||||
{index !== 0 && <Divider />}
|
||||
|
||||
<div key={uid + index} className="w-full font-mono">
|
||||
<span className="text-red-500">[{name}]: </span>
|
||||
<span>{item}</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
})
|
||||
) : (
|
||||
<div className="w-full h-full min-h-48 flex flex-col justify-center items-center">
|
||||
<RamenDining className="!size-10" />
|
||||
<p>No Log</p>
|
||||
</div>
|
||||
)}
|
||||
</VList>
|
||||
</Expand>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -4,7 +4,17 @@ import "monaco-editor/esm/vs/editor/editor.all.js";
|
||||
// langs
|
||||
import "monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js";
|
||||
import "monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution.js";
|
||||
import "monaco-editor/esm/vs/basic-languages/lua/lua.contribution.js";
|
||||
|
||||
// language services
|
||||
import "monaco-editor/esm/vs/language/typescript/monaco.contribution.js";
|
||||
|
||||
import * as monaco from "monaco-editor/esm/vs/editor/editor.api";
|
||||
|
||||
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
|
||||
target: monaco.languages.typescript.ScriptTarget.ES2020,
|
||||
allowNonTsExtensions: true,
|
||||
allowJs: true,
|
||||
});
|
||||
|
||||
export { monaco };
|
||||
|
@@ -48,7 +48,17 @@ export default defineConfig(({ command }) => {
|
||||
react({
|
||||
// jsxImportSource: "@emotion/react",
|
||||
babel: {
|
||||
plugins: ["@emotion/babel-plugin"],
|
||||
plugins: [
|
||||
"@emotion/babel-plugin",
|
||||
[
|
||||
"babel-plugin-react-compiler",
|
||||
{
|
||||
sources: (filename) => {
|
||||
return filename.indexOf("src") !== -1;
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
}),
|
||||
generouted(),
|
||||
|
@@ -109,9 +109,9 @@
|
||||
"tsx": "4.11.0",
|
||||
"typescript": "5.4.5"
|
||||
},
|
||||
"packageManager": "pnpm@9.1.2+sha512.127dc83b9ea10c32be65d22a8efb4a65fb952e8fefbdfded39bdc3c97efc32d31b48b00420df2c1187ace28c921c902f0cb5a134a4d032b8b5295cbfa2c681e2",
|
||||
"packageManager": "pnpm@9.1.3",
|
||||
"engines": {
|
||||
"node": "21.7.3"
|
||||
"node": "22.2.0"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
|
178
clash-nyanpasu/pnpm-lock.yaml
generated
178
clash-nyanpasu/pnpm-lock.yaml
generated
@@ -206,6 +206,9 @@ importers:
|
||||
ahooks:
|
||||
specifier: 3.8.0
|
||||
version: 3.8.0(react@19.0.0-rc-935180c7e0-20240524)
|
||||
allotment:
|
||||
specifier: 1.20.2
|
||||
version: 1.20.2(react-dom@19.0.0-rc-935180c7e0-20240524(react@19.0.0-rc-935180c7e0-20240524))(react@19.0.0-rc-935180c7e0-20240524)
|
||||
axios:
|
||||
specifier: 1.7.2
|
||||
version: 1.7.2
|
||||
@@ -219,8 +222,8 @@ importers:
|
||||
specifier: 23.11.5
|
||||
version: 23.11.5
|
||||
jotai:
|
||||
specifier: 2.8.1
|
||||
version: 2.8.1(react@19.0.0-rc-935180c7e0-20240524)(types-react@19.0.0-rc.0)
|
||||
specifier: 2.8.2
|
||||
version: 2.8.2(react@19.0.0-rc-935180c7e0-20240524)(types-react@19.0.0-rc.0)
|
||||
monaco-editor:
|
||||
specifier: 0.49.0
|
||||
version: 0.49.0
|
||||
@@ -294,6 +297,9 @@ importers:
|
||||
'@vitejs/plugin-react':
|
||||
specifier: 4.3.0
|
||||
version: 4.3.0(vite@5.2.11(@types/node@20.12.12)(less@4.2.0)(sass@1.77.2)(stylus@0.62.0))
|
||||
babel-plugin-react-compiler:
|
||||
specifier: 0.0.0-experimental-592953e-20240517
|
||||
version: 0.0.0-experimental-592953e-20240517
|
||||
sass:
|
||||
specifier: 1.77.2
|
||||
version: 1.77.2
|
||||
@@ -427,6 +433,9 @@ packages:
|
||||
resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/generator@7.2.0':
|
||||
resolution: {integrity: sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==}
|
||||
|
||||
'@babel/generator@7.24.5':
|
||||
resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
@@ -1039,6 +1048,10 @@ packages:
|
||||
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@jest/types@24.9.0':
|
||||
resolution: {integrity: sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.5':
|
||||
resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
@@ -1548,6 +1561,15 @@ packages:
|
||||
'@types/http-cache-semantics@4.0.4':
|
||||
resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
|
||||
|
||||
'@types/istanbul-lib-coverage@2.0.6':
|
||||
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
|
||||
|
||||
'@types/istanbul-lib-report@3.0.3':
|
||||
resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==}
|
||||
|
||||
'@types/istanbul-reports@1.1.2':
|
||||
resolution: {integrity: sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==}
|
||||
|
||||
'@types/js-cookie@3.0.6':
|
||||
resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==}
|
||||
|
||||
@@ -1605,6 +1627,12 @@ packages:
|
||||
'@types/unist@3.0.2':
|
||||
resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==}
|
||||
|
||||
'@types/yargs-parser@21.0.3':
|
||||
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
|
||||
|
||||
'@types/yargs@13.0.12':
|
||||
resolution: {integrity: sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==}
|
||||
|
||||
'@types/yauzl@2.10.3':
|
||||
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
|
||||
|
||||
@@ -1709,6 +1737,12 @@ packages:
|
||||
ajv@8.13.0:
|
||||
resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==}
|
||||
|
||||
allotment@1.20.2:
|
||||
resolution: {integrity: sha512-TaCuHfYNcsJS9EPk04M7TlG5Rl3vbAdHeAyrTE9D5vbpzV+wxnRoUrulDbfnzaQcPIZKpHJNixDOoZNuzliKEA==}
|
||||
peerDependencies:
|
||||
react: npm:react@rc
|
||||
react-dom: npm:react-dom@rc
|
||||
|
||||
ansi-align@2.0.0:
|
||||
resolution: {integrity: sha512-TdlOggdA/zURfMYa7ABC66j+oqfMew58KpJMbUlH3bcZP1b+cBHIHDDn5uH9INsxrHBPjsqM0tDB4jPTF/vgJA==}
|
||||
|
||||
@@ -1720,6 +1754,10 @@ packages:
|
||||
resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
ansi-regex@4.1.1:
|
||||
resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1822,6 +1860,9 @@ packages:
|
||||
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
|
||||
engines: {node: '>=10', npm: '>=6'}
|
||||
|
||||
babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517:
|
||||
resolution: {integrity: sha512-OjG1SVaeQZaJrqkMFJatg8W/MTow8Ak5rx2SI0ETQBO1XvOk/XZGMbltNCPdFJLKghBYoBjC+Y3Ap/Xr7B01mA==}
|
||||
|
||||
bail@2.0.2:
|
||||
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
|
||||
|
||||
@@ -1957,6 +1998,9 @@ packages:
|
||||
ci-info@1.6.0:
|
||||
resolution: {integrity: sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==}
|
||||
|
||||
classnames@2.5.1:
|
||||
resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
|
||||
|
||||
cli-boxes@1.0.0:
|
||||
resolution: {integrity: sha512-3Fo5wu8Ytle8q9iCzS4D2MWVL2X7JVWRiS1BnXbTFDhS9c/REkM9vd1AmabsoZoY5/dGi5TT9iKL8Kb6DeBRQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -2776,6 +2820,7 @@ packages:
|
||||
|
||||
glob@7.2.3:
|
||||
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
|
||||
deprecated: Glob versions prior to v9 are no longer supported
|
||||
|
||||
global-agent@3.0.0:
|
||||
resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
|
||||
@@ -2981,6 +3026,9 @@ packages:
|
||||
intersection-observer@0.12.2:
|
||||
resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==}
|
||||
|
||||
invariant@2.2.4:
|
||||
resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
|
||||
|
||||
ip-address@9.0.5:
|
||||
resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==}
|
||||
engines: {node: '>= 12'}
|
||||
@@ -3202,8 +3250,8 @@ packages:
|
||||
resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==}
|
||||
hasBin: true
|
||||
|
||||
jotai@2.8.1:
|
||||
resolution: {integrity: sha512-Gmk5Y3yJL/vN5S0rQ6AaWpXH5Q+HBGHThMHXfylVzXGVuO8YxPRtZf8Y9XYvl+h7ZMQXoHNdFi37vNsJFsiszQ==}
|
||||
jotai@2.8.2:
|
||||
resolution: {integrity: sha512-AU+EU82YqP94izfbGYQQL3oa/06gmn+Ijf/CKx0QybAURtbqh2e4N6zA2fxeIh0JEUgASF6z5IhagJ8NicR95A==}
|
||||
engines: {node: '>=12.20.0'}
|
||||
peerDependencies:
|
||||
'@types/react': npm:types-react@rc
|
||||
@@ -3340,6 +3388,15 @@ packages:
|
||||
lodash.camelcase@4.3.0:
|
||||
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
|
||||
|
||||
lodash.clamp@4.0.3:
|
||||
resolution: {integrity: sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg==}
|
||||
|
||||
lodash.debounce@4.0.8:
|
||||
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
|
||||
|
||||
lodash.isequal@4.5.0:
|
||||
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
|
||||
|
||||
lodash.isplainobject@4.0.6:
|
||||
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||
|
||||
@@ -4004,6 +4061,10 @@ packages:
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
|
||||
pretty-format@24.9.0:
|
||||
resolution: {integrity: sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
progress@2.0.3:
|
||||
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
@@ -4240,6 +4301,7 @@ packages:
|
||||
|
||||
rimraf@3.0.2:
|
||||
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
||||
deprecated: Rimraf versions prior to v4 are no longer supported
|
||||
hasBin: true
|
||||
|
||||
roarr@2.15.4:
|
||||
@@ -4621,6 +4683,10 @@ packages:
|
||||
trim-lines@3.0.1:
|
||||
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
|
||||
|
||||
trim-right@1.0.1:
|
||||
resolution: {integrity: sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
trough@2.2.0:
|
||||
resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
|
||||
|
||||
@@ -4790,6 +4856,12 @@ packages:
|
||||
resolution: {integrity: sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
use-resize-observer@9.1.0:
|
||||
resolution: {integrity: sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==}
|
||||
peerDependencies:
|
||||
react: npm:react@rc
|
||||
react-dom: npm:react-dom@rc
|
||||
|
||||
use-sync-external-store@1.2.2:
|
||||
resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==}
|
||||
peerDependencies:
|
||||
@@ -5010,6 +5082,15 @@ packages:
|
||||
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
|
||||
engines: {node: '>=12.20'}
|
||||
|
||||
zod-validation-error@2.1.0:
|
||||
resolution: {integrity: sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
peerDependencies:
|
||||
zod: ^3.18.0
|
||||
|
||||
zod@3.23.8:
|
||||
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
|
||||
|
||||
zwitch@2.0.4:
|
||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||
|
||||
@@ -5063,6 +5144,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/generator@7.2.0':
|
||||
dependencies:
|
||||
'@babel/types': 7.24.5
|
||||
jsesc: 2.5.2
|
||||
lodash: 4.17.21
|
||||
source-map: 0.5.7
|
||||
trim-right: 1.0.1
|
||||
|
||||
'@babel/generator@7.24.5':
|
||||
dependencies:
|
||||
'@babel/types': 7.24.5
|
||||
@@ -5635,6 +5724,12 @@ snapshots:
|
||||
wrap-ansi: 8.1.0
|
||||
wrap-ansi-cjs: wrap-ansi@7.0.0
|
||||
|
||||
'@jest/types@24.9.0':
|
||||
dependencies:
|
||||
'@types/istanbul-lib-coverage': 2.0.6
|
||||
'@types/istanbul-reports': 1.1.2
|
||||
'@types/yargs': 13.0.12
|
||||
|
||||
'@jridgewell/gen-mapping@0.3.5':
|
||||
dependencies:
|
||||
'@jridgewell/set-array': 1.2.1
|
||||
@@ -6107,6 +6202,17 @@ snapshots:
|
||||
|
||||
'@types/http-cache-semantics@4.0.4': {}
|
||||
|
||||
'@types/istanbul-lib-coverage@2.0.6': {}
|
||||
|
||||
'@types/istanbul-lib-report@3.0.3':
|
||||
dependencies:
|
||||
'@types/istanbul-lib-coverage': 2.0.6
|
||||
|
||||
'@types/istanbul-reports@1.1.2':
|
||||
dependencies:
|
||||
'@types/istanbul-lib-coverage': 2.0.6
|
||||
'@types/istanbul-lib-report': 3.0.3
|
||||
|
||||
'@types/js-cookie@3.0.6': {}
|
||||
|
||||
'@types/json5@0.0.29': {}
|
||||
@@ -6165,6 +6271,12 @@ snapshots:
|
||||
|
||||
'@types/unist@3.0.2': {}
|
||||
|
||||
'@types/yargs-parser@21.0.3': {}
|
||||
|
||||
'@types/yargs@13.0.12':
|
||||
dependencies:
|
||||
'@types/yargs-parser': 21.0.3
|
||||
|
||||
'@types/yauzl@2.10.3':
|
||||
dependencies:
|
||||
'@types/node': 20.12.12
|
||||
@@ -6310,6 +6422,17 @@ snapshots:
|
||||
require-from-string: 2.0.2
|
||||
uri-js: 4.4.1
|
||||
|
||||
allotment@1.20.2(react-dom@19.0.0-rc-935180c7e0-20240524(react@19.0.0-rc-935180c7e0-20240524))(react@19.0.0-rc-935180c7e0-20240524):
|
||||
dependencies:
|
||||
classnames: 2.5.1
|
||||
eventemitter3: 5.0.1
|
||||
lodash.clamp: 4.0.3
|
||||
lodash.debounce: 4.0.8
|
||||
lodash.isequal: 4.5.0
|
||||
react: 19.0.0-rc-935180c7e0-20240524
|
||||
react-dom: 19.0.0-rc-935180c7e0-20240524(react@19.0.0-rc-935180c7e0-20240524)
|
||||
use-resize-observer: 9.1.0(react-dom@19.0.0-rc-935180c7e0-20240524(react@19.0.0-rc-935180c7e0-20240524))(react@19.0.0-rc-935180c7e0-20240524)
|
||||
|
||||
ansi-align@2.0.0:
|
||||
dependencies:
|
||||
string-width: 2.1.1
|
||||
@@ -6318,6 +6441,8 @@ snapshots:
|
||||
|
||||
ansi-regex@3.0.1: {}
|
||||
|
||||
ansi-regex@4.1.1: {}
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-regex@6.0.1: {}
|
||||
@@ -6455,6 +6580,16 @@ snapshots:
|
||||
cosmiconfig: 7.1.0
|
||||
resolve: 1.22.8
|
||||
|
||||
babel-plugin-react-compiler@0.0.0-experimental-592953e-20240517:
|
||||
dependencies:
|
||||
'@babel/generator': 7.2.0
|
||||
'@babel/types': 7.24.5
|
||||
chalk: 4.1.2
|
||||
invariant: 2.2.4
|
||||
pretty-format: 24.9.0
|
||||
zod: 3.23.8
|
||||
zod-validation-error: 2.1.0(zod@3.23.8)
|
||||
|
||||
bail@2.0.2: {}
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
@@ -6592,6 +6727,8 @@ snapshots:
|
||||
|
||||
ci-info@1.6.0: {}
|
||||
|
||||
classnames@2.5.1: {}
|
||||
|
||||
cli-boxes@1.0.0: {}
|
||||
|
||||
cli-cursor@4.0.0:
|
||||
@@ -7815,6 +7952,10 @@ snapshots:
|
||||
|
||||
intersection-observer@0.12.2: {}
|
||||
|
||||
invariant@2.2.4:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
ip-address@9.0.5:
|
||||
dependencies:
|
||||
jsbn: 1.1.0
|
||||
@@ -8004,7 +8145,7 @@ snapshots:
|
||||
|
||||
jiti@1.21.0: {}
|
||||
|
||||
jotai@2.8.1(react@19.0.0-rc-935180c7e0-20240524)(types-react@19.0.0-rc.0):
|
||||
jotai@2.8.2(react@19.0.0-rc-935180c7e0-20240524)(types-react@19.0.0-rc.0):
|
||||
optionalDependencies:
|
||||
'@types/react': types-react@19.0.0-rc.0
|
||||
react: 19.0.0-rc-935180c7e0-20240524
|
||||
@@ -8138,6 +8279,12 @@ snapshots:
|
||||
|
||||
lodash.camelcase@4.3.0: {}
|
||||
|
||||
lodash.clamp@4.0.3: {}
|
||||
|
||||
lodash.debounce@4.0.8: {}
|
||||
|
||||
lodash.isequal@4.5.0: {}
|
||||
|
||||
lodash.isplainobject@4.0.6: {}
|
||||
|
||||
lodash.kebabcase@4.1.1: {}
|
||||
@@ -8860,6 +9007,13 @@ snapshots:
|
||||
|
||||
prettier@3.2.5: {}
|
||||
|
||||
pretty-format@24.9.0:
|
||||
dependencies:
|
||||
'@jest/types': 24.9.0
|
||||
ansi-regex: 4.1.1
|
||||
ansi-styles: 3.2.1
|
||||
react-is: 16.13.1
|
||||
|
||||
progress@2.0.3: {}
|
||||
|
||||
prop-types@15.8.1:
|
||||
@@ -9606,6 +9760,8 @@ snapshots:
|
||||
|
||||
trim-lines@3.0.1: {}
|
||||
|
||||
trim-right@1.0.1: {}
|
||||
|
||||
trough@2.2.0: {}
|
||||
|
||||
ts-api-utils@1.3.0(typescript@5.4.5):
|
||||
@@ -9818,6 +9974,12 @@ snapshots:
|
||||
dependencies:
|
||||
prepend-http: 1.0.4
|
||||
|
||||
use-resize-observer@9.1.0(react-dom@19.0.0-rc-935180c7e0-20240524(react@19.0.0-rc-935180c7e0-20240524))(react@19.0.0-rc-935180c7e0-20240524):
|
||||
dependencies:
|
||||
'@juggle/resize-observer': 3.4.0
|
||||
react: 19.0.0-rc-935180c7e0-20240524
|
||||
react-dom: 19.0.0-rc-935180c7e0-20240524(react@19.0.0-rc-935180c7e0-20240524)
|
||||
|
||||
use-sync-external-store@1.2.2(react@19.0.0-rc-935180c7e0-20240524):
|
||||
dependencies:
|
||||
react: 19.0.0-rc-935180c7e0-20240524
|
||||
@@ -10035,4 +10197,10 @@ snapshots:
|
||||
|
||||
yocto-queue@1.0.0: {}
|
||||
|
||||
zod-validation-error@2.1.0(zod@3.23.8):
|
||||
dependencies:
|
||||
zod: 3.23.8
|
||||
|
||||
zod@3.23.8: {}
|
||||
|
||||
zwitch@2.0.4: {}
|
||||
|
@@ -97,7 +97,7 @@ const isValidFormat = (fileName: string): boolean => {
|
||||
file: reourceMappping,
|
||||
forceDocument: true,
|
||||
caption: `Clash Nyanpasu Nightly Build ${GIT_SHORT_HASH}`,
|
||||
workers: 10,
|
||||
workers: 16,
|
||||
progressCallback: (progress) => consola.start(`Uploading ${progress}`),
|
||||
});
|
||||
|
||||
@@ -115,7 +115,7 @@ const isValidFormat = (fileName: string): boolean => {
|
||||
"Check out on GitHub:",
|
||||
` - https://github.com/LibNyanpasu/clash-nyanpasu/releases/tag/v${version}`,
|
||||
],
|
||||
workers: 10,
|
||||
workers: 16,
|
||||
progressCallback: (progress) => consola.start(`Uploading ${progress}`),
|
||||
});
|
||||
|
||||
|
@@ -36,7 +36,7 @@
|
||||
"i18next": "^23.11.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
"meta-json-schema": "1.18.5-alpha",
|
||||
"monaco-editor": "^0.48.0",
|
||||
"monaco-editor": "^0.47.0",
|
||||
"monaco-yaml": "^5.1.1",
|
||||
"types-pac": "^1.0.2",
|
||||
"nanoid": "^5.0.7",
|
||||
|
28
clash-verge-rev/pnpm-lock.yaml
generated
28
clash-verge-rev/pnpm-lock.yaml
generated
@@ -62,11 +62,11 @@ importers:
|
||||
specifier: 1.18.5-alpha
|
||||
version: 1.18.5-alpha
|
||||
monaco-editor:
|
||||
specifier: ^0.48.0
|
||||
version: 0.48.0
|
||||
specifier: ^0.47.0
|
||||
version: 0.47.0
|
||||
monaco-yaml:
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1(monaco-editor@0.48.0)
|
||||
version: 5.1.1(monaco-editor@0.47.0)
|
||||
nanoid:
|
||||
specifier: ^5.0.7
|
||||
version: 5.0.7
|
||||
@@ -172,7 +172,7 @@ importers:
|
||||
version: 5.2.11(@types/node@20.12.10)(sass@1.77.0)
|
||||
vite-plugin-monaco-editor:
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0(monaco-editor@0.48.0)
|
||||
version: 1.1.0(monaco-editor@0.47.0)
|
||||
vite-plugin-svgr:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0(rollup@4.17.2)(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.10)(sass@1.77.0))
|
||||
@@ -2607,10 +2607,10 @@ packages:
|
||||
engines: { node: ">=10" }
|
||||
hasBin: true
|
||||
|
||||
monaco-editor@0.48.0:
|
||||
monaco-editor@0.47.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-goSDElNqFfw7iDHMg8WDATkfcyeLTNpBHQpO8incK6p5qZt5G/1j41X0xdGzpIkGojGXM+QiRQyLjnfDVvrpwA==,
|
||||
integrity: sha512-VabVvHvQ9QmMwXu4du008ZDuyLnHs9j7ThVFsiJoXSOQk18+LF89N4ADzPbFenm0W4V2bGHnFBztIRQTgBfxzw==,
|
||||
}
|
||||
|
||||
monaco-languageserver-types@0.3.3:
|
||||
@@ -5080,7 +5080,7 @@ snapshots:
|
||||
|
||||
mkdirp@1.0.4: {}
|
||||
|
||||
monaco-editor@0.48.0: {}
|
||||
monaco-editor@0.47.0: {}
|
||||
|
||||
monaco-languageserver-types@0.3.3:
|
||||
dependencies:
|
||||
@@ -5094,19 +5094,19 @@ snapshots:
|
||||
|
||||
monaco-types@0.1.0: {}
|
||||
|
||||
monaco-worker-manager@2.0.1(monaco-editor@0.48.0):
|
||||
monaco-worker-manager@2.0.1(monaco-editor@0.47.0):
|
||||
dependencies:
|
||||
monaco-editor: 0.48.0
|
||||
monaco-editor: 0.47.0
|
||||
|
||||
monaco-yaml@5.1.1(monaco-editor@0.48.0):
|
||||
monaco-yaml@5.1.1(monaco-editor@0.47.0):
|
||||
dependencies:
|
||||
"@types/json-schema": 7.0.15
|
||||
jsonc-parser: 3.2.1
|
||||
monaco-editor: 0.48.0
|
||||
monaco-editor: 0.47.0
|
||||
monaco-languageserver-types: 0.3.3
|
||||
monaco-marker-data-provider: 1.2.2
|
||||
monaco-types: 0.1.0
|
||||
monaco-worker-manager: 2.0.1(monaco-editor@0.48.0)
|
||||
monaco-worker-manager: 2.0.1(monaco-editor@0.47.0)
|
||||
path-browserify: 1.0.1
|
||||
prettier: 2.8.8
|
||||
vscode-languageserver-textdocument: 1.0.11
|
||||
@@ -5534,9 +5534,9 @@ snapshots:
|
||||
unist-util-stringify-position: 4.0.0
|
||||
vfile-message: 4.0.2
|
||||
|
||||
vite-plugin-monaco-editor@1.1.0(monaco-editor@0.48.0):
|
||||
vite-plugin-monaco-editor@1.1.0(monaco-editor@0.47.0):
|
||||
dependencies:
|
||||
monaco-editor: 0.48.0
|
||||
monaco-editor: 0.47.0
|
||||
|
||||
vite-plugin-svgr@4.2.0(rollup@4.17.2)(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.10)(sass@1.77.0)):
|
||||
dependencies:
|
||||
|
@@ -1,9 +1,16 @@
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { List, Button, Select, MenuItem } from "@mui/material";
|
||||
import {
|
||||
List,
|
||||
Button,
|
||||
Select,
|
||||
MenuItem,
|
||||
styled,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
} from "@mui/material";
|
||||
import { useVerge } from "@/hooks/use-verge";
|
||||
import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
|
||||
import { SettingItem } from "./setting-comp";
|
||||
import { GuardState } from "./guard-state";
|
||||
import { open as openDialog } from "@tauri-apps/api/dialog";
|
||||
import { convertFileSrc } from "@tauri-apps/api/tauri";
|
||||
@@ -77,7 +84,8 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
onCancel={() => setOpen(false)}
|
||||
>
|
||||
<List>
|
||||
<SettingItem label={t("Traffic Graph")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Traffic Graph")} />
|
||||
<GuardState
|
||||
value={verge?.traffic_graph ?? true}
|
||||
valueProps="checked"
|
||||
@@ -88,9 +96,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
>
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("Memory Usage")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Memory Usage")} />
|
||||
<GuardState
|
||||
value={verge?.enable_memory_usage ?? true}
|
||||
valueProps="checked"
|
||||
@@ -101,9 +110,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
>
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("Proxy Group Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Proxy Group Icon")} />
|
||||
<GuardState
|
||||
value={verge?.enable_group_icon ?? true}
|
||||
valueProps="checked"
|
||||
@@ -114,9 +124,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
>
|
||||
<Switch edge="end" />
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("Menu Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Menu Icon")} />
|
||||
<GuardState
|
||||
value={verge?.menu_icon ?? "monochrome"}
|
||||
onCatch={onError}
|
||||
@@ -130,9 +141,11 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
<MenuItem value="disable">{t("Disable")}</MenuItem>
|
||||
</Select>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
{OS === "macos" && (
|
||||
<SettingItem label={t("Tray Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Tray Icon")} />
|
||||
<GuardState
|
||||
value={verge?.tray_icon ?? "monochrome"}
|
||||
onCatch={onError}
|
||||
@@ -148,10 +161,11 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
<MenuItem value="colorful">{t("Colorful")}</MenuItem>
|
||||
</Select>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
)}
|
||||
|
||||
<SettingItem label={t("Common Tray Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Common Tray Icon")} />
|
||||
<GuardState
|
||||
value={verge?.common_tray_icon}
|
||||
onCatch={onError}
|
||||
@@ -194,9 +208,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
{verge?.common_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("System Proxy Tray Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("System Proxy Tray Icon")} />
|
||||
<GuardState
|
||||
value={verge?.sysproxy_tray_icon}
|
||||
onCatch={onError}
|
||||
@@ -239,9 +254,10 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
{verge?.sysproxy_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
|
||||
<SettingItem label={t("Tun Tray Icon")}>
|
||||
<Item>
|
||||
<ListItemText primary={t("Tun Tray Icon")} />
|
||||
<GuardState
|
||||
value={verge?.tun_tray_icon}
|
||||
onCatch={onError}
|
||||
@@ -282,8 +298,12 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||
{verge?.tun_tray_icon ? t("Clear") : t("Browse")}
|
||||
</Button>
|
||||
</GuardState>
|
||||
</SettingItem>
|
||||
</Item>
|
||||
</List>
|
||||
</BaseDialog>
|
||||
);
|
||||
});
|
||||
|
||||
const Item = styled(ListItem)(() => ({
|
||||
padding: "5px 2px",
|
||||
}));
|
||||
|
@@ -250,19 +250,17 @@ function connect_status()
|
||||
local e = {}
|
||||
e.use_time = ""
|
||||
local url = luci.http.formvalue("url")
|
||||
local is_baidu = string.find(url, "baidu")
|
||||
local pw_switch = uci:get(appname, "@global[0]", "enabled")
|
||||
local baidu = string.find(url, "baidu")
|
||||
local enabled = uci:get(appname, "@global[0]", "enabled")
|
||||
local chn_list = uci:get(appname, "@global[0]", "chn_list")
|
||||
local gfw_list = uci:get(appname, "@global[0]", "use_gfw_list") or "1"
|
||||
local proxy_mode = uci:get(appname, "@global[0]", "tcp_proxy_mode")
|
||||
local socks_port = uci:get(appname, "@global[0]", "tcp_node_socks_port")
|
||||
if pw_switch ~= 0 then
|
||||
if chn_list == "proxy" then
|
||||
if is_baidu ~= nil then
|
||||
url = "--socks5 127.0.0.1:" .. socks_port .. " " .. url
|
||||
end
|
||||
else
|
||||
if is_baidu == nil then
|
||||
url = "--socks5 127.0.0.1:" .. socks_port .. " " .. url
|
||||
end
|
||||
if enabled ~= 0 then
|
||||
if (chn_list == "proxy" and gfw_list == 0 and proxy_mode ~= "proxy" and baidu ~= nil) or (chn_list == 0 and gfw_list == 0 and proxy_mode == "proxy") then
|
||||
url = "--socks5 127.0.0.1:" .. socks_port .. " " .. url
|
||||
elseif baidu == nil then
|
||||
url = "--socks5 127.0.0.1:" .. socks_port .. " " .. url
|
||||
end
|
||||
end
|
||||
local result = luci.sys.exec('curl --connect-timeout 3 -o /dev/null -I -sk -w "%{http_code}:%{time_appconnect}" ' .. url)
|
||||
|
@@ -466,11 +466,8 @@ luci.sys.call("uci commit " .. name)
|
||||
|
||||
if reboot == 1 then
|
||||
if arg3 == "cron" then
|
||||
local f = io.open("/var/lock/" .. name .. ".lock", "r")
|
||||
if f == nil then
|
||||
if not nixio.fs.access("/var/lock/" .. name .. ".lock") then
|
||||
luci.sys.call("touch /tmp/lock/" .. name .. "_cron.lock")
|
||||
else
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
@@ -1166,11 +1166,8 @@ local function update_node(manual)
|
||||
end
|
||||
|
||||
if arg[3] == "cron" then
|
||||
local f = io.open("/var/lock/" .. appname .. ".lock", "r")
|
||||
if f == nil then
|
||||
if not nixio.fs.access("/var/lock/" .. appname .. ".lock") then
|
||||
luci.sys.call("touch /tmp/lock/" .. appname .. "_cron.lock")
|
||||
else
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
4
shadowsocks-rust/Cargo.lock
generated
4
shadowsocks-rust/Cargo.lock
generated
@@ -921,9 +921,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "etherparse"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "095ab548cf452be5813424558a18af88f0a620d0f4a3d8793aa09311a3b6fa5f"
|
||||
checksum = "21696e6dfe1057a166a042c6d27b89a46aad2ee1003e6e1e03c49d54fd3270d7"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
]
|
||||
|
@@ -168,7 +168,7 @@ iprange = "0.6"
|
||||
regex = "1.4"
|
||||
|
||||
tun = { version = "0.6", optional = true, features = ["async"] }
|
||||
etherparse = { version = "0.14", optional = true }
|
||||
etherparse = { version = "0.15", optional = true }
|
||||
smoltcp = { version = "0.11", optional = true, default-features = false, features = [
|
||||
"std",
|
||||
"log",
|
||||
|
@@ -3,7 +3,7 @@
|
||||
use std::io;
|
||||
|
||||
use hickory_resolver::proto::{
|
||||
op::{header::MessageType, response_code::ResponseCode, Message, OpCode},
|
||||
op::{header::MessageType, response_code::ResponseCode, Header, Message, OpCode},
|
||||
rr::{
|
||||
rdata::{A, AAAA},
|
||||
DNSClass,
|
||||
@@ -18,15 +18,16 @@ use super::manager::FakeDnsManager;
|
||||
|
||||
pub async fn handle_dns_request(req_message: &Message, manager: &FakeDnsManager) -> io::Result<Message> {
|
||||
let mut rsp_message = Message::new();
|
||||
rsp_message.set_id(req_message.id());
|
||||
rsp_message.set_message_type(MessageType::Response);
|
||||
rsp_message.set_recursion_desired(false);
|
||||
rsp_message.set_recursion_available(false);
|
||||
let rsp_header = Header::response_from_request(req_message.header());
|
||||
rsp_message.set_header(rsp_header);
|
||||
|
||||
if req_message.op_code() != OpCode::Query || req_message.message_type() != MessageType::Query {
|
||||
rsp_message.set_response_code(ResponseCode::NotImp);
|
||||
} else {
|
||||
for query in req_message.queries() {
|
||||
// Copy all the queries into response.
|
||||
rsp_message.add_query(query.clone());
|
||||
|
||||
if query.query_class() != DNSClass::IN {
|
||||
let record = Record::<RData>::with(query.name().clone(), query.query_type(), 0);
|
||||
rsp_message.add_answer(record);
|
||||
|
@@ -10,7 +10,7 @@ use std::{
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use hickory_resolver::proto::{
|
||||
op::{header::MessageType, response_code::ResponseCode, Message},
|
||||
op::{response_code::ResponseCode, Message},
|
||||
serialize::binary::{BinEncodable, BinEncoder, EncodeMode},
|
||||
};
|
||||
use log::{error, trace};
|
||||
@@ -139,12 +139,7 @@ impl FakeDnsTcpServer {
|
||||
Err(err) => {
|
||||
error!("failed to handle DNS request, error: {}", err);
|
||||
|
||||
let mut rsp_message = Message::new();
|
||||
rsp_message.set_id(req_message.id());
|
||||
rsp_message.set_message_type(MessageType::Response);
|
||||
rsp_message.set_response_code(ResponseCode::ServFail);
|
||||
|
||||
rsp_message
|
||||
Message::error_msg(req_message.id(), req_message.op_code(), ResponseCode::ServFail)
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
use std::{io, net::SocketAddr, sync::Arc, time::Duration};
|
||||
|
||||
use hickory_resolver::proto::op::{header::MessageType, response_code::ResponseCode, Message};
|
||||
use hickory_resolver::proto::op::{response_code::ResponseCode, Message};
|
||||
use log::error;
|
||||
use shadowsocks::{lookup_then, net::UdpSocket as ShadowUdpSocket, ServerAddr};
|
||||
use tokio::time;
|
||||
@@ -69,12 +69,7 @@ impl FakeDnsUdpServer {
|
||||
Err(err) => {
|
||||
error!("failed to handle DNS request, error: {}", err);
|
||||
|
||||
let mut rsp_message = Message::new();
|
||||
rsp_message.set_id(req_message.id());
|
||||
rsp_message.set_message_type(MessageType::Response);
|
||||
rsp_message.set_response_code(ResponseCode::ServFail);
|
||||
|
||||
rsp_message
|
||||
Message::error_msg(req_message.id(), req_message.op_code(), ResponseCode::ServFail)
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -36,7 +36,6 @@ nfpms:
|
||||
file_name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
|
||||
builds:
|
||||
- main
|
||||
vendor: sagernet
|
||||
homepage: https://sing-box.sagernet.org/
|
||||
maintainer: nekohasekai <contact-git@sekai.icu>
|
||||
description: The universal proxy platform.
|
||||
|
@@ -113,7 +113,6 @@ nfpms:
|
||||
file_name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
|
||||
builds:
|
||||
- main
|
||||
vendor: sagernet
|
||||
homepage: https://sing-box.sagernet.org/
|
||||
maintainer: nekohasekai <contact-git@sekai.icu>
|
||||
description: The universal proxy platform.
|
||||
|
113
sing-box/common/sniff/bittorrent.go
Normal file
113
sing-box/common/sniff/bittorrent.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package sniff
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
)
|
||||
|
||||
const (
|
||||
trackerConnectFlag = iota
|
||||
trackerAnnounceFlag
|
||||
trackerScrapeFlag
|
||||
|
||||
trackerProtocolID = 0x41727101980
|
||||
|
||||
trackerConnectMinSize = 16
|
||||
trackerAnnounceMinSize = 20
|
||||
trackerScrapeMinSize = 8
|
||||
)
|
||||
|
||||
// BitTorrent detects if the stream is a BitTorrent connection.
|
||||
// For the BitTorrent protocol specification, see https://www.bittorrent.org/beps/bep_0003.html
|
||||
func BitTorrent(_ context.Context, reader io.Reader) (*adapter.InboundContext, error) {
|
||||
var first byte
|
||||
err := binary.Read(reader, binary.BigEndian, &first)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if first != 19 {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
var protocol [19]byte
|
||||
_, err = reader.Read(protocol[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if string(protocol[:]) != "BitTorrent protocol" {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
return &adapter.InboundContext{
|
||||
Protocol: C.ProtocolBitTorrent,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UTP detects if the packet is a uTP connection packet.
|
||||
// For the uTP protocol specification, see
|
||||
// 1. https://www.bittorrent.org/beps/bep_0029.html
|
||||
// 2. https://github.com/bittorrent/libutp/blob/2b364cbb0650bdab64a5de2abb4518f9f228ec44/utp_internal.cpp#L112
|
||||
func UTP(_ context.Context, packet []byte) (*adapter.InboundContext, error) {
|
||||
// A valid uTP packet must be at least 20 bytes long.
|
||||
if len(packet) < 20 {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
version := packet[0] & 0x0F
|
||||
ty := packet[0] >> 4
|
||||
if version != 1 || ty > 4 {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
// Validate the extensions
|
||||
extension := packet[1]
|
||||
reader := bytes.NewReader(packet[20:])
|
||||
for extension != 0 {
|
||||
err := binary.Read(reader, binary.BigEndian, &extension)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var length byte
|
||||
err = binary.Read(reader, binary.BigEndian, &length)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, err = reader.Seek(int64(length), io.SeekCurrent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &adapter.InboundContext{
|
||||
Protocol: C.ProtocolBitTorrent,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UDPTracker detects if the packet is a UDP Tracker Protocol packet.
|
||||
// For the UDP Tracker Protocol specification, see https://www.bittorrent.org/beps/bep_0015.html
|
||||
func UDPTracker(_ context.Context, packet []byte) (*adapter.InboundContext, error) {
|
||||
switch {
|
||||
case len(packet) >= trackerConnectMinSize &&
|
||||
binary.BigEndian.Uint64(packet[:8]) == trackerProtocolID &&
|
||||
binary.BigEndian.Uint32(packet[8:12]) == trackerConnectFlag:
|
||||
fallthrough
|
||||
case len(packet) >= trackerAnnounceMinSize &&
|
||||
binary.BigEndian.Uint32(packet[8:12]) == trackerAnnounceFlag:
|
||||
fallthrough
|
||||
case len(packet) >= trackerScrapeMinSize &&
|
||||
binary.BigEndian.Uint32(packet[8:12]) == trackerScrapeFlag:
|
||||
return &adapter.InboundContext{
|
||||
Protocol: C.ProtocolBitTorrent,
|
||||
}, nil
|
||||
default:
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
}
|
81
sing-box/common/sniff/bittorrent_test.go
Normal file
81
sing-box/common/sniff/bittorrent_test.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package sniff_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/sagernet/sing-box/common/sniff"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSniffBittorrent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
packets := []string{
|
||||
"13426974546f7272656e742070726f746f636f6c0000000000100000e21ea9569b69bab33c97851d0298bdfa89bc90922d5554313631302dea812fcd6a3563e3be40c1d1",
|
||||
"13426974546f7272656e742070726f746f636f6c00000000001000052aa4f5a7e209e54b32803d43670971c4c8caaa052d5452333030302d653369733079647675763638",
|
||||
"13426974546f7272656e742070726f746f636f6c00000000001000052aa4f5a7e209e54b32803d43670971c4c8caaa052d5452343035302d6f7a316c6e79377931716130",
|
||||
}
|
||||
|
||||
for _, pkt := range packets {
|
||||
pkt, err := hex.DecodeString(pkt)
|
||||
require.NoError(t, err)
|
||||
metadata, err := sniff.BitTorrent(context.TODO(), bytes.NewReader(pkt))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, C.ProtocolBitTorrent, metadata.Protocol)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSniffUTP(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
packets := []string{
|
||||
"010041a282d7ee7b583afb160004000006d8318da776968f92d666f7963f32dae23ba0d2c810d8b8209cc4939f54fde9eeaa521c2c20c9ba7f43f4fb0375f28de06643b5e3ca4685ab7ac76adca99783be72ef05ed59ef4234f5712b75b4c7c0d7bee8fe2ca20ad626ba5bb0ffcc16bf06790896f888048cf72716419a07db1a3dca4550fbcea75b53e97235168a221cf3e553dfbb723961bd719fab038d86e0ecb74747f5a2cd669de1c4b9ad375f3a492d09d98cdfad745435625401315bbba98d35d32086299801377b93495a63a9efddb8d05f5b37a5c5b1c0a25e917f12007bb5e05013ada8aff544fab8cadf61d80ddb0b60f12741e44515a109d144fd53ef845acb4b5ccf0d6fc302d7003d76df3fc3423bb0237301c9e88f900c2d392a8e0fdb36d143cf7527a93fd0a2638b746e72f6699fffcd4fd15348fce780d4caa04382fd9faf1ca0ae377ca805da7536662b84f5ee18dd3ae38fcb095a7543e55f9069ae92c8cf54ae44e97b558d35e2545c66601ed2149cbc32bd6df199a2be7cf0da8b2ff137e0d23e776bc87248425013876d3a3cc31a83b424b752bd0346437f24b532978005d8f5b1b0be1a37a2489c32a18a9ad3118e3f9d30eb299bffae18e1f0677c2a5c185e62519093fe6bc2b7339299ea50a587989f726ca6443a75dd5bb936f6367c6355d80fae53ff529d740b2e5576e3eefdf1fdbfc69c3c8d8ac750512635de63e054bee1d3b689bc1b2bc3d2601e42a00b5c89066d173d4ae7ffedfd2274e5cf6d868fbe640aedb69b8246142f00b32d459974287537ddd5373460dcbc92f5cfdd7a3ed6020822ae922d947893752ca1983d0d32977374c384ac8f5ab566859019b7351526b9f13e932037a55bb052d9deb3b3c23317e0784fdc51a64f2159bfea3b069cf5caf02ee2c3c1a6b6b427bb16165713e8802d95b5c8ed77953690e994bd38c9ae113fedaf6ee7fc2b96c032ceafc2a530ad0422e84546b9c6ad8ef6ea02fa508abddd1805c38a7b42e9b7c971b1b636865ebec06ed754bb404cd6b4e6cc8cb77bd4a0c43410d5cd5ef8fe853a66d49b3b9e06cb141236cdbfdd5761601dc54d1250b86c660e0f898fe62526fdd9acf0eab60a3bbbb2151970461f28f10b31689594bea646c4b03ee197d63bdef4e5a7c22716b3bb9494a83b78ecd81b338b80ac6c09c43485b1b09ba41c74343832c78f0520c1d659ac9eb1502094141e82fb9e5e620970ebc0655514c43c294a7714cbf9a499d277daf089f556398a01589a77494bec8bfb60a108f3813b55368672b88c1af40f6b3c8b513f7c70c3e0efce85228b8b9ec67ba0393f9f7305024d8e2da6a26cf85613d14f249170ce1000089df4c9c260df7f8292aa2ecb5d5bac97656d59aa248caedea2d198e51ce87baece338716d114b458de02d65c9ff808ca5b5b73723b4d1e962d9ac2d98176544dc9984cf8554d07820ef3dd0861cfe57b478328046380de589adad94ee44743ffac73bb7361feca5d56f07cf8ce75080e261282ae30350d7882679b15cab9e7e53ddf93310b33f7390ae5d318bb53f387e6af5d0ef4f947fc9cb8e7e38b52c7f8d772ece6156b38d88796ea19df02c53723b44df7c76315a0de9462f27287e682d2b4cda1a68fe00d7e48c51ee981be44e1ca940fb5190c12655edb4a83c3a4f33e48a015692df4f0b3d61656e362aca657b5ae8c12db5a0db3db1e45135ee918b66918f40e53c4f83e9da0cddfe63f736ae751ab3837a30ae3220d8e8e311487093a7b90c7e7e40dd54ca750e19452f9193aa892aa6a6229ab493dadae988b1724f7898ee69c36d3eb7364c4adbeca811cfe2065873e78c2b6dfdf1595f7a7831c07e03cda82e4f86f76438dfb2b07c13638ce7b509cfa71b88b5102b39a203b423202088e1c2103319cb32c13c1e546ff8612fa194c95a7808ab767c265a1bd5fa0efed5c8ec1701876a00ec8",
|
||||
"01001ecb68176f215d04326300100000dbcf30292d14b54e9ee2d115ee5b8ebc7fad3e882d4fcdd0c14c6b917c11cb4c6a9f410b52a33ae97c2ac77c7a2b122b8955e09af3c5c595f1b2e79ca57cfe44c44e069610773b9bc9ba223d7f6b383e3adddd03fb88a8476028e30979c2ef321ffc97c5c132bcf9ac5b410bbb5ec6cefca3c7209202a14c5ae922b6b157b0a80249d13ffe5b996af0bc8e54ba576d148372494303e7ead0602b05b9c8fc97d48508a028a04d63a1fd28b0edfcd5c51715f63188b53eefede98a76912dca98518551a8856567307a56a702cbfcc115ea0c755b418bc2c7b57721239b82f09fb24328a4b0ce0f109bcb2a64e04b8aadb1f8487585425acdf8fc4ec8ea93cfcec5ac098bb29d42ddef6e46b03f34a5de28316726699b7cb5195c33e5c48abe87d591d63f9991c84c30819d186d6e0e95fd83c8dff07aa669c4430989bcaccfeacb9bcadbdb4d8f1964dbeb9687745656edd30b21c66cc0a1d742a78717d134a19a7f02d285a4973b1a198c00cfdff4676608dc4f3e817e3463c3b4e2c80d3e8d4fbac541a58a2fb7ad6939f607f8144eff6c8b0adc28ee5609ea158987519892fb",
|
||||
"21001ecb6817f2805d044fd700100000dbd03029",
|
||||
"410277ef0b1fb1f60000000000040000c233000000080000000000000000",
|
||||
}
|
||||
|
||||
for _, pkt := range packets {
|
||||
pkt, err := hex.DecodeString(pkt)
|
||||
require.NoError(t, err)
|
||||
|
||||
metadata, err := sniff.UTP(context.TODO(), pkt)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, C.ProtocolBitTorrent, metadata.Protocol)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSniffUDPTracker(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
connectPackets := []string{
|
||||
// connect packets
|
||||
"00000417271019800000000078e90560",
|
||||
"00000417271019800000000022c5d64d",
|
||||
"000004172710198000000000b3863541",
|
||||
|
||||
// announce packets
|
||||
"3d7592ead4b8c9e300000001b871a3820000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002092f616e6e6f756e6365",
|
||||
"3d7592ead4b8c9e30000000188deed1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002092f616e6e6f756e6365",
|
||||
"3d7592ead4b8c9e300000001ceb948ad0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a3362cdb7020ff920e5aa642c3d4066950dd1f01f4d00000000000000000000000000000000000000000000000000000000000000000000000000000000000002092f616e6e6f756e6365",
|
||||
|
||||
// scrape packets
|
||||
"3d7592ead4b8c9e300000002d2f4bba5a94a8fe5ccb19ba61c4c0873d391e987982fbbd3",
|
||||
"3d7592ead4b8c9e300000002441243292aae6c35c94fcfb415dbe95f408b9ce91ee846ed",
|
||||
"3d7592ead4b8c9e300000002b2aa461b1ad1fa9661cf3fe45fb2504ad52ec6c67758e294",
|
||||
}
|
||||
|
||||
for _, pkt := range connectPackets {
|
||||
pkt, err := hex.DecodeString(pkt)
|
||||
require.NoError(t, err)
|
||||
|
||||
metadata, err := sniff.UDPTracker(context.TODO(), pkt)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, C.ProtocolBitTorrent, metadata.Protocol)
|
||||
}
|
||||
}
|
@@ -1,9 +1,10 @@
|
||||
package constant
|
||||
|
||||
const (
|
||||
ProtocolTLS = "tls"
|
||||
ProtocolHTTP = "http"
|
||||
ProtocolQUIC = "quic"
|
||||
ProtocolDNS = "dns"
|
||||
ProtocolSTUN = "stun"
|
||||
ProtocolTLS = "tls"
|
||||
ProtocolHTTP = "http"
|
||||
ProtocolQUIC = "quic"
|
||||
ProtocolDNS = "dns"
|
||||
ProtocolSTUN = "stun"
|
||||
ProtocolBitTorrent = "bittorrent"
|
||||
)
|
||||
|
@@ -2,6 +2,28 @@
|
||||
icon: material/alert-decagram
|
||||
---
|
||||
|
||||
#### 1.10.0-alpha.1
|
||||
|
||||
* Add tailing comma support in JSON configuration
|
||||
* Add simple auto redirect for Android **1**
|
||||
* Add bittorrent sniffer **2**
|
||||
|
||||
**1**:
|
||||
|
||||
It allows you to use redirect inbound in the sing-box Android client
|
||||
and automatically configures IPv4 TCP redirection via su.
|
||||
|
||||
This may alleviate the symptoms of some OCD patients who think that
|
||||
redirect can effectively save power compared to the system HTTP Proxy.
|
||||
|
||||
See [Redirect](/configuration/inbound/redirect/).
|
||||
|
||||
**2**:
|
||||
|
||||
It doesn't exactly work right now. Do not use it for anything other than blocking bittorrent traffics.
|
||||
|
||||
See [Protocol Sniff](/configuration/route/sniff/).
|
||||
|
||||
### 1.9.0
|
||||
|
||||
* Fixes and improvements
|
||||
|
@@ -1,3 +1,11 @@
|
||||
---
|
||||
icon: material/new-box
|
||||
---
|
||||
|
||||
!!! quote "Changes in sing-box 1.9.0"
|
||||
|
||||
:material-plus: [auto_redirect](#auto_redirect)
|
||||
|
||||
!!! quote ""
|
||||
|
||||
Only supported on Linux and macOS.
|
||||
@@ -9,6 +17,11 @@
|
||||
"type": "redirect",
|
||||
"tag": "redirect-in",
|
||||
|
||||
"auto_redirect": {
|
||||
"enabled": false,
|
||||
"continue_on_no_permission": false
|
||||
},
|
||||
|
||||
... // Listen Fields
|
||||
}
|
||||
```
|
||||
@@ -16,3 +29,23 @@
|
||||
### Listen Fields
|
||||
|
||||
See [Listen Fields](/configuration/shared/listen/) for details.
|
||||
|
||||
### Fields
|
||||
|
||||
#### `auto_redirect`
|
||||
|
||||
!!! question "Since sing-box 1.10.0"
|
||||
|
||||
!!! quote ""
|
||||
|
||||
Only supported on Android.
|
||||
|
||||
Automatically add iptables nat rules to hijack **IPv4 TCP** connections.
|
||||
|
||||
It is expected to run with the Android graphical client (it will attempt to su at runtime).
|
||||
|
||||
#### `auto_redirect.continue_on_no_permission`
|
||||
|
||||
!!! question "Since sing-box 1.10.0"
|
||||
|
||||
Ignore errors when the Android device is not rooted or is denied root access.
|
||||
|
@@ -1,3 +1,11 @@
|
||||
---
|
||||
icon: material/new-box
|
||||
---
|
||||
|
||||
!!! quote "sing-box 1.10.0 中的更改"
|
||||
|
||||
:material-plus: [auto_redirect](#auto_redirect)
|
||||
|
||||
!!! quote ""
|
||||
|
||||
仅支持 Linux 和 macOS。
|
||||
@@ -9,9 +17,35 @@
|
||||
"type": "redirect",
|
||||
"tag": "redirect-in",
|
||||
|
||||
"auto_redirect": {
|
||||
"enabled": false,
|
||||
"continue_on_no_permission": false
|
||||
},
|
||||
|
||||
... // 监听字段
|
||||
}
|
||||
```
|
||||
|
||||
### 监听字段
|
||||
|
||||
参阅 [监听字段](/zh/configuration/shared/listen/)。
|
||||
|
||||
### 字段
|
||||
|
||||
#### `auto_redirect`
|
||||
|
||||
!!! question "自 sing-box 1.10.0 起"
|
||||
|
||||
!!! quote ""
|
||||
|
||||
仅支持 Android。
|
||||
|
||||
自动添加 iptables nat 规则以劫持 **IPv4 TCP** 连接。
|
||||
|
||||
它预计与 Android 图形客户端一起运行(将在运行时尝试 su)。
|
||||
|
||||
#### `auto_redirect.continue_on_no_permission`
|
||||
|
||||
!!! question "自 sing-box 1.10.0 起"
|
||||
|
||||
当 Android 设备未获得 root 权限或 root 访问权限被拒绝时,忽略错误。
|
||||
|
@@ -2,10 +2,11 @@ If enabled in the inbound, the protocol and domain name (if present) of by the c
|
||||
|
||||
#### Supported Protocols
|
||||
|
||||
| Network | Protocol | Domain Name |
|
||||
|:-------:|:--------:|:-----------:|
|
||||
| TCP | HTTP | Host |
|
||||
| TCP | TLS | Server Name |
|
||||
| UDP | QUIC | Server Name |
|
||||
| UDP | STUN | / |
|
||||
| TCP/UDP | DNS | / |
|
||||
| Network | Protocol | Domain Name |
|
||||
|:-------:|:-----------:|:-----------:|
|
||||
| TCP | HTTP | Host |
|
||||
| TCP | TLS | Server Name |
|
||||
| UDP | QUIC | Server Name |
|
||||
| UDP | STUN | / |
|
||||
| TCP/UDP | DNS | / |
|
||||
| TCP/UDP | BitTorrent | / |
|
@@ -2,10 +2,11 @@
|
||||
|
||||
#### 支持的协议
|
||||
|
||||
| 网络 | 协议 | 域名 |
|
||||
|:-------:|:----:|:-----------:|
|
||||
| TCP | HTTP | Host |
|
||||
| TCP | TLS | Server Name |
|
||||
| UDP | QUIC | Server Name |
|
||||
| UDP | STUN | / |
|
||||
| TCP/UDP | DNS | / |
|
||||
| 网络 | 协议 | 域名 |
|
||||
|:-------:|:-----------:|:-----------:|
|
||||
| TCP | HTTP | Host |
|
||||
| TCP | TLS | Server Name |
|
||||
| UDP | QUIC | Server Name |
|
||||
| UDP | STUN | / |
|
||||
| TCP/UDP | DNS | / |
|
||||
| TCP/UDP | BitTorrent | / |
|
@@ -26,7 +26,7 @@ require (
|
||||
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f
|
||||
github.com/sagernet/quic-go v0.43.1-beta.1
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||
github.com/sagernet/sing v0.4.0-beta.20
|
||||
github.com/sagernet/sing v0.5.0-alpha.4
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.18
|
||||
github.com/sagernet/sing-mux v0.2.0
|
||||
github.com/sagernet/sing-quic v0.2.0-beta.5
|
||||
|
@@ -106,8 +106,8 @@ github.com/sagernet/quic-go v0.43.1-beta.1/go.mod h1:BkrQYeop7Jx3hN3TW8/76CXcdhY
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||
github.com/sagernet/sing v0.4.0-beta.20 h1:8rEepj4LMcR0Wd389fJIziv/jr3MBtX5qXBHsfxJ+dY=
|
||||
github.com/sagernet/sing v0.4.0-beta.20/go.mod h1:PFQKbElc2Pke7faBLv8oEba5ehtKO21Ho+TkYemTI3Y=
|
||||
github.com/sagernet/sing v0.5.0-alpha.4 h1:8ljxrEq1BMcDuGe8FxoeUGasPUXQsIywpUusGrlGkQ0=
|
||||
github.com/sagernet/sing v0.5.0-alpha.4/go.mod h1:Xh4KO9nGdvm4K/LVg9Xn9jSxJdqe9KcXbAzNC1S2qfw=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.18 h1:6vzXZThRdA7YUzBOpSbUT48XRumtl/KIpIHFSOP0za8=
|
||||
github.com/sagernet/sing-dns v0.2.0-beta.18/go.mod h1:k/dmFcQpg6+m08gC1yQBy+13+QkuLqpKr4bIreq4U24=
|
||||
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
|
||||
|
@@ -19,7 +19,7 @@ func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, o
|
||||
case C.TypeTun:
|
||||
return NewTun(ctx, router, logger, options.Tag, options.TunOptions, platformInterface)
|
||||
case C.TypeRedirect:
|
||||
return NewRedirect(ctx, router, logger, options.Tag, options.RedirectOptions), nil
|
||||
return NewRedirect(ctx, router, logger, options.Tag, options.RedirectOptions)
|
||||
case C.TypeTProxy:
|
||||
return NewTProxy(ctx, router, logger, options.Tag, options.TProxyOptions), nil
|
||||
case C.TypeDirect:
|
||||
|
@@ -2,25 +2,36 @@ package inbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/redir"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type Redirect struct {
|
||||
myInboundAdapter
|
||||
autoRedirect option.AutoRedirectOptions
|
||||
needSu bool
|
||||
suPath string
|
||||
}
|
||||
|
||||
func NewRedirect(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.RedirectInboundOptions) *Redirect {
|
||||
func NewRedirect(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.RedirectInboundOptions) (*Redirect, error) {
|
||||
redirect := &Redirect{
|
||||
myInboundAdapter{
|
||||
myInboundAdapter: myInboundAdapter{
|
||||
protocol: C.TypeRedirect,
|
||||
network: []string{N.NetworkTCP},
|
||||
ctx: ctx,
|
||||
@@ -29,9 +40,27 @@ func NewRedirect(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
tag: tag,
|
||||
listenOptions: options.ListenOptions,
|
||||
},
|
||||
autoRedirect: common.PtrValueOrDefault(options.AutoRedirect),
|
||||
}
|
||||
if redirect.autoRedirect.Enabled {
|
||||
if !C.IsAndroid {
|
||||
return nil, E.New("auto redirect is only supported on Android")
|
||||
}
|
||||
userId := os.Getuid()
|
||||
if userId != 0 {
|
||||
suPath, err := exec.LookPath("/bin/su")
|
||||
if err == nil {
|
||||
redirect.needSu = true
|
||||
redirect.suPath = suPath
|
||||
} else if redirect.autoRedirect.ContinueOnNoPermission {
|
||||
redirect.autoRedirect.Enabled = false
|
||||
} else {
|
||||
return nil, E.Extend(E.Cause(err, "root permission is required for auto redirect"), os.Getenv("PATH"))
|
||||
}
|
||||
}
|
||||
}
|
||||
redirect.connHandler = redirect
|
||||
return redirect
|
||||
return redirect, nil
|
||||
}
|
||||
|
||||
func (r *Redirect) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||
@@ -42,3 +71,72 @@ func (r *Redirect) NewConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||
metadata.Destination = M.SocksaddrFromNetIP(destination)
|
||||
return r.newConnection(ctx, conn, metadata)
|
||||
}
|
||||
|
||||
func (r *Redirect) Start() error {
|
||||
err := r.myInboundAdapter.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if r.autoRedirect.Enabled {
|
||||
r.cleanupRedirect()
|
||||
err = r.setupRedirect()
|
||||
if err != nil {
|
||||
var exitError *exec.ExitError
|
||||
if errors.As(err, &exitError) && exitError.ExitCode() == 13 && r.autoRedirect.ContinueOnNoPermission {
|
||||
r.logger.Error(E.Cause(err, "setup auto redirect"))
|
||||
return nil
|
||||
}
|
||||
r.cleanupRedirect()
|
||||
return E.Cause(err, "setup auto redirect")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Redirect) Close() error {
|
||||
if r.autoRedirect.Enabled {
|
||||
r.cleanupRedirect()
|
||||
}
|
||||
return r.myInboundAdapter.Close()
|
||||
}
|
||||
|
||||
func (r *Redirect) setupRedirect() error {
|
||||
myUid := os.Getuid()
|
||||
tcpPort := M.AddrPortFromNet(r.tcpListener.Addr()).Port()
|
||||
interfaceRules := common.FlatMap(r.router.(adapter.Router).InterfaceFinder().Interfaces(), func(it control.Interface) []string {
|
||||
return common.Map(common.Filter(it.Addresses, func(it netip.Prefix) bool { return it.Addr().Is4() }), func(it netip.Prefix) string {
|
||||
return "iptables -t nat -A sing-box -p tcp -j RETURN -d " + it.String()
|
||||
})
|
||||
})
|
||||
return r.runAndroidShell(`
|
||||
set -e -o pipefail
|
||||
iptables -t nat -N sing-box
|
||||
` + strings.Join(interfaceRules, "\n") + `
|
||||
iptables -t nat -A sing-box -j RETURN -m owner --uid-owner ` + F.ToString(myUid) + `
|
||||
iptables -t nat -A sing-box -p tcp -j REDIRECT --to-ports ` + F.ToString(tcpPort) + `
|
||||
iptables -t nat -A OUTPUT -p tcp -j sing-box
|
||||
`)
|
||||
}
|
||||
|
||||
func (r *Redirect) cleanupRedirect() {
|
||||
_ = r.runAndroidShell(`
|
||||
iptables -t nat -D OUTPUT -p tcp -j sing-box
|
||||
iptables -t nat -F sing-box
|
||||
iptables -t nat -X sing-box
|
||||
`)
|
||||
}
|
||||
|
||||
func (r *Redirect) runAndroidShell(content string) error {
|
||||
var command *exec.Cmd
|
||||
if r.needSu {
|
||||
command = exec.Command(r.suPath, "-c", "sh")
|
||||
} else {
|
||||
command = exec.Command("sh")
|
||||
}
|
||||
command.Stdin = strings.NewReader(content)
|
||||
combinedOutput, err := command.CombinedOutput()
|
||||
if err != nil {
|
||||
return E.Extend(err, string(combinedOutput))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -2,6 +2,12 @@ package option
|
||||
|
||||
type RedirectInboundOptions struct {
|
||||
ListenOptions
|
||||
AutoRedirect *AutoRedirectOptions `json:"auto_redirect,omitempty"`
|
||||
}
|
||||
|
||||
type AutoRedirectOptions struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
ContinueOnNoPermission bool `json:"continue_on_no_permission,omitempty"`
|
||||
}
|
||||
|
||||
type TProxyInboundOptions struct {
|
||||
|
@@ -850,7 +850,16 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||
|
||||
if metadata.InboundOptions.SniffEnabled {
|
||||
buffer := buf.NewPacket()
|
||||
sniffMetadata, err := sniff.PeekStream(ctx, conn, buffer, time.Duration(metadata.InboundOptions.SniffTimeout), sniff.StreamDomainNameQuery, sniff.TLSClientHello, sniff.HTTPHost)
|
||||
sniffMetadata, err := sniff.PeekStream(
|
||||
ctx,
|
||||
conn,
|
||||
buffer,
|
||||
time.Duration(metadata.InboundOptions.SniffTimeout),
|
||||
sniff.StreamDomainNameQuery,
|
||||
sniff.TLSClientHello,
|
||||
sniff.HTTPHost,
|
||||
sniff.BitTorrent,
|
||||
)
|
||||
if sniffMetadata != nil {
|
||||
metadata.Protocol = sniffMetadata.Protocol
|
||||
metadata.Domain = sniffMetadata.Domain
|
||||
@@ -977,7 +986,15 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||
metadata.Destination = destination
|
||||
}
|
||||
if metadata.InboundOptions.SniffEnabled {
|
||||
sniffMetadata, _ := sniff.PeekPacket(ctx, buffer.Bytes(), sniff.DomainNameQuery, sniff.QUICClientHello, sniff.STUNMessage)
|
||||
sniffMetadata, _ := sniff.PeekPacket(
|
||||
ctx,
|
||||
buffer.Bytes(),
|
||||
sniff.DomainNameQuery,
|
||||
sniff.QUICClientHello,
|
||||
sniff.STUNMessage,
|
||||
sniff.UTP,
|
||||
sniff.UDPTracker,
|
||||
)
|
||||
if sniffMetadata != nil {
|
||||
metadata.Protocol = sniffMetadata.Protocol
|
||||
metadata.Domain = sniffMetadata.Domain
|
||||
|
@@ -250,19 +250,17 @@ function connect_status()
|
||||
local e = {}
|
||||
e.use_time = ""
|
||||
local url = luci.http.formvalue("url")
|
||||
local is_baidu = string.find(url, "baidu")
|
||||
local pw_switch = uci:get(appname, "@global[0]", "enabled")
|
||||
local baidu = string.find(url, "baidu")
|
||||
local enabled = uci:get(appname, "@global[0]", "enabled")
|
||||
local chn_list = uci:get(appname, "@global[0]", "chn_list")
|
||||
local gfw_list = uci:get(appname, "@global[0]", "use_gfw_list") or "1"
|
||||
local proxy_mode = uci:get(appname, "@global[0]", "tcp_proxy_mode")
|
||||
local socks_port = uci:get(appname, "@global[0]", "tcp_node_socks_port")
|
||||
if pw_switch ~= 0 then
|
||||
if chn_list == "proxy" then
|
||||
if is_baidu ~= nil then
|
||||
url = "--socks5 127.0.0.1:" .. socks_port .. " " .. url
|
||||
end
|
||||
else
|
||||
if is_baidu == nil then
|
||||
url = "--socks5 127.0.0.1:" .. socks_port .. " " .. url
|
||||
end
|
||||
if enabled ~= 0 then
|
||||
if (chn_list == "proxy" and gfw_list == 0 and proxy_mode ~= "proxy" and baidu ~= nil) or (chn_list == 0 and gfw_list == 0 and proxy_mode == "proxy") then
|
||||
url = "--socks5 127.0.0.1:" .. socks_port .. " " .. url
|
||||
elseif baidu == nil then
|
||||
url = "--socks5 127.0.0.1:" .. socks_port .. " " .. url
|
||||
end
|
||||
end
|
||||
local result = luci.sys.exec('curl --connect-timeout 3 -o /dev/null -I -sk -w "%{http_code}:%{time_appconnect}" ' .. url)
|
||||
|
@@ -466,11 +466,8 @@ luci.sys.call("uci commit " .. name)
|
||||
|
||||
if reboot == 1 then
|
||||
if arg3 == "cron" then
|
||||
local f = io.open("/var/lock/" .. name .. ".lock", "r")
|
||||
if f == nil then
|
||||
if not nixio.fs.access("/var/lock/" .. name .. ".lock") then
|
||||
luci.sys.call("touch /tmp/lock/" .. name .. "_cron.lock")
|
||||
else
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
@@ -1166,11 +1166,8 @@ local function update_node(manual)
|
||||
end
|
||||
|
||||
if arg[3] == "cron" then
|
||||
local f = io.open("/var/lock/" .. appname .. ".lock", "r")
|
||||
if f == nil then
|
||||
if not nixio.fs.access("/var/lock/" .. appname .. ".lock") then
|
||||
luci.sys.call("touch /tmp/lock/" .. appname .. "_cron.lock")
|
||||
else
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
@@ -6,12 +6,12 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=sing-box
|
||||
PKG_VERSION:=1.8.14
|
||||
PKG_VERSION:=1.9.0
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)?
|
||||
PKG_HASH:=2ba7cfa097f5963ba304d47606e7a6b61bf881eb86cbed78fa6e4efae44a0a5f
|
||||
PKG_HASH:=cb1d91e362f4dd7c35f7bb040514414861a045a76301af8257134c65f7a45c36
|
||||
|
||||
PKG_LICENSE:=GPL-3.0-or-later
|
||||
PKG_LICENSE_FILES:=LICENSE
|
||||
|
@@ -30,7 +30,7 @@ define Download/geosite
|
||||
HASH:=25d6120b009498ac83ae723e9751a19ff545fac4800dad53ab6e2592c3407533
|
||||
endef
|
||||
|
||||
GEOSITE_IRAN_VER:=202405201648
|
||||
GEOSITE_IRAN_VER:=202405270027
|
||||
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
|
||||
define Download/geosite-ir
|
||||
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
|
||||
|
19
yass/.github/workflows/releases-mingw.yml
vendored
19
yass/.github/workflows/releases-mingw.yml
vendored
@@ -45,15 +45,6 @@ jobs:
|
||||
# unshallow must come first otherwise submodule may be get unshallowed
|
||||
git fetch --tags --unshallow
|
||||
git submodule update --init --depth 1
|
||||
- name: Cache clang, nasm and wixtoolset 3
|
||||
id: clang-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
third_party/nasm
|
||||
third_party/llvm-build/Release+Asserts
|
||||
third_party/wix311
|
||||
key: ${{ runner.os }}-toolchain-${{ hashFiles('CLANG_REVISION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache mingw64 toolchain
|
||||
id: mingw64-cache
|
||||
uses: actions/cache@v4
|
||||
@@ -74,10 +65,6 @@ jobs:
|
||||
run: |
|
||||
choco upgrade -y llvm --version=17.0.6
|
||||
clang -v
|
||||
- name: "Download dependency: clang, nasm and wixtoolset 3"
|
||||
if: ${{ steps.clang-cache.outputs.cache-hit != 'true' }}
|
||||
run: |
|
||||
scripts\download-toolchain.bat
|
||||
- name: "Download dependency: mingw64"
|
||||
if: ${{ steps.mingw64-cache.outputs.cache-hit != 'true' }}
|
||||
run: |
|
||||
@@ -87,6 +74,10 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
./scripts/download-curl-mingw.sh ${{ matrix.arch }}
|
||||
- name: "Download dependency: nasm (chocolatey)"
|
||||
run: |
|
||||
choco install -y nasm
|
||||
"C:\Program Files\NASM\nasm" --version
|
||||
- name: "Download dependency: cmake (chocolatey)"
|
||||
run: |
|
||||
choco install -y cmake.portable --version=3.28.5
|
||||
@@ -116,7 +107,7 @@ jobs:
|
||||
set "CXXFLAGS=-I %CD%\third_party\${{ matrix.mingw_dir }}\lib\gcc\${{ matrix.arch }}-w64-mingw32\${{ matrix.gcc_ver }}\include"
|
||||
set "LDFLAGS=-Wl,-L%CD%\third_party\${{ matrix.mingw_dir }}\lib -Wl,-L%CD%\third_party\${{ matrix.mingw_dir }}\lib\gcc\${{ matrix.arch }}-w64-mingw32\${{ matrix.gcc_ver }}"
|
||||
set "Path=%CD%\third_party\${{ matrix.mingw_dir }}\bin;%Path%"
|
||||
set "Path=%CD%\third_party\nasm;%Path%"
|
||||
set "Path=C:\Program Files\NASM\nasm;%Path%"
|
||||
REM for clang.exe and clang++.exe
|
||||
REM set "Path=C:\Program Files\LLVM\bin;%Path%"
|
||||
|
||||
|
68
yass/.github/workflows/releases-rpm.yml
vendored
68
yass/.github/workflows/releases-rpm.yml
vendored
@@ -47,6 +47,7 @@ jobs:
|
||||
- 'centos8'
|
||||
- 'fedora39'
|
||||
- 'alpine320'
|
||||
- 'i386-alpine320'
|
||||
- 'opensuse15'
|
||||
# - 'centos9'
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -162,14 +163,13 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
container:
|
||||
- 'alpine320'
|
||||
runs-on: ubuntu-22.04
|
||||
include:
|
||||
- container: 'alpine320'
|
||||
arch: amd64
|
||||
- container: 'i386-alpine320'
|
||||
arch: i386
|
||||
runs-on: ubuntu-20.04
|
||||
needs: docker_publish
|
||||
container:
|
||||
image: 'ghcr.io/chilledheart/${{ matrix.container }}'
|
||||
env:
|
||||
DISTRO: ${{ matrix.container }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Checkout with shallow submodules
|
||||
@@ -179,6 +179,16 @@ jobs:
|
||||
# unshallow must come first otherwise submodule may be get unshallowed
|
||||
git fetch --tags --unshallow
|
||||
git submodule update --init --depth 1
|
||||
- name: Set SDK_ROOT
|
||||
run: |
|
||||
echo "SDK_ROOT=${{ github.workspace }}/${{ matrix.arch }}-alpine320-sysroot" >> $GITHUB_ENV
|
||||
- name: Cache clang
|
||||
id: clang-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
third_party/llvm-build/Release+Asserts
|
||||
key: ${{ runner.os }}-toolchain-${{ hashFiles('CLANG_REVISION') }}-v${{ env.CACHE_EPOCH }}
|
||||
- name: Cache golang
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
@@ -188,20 +198,50 @@ jobs:
|
||||
key: ${{ runner.os }}-go-docker-${{ hashFiles('**/go.sum') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-go-docker-
|
||||
- name: Populate sysroot from docker image
|
||||
run: |
|
||||
docker pull ghcr.io/chilledheart/${{ matrix.container }}
|
||||
mkdir -p "${{ env.SDK_ROOT }}"
|
||||
docker export $(docker create ghcr.io/chilledheart/${{ matrix.container }}) | tar -C "${{ env.SDK_ROOT }}" -xf -
|
||||
- name: Build build tool
|
||||
run: |
|
||||
cd tools
|
||||
go build
|
||||
- name: "Install dependency: prebuilt clang and clang-tidy binaries"
|
||||
if: ${{ steps.clang-cache.outputs.cache-hit != 'true' }}
|
||||
run: |
|
||||
./scripts/download-clang-prebuilt-binaries.py
|
||||
rm -f third_party/llvm-build/Release+Asserts/*.tgz
|
||||
- name: Change ubuntu mirror
|
||||
run: |
|
||||
sudo sed -i 's/azure.archive.ubuntu.com/azure.archive.ubuntu.com/g' /etc/apt/sources.list
|
||||
sudo apt-get update -qq
|
||||
- name: Populate depedencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y cmake ninja-build pkg-config gettext bubblewrap
|
||||
# libc6-i386 interferes with x86 build
|
||||
sudo apt remove libc6-i386
|
||||
- name: Populate dependencie (cmake, overwrite)
|
||||
run: |
|
||||
curl -L -O https://github.com/Kitware/CMake/releases/download/v3.28.5/cmake-3.28.5-linux-x86_64.tar.gz
|
||||
sudo tar -C /usr/local --strip-components=1 -xf cmake-3.28.5-linux-x86_64.tar.gz
|
||||
cmake --version
|
||||
rm -f *.tar.gz
|
||||
- name: Build TGZ packages
|
||||
run: |
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
./tools/build --arch amd64 --system linux --subsystem musl -build-benchmark -build-test \
|
||||
--cmake-build-type MinSizeRel
|
||||
- name: Run tests (amd64)
|
||||
./tools/build --arch ${{ matrix.arch }} --system linux --subsystem musl \
|
||||
--sysroot "${{ env.SDK_ROOT }}" \
|
||||
-build-test --cmake-build-type MinSizeRel
|
||||
- name: Run tests
|
||||
run: |
|
||||
./build-linux-musl-amd64/yass_test
|
||||
./build-linux-musl-amd64/yass_benchmark
|
||||
bwrap --die-with-parent --bind "${{ env.SDK_ROOT }}" / \
|
||||
--ro-bind /sys /sys \
|
||||
--ro-bind /etc/resolv.conf /etc/resolv.conf \
|
||||
--proc /proc --dev /dev \
|
||||
--unshare-all --share-net \
|
||||
--bind $PWD/build-linux-musl-${{ matrix.arch }} /tmp \
|
||||
/tmp/yass_test
|
||||
- name: Upload dist tarball (including debuginfo)
|
||||
if: ${{ github.event_name == 'release' }}
|
||||
env:
|
||||
|
2
yass/.gitignore
vendored
2
yass/.gitignore
vendored
@@ -89,3 +89,5 @@ local.properties
|
||||
/rustc-1.77.2-src
|
||||
/rustc-1.78.0-src
|
||||
/third_party/rust-ohos
|
||||
/i386-alpine320-sysroot
|
||||
/amd64-alpine320-sysroot
|
||||
|
@@ -590,6 +590,7 @@ if (CMAKE_CROSSCOMPILING AND (CMAKE_SYSROOT OR CMAKE_OSX_SYSROOT))
|
||||
if (NOT EXISTS ${_SYSROOT})
|
||||
message(FATAL_ERROR "Invalid sysroot ${_SYSROOT}")
|
||||
endif()
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(ENV{PKG_CONFIG_DIR} "")
|
||||
set(ENV{PKG_CONFIG_LIBDIR} "${_SYSROOT}/usr/lib64/pkgconfig:${_SYSROOT}/usr/lib/pkgconfig:${_SYSROOT}/lib/pkgconfig:${_SYSROOT}/usr/share/pkgconfig")
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||
@@ -614,6 +615,10 @@ if (UNIX AND CMAKE_CROSSCOMPILING AND CMAKE_SYSROOT AND COMPILER_CLANG AND NOT C
|
||||
if (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv32")
|
||||
file(GLOB _GCC_SYSROOT "${CMAKE_SYSROOT}/../lib/gcc/*/*.*.*")
|
||||
endif()
|
||||
# fix up for raw sysroot from docker
|
||||
if (NOT _GCC_SYSROOT)
|
||||
file(GLOB _GCC_SYSROOT "${CMAKE_SYSROOT}/usr/lib/gcc/*/*.*.*")
|
||||
endif()
|
||||
if (_GCC_SYSROOT)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --gcc-install-dir=${_GCC_SYSROOT}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-install-dir=${_GCC_SYSROOT}")
|
||||
|
@@ -1,9 +1,2 @@
|
||||
FROM alpine:3.20
|
||||
RUN apk add --no-cache git bash perl curl go tar && \
|
||||
apk add --no-cache build-base binutils-gold linux-headers cmake ninja-build curl-dev && \
|
||||
apk add --no-cache gtk+3.0-dev gettext && \
|
||||
apk add --no-cache llvm clang lld && \
|
||||
ln -sf /usr/lib/ninja-build/bin/ninja /usr/bin/ninja
|
||||
# https://github.com/cli/cli/blob/trunk/docs/install_linux.md
|
||||
RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
|
||||
RUN apk add --no-cache github-cli@community
|
||||
RUN apk add --no-cache bash tar build-base linux-headers curl-dev gtk+3.0-dev
|
||||
|
2
yass/docker/i386-alpine320.Dockerfile
Normal file
2
yass/docker/i386-alpine320.Dockerfile
Normal file
@@ -0,0 +1,2 @@
|
||||
FROM i386/alpine:3.20
|
||||
RUN apk add --no-cache bash tar build-base linux-headers curl-dev gtk+3.0-dev
|
@@ -8,15 +8,15 @@ REM Usage: download-toolchain.bat
|
||||
echo "Install dependency: prebuilt nasm"
|
||||
|
||||
cd third_party
|
||||
curl -C - -L -O https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/win64/nasm-2.15.05-win64.zip
|
||||
curl -C - -L -O https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/win64/nasm-2.16.03-win64.zip
|
||||
if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL%
|
||||
"C:\Program Files\7-Zip\7z.exe" x nasm-2.15.05-win64.zip -aoa
|
||||
"C:\Program Files\7-Zip\7z.exe" x nasm-2.16.03-win64.zip -aoa
|
||||
if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL%
|
||||
rmdir /s /q nasm
|
||||
rename nasm-2.15.05 nasm
|
||||
rename nasm-2.16.03 nasm
|
||||
if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL%
|
||||
cd ..
|
||||
del /s /q third_party\nasm-2.15*.zip
|
||||
del /s /q third_party\nasm-2*.zip
|
||||
|
||||
echo "Install dependency: prebuilt clang and clang-tidy binaries"
|
||||
|
||||
|
1
yt-dlp/.github/PULL_REQUEST_TEMPLATE.md
vendored
1
yt-dlp/.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -28,7 +28,6 @@ Fixes #
|
||||
### Before submitting a *pull request* make sure you have:
|
||||
- [ ] At least skimmed through [contributing guidelines](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#developer-instructions) including [yt-dlp coding conventions](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#yt-dlp-coding-conventions)
|
||||
- [ ] [Searched](https://github.com/yt-dlp/yt-dlp/search?q=is%3Apr&type=Issues) the bugtracker for similar pull requests
|
||||
- [ ] Checked the code with [flake8](https://pypi.python.org/pypi/flake8) and [ran relevant tests](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#developer-instructions)
|
||||
|
||||
### In order to be accepted and merged into yt-dlp each piece of code must be in public domain or released under [Unlicense](http://unlicense.org/). Check all of the following options that apply:
|
||||
- [ ] I am the original author of this code and I am willing to release it under [Unlicense](http://unlicense.org/)
|
||||
|
2
yt-dlp/.github/workflows/core.yml
vendored
2
yt-dlp/.github/workflows/core.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install test requirements
|
||||
run: python3 ./devscripts/install_deps.py --include dev --include curl-cffi
|
||||
run: python3 ./devscripts/install_deps.py --include test --include curl-cffi
|
||||
- name: Run tests
|
||||
continue-on-error: False
|
||||
run: |
|
||||
|
16
yt-dlp/.github/workflows/quick-test.yml
vendored
16
yt-dlp/.github/workflows/quick-test.yml
vendored
@@ -15,13 +15,13 @@ jobs:
|
||||
with:
|
||||
python-version: '3.8'
|
||||
- name: Install test requirements
|
||||
run: python3 ./devscripts/install_deps.py --include dev
|
||||
run: python3 ./devscripts/install_deps.py --include test
|
||||
- name: Run tests
|
||||
run: |
|
||||
python3 -m yt_dlp -v || true
|
||||
python3 ./devscripts/run_tests.py core
|
||||
flake8:
|
||||
name: Linter
|
||||
check:
|
||||
name: Code check
|
||||
if: "!contains(github.event.head_commit.message, 'ci skip all')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -29,9 +29,11 @@ jobs:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.8'
|
||||
- name: Install flake8
|
||||
run: python3 ./devscripts/install_deps.py -o --include dev
|
||||
- name: Install dev dependencies
|
||||
run: python3 ./devscripts/install_deps.py -o --include static-analysis
|
||||
- name: Make lazy extractors
|
||||
run: python3 ./devscripts/make_lazy_extractors.py
|
||||
- name: Run flake8
|
||||
run: flake8 .
|
||||
- name: Run ruff
|
||||
run: ruff check --output-format github .
|
||||
- name: Run autopep8
|
||||
run: autopep8 --diff .
|
||||
|
2
yt-dlp/.gitignore
vendored
2
yt-dlp/.gitignore
vendored
@@ -67,7 +67,7 @@ cookies
|
||||
# Python
|
||||
*.pyc
|
||||
*.pyo
|
||||
.pytest_cache
|
||||
.*_cache
|
||||
wine-py2exe/
|
||||
py2exe.log
|
||||
build/
|
||||
|
14
yt-dlp/.pre-commit-config.yaml
Normal file
14
yt-dlp/.pre-commit-config.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: linter
|
||||
name: Apply linter fixes
|
||||
entry: ruff check --fix .
|
||||
language: system
|
||||
types: [python]
|
||||
require_serial: true
|
||||
- id: format
|
||||
name: Apply formatting fixes
|
||||
entry: autopep8 --in-place .
|
||||
language: system
|
||||
types: [python]
|
9
yt-dlp/.pre-commit-hatch.yaml
Normal file
9
yt-dlp/.pre-commit-hatch.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
repos:
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: fix
|
||||
name: Apply code fixes
|
||||
entry: hatch fmt
|
||||
language: system
|
||||
types: [python]
|
||||
require_serial: true
|
@@ -134,18 +134,53 @@ We follow [youtube-dl's policy](https://github.com/ytdl-org/youtube-dl#can-you-a
|
||||
|
||||
# DEVELOPER INSTRUCTIONS
|
||||
|
||||
Most users do not need to build yt-dlp and can [download the builds](https://github.com/yt-dlp/yt-dlp/releases) or get them via [the other installation methods](README.md#installation).
|
||||
Most users do not need to build yt-dlp and can [download the builds](https://github.com/yt-dlp/yt-dlp/releases), get them via [the other installation methods](README.md#installation) or directly run it using `python -m yt_dlp`.
|
||||
|
||||
To run yt-dlp as a developer, you don't need to build anything either. Simply execute
|
||||
`yt-dlp` uses [`hatch`](<https://hatch.pypa.io>) as a project management tool.
|
||||
You can easily install it using [`pipx`](<https://pipx.pypa.io>) via `pipx install hatch`, or else via `pip` or your package manager of choice. Make sure you are using at least version `1.10.0`, otherwise some functionality might not work as expected.
|
||||
|
||||
python3 -m yt_dlp
|
||||
If you plan on contributing to `yt-dlp`, best practice is to start by running the following command:
|
||||
|
||||
To run all the available core tests, use:
|
||||
```shell
|
||||
$ hatch run setup
|
||||
```
|
||||
|
||||
python3 devscripts/run_tests.py
|
||||
The above command will install a `pre-commit` hook so that required checks/fixes (linting, formatting) will run automatically before each commit. If any code needs to be linted or formatted, then the commit will be blocked and the necessary changes will be made; you should review all edits and re-commit the fixed version.
|
||||
|
||||
After this you can use `hatch shell` to enable a virtual environment that has `yt-dlp` and its development dependencies installed.
|
||||
|
||||
In addition, the following script commands can be used to run simple tasks such as linting or testing (without having to run `hatch shell` first):
|
||||
* `hatch fmt`: Automatically fix linter violations and apply required code formatting changes
|
||||
* See `hatch fmt --help` for more info
|
||||
* `hatch test`: Run extractor or core tests
|
||||
* See `hatch test --help` for more info
|
||||
|
||||
See item 6 of [new extractor tutorial](#adding-support-for-a-new-site) for how to run extractor specific test cases.
|
||||
|
||||
While it is strongly recommended to use `hatch` for yt-dlp development, if you are unable to do so, alternatively you can manually create a virtual environment and use the following commands:
|
||||
|
||||
```shell
|
||||
# To only install development dependencies:
|
||||
$ python -m devscripts.install_deps --include dev
|
||||
|
||||
# Or, for an editable install plus dev dependencies:
|
||||
$ python -m pip install -e ".[default,dev]"
|
||||
|
||||
# To setup the pre-commit hook:
|
||||
$ pre-commit install
|
||||
|
||||
# To be used in place of `hatch test`:
|
||||
$ python -m devscripts.run_tests
|
||||
|
||||
# To be used in place of `hatch fmt`:
|
||||
$ ruff check --fix .
|
||||
$ autopep8 --in-place .
|
||||
|
||||
# To only check code instead of applying fixes:
|
||||
$ ruff check .
|
||||
$ autopep8 --diff .
|
||||
```
|
||||
|
||||
If you want to create a build of yt-dlp yourself, you can follow the instructions [here](README.md#compile).
|
||||
|
||||
|
||||
@@ -165,12 +200,16 @@ After you have ensured this site is distributing its content legally, you can fo
|
||||
1. [Fork this repository](https://github.com/yt-dlp/yt-dlp/fork)
|
||||
1. Check out the source code with:
|
||||
|
||||
git clone git@github.com:YOUR_GITHUB_USERNAME/yt-dlp.git
|
||||
```shell
|
||||
$ git clone git@github.com:YOUR_GITHUB_USERNAME/yt-dlp.git
|
||||
```
|
||||
|
||||
1. Start a new git branch with
|
||||
|
||||
cd yt-dlp
|
||||
git checkout -b yourextractor
|
||||
```shell
|
||||
$ cd yt-dlp
|
||||
$ git checkout -b yourextractor
|
||||
```
|
||||
|
||||
1. Start with this simple template and save it to `yt_dlp/extractor/yourextractor.py`:
|
||||
|
||||
@@ -217,21 +256,27 @@ After you have ensured this site is distributing its content legally, you can fo
|
||||
# TODO more properties (see yt_dlp/extractor/common.py)
|
||||
}
|
||||
```
|
||||
1. Add an import in [`yt_dlp/extractor/_extractors.py`](yt_dlp/extractor/_extractors.py). Note that the class name must end with `IE`.
|
||||
1. Run `python3 devscripts/run_tests.py YourExtractor`. This *may fail* at first, but you can continually re-run it until you're done. Upon failure, it will output the missing fields and/or correct values which you can copy. If you decide to add more than one test, the tests will then be named `YourExtractor`, `YourExtractor_1`, `YourExtractor_2`, etc. Note that tests with an `only_matching` key in the test's dict are not included in the count. You can also run all the tests in one go with `YourExtractor_all`
|
||||
1. Add an import in [`yt_dlp/extractor/_extractors.py`](yt_dlp/extractor/_extractors.py). Note that the class name must end with `IE`. Also note that when adding a parenthesized import group, the last import in the group must have a trailing comma in order for this formatting to be respected by our code formatter.
|
||||
1. Run `hatch test YourExtractor`. This *may fail* at first, but you can continually re-run it until you're done. Upon failure, it will output the missing fields and/or correct values which you can copy. If you decide to add more than one test, the tests will then be named `YourExtractor`, `YourExtractor_1`, `YourExtractor_2`, etc. Note that tests with an `only_matching` key in the test's dict are not included in the count. You can also run all the tests in one go with `YourExtractor_all`
|
||||
1. Make sure you have at least one test for your extractor. Even if all videos covered by the extractor are expected to be inaccessible for automated testing, tests should still be added with a `skip` parameter indicating why the particular test is disabled from running.
|
||||
1. Have a look at [`yt_dlp/extractor/common.py`](yt_dlp/extractor/common.py) for possible helper methods and a [detailed description of what your extractor should and may return](yt_dlp/extractor/common.py#L119-L440). Add tests and code for as many as you want.
|
||||
1. Make sure your code follows [yt-dlp coding conventions](#yt-dlp-coding-conventions) and check the code with [flake8](https://flake8.pycqa.org/en/latest/index.html#quickstart):
|
||||
1. Make sure your code follows [yt-dlp coding conventions](#yt-dlp-coding-conventions), passes [ruff](https://docs.astral.sh/ruff/tutorial/#getting-started) code checks and is properly formatted:
|
||||
|
||||
$ flake8 yt_dlp/extractor/yourextractor.py
|
||||
```shell
|
||||
$ hatch fmt --check
|
||||
```
|
||||
|
||||
You can use `hatch fmt` to automatically fix problems.
|
||||
|
||||
1. Make sure your code works under all [Python](https://www.python.org/) versions supported by yt-dlp, namely CPython and PyPy for Python 3.8 and above. Backward compatibility is not required for even older versions of Python.
|
||||
1. When the tests pass, [add](https://git-scm.com/docs/git-add) the new files, [commit](https://git-scm.com/docs/git-commit) them and [push](https://git-scm.com/docs/git-push) the result, like this:
|
||||
|
||||
$ git add yt_dlp/extractor/_extractors.py
|
||||
$ git add yt_dlp/extractor/yourextractor.py
|
||||
$ git commit -m '[yourextractor] Add extractor'
|
||||
$ git push origin yourextractor
|
||||
```shell
|
||||
$ git add yt_dlp/extractor/_extractors.py
|
||||
$ git add yt_dlp/extractor/yourextractor.py
|
||||
$ git commit -m '[yourextractor] Add extractor'
|
||||
$ git push origin yourextractor
|
||||
```
|
||||
|
||||
1. Finally, [create a pull request](https://help.github.com/articles/creating-a-pull-request). We'll then review and merge it.
|
||||
|
||||
|
@@ -610,3 +610,23 @@ Offert4324
|
||||
sta1us
|
||||
Tomoka1
|
||||
trwstin
|
||||
alexhuot1
|
||||
clienthax
|
||||
DaPotato69
|
||||
emqi
|
||||
hugohaa
|
||||
imanoreotwe
|
||||
JakeFinley96
|
||||
lostfictions
|
||||
minamotorin
|
||||
ocococococ
|
||||
Podiumnoche
|
||||
RasmusAntons
|
||||
roeniss
|
||||
shoxie007
|
||||
Szpachlarz
|
||||
The-MAGI
|
||||
TuxCoder
|
||||
voidful
|
||||
vtexier
|
||||
WyohKnott
|
||||
|
@@ -4,6 +4,116 @@
|
||||
# To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master
|
||||
-->
|
||||
|
||||
### 2024.05.26
|
||||
|
||||
#### Core changes
|
||||
- [Better warning when requested subs format not found](https://github.com/yt-dlp/yt-dlp/commit/7e4259dff0b681a3f0e8a930799ce0394328c86e) ([#9873](https://github.com/yt-dlp/yt-dlp/issues/9873)) by [DaPotato69](https://github.com/DaPotato69)
|
||||
- [Merged with youtube-dl a08f2b7](https://github.com/yt-dlp/yt-dlp/commit/a4da9db87b6486b270c15dfa07ab5bfedc83f6bd) by [bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K)
|
||||
- [Warn if lack of ffmpeg alters format selection](https://github.com/yt-dlp/yt-dlp/commit/96da9525043f78aca4544d01761b13b2140e9ae6) ([#9805](https://github.com/yt-dlp/yt-dlp/issues/9805)) by [pukkandan](https://github.com/pukkandan), [seproDev](https://github.com/seproDev)
|
||||
- **cookies**
|
||||
- [Add `--cookies-from-browser` support for Whale](https://github.com/yt-dlp/yt-dlp/commit/dd9ad97b1fbdd36c086b8ba82328a4d954f78f8e) ([#9649](https://github.com/yt-dlp/yt-dlp/issues/9649)) by [roeniss](https://github.com/roeniss)
|
||||
- [Get chrome session cookies with `--cookies-from-browser`](https://github.com/yt-dlp/yt-dlp/commit/f1f158976e38d38a260762accafe7bbe6d451151) ([#9747](https://github.com/yt-dlp/yt-dlp/issues/9747)) by [StefanLobbenmeier](https://github.com/StefanLobbenmeier)
|
||||
- **windows**: [Improve shell quoting and tests](https://github.com/yt-dlp/yt-dlp/commit/64766459e37451b665c1464073c28361fbcf1c25) ([#9802](https://github.com/yt-dlp/yt-dlp/issues/9802)) by [Grub4K](https://github.com/Grub4K) (With fixes in [7e26bd5](https://github.com/yt-dlp/yt-dlp/commit/7e26bd53f9c5893518fde81dfd0079ec08dd841e))
|
||||
|
||||
#### Extractor changes
|
||||
- [Add POST data hash to `--write-pages` filenames](https://github.com/yt-dlp/yt-dlp/commit/61b17437dc14a1c7e90ff48a6198df77828c6df4) ([#9879](https://github.com/yt-dlp/yt-dlp/issues/9879)) by [minamotorin](https://github.com/minamotorin) (With fixes in [c999bac](https://github.com/yt-dlp/yt-dlp/commit/c999bac02c5a4f755b2a82488a975e91c988ffd8) by [bashonly](https://github.com/bashonly))
|
||||
- [Make `_search_nextjs_data` non fatal](https://github.com/yt-dlp/yt-dlp/commit/3ee1194288981c4f2c4abd8315326de0c424d2ce) ([#8937](https://github.com/yt-dlp/yt-dlp/issues/8937)) by [Grub4K](https://github.com/Grub4K)
|
||||
- **afreecatv**: live: [Add `cdn` extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/315b3544296bb83012e20ee3af9d3cbf5600dd1c) ([#9666](https://github.com/yt-dlp/yt-dlp/issues/9666)) by [bashonly](https://github.com/bashonly)
|
||||
- **alura**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/fc2879ecb05aaad36869609d154e4321362c1f63) ([#9658](https://github.com/yt-dlp/yt-dlp/issues/9658)) by [hugohaa](https://github.com/hugohaa)
|
||||
- **artetv**: [Label forced subtitles](https://github.com/yt-dlp/yt-dlp/commit/7b5674949fd03a33b47b67b31d56a5adf1c48c91) ([#9945](https://github.com/yt-dlp/yt-dlp/issues/9945)) by [vtexier](https://github.com/vtexier)
|
||||
- **bbc**: [Fix and extend extraction](https://github.com/yt-dlp/yt-dlp/commit/7975ddf245d22af034d5b983eeb1c5ec6c2ce053) ([#9705](https://github.com/yt-dlp/yt-dlp/issues/9705)) by [dirkf](https://github.com/dirkf), [kylegustavo](https://github.com/kylegustavo), [pukkandan](https://github.com/pukkandan)
|
||||
- **bilibili**: [Fix `--geo-verification-proxy` support](https://github.com/yt-dlp/yt-dlp/commit/2338827072dacab0f15348b70aec8685feefc8d1) ([#9817](https://github.com/yt-dlp/yt-dlp/issues/9817)) by [fireattack](https://github.com/fireattack)
|
||||
- **bilibilispacevideo**
|
||||
- [Better error message](https://github.com/yt-dlp/yt-dlp/commit/06d52c87314e0bbc16c43c405090843885577b88) ([#9839](https://github.com/yt-dlp/yt-dlp/issues/9839)) by [fireattack](https://github.com/fireattack)
|
||||
- [Fix extraction](https://github.com/yt-dlp/yt-dlp/commit/4cc99d7b6cce8b39506ead01407445d576b63ee4) ([#9905](https://github.com/yt-dlp/yt-dlp/issues/9905)) by [c-basalt](https://github.com/c-basalt)
|
||||
- **boosty**: [Add cookies support](https://github.com/yt-dlp/yt-dlp/commit/145dc6f6563e80d2da1b3e9aea2ffa795b71622c) ([#9522](https://github.com/yt-dlp/yt-dlp/issues/9522)) by [RasmusAntons](https://github.com/RasmusAntons)
|
||||
- **brilliantpala**: [Fix login](https://github.com/yt-dlp/yt-dlp/commit/eead3bbc01f6529862bdad1f0b2adeabda4f006e) ([#9788](https://github.com/yt-dlp/yt-dlp/issues/9788)) by [pzhlkj6612](https://github.com/pzhlkj6612)
|
||||
- **canalalpha**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/00a9f2e1f7fa69499221f2e8dd73a08efeef79bc) ([#9675](https://github.com/yt-dlp/yt-dlp/issues/9675)) by [kclauhk](https://github.com/kclauhk)
|
||||
- **cbc.ca**: player: [Improve `_VALID_URL`](https://github.com/yt-dlp/yt-dlp/commit/c8bf48f3a8fa29587e7c73ef5a7710385a5ea725) ([#9866](https://github.com/yt-dlp/yt-dlp/issues/9866)) by [carusocr](https://github.com/carusocr)
|
||||
- **cda**: [Fix age-gated web extraction](https://github.com/yt-dlp/yt-dlp/commit/6d8a53d870ff6795f509085bfbf3981417999038) ([#9939](https://github.com/yt-dlp/yt-dlp/issues/9939)) by [dirkf](https://github.com/dirkf), [emqi](https://github.com/emqi), [Podiumnoche](https://github.com/Podiumnoche), [Szpachlarz](https://github.com/Szpachlarz)
|
||||
- **commonmistakes**: [Raise error on blob URLs](https://github.com/yt-dlp/yt-dlp/commit/98d71d8c5e5dab08b561ee6f137e968d2a004262) ([#9897](https://github.com/yt-dlp/yt-dlp/issues/9897)) by [seproDev](https://github.com/seproDev)
|
||||
- **crunchyroll**
|
||||
- [Always make metadata available](https://github.com/yt-dlp/yt-dlp/commit/cb2fb4a643949322adba561ca73bcba3221ec0c5) ([#9772](https://github.com/yt-dlp/yt-dlp/issues/9772)) by [bashonly](https://github.com/bashonly)
|
||||
- [Fix auth and remove cookies support](https://github.com/yt-dlp/yt-dlp/commit/ff38a011d57b763f3a69bebd25a5dc9044a717ce) ([#9749](https://github.com/yt-dlp/yt-dlp/issues/9749)) by [bashonly](https://github.com/bashonly)
|
||||
- [Fix stream extraction](https://github.com/yt-dlp/yt-dlp/commit/f2816634e3be88fe158b342ee33918de3c272a54) ([#10005](https://github.com/yt-dlp/yt-dlp/issues/10005)) by [bashonly](https://github.com/bashonly)
|
||||
- [Support browser impersonation](https://github.com/yt-dlp/yt-dlp/commit/5904853ae5788509fdc4892cb7ecdfa9ae7f78e6) ([#9857](https://github.com/yt-dlp/yt-dlp/issues/9857)) by [bashonly](https://github.com/bashonly)
|
||||
- **dangalplay**: [Add extractors](https://github.com/yt-dlp/yt-dlp/commit/0d067e77c3f5527946fb0c22ee1c7011994cba40) ([#10021](https://github.com/yt-dlp/yt-dlp/issues/10021)) by [bashonly](https://github.com/bashonly)
|
||||
- **discoveryplus**: [Fix dmax.de and related extractors](https://github.com/yt-dlp/yt-dlp/commit/90d2da311bbb5dc06f385ee428c7e4590936e995) ([#10020](https://github.com/yt-dlp/yt-dlp/issues/10020)) by [bashonly](https://github.com/bashonly)
|
||||
- **eplus**: [Handle URLs without videos](https://github.com/yt-dlp/yt-dlp/commit/351dc0bc334c4e1b5f00c152818c3ec0ed71f788) ([#9855](https://github.com/yt-dlp/yt-dlp/issues/9855)) by [pzhlkj6612](https://github.com/pzhlkj6612)
|
||||
- **europarlwebstream**: [Support new URL format](https://github.com/yt-dlp/yt-dlp/commit/800a43983e5fb719526ce4cb3956216085c63268) ([#9647](https://github.com/yt-dlp/yt-dlp/issues/9647)) by [seproDev](https://github.com/seproDev), [voidful](https://github.com/voidful)
|
||||
- **facebook**: [Fix DASH formats extraction](https://github.com/yt-dlp/yt-dlp/commit/e3b42d8b1b8bcfff7ba146c19fc3f6f6ba843cea) ([#9734](https://github.com/yt-dlp/yt-dlp/issues/9734)) by [bashonly](https://github.com/bashonly)
|
||||
- **godresource**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/65e709d23530959075816e966c42179ad46e8e3b) ([#9629](https://github.com/yt-dlp/yt-dlp/issues/9629)) by [HobbyistDev](https://github.com/HobbyistDev)
|
||||
- **googledrive**: [Fix formats extraction](https://github.com/yt-dlp/yt-dlp/commit/85ec2a337ac325cf6427cbafd56f0a034c1a5218) ([#9908](https://github.com/yt-dlp/yt-dlp/issues/9908)) by [WyohKnott](https://github.com/WyohKnott)
|
||||
- **hearthisat**: [Improve `_VALID_URL`](https://github.com/yt-dlp/yt-dlp/commit/5bbfdb7c999b22f1aeca0c3489c167d6eb73013b) ([#9949](https://github.com/yt-dlp/yt-dlp/issues/9949)) by [bohwaz](https://github.com/bohwaz), [seproDev](https://github.com/seproDev)
|
||||
- **hytale**: [Use `CloudflareStreamIE` explicitly](https://github.com/yt-dlp/yt-dlp/commit/31b417e1d1ccc67d5c027bf8878f483dc34cb118) ([#9672](https://github.com/yt-dlp/yt-dlp/issues/9672)) by [llamasblade](https://github.com/llamasblade)
|
||||
- **instagram**: [Support `/reels/` URLs](https://github.com/yt-dlp/yt-dlp/commit/06cb0638392b607b47d3c2ac48eb2ebecb0f060d) ([#9539](https://github.com/yt-dlp/yt-dlp/issues/9539)) by [amir16yp](https://github.com/amir16yp)
|
||||
- **jiocinema**: [Add extractors](https://github.com/yt-dlp/yt-dlp/commit/1463945ae5fb05986a0bd1aa02e41d1a08d93a02) ([#10026](https://github.com/yt-dlp/yt-dlp/issues/10026)) by [bashonly](https://github.com/bashonly)
|
||||
- **jiosaavn**: [Extract via API and fix playlists](https://github.com/yt-dlp/yt-dlp/commit/0c21c53885cf03f4040467ae8c44d7ff51016116) ([#9656](https://github.com/yt-dlp/yt-dlp/issues/9656)) by [bashonly](https://github.com/bashonly)
|
||||
- **lci**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/5a2eebc76770fca91ffabeff658d560f716fec80) ([#10025](https://github.com/yt-dlp/yt-dlp/issues/10025)) by [ocococococ](https://github.com/ocococococ)
|
||||
- **mixch**: [Extract comments](https://github.com/yt-dlp/yt-dlp/commit/b38018b781b062d5169d104ab430489aef8e7f1e) ([#9860](https://github.com/yt-dlp/yt-dlp/issues/9860)) by [pzhlkj6612](https://github.com/pzhlkj6612)
|
||||
- **moviepilot**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/296df0da1d38a44d34c99b60a18066c301774537) ([#9366](https://github.com/yt-dlp/yt-dlp/issues/9366)) by [panatexxa](https://github.com/panatexxa)
|
||||
- **netease**: program: [Improve `--no-playlist` message](https://github.com/yt-dlp/yt-dlp/commit/73f12119b52d98281804b0c072b2ed6aa841ec88) ([#9488](https://github.com/yt-dlp/yt-dlp/issues/9488)) by [pzhlkj6612](https://github.com/pzhlkj6612)
|
||||
- **nfb**: [Fix extractors](https://github.com/yt-dlp/yt-dlp/commit/0a1a8e3005f66c44bf67633dccd4df19c3fccd1a) ([#9650](https://github.com/yt-dlp/yt-dlp/issues/9650)) by [rrgomes](https://github.com/rrgomes)
|
||||
- **ntslive**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/be7db1a5a8c483726c511c30ea4689cbb8b27962) ([#9641](https://github.com/yt-dlp/yt-dlp/issues/9641)) by [lostfictions](https://github.com/lostfictions)
|
||||
- **orf**: on: [Improve extraction](https://github.com/yt-dlp/yt-dlp/commit/0dd53faeca2ba0ce138e4092d07b5f2dbf2422f9) ([#9677](https://github.com/yt-dlp/yt-dlp/issues/9677)) by [TuxCoder](https://github.com/TuxCoder)
|
||||
- **orftvthek**: [Remove extractor](https://github.com/yt-dlp/yt-dlp/commit/3779f2a307ba3ef1d28e107cdd71b221dfb4eb36) ([#10011](https://github.com/yt-dlp/yt-dlp/issues/10011)) by [seproDev](https://github.com/seproDev)
|
||||
- **patreon**
|
||||
- [Extract multiple embeds](https://github.com/yt-dlp/yt-dlp/commit/036e0d92c6052465673d459678322ea03e61483d) ([#9850](https://github.com/yt-dlp/yt-dlp/issues/9850)) by [bashonly](https://github.com/bashonly)
|
||||
- [Fix Vimeo embed extraction](https://github.com/yt-dlp/yt-dlp/commit/c9ce57d9bf51541da2381d99bc096a9d0ddf1f27) ([#9712](https://github.com/yt-dlp/yt-dlp/issues/9712)) by [bashonly](https://github.com/bashonly)
|
||||
- **piapro**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/3ba8de62d61d782256f5c1e9939a0762039657de) ([#9311](https://github.com/yt-dlp/yt-dlp/issues/9311)) by [FinnRG](https://github.com/FinnRG), [seproDev](https://github.com/seproDev)
|
||||
- **pornhub**: [Fix login by email address](https://github.com/yt-dlp/yt-dlp/commit/518c1afc1592cae3e4eb39dc646b5bc059333112) ([#9914](https://github.com/yt-dlp/yt-dlp/issues/9914)) by [feederbox826](https://github.com/feederbox826)
|
||||
- **qub**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/6b54cccdcb892bca3e55993480d8b86f1c7e6da6) ([#7019](https://github.com/yt-dlp/yt-dlp/issues/7019)) by [alexhuot1](https://github.com/alexhuot1), [dirkf](https://github.com/dirkf)
|
||||
- **reddit**: [Fix subtitles extraction](https://github.com/yt-dlp/yt-dlp/commit/82f4f4444e26daf35b7302c406fe2312f78f619e) ([#10006](https://github.com/yt-dlp/yt-dlp/issues/10006)) by [kclauhk](https://github.com/kclauhk)
|
||||
- **soundcloud**
|
||||
- [Add `formats` extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/beaf832c7a9d57833f365ce18f6115b88071b296) ([#10004](https://github.com/yt-dlp/yt-dlp/issues/10004)) by [bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K)
|
||||
- [Extract `genres`](https://github.com/yt-dlp/yt-dlp/commit/231c2eacc41b06b65c63edf94c0d04768a5da607) ([#9821](https://github.com/yt-dlp/yt-dlp/issues/9821)) by [bashonly](https://github.com/bashonly)
|
||||
- **taptap**: [Add extractors](https://github.com/yt-dlp/yt-dlp/commit/63b569bc5e7d461753637a20ad84a575adee4c0a) ([#9776](https://github.com/yt-dlp/yt-dlp/issues/9776)) by [c-basalt](https://github.com/c-basalt)
|
||||
- **tele5**: [Overhaul extractor](https://github.com/yt-dlp/yt-dlp/commit/c92e4e625e9e6bbbbf8e3b20c3e7ebe57c16072d) ([#10024](https://github.com/yt-dlp/yt-dlp/issues/10024)) by [bashonly](https://github.com/bashonly)
|
||||
- **theatercomplextown**: [Fix extractors](https://github.com/yt-dlp/yt-dlp/commit/8056a3026ed6ec6a6d0ed56fdd7ebcd16e928341) ([#9754](https://github.com/yt-dlp/yt-dlp/issues/9754)) by [bashonly](https://github.com/bashonly)
|
||||
- **tiktok**
|
||||
- [Add `device_id` extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/3584b8390bd21c0393a3079eeee71aed56a1c1d8) ([#9951](https://github.com/yt-dlp/yt-dlp/issues/9951)) by [bashonly](https://github.com/bashonly)
|
||||
- [Extract all web formats](https://github.com/yt-dlp/yt-dlp/commit/4ccd73fea0f6f4be343e1ec7f22dd03799addcf8) ([#9960](https://github.com/yt-dlp/yt-dlp/issues/9960)) by [bashonly](https://github.com/bashonly)
|
||||
- [Extract via mobile API only if extractor-arg is passed](https://github.com/yt-dlp/yt-dlp/commit/41ba4a808b597a3afed78c89675a30deb6844450) ([#9938](https://github.com/yt-dlp/yt-dlp/issues/9938)) by [bashonly](https://github.com/bashonly)
|
||||
- [Fix subtitles extraction](https://github.com/yt-dlp/yt-dlp/commit/eef1e9f44ff14c5e65b759bb1eafa3946cdaf719) ([#9961](https://github.com/yt-dlp/yt-dlp/issues/9961)) by [bashonly](https://github.com/bashonly)
|
||||
- collection: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/119d41f27061d220d276a2d38cfc8d873437452a) ([#9986](https://github.com/yt-dlp/yt-dlp/issues/9986)) by [bashonly](https://github.com/bashonly), [imanoreotwe](https://github.com/imanoreotwe)
|
||||
- user: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/347f13dd9bccc2b4db3ea25689410d45d8370ed4) ([#9661](https://github.com/yt-dlp/yt-dlp/issues/9661)) by [bashonly](https://github.com/bashonly)
|
||||
- **tv5monde**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/6db96268c521e945d42649607db1574f5d92e082) ([#9143](https://github.com/yt-dlp/yt-dlp/issues/9143)) by [alard](https://github.com/alard), [seproDev](https://github.com/seproDev)
|
||||
- **twitter**
|
||||
- [Fix auth for x.com migration](https://github.com/yt-dlp/yt-dlp/commit/3e35aa32c74bc108375be8c8b6b3bfc90dfff1b4) ([#9952](https://github.com/yt-dlp/yt-dlp/issues/9952)) by [bashonly](https://github.com/bashonly)
|
||||
- [Support x.com URLs](https://github.com/yt-dlp/yt-dlp/commit/4813173e4544f125d6f2afc31e600727d761b8dd) ([#9926](https://github.com/yt-dlp/yt-dlp/issues/9926)) by [bashonly](https://github.com/bashonly)
|
||||
- **vk**: [Improve format extraction](https://github.com/yt-dlp/yt-dlp/commit/df5c9e733aaba703cf285c0372b6d61629330c82) ([#9885](https://github.com/yt-dlp/yt-dlp/issues/9885)) by [seproDev](https://github.com/seproDev)
|
||||
- **wrestleuniverse**: [Avoid partial stream formats](https://github.com/yt-dlp/yt-dlp/commit/c4853655cb9a793129280806af643de43c48f4d5) ([#9800](https://github.com/yt-dlp/yt-dlp/issues/9800)) by [bashonly](https://github.com/bashonly)
|
||||
- **xiaohongshu**: [Add extractor](https://github.com/yt-dlp/yt-dlp/commit/a2e9031605d87c469be9ce98dbbdf4960b727338) ([#9646](https://github.com/yt-dlp/yt-dlp/issues/9646)) by [HobbyistDev](https://github.com/HobbyistDev)
|
||||
- **xvideos**: quickies: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/b207d26f83fb8ab0ce56df74dff43ff583a3264f) ([#9834](https://github.com/yt-dlp/yt-dlp/issues/9834)) by [JakeFinley96](https://github.com/JakeFinley96)
|
||||
- **youporn**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/351368cb9a6731b886a58f5a10fd6b302bbe47be) ([#8827](https://github.com/yt-dlp/yt-dlp/issues/8827)) by [The-MAGI](https://github.com/The-MAGI)
|
||||
- **youtube**
|
||||
- [Add `mediaconnect` client](https://github.com/yt-dlp/yt-dlp/commit/cf212d0a331aba05c32117573f760cdf3af8c62f) ([#9546](https://github.com/yt-dlp/yt-dlp/issues/9546)) by [clienthax](https://github.com/clienthax)
|
||||
- [Extract upload timestamp if available](https://github.com/yt-dlp/yt-dlp/commit/96a134dea6397a5f2131947c427aac52c8b4e677) ([#9856](https://github.com/yt-dlp/yt-dlp/issues/9856)) by [coletdjnz](https://github.com/coletdjnz)
|
||||
- [Fix comments extraction](https://github.com/yt-dlp/yt-dlp/commit/8e15177b4113c355989881e4e030f695a9b59c3a) ([#9775](https://github.com/yt-dlp/yt-dlp/issues/9775)) by [bbilly1](https://github.com/bbilly1), [jakeogh](https://github.com/jakeogh), [minamotorin](https://github.com/minamotorin), [shoxie007](https://github.com/shoxie007)
|
||||
- [Remove `android` from default clients](https://github.com/yt-dlp/yt-dlp/commit/12d8ea8246fa901de302ff5cc748caddadc82f41) ([#9553](https://github.com/yt-dlp/yt-dlp/issues/9553)) by [bashonly](https://github.com/bashonly), [coletdjnz](https://github.com/coletdjnz)
|
||||
- **zenyandex**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/c4b87dd885ee5391e5f481e7c8bd550a7c543623) ([#9813](https://github.com/yt-dlp/yt-dlp/issues/9813)) by [src-tinkerer](https://github.com/src-tinkerer)
|
||||
|
||||
#### Networking changes
|
||||
- [Add `extensions` attribute to `Response`](https://github.com/yt-dlp/yt-dlp/commit/bec9a59e8ec82c18e3bf9268eaa436793dd52e35) ([#9756](https://github.com/yt-dlp/yt-dlp/issues/9756)) by [bashonly](https://github.com/bashonly)
|
||||
- **Request Handler**
|
||||
- requests
|
||||
- [Patch support for `requests` 2.32.2+](https://github.com/yt-dlp/yt-dlp/commit/3f7999533ebe41c2a579d91b4e4cb211cfcd3bc0) ([#9992](https://github.com/yt-dlp/yt-dlp/issues/9992)) by [Grub4K](https://github.com/Grub4K)
|
||||
- [Update to `requests` 2.32.0](https://github.com/yt-dlp/yt-dlp/commit/c36513f1be2ef3d3cec864accbffda1afaa06ffd) ([#9980](https://github.com/yt-dlp/yt-dlp/issues/9980)) by [coletdjnz](https://github.com/coletdjnz)
|
||||
|
||||
#### Misc. changes
|
||||
- [Add `hatch`, `ruff`, `pre-commit` and improve dev docs](https://github.com/yt-dlp/yt-dlp/commit/e897bd8292a41999cf51dba91b390db5643c72db) ([#7409](https://github.com/yt-dlp/yt-dlp/issues/7409)) by [bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K), [seproDev](https://github.com/seproDev)
|
||||
- **build**
|
||||
- [Migrate `linux_exe` to static musl builds](https://github.com/yt-dlp/yt-dlp/commit/ac817bc83efd939dca3e40c4b527d0ccfc77172b) ([#9811](https://github.com/yt-dlp/yt-dlp/issues/9811)) by [bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K)
|
||||
- [Normalize `curl_cffi` group to `curl-cffi`](https://github.com/yt-dlp/yt-dlp/commit/02483bea1c4dbe1bace8ca4d19700104fbb8a00f) ([#9698](https://github.com/yt-dlp/yt-dlp/issues/9698)) by [bashonly](https://github.com/bashonly) (With fixes in [89f535e](https://github.com/yt-dlp/yt-dlp/commit/89f535e2656964b4061c25a7739d4d6ba0a30568))
|
||||
- [Run `macos_legacy` job on `macos-12`](https://github.com/yt-dlp/yt-dlp/commit/1a366403d9c26b992faa77e00f4d02ead57559e3) ([#9804](https://github.com/yt-dlp/yt-dlp/issues/9804)) by [bashonly](https://github.com/bashonly)
|
||||
- [`macos` job requires `setuptools<70`](https://github.com/yt-dlp/yt-dlp/commit/78c57cc0e0998b8ed90e4306f410aa4be4115cd7) ([#9993](https://github.com/yt-dlp/yt-dlp/issues/9993)) by [bashonly](https://github.com/bashonly)
|
||||
- **cleanup**
|
||||
- [Remove questionable extractors](https://github.com/yt-dlp/yt-dlp/commit/01395a34345d1c6ba1b73ca92f94dd200dc45341) ([#9911](https://github.com/yt-dlp/yt-dlp/issues/9911)) by [seproDev](https://github.com/seproDev)
|
||||
- Miscellaneous: [5c019f6](https://github.com/yt-dlp/yt-dlp/commit/5c019f6328ad40d66561eac3c4de0b3cd070d0f6), [ae2af11](https://github.com/yt-dlp/yt-dlp/commit/ae2af1104f80caf2f47544763a33db2c17a3e1de) by [bashonly](https://github.com/bashonly), [Grub4K](https://github.com/Grub4K), [seproDev](https://github.com/seproDev)
|
||||
- **test**
|
||||
- [Add HTTP proxy tests](https://github.com/yt-dlp/yt-dlp/commit/3c7a287e281d9f9a353dce8902ff78a84c24a040) ([#9578](https://github.com/yt-dlp/yt-dlp/issues/9578)) by [coletdjnz](https://github.com/coletdjnz)
|
||||
- [Fix connect timeout test](https://github.com/yt-dlp/yt-dlp/commit/53b4d44f55cca66ac33dab092ef2a30b1164b684) ([#9906](https://github.com/yt-dlp/yt-dlp/issues/9906)) by [coletdjnz](https://github.com/coletdjnz)
|
||||
|
||||
### 2024.04.09
|
||||
|
||||
#### Important changes
|
||||
|
@@ -27,7 +27,7 @@ clean-dist:
|
||||
yt_dlp/extractor/lazy_extractors.py *.spec CONTRIBUTING.md.tmp yt-dlp yt-dlp.exe yt_dlp.egg-info/ AUTHORS
|
||||
clean-cache:
|
||||
find . \( \
|
||||
-type d -name .pytest_cache -o -type d -name __pycache__ -o -name "*.pyc" -o -name "*.class" \
|
||||
-type d -name ".*_cache" -o -type d -name __pycache__ -o -name "*.pyc" -o -name "*.class" \
|
||||
\) -prune -exec rm -rf {} \;
|
||||
|
||||
completion-bash: completions/bash/yt-dlp
|
||||
@@ -70,14 +70,15 @@ uninstall:
|
||||
rm -f $(DESTDIR)$(SHAREDIR)/fish/vendor_completions.d/yt-dlp.fish
|
||||
|
||||
codetest:
|
||||
flake8 .
|
||||
ruff check .
|
||||
autopep8 --diff .
|
||||
|
||||
test:
|
||||
$(PYTHON) -m pytest
|
||||
$(PYTHON) -m pytest -Werror
|
||||
$(MAKE) codetest
|
||||
|
||||
offlinetest: codetest
|
||||
$(PYTHON) -m pytest -k "not download"
|
||||
$(PYTHON) -m pytest -Werror -m "not download"
|
||||
|
||||
CODE_FOLDERS_CMD = find yt_dlp -type f -name '__init__.py' | sed 's,/__init__.py,,' | grep -v '/__' | sort
|
||||
CODE_FOLDERS != $(CODE_FOLDERS_CMD)
|
||||
@@ -151,7 +152,7 @@ yt-dlp.tar.gz: all
|
||||
--exclude '*.pyo' \
|
||||
--exclude '*~' \
|
||||
--exclude '__pycache__' \
|
||||
--exclude '.pytest_cache' \
|
||||
--exclude '.*_cache' \
|
||||
--exclude '.git' \
|
||||
-- \
|
||||
README.md supportedsites.md Changelog.md LICENSE \
|
||||
|
@@ -108,7 +108,6 @@ File|Description
|
||||
[yt-dlp_x86.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_x86.exe)|Windows (Win7 SP1+) standalone x86 (32-bit) binary
|
||||
[yt-dlp_min.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_min.exe)|Windows (Win7 SP1+) standalone x64 binary built with `py2exe`<br/> ([Not recommended](#standalone-py2exe-builds-windows))
|
||||
[yt-dlp_linux](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux)|Linux standalone x64 binary
|
||||
[yt-dlp_linux.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux.zip)|Unpackaged Linux executable (no auto-update)
|
||||
[yt-dlp_linux_armv7l](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_armv7l)|Linux standalone armv7l (32-bit) binary
|
||||
[yt-dlp_linux_aarch64](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_linux_aarch64)|Linux standalone aarch64 (64-bit) binary
|
||||
[yt-dlp_win.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win.zip)|Unpackaged Windows executable (no auto-update)
|
||||
@@ -170,7 +169,7 @@ Example usage:
|
||||
yt-dlp --update-to nightly
|
||||
|
||||
# To install nightly with pip:
|
||||
python3 -m pip install -U --pre yt-dlp[default]
|
||||
python3 -m pip install -U --pre "yt-dlp[default]"
|
||||
```
|
||||
|
||||
## DEPENDENCIES
|
||||
@@ -202,7 +201,7 @@ While all the other dependencies are optional, `ffmpeg` and `ffprobe` are highly
|
||||
The following provide support for impersonating browser requests. This may be required for some sites that employ TLS fingerprinting.
|
||||
|
||||
* [**curl_cffi**](https://github.com/yifeikong/curl_cffi) (recommended) - Python binding for [curl-impersonate](https://github.com/lwthiker/curl-impersonate). Provides impersonation targets for Chrome, Edge and Safari. Licensed under [MIT](https://github.com/yifeikong/curl_cffi/blob/main/LICENSE)
|
||||
* Can be installed with the `curl-cffi` group, e.g. `pip install yt-dlp[default,curl-cffi]`
|
||||
* Can be installed with the `curl-cffi` group, e.g. `pip install "yt-dlp[default,curl-cffi]"`
|
||||
* Currently only included in `yt-dlp.exe` and `yt-dlp_macos` builds
|
||||
|
||||
|
||||
@@ -666,16 +665,17 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git
|
||||
The name of the browser to load cookies
|
||||
from. Currently supported browsers are:
|
||||
brave, chrome, chromium, edge, firefox,
|
||||
opera, safari, vivaldi, whale. Optionally, the
|
||||
KEYRING used for decrypting Chromium cookies
|
||||
on Linux, the name/path of the PROFILE to
|
||||
load cookies from, and the CONTAINER name
|
||||
(if Firefox) ("none" for no container) can
|
||||
be given with their respective seperators.
|
||||
By default, all containers of the most
|
||||
recently accessed profile are used.
|
||||
Currently supported keyrings are: basictext,
|
||||
gnomekeyring, kwallet, kwallet5, kwallet6
|
||||
opera, safari, vivaldi, whale. Optionally,
|
||||
the KEYRING used for decrypting Chromium
|
||||
cookies on Linux, the name/path of the
|
||||
PROFILE to load cookies from, and the
|
||||
CONTAINER name (if Firefox) ("none" for no
|
||||
container) can be given with their
|
||||
respective seperators. By default, all
|
||||
containers of the most recently accessed
|
||||
profile are used. Currently supported
|
||||
keyrings are: basictext, gnomekeyring,
|
||||
kwallet, kwallet5, kwallet6
|
||||
--no-cookies-from-browser Do not load cookies from browser (default)
|
||||
--cache-dir DIR Location in the filesystem where yt-dlp can
|
||||
store some downloaded information (such as
|
||||
@@ -1751,7 +1751,7 @@ $ yt-dlp --replace-in-metadata "title,uploader" "[ _]" "-"
|
||||
|
||||
# EXTRACTOR ARGUMENTS
|
||||
|
||||
Some extractors accept additional arguments which can be passed using `--extractor-args KEY:ARGS`. `ARGS` is a `;` (semicolon) separated string of `ARG=VAL1,VAL2`. E.g. `--extractor-args "youtube:player-client=android_embedded,web;include_live_dash" --extractor-args "funimation:version=uncut"`
|
||||
Some extractors accept additional arguments which can be passed using `--extractor-args KEY:ARGS`. `ARGS` is a `;` (semicolon) separated string of `ARG=VAL1,VAL2`. E.g. `--extractor-args "youtube:player-client=android_embedded,web;formats=incomplete" --extractor-args "funimation:version=uncut"`
|
||||
|
||||
Note: In CLI, `ARG` can use `-` instead of `_`; e.g. `youtube:player-client"` becomes `youtube:player_client"`
|
||||
|
||||
@@ -2123,7 +2123,7 @@ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
||||
|
||||
### New features
|
||||
|
||||
* Forked from [**yt-dlc@f9401f2**](https://github.com/blackjack4494/yt-dlc/commit/f9401f2a91987068139c5f757b12fc711d4c0cee) and merged with [**youtube-dl@be008e6**](https://github.com/ytdl-org/youtube-dl/commit/be008e657d79832642e2158557c899249c9e31cd) ([exceptions](https://github.com/yt-dlp/yt-dlp/issues/21))
|
||||
* Forked from [**yt-dlc@f9401f2**](https://github.com/blackjack4494/yt-dlc/commit/f9401f2a91987068139c5f757b12fc711d4c0cee) and merged with [**youtube-dl@a08f2b7**](https://github.com/ytdl-org/youtube-dl/commit/a08f2b7e4567cdc50c0614ee0a4ffdff49b8b6e6) ([exceptions](https://github.com/yt-dlp/yt-dlp/issues/21))
|
||||
|
||||
* **[SponsorBlock Integration](#sponsorblock-options)**: You can mark/remove sponsor sections in YouTube videos by utilizing the [SponsorBlock](https://sponsor.ajay.app) API
|
||||
|
||||
@@ -2333,6 +2333,7 @@ These options may no longer work as intended
|
||||
--write-annotations No supported site has annotations now
|
||||
--no-write-annotations Default
|
||||
--compat-options seperate-video-versions No longer needed
|
||||
--compat-options no-youtube-prefer-utc-upload-date No longer supported
|
||||
|
||||
#### Removed
|
||||
These options were deprecated since 2014 and have now been entirely removed
|
||||
|
@@ -147,5 +147,27 @@
|
||||
"action": "add",
|
||||
"when": "9590cc6b4768e190183d7d071a6c78170889116a",
|
||||
"short": "[priority] Security: [[CVE-2024-22423](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-22423)] [Prevent RCE when using `--exec` with `%q` on Windows](https://github.com/yt-dlp/yt-dlp/security/advisories/GHSA-hjq6-52gw-2g7p)\n - The shell escape function now properly escapes `%`, `\\` and `\\n`.\n - `utils.Popen` has been patched accordingly."
|
||||
},
|
||||
{
|
||||
"action": "change",
|
||||
"when": "41ba4a808b597a3afed78c89675a30deb6844450",
|
||||
"short": "[ie/tiktok] Extract via mobile API only if extractor-arg is passed (#9938)",
|
||||
"authors": ["bashonly"]
|
||||
},
|
||||
{
|
||||
"action": "remove",
|
||||
"when": "6e36d17f404556f0e3a43f441c477a71a91877d9"
|
||||
},
|
||||
{
|
||||
"action": "change",
|
||||
"when": "beaf832c7a9d57833f365ce18f6115b88071b296",
|
||||
"short": "[ie/soundcloud] Add `formats` extractor-arg (#10004)",
|
||||
"authors": ["bashonly", "Grub4K"]
|
||||
},
|
||||
{
|
||||
"action": "change",
|
||||
"when": "5c019f6328ad40d66561eac3c4de0b3cd070d0f6",
|
||||
"short": "[cleanup] Misc (#9765)",
|
||||
"authors": ["bashonly", "Grub4K", "seproDev"]
|
||||
}
|
||||
]
|
||||
|
@@ -42,17 +42,25 @@ def parse_args():
|
||||
def main():
|
||||
args = parse_args()
|
||||
project_table = parse_toml(read_file(args.input))['project']
|
||||
recursive_pattern = re.compile(rf'{project_table["name"]}\[(?P<group_name>[\w-]+)\]')
|
||||
optional_groups = project_table['optional-dependencies']
|
||||
excludes = args.exclude or []
|
||||
|
||||
def yield_deps(group):
|
||||
for dep in group:
|
||||
if mobj := recursive_pattern.fullmatch(dep):
|
||||
yield from optional_groups.get(mobj.group('group_name'), [])
|
||||
else:
|
||||
yield dep
|
||||
|
||||
targets = []
|
||||
if not args.only_optional: # `-o` should exclude 'dependencies' and the 'default' group
|
||||
targets.extend(project_table['dependencies'])
|
||||
if 'default' not in excludes: # `--exclude default` should exclude entire 'default' group
|
||||
targets.extend(optional_groups['default'])
|
||||
targets.extend(yield_deps(optional_groups['default']))
|
||||
|
||||
for include in filter(None, map(optional_groups.get, args.include or [])):
|
||||
targets.extend(include)
|
||||
targets.extend(yield_deps(include))
|
||||
|
||||
targets = [t for t in targets if re.match(r'[\w-]+', t).group(0).lower() not in excludes]
|
||||
|
||||
|
@@ -1,4 +0,0 @@
|
||||
@echo off
|
||||
|
||||
>&2 echo run_tests.bat is deprecated. Please use `devscripts/run_tests.py` instead
|
||||
python %~dp0run_tests.py %~1
|
@@ -4,6 +4,7 @@ import argparse
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
@@ -18,6 +19,8 @@ def parse_args():
|
||||
'test', help='a extractor tests, or one of "core" or "download"', nargs='*')
|
||||
parser.add_argument(
|
||||
'-k', help='run a test matching EXPRESSION. Same as "pytest -k"', metavar='EXPRESSION')
|
||||
parser.add_argument(
|
||||
'--pytest-args', help='arguments to passthrough to pytest')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -26,15 +29,16 @@ def run_tests(*tests, pattern=None, ci=False):
|
||||
run_download = 'download' in tests
|
||||
tests = list(map(fix_test_name, tests))
|
||||
|
||||
arguments = ['pytest', '-Werror', '--tb=short']
|
||||
pytest_args = args.pytest_args or os.getenv('HATCH_TEST_ARGS', '')
|
||||
arguments = ['pytest', '-Werror', '--tb=short', *shlex.split(pytest_args)]
|
||||
if ci:
|
||||
arguments.append('--color=yes')
|
||||
if pattern:
|
||||
arguments.extend(['-k', pattern])
|
||||
if run_core:
|
||||
arguments.extend(['-m', 'not download'])
|
||||
elif run_download:
|
||||
arguments.extend(['-m', 'download'])
|
||||
elif pattern:
|
||||
arguments.extend(['-k', pattern])
|
||||
else:
|
||||
arguments.extend(
|
||||
f'test/test_download.py::TestDownload::test_{test}' for test in tests)
|
||||
@@ -46,13 +50,13 @@ def run_tests(*tests, pattern=None, ci=False):
|
||||
pass
|
||||
|
||||
arguments = [sys.executable, '-Werror', '-m', 'unittest']
|
||||
if pattern:
|
||||
arguments.extend(['-k', pattern])
|
||||
if run_core:
|
||||
print('"pytest" needs to be installed to run core tests', file=sys.stderr, flush=True)
|
||||
return 1
|
||||
elif run_download:
|
||||
arguments.append('test.test_download')
|
||||
elif pattern:
|
||||
arguments.extend(['-k', pattern])
|
||||
else:
|
||||
arguments.extend(
|
||||
f'test.test_download.TestDownload.test_{test}' for test in tests)
|
||||
|
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
>&2 echo 'run_tests.sh is deprecated. Please use `devscripts/run_tests.py` instead'
|
||||
python3 devscripts/run_tests.py "$1"
|
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Allow execution from anywhere
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
import warnings
|
||||
|
||||
from bundle.pyinstaller import main
|
||||
|
||||
warnings.warn(DeprecationWarning('`pyinst.py` is deprecated and will be removed in a future version. '
|
||||
'Use `bundle.pyinstaller` instead'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@@ -66,9 +66,16 @@ build = [
|
||||
"wheel",
|
||||
]
|
||||
dev = [
|
||||
"flake8",
|
||||
"isort",
|
||||
"pytest",
|
||||
"pre-commit",
|
||||
"yt-dlp[static-analysis]",
|
||||
"yt-dlp[test]",
|
||||
]
|
||||
static-analysis = [
|
||||
"autopep8~=2.0",
|
||||
"ruff~=0.4.4",
|
||||
]
|
||||
test = [
|
||||
"pytest~=8.1",
|
||||
]
|
||||
pyinstaller = [
|
||||
"pyinstaller>=6.3; sys_platform!='darwin'",
|
||||
@@ -126,3 +133,146 @@ artifacts = ["/yt_dlp/extractor/lazy_extractors.py"]
|
||||
[tool.hatch.version]
|
||||
path = "yt_dlp/version.py"
|
||||
pattern = "_pkg_version = '(?P<version>[^']+)'"
|
||||
|
||||
[tool.hatch.envs.default]
|
||||
features = ["curl-cffi", "default"]
|
||||
dependencies = ["pre-commit"]
|
||||
path = ".venv"
|
||||
installer = "uv"
|
||||
|
||||
[tool.hatch.envs.default.scripts]
|
||||
setup = "pre-commit install --config .pre-commit-hatch.yaml"
|
||||
yt-dlp = "python -Werror -Xdev -m yt_dlp {args}"
|
||||
|
||||
[tool.hatch.envs.hatch-static-analysis]
|
||||
detached = true
|
||||
features = ["static-analysis"]
|
||||
dependencies = [] # override hatch ruff version
|
||||
config-path = "pyproject.toml"
|
||||
|
||||
[tool.hatch.envs.hatch-static-analysis.scripts]
|
||||
format-check = "autopep8 --diff {args:.}"
|
||||
format-fix = "autopep8 --in-place {args:.}"
|
||||
lint-check = "ruff check {args:.}"
|
||||
lint-fix = "ruff check --fix {args:.}"
|
||||
|
||||
[tool.hatch.envs.hatch-test]
|
||||
features = ["test"]
|
||||
dependencies = [
|
||||
"pytest-randomly~=3.15",
|
||||
"pytest-rerunfailures~=14.0",
|
||||
"pytest-xdist[psutil]~=3.5",
|
||||
]
|
||||
|
||||
[tool.hatch.envs.hatch-test.scripts]
|
||||
run = "python -m devscripts.run_tests {args}"
|
||||
run-cov = "echo Code coverage not implemented && exit 1"
|
||||
|
||||
[[tool.hatch.envs.hatch-test.matrix]]
|
||||
python = [
|
||||
"3.8",
|
||||
"3.9",
|
||||
"3.10",
|
||||
"3.11",
|
||||
"3.12",
|
||||
"pypy3.8",
|
||||
"pypy3.9",
|
||||
"pypy3.10",
|
||||
]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
|
||||
[tool.ruff.lint]
|
||||
ignore = [
|
||||
"E402", # module level import not at top of file
|
||||
"E501", # line too long
|
||||
"E731", # do not assign a lambda expression, use a def
|
||||
"E741", # ambiguous variable name
|
||||
]
|
||||
select = [
|
||||
"E", # pycodestyle errors
|
||||
"W", # pycodestyle warnings
|
||||
"F", # pyflakes
|
||||
"I", # import order
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"devscripts/lazy_load_template.py" = ["F401"]
|
||||
"!yt_dlp/extractor/**.py" = ["I"]
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
known-first-party = [
|
||||
"bundle",
|
||||
"devscripts",
|
||||
"test",
|
||||
]
|
||||
relative-imports-order = "closest-to-furthest"
|
||||
|
||||
[tool.autopep8]
|
||||
max_line_length = 120
|
||||
recursive = true
|
||||
exit-code = true
|
||||
jobs = 0
|
||||
select = [
|
||||
"E101",
|
||||
"E112",
|
||||
"E113",
|
||||
"E115",
|
||||
"E116",
|
||||
"E117",
|
||||
"E121",
|
||||
"E122",
|
||||
"E123",
|
||||
"E124",
|
||||
"E125",
|
||||
"E126",
|
||||
"E127",
|
||||
"E128",
|
||||
"E129",
|
||||
"E131",
|
||||
"E201",
|
||||
"E202",
|
||||
"E203",
|
||||
"E211",
|
||||
"E221",
|
||||
"E222",
|
||||
"E223",
|
||||
"E224",
|
||||
"E225",
|
||||
"E226",
|
||||
"E227",
|
||||
"E228",
|
||||
"E231",
|
||||
"E241",
|
||||
"E242",
|
||||
"E251",
|
||||
"E252",
|
||||
"E261",
|
||||
"E262",
|
||||
"E265",
|
||||
"E266",
|
||||
"E271",
|
||||
"E272",
|
||||
"E273",
|
||||
"E274",
|
||||
"E275",
|
||||
"E301",
|
||||
"E302",
|
||||
"E303",
|
||||
"E304",
|
||||
"E305",
|
||||
"E306",
|
||||
"E502",
|
||||
"E701",
|
||||
"E702",
|
||||
"E704",
|
||||
"W391",
|
||||
"W504",
|
||||
]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "-ra -v --strict-markers"
|
||||
markers = [
|
||||
"download",
|
||||
]
|
||||
|
@@ -14,12 +14,6 @@ remove-duplicate-keys = true
|
||||
remove-unused-variables = true
|
||||
|
||||
|
||||
[tool:pytest]
|
||||
addopts = -ra -v --strict-markers
|
||||
markers =
|
||||
download
|
||||
|
||||
|
||||
[tox:tox]
|
||||
skipsdist = true
|
||||
envlist = py{38,39,310,311,312},pypy{38,39,310}
|
||||
|
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Allow execution from anywhere
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
import warnings
|
||||
|
||||
|
||||
if sys.argv[1:2] == ['py2exe']:
|
||||
warnings.warn(DeprecationWarning('`setup.py py2exe` is deprecated and will be removed in a future version. '
|
||||
'Use `bundle.py2exe` instead'))
|
||||
|
||||
import bundle.py2exe
|
||||
|
||||
bundle.py2exe.main()
|
||||
|
||||
elif 'build_lazy_extractors' in sys.argv:
|
||||
warnings.warn(DeprecationWarning('`setup.py build_lazy_extractors` is deprecated and will be removed in a future version. '
|
||||
'Use `devscripts.make_lazy_extractors` instead'))
|
||||
|
||||
import subprocess
|
||||
|
||||
os.chdir(sys.path[0])
|
||||
print('running build_lazy_extractors')
|
||||
subprocess.run([sys.executable, 'devscripts/make_lazy_extractors.py'])
|
||||
|
||||
else:
|
||||
|
||||
print(
|
||||
'ERROR: Building by calling `setup.py` is deprecated. '
|
||||
'Use a build frontend like `build` instead. ',
|
||||
'Refer to https://build.pypa.io for more info', file=sys.stderr)
|
||||
sys.exit(1)
|
@@ -14,7 +14,6 @@
|
||||
- **6play**
|
||||
- **7plus**
|
||||
- **8tracks**
|
||||
- **91porn**
|
||||
- **9c9media**
|
||||
- **9gag**: 9GAG
|
||||
- **9News**
|
||||
@@ -220,7 +219,7 @@
|
||||
- **BusinessInsider**
|
||||
- **BuzzFeed**
|
||||
- **BYUtv**: (**Currently broken**)
|
||||
- **CableAV**
|
||||
- **CaffeineTV**
|
||||
- **Callin**
|
||||
- **Caltrans**
|
||||
- **CAM4**
|
||||
@@ -333,6 +332,8 @@
|
||||
- **DailyWirePodcast**
|
||||
- **damtomo:record**
|
||||
- **damtomo:video**
|
||||
- **dangalplay**: [*dangalplay*](## "netrc machine")
|
||||
- **dangalplay:season**: [*dangalplay*](## "netrc machine")
|
||||
- **daum.net**
|
||||
- **daum.net:clip**
|
||||
- **daum.net:playlist**
|
||||
@@ -396,7 +397,6 @@
|
||||
- **EinsUndEinsTV**: [*1und1tv*](## "netrc machine")
|
||||
- **EinsUndEinsTVLive**: [*1und1tv*](## "netrc machine")
|
||||
- **EinsUndEinsTVRecordings**: [*1und1tv*](## "netrc machine")
|
||||
- **Einthusan**
|
||||
- **eitb.tv**
|
||||
- **ElementorEmbed**
|
||||
- **Elonet**
|
||||
@@ -498,6 +498,7 @@
|
||||
- **GameStar**
|
||||
- **Gaskrank**
|
||||
- **Gazeta**: (**Currently broken**)
|
||||
- **GBNews**: GB News clips, features and live streams
|
||||
- **GDCVault**: [*gdcvault*](## "netrc machine") (**Currently broken**)
|
||||
- **GediDigital**
|
||||
- **gem.cbc.ca**: [*cbcgem*](## "netrc machine")
|
||||
@@ -527,6 +528,7 @@
|
||||
- **GMANetworkVideo**
|
||||
- **Go**
|
||||
- **GoDiscovery**
|
||||
- **GodResource**
|
||||
- **GodTube**: (**Currently broken**)
|
||||
- **Gofile**
|
||||
- **Golem**
|
||||
@@ -630,11 +632,11 @@
|
||||
- **iwara:user**: [*iwara*](## "netrc machine")
|
||||
- **Ixigua**
|
||||
- **Izlesene**
|
||||
- **Jable**
|
||||
- **JablePlaylist**
|
||||
- **Jamendo**
|
||||
- **JamendoAlbum**
|
||||
- **JeuxVideo**: (**Currently broken**)
|
||||
- **jiocinema**: [*jiocinema*](## "netrc machine")
|
||||
- **jiocinema:series**: [*jiocinema*](## "netrc machine")
|
||||
- **jiosaavn:album**
|
||||
- **jiosaavn:playlist**
|
||||
- **jiosaavn:song**
|
||||
@@ -974,6 +976,7 @@
|
||||
- **NRKTVSeason**
|
||||
- **NRKTVSeries**
|
||||
- **NRLTV**: (**Currently broken**)
|
||||
- **nts.live**
|
||||
- **ntv.ru**
|
||||
- **NubilesPorn**: [*nubiles-porn*](## "netrc machine")
|
||||
- **nuum:live**
|
||||
@@ -1015,7 +1018,6 @@
|
||||
- **orf:on**
|
||||
- **orf:podcast**
|
||||
- **orf:radio**
|
||||
- **orf:tvthek**: ORF TVthek
|
||||
- **OsnatelTV**: [*osnateltv*](## "netrc machine")
|
||||
- **OsnatelTVLive**: [*osnateltv*](## "netrc machine")
|
||||
- **OsnatelTVRecordings**: [*osnateltv*](## "netrc machine")
|
||||
@@ -1394,6 +1396,10 @@
|
||||
- **SztvHu**
|
||||
- **t-online.de**: (**Currently broken**)
|
||||
- **Tagesschau**: (**Currently broken**)
|
||||
- **TapTapApp**
|
||||
- **TapTapAppIntl**
|
||||
- **TapTapMoment**
|
||||
- **TapTapPostIntl**
|
||||
- **Tass**: (**Currently broken**)
|
||||
- **TBS**
|
||||
- **TBSJPEpisode**
|
||||
@@ -1412,7 +1418,7 @@
|
||||
- **TedSeries**
|
||||
- **TedTalk**
|
||||
- **Tele13**
|
||||
- **Tele5**: (**Currently broken**)
|
||||
- **Tele5**
|
||||
- **TeleBruxelles**
|
||||
- **TelecaribePlay**
|
||||
- **Telecinco**: telecinco.es, cuatro.com and mediaset.es
|
||||
@@ -1452,11 +1458,12 @@
|
||||
- **ThreeSpeak**
|
||||
- **ThreeSpeakUser**
|
||||
- **TikTok**
|
||||
- **tiktok:collection**
|
||||
- **tiktok:effect**: (**Currently broken**)
|
||||
- **tiktok:live**
|
||||
- **tiktok:sound**: (**Currently broken**)
|
||||
- **tiktok:tag**: (**Currently broken**)
|
||||
- **tiktok:user**: (**Currently broken**)
|
||||
- **tiktok:user**
|
||||
- **TLC**
|
||||
- **TMZ**
|
||||
- **TNAFlix**
|
||||
@@ -1501,7 +1508,7 @@
|
||||
- **tv2play.hu**
|
||||
- **tv2playseries.hu**
|
||||
- **TV4**: tv4.se and tv4play.se
|
||||
- **TV5MondePlus**: TV5MONDE+
|
||||
- **TV5MONDE**
|
||||
- **tv5unis**
|
||||
- **tv5unis:video**
|
||||
- **tv8.it**
|
||||
@@ -1639,8 +1646,6 @@
|
||||
- **voicy**: (**Currently broken**)
|
||||
- **voicy:channel**: (**Currently broken**)
|
||||
- **VolejTV**
|
||||
- **Voot**: [*voot*](## "netrc machine") (**Currently broken**)
|
||||
- **VootSeries**: [*voot*](## "netrc machine") (**Currently broken**)
|
||||
- **VoxMedia**
|
||||
- **VoxMediaVolume**
|
||||
- **vpro**: npo.nl, ntr.nl, omroepwnl.nl, zapp.nl and npo3.nl
|
||||
@@ -1715,10 +1720,10 @@
|
||||
- **wykop:post:comment**
|
||||
- **Xanimu**
|
||||
- **XboxClips**
|
||||
- **XFileShare**: XFileShare based sites: Aparat, ClipWatching, GoUnlimited, GoVid, HolaVid, Streamty, TheVideoBee, Uqload, VidBom, vidlo, VidLocker, VidShare, VUp, WolfStream, XVideoSharing
|
||||
- **XHamster**
|
||||
- **XHamsterEmbed**
|
||||
- **XHamsterUser**
|
||||
- **XiaoHongShu**: 小红书
|
||||
- **ximalaya**: 喜马拉雅FM
|
||||
- **ximalaya:album**: 喜马拉雅FM 专辑
|
||||
- **xinpianchang**: xinpianchang.com (**Currently broken**)
|
||||
@@ -1749,8 +1754,12 @@
|
||||
- **YouNowLive**
|
||||
- **YouNowMoment**
|
||||
- **YouPorn**
|
||||
- **YourPorn**
|
||||
- **YourUpload**
|
||||
- **YouPornCategory**: YouPorn category, with sorting, filtering and pagination
|
||||
- **YouPornChannel**: YouPorn channel, with sorting and pagination
|
||||
- **YouPornCollection**: YouPorn collection (user playlist), with sorting and pagination
|
||||
- **YouPornStar**: YouPorn Pornstar, with description, sorting and pagination
|
||||
- **YouPornTag**: YouPorn tag (porntags), with sorting, filtering and pagination
|
||||
- **YouPornVideos**: YouPorn video (browse) playlists, with sorting, filtering and pagination
|
||||
- **youtube**: YouTube
|
||||
- **youtube:clip**
|
||||
- **youtube:favorites**: YouTube liked videos; ":ytfav" keyword (requires cookies)
|
||||
|
@@ -1912,7 +1912,7 @@ jwplayer("mediaplayer").setup({"abouttext":"Visit Indie DB","aboutlink":"http:\/
|
||||
self.assertEqual(self.ie._search_nextjs_data('', None, fatal=False), {})
|
||||
self.assertEqual(self.ie._search_nextjs_data('', None, default=None), None)
|
||||
self.assertEqual(self.ie._search_nextjs_data('', None, default={}), {})
|
||||
with self.assertRaises(DeprecationWarning):
|
||||
with self.assertWarns(DeprecationWarning):
|
||||
self.assertEqual(self.ie._search_nextjs_data('', None, default='{}'), {})
|
||||
|
||||
|
||||
|
@@ -93,6 +93,7 @@ if urllib3:
|
||||
|
||||
This allows us to chain multiple TLS connections.
|
||||
"""
|
||||
|
||||
def __init__(self, socket, ssl_context, server_hostname=None, suppress_ragged_eofs=True, server_side=False):
|
||||
self.incoming = ssl.MemoryBIO()
|
||||
self.outgoing = ssl.MemoryBIO()
|
||||
|
@@ -5,6 +5,7 @@ import os
|
||||
import sys
|
||||
import unittest
|
||||
import warnings
|
||||
import datetime as dt
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
@@ -27,6 +28,7 @@ from yt_dlp.utils import (
|
||||
ExtractorError,
|
||||
InAdvancePagedList,
|
||||
LazyList,
|
||||
NO_DEFAULT,
|
||||
OnDemandPagedList,
|
||||
Popen,
|
||||
age_restricted,
|
||||
@@ -768,6 +770,11 @@ class TestUtil(unittest.TestCase):
|
||||
|
||||
def test_parse_iso8601(self):
|
||||
self.assertEqual(parse_iso8601('2014-03-23T23:04:26+0100'), 1395612266)
|
||||
self.assertEqual(parse_iso8601('2014-03-23T23:04:26-07:00'), 1395641066)
|
||||
self.assertEqual(parse_iso8601('2014-03-23T23:04:26', timezone=dt.timedelta(hours=-7)), 1395641066)
|
||||
self.assertEqual(parse_iso8601('2014-03-23T23:04:26', timezone=NO_DEFAULT), None)
|
||||
# default does not override timezone in date_str
|
||||
self.assertEqual(parse_iso8601('2014-03-23T23:04:26-07:00', timezone=dt.timedelta(hours=-10)), 1395641066)
|
||||
self.assertEqual(parse_iso8601('2014-03-23T22:04:26+0000'), 1395612266)
|
||||
self.assertEqual(parse_iso8601('2014-03-23T22:04:26Z'), 1395612266)
|
||||
self.assertEqual(parse_iso8601('2014-03-23T22:04:26.1234Z'), 1395612266)
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -6,10 +6,10 @@ import time
|
||||
from .common import InfoExtractor
|
||||
from ..compat import compat_str
|
||||
from ..utils import (
|
||||
dict_get,
|
||||
ExtractorError,
|
||||
js_to_json,
|
||||
dict_get,
|
||||
int_or_none,
|
||||
js_to_json,
|
||||
parse_iso8601,
|
||||
str_or_none,
|
||||
traverse_obj,
|
||||
|
@@ -12,20 +12,21 @@ import urllib.parse
|
||||
import urllib.request
|
||||
import urllib.response
|
||||
import uuid
|
||||
from ..utils.networking import clean_proxies
|
||||
|
||||
from .common import InfoExtractor
|
||||
from ..aes import aes_ecb_decrypt
|
||||
from ..utils import (
|
||||
ExtractorError,
|
||||
OnDemandPagedList,
|
||||
bytes_to_intlist,
|
||||
decode_base_n,
|
||||
int_or_none,
|
||||
intlist_to_bytes,
|
||||
OnDemandPagedList,
|
||||
time_seconds,
|
||||
traverse_obj,
|
||||
update_url_query,
|
||||
)
|
||||
from ..utils.networking import clean_proxies
|
||||
|
||||
|
||||
def add_opener(ydl, handler): # FIXME: Create proper API in .networking
|
||||
|
@@ -3,10 +3,10 @@ from ..utils import (
|
||||
float_or_none,
|
||||
format_field,
|
||||
int_or_none,
|
||||
str_or_none,
|
||||
traverse_obj,
|
||||
parse_codecs,
|
||||
parse_qs,
|
||||
str_or_none,
|
||||
traverse_obj,
|
||||
)
|
||||
|
||||
|
||||
|
@@ -10,18 +10,18 @@ from ..aes import aes_cbc_decrypt_bytes, unpad_pkcs7
|
||||
from ..compat import compat_b64decode
|
||||
from ..networking.exceptions import HTTPError
|
||||
from ..utils import (
|
||||
ExtractorError,
|
||||
ass_subtitles_timecode,
|
||||
bytes_to_intlist,
|
||||
bytes_to_long,
|
||||
ExtractorError,
|
||||
float_or_none,
|
||||
int_or_none,
|
||||
intlist_to_bytes,
|
||||
long_to_bytes,
|
||||
parse_iso8601,
|
||||
pkcs1pad,
|
||||
strip_or_none,
|
||||
str_or_none,
|
||||
strip_or_none,
|
||||
try_get,
|
||||
unified_strdate,
|
||||
urlencode_postdata,
|
||||
|
@@ -4,11 +4,11 @@ import re
|
||||
from .common import InfoExtractor
|
||||
from ..compat import compat_str
|
||||
from ..utils import (
|
||||
ISO639Utils,
|
||||
OnDemandPagedList,
|
||||
float_or_none,
|
||||
int_or_none,
|
||||
ISO639Utils,
|
||||
join_nonempty,
|
||||
OnDemandPagedList,
|
||||
parse_duration,
|
||||
str_or_none,
|
||||
str_to_int,
|
||||
|
@@ -5,7 +5,7 @@ from ..utils import (
|
||||
int_or_none,
|
||||
mimetype2ext,
|
||||
parse_iso8601,
|
||||
traverse_obj
|
||||
traverse_obj,
|
||||
)
|
||||
|
||||
|
||||
|
@@ -12,7 +12,6 @@ from ..utils import (
|
||||
)
|
||||
from ..utils.traversal import traverse_obj
|
||||
|
||||
|
||||
_FIELDS = '''
|
||||
_id
|
||||
clipImageSource
|
||||
|
@@ -1,9 +1,9 @@
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
parse_iso8601,
|
||||
int_or_none,
|
||||
parse_duration,
|
||||
parse_filesize,
|
||||
int_or_none,
|
||||
parse_iso8601,
|
||||
)
|
||||
|
||||
|
||||
|
@@ -1,17 +1,13 @@
|
||||
import re
|
||||
|
||||
from .common import InfoExtractor
|
||||
|
||||
from ..compat import (
|
||||
compat_urlparse,
|
||||
)
|
||||
|
||||
from ..compat import compat_urlparse
|
||||
from ..utils import (
|
||||
ExtractorError,
|
||||
clean_html,
|
||||
int_or_none,
|
||||
urlencode_postdata,
|
||||
urljoin,
|
||||
int_or_none,
|
||||
clean_html,
|
||||
ExtractorError
|
||||
)
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
from .common import InfoExtractor
|
||||
from .youtube import YoutubeIE
|
||||
from .vimeo import VimeoIE
|
||||
from .youtube import YoutubeIE
|
||||
from ..utils import (
|
||||
int_or_none,
|
||||
parse_iso8601,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
determine_ext,
|
||||
ExtractorError,
|
||||
determine_ext,
|
||||
int_or_none,
|
||||
mimetype2ext,
|
||||
parse_iso8601,
|
||||
|
@@ -5,7 +5,7 @@ from ..utils import (
|
||||
int_or_none,
|
||||
str_or_none,
|
||||
traverse_obj,
|
||||
unified_timestamp
|
||||
unified_timestamp,
|
||||
)
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import re
|
||||
|
||||
from .common import InfoExtractor
|
||||
from ..utils import url_or_none, merge_dicts
|
||||
from ..utils import merge_dicts, url_or_none
|
||||
|
||||
|
||||
class AngelIE(InfoExtractor):
|
||||
|
@@ -1,8 +1,5 @@
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
str_to_int,
|
||||
ExtractorError
|
||||
)
|
||||
from ..utils import ExtractorError, str_to_int
|
||||
|
||||
|
||||
class AppleConnectIE(InfoExtractor):
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import re
|
||||
import json
|
||||
import re
|
||||
|
||||
from .common import InfoExtractor
|
||||
from ..compat import compat_urlparse
|
||||
|
@@ -4,8 +4,8 @@ from ..compat import (
|
||||
compat_urllib_parse_urlparse,
|
||||
)
|
||||
from ..utils import (
|
||||
format_field,
|
||||
float_or_none,
|
||||
format_field,
|
||||
int_or_none,
|
||||
parse_iso8601,
|
||||
remove_start,
|
||||
|
@@ -2,10 +2,10 @@ import datetime as dt
|
||||
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
ExtractorError,
|
||||
float_or_none,
|
||||
jwt_encode_hs256,
|
||||
try_get,
|
||||
ExtractorError,
|
||||
)
|
||||
|
||||
|
||||
|
@@ -2,8 +2,8 @@ import base64
|
||||
|
||||
from .common import InfoExtractor
|
||||
from ..compat import (
|
||||
compat_urllib_parse_urlencode,
|
||||
compat_str,
|
||||
compat_urllib_parse_urlencode,
|
||||
)
|
||||
from ..utils import (
|
||||
format_field,
|
||||
|
@@ -2,12 +2,12 @@ import math
|
||||
|
||||
from .common import InfoExtractor
|
||||
from ..compat import (
|
||||
compat_urllib_parse_urlparse,
|
||||
compat_parse_qs,
|
||||
compat_urllib_parse_urlparse,
|
||||
)
|
||||
from ..utils import (
|
||||
format_field,
|
||||
InAdvancePagedList,
|
||||
format_field,
|
||||
traverse_obj,
|
||||
unified_timestamp,
|
||||
)
|
||||
|
@@ -2,11 +2,11 @@ import json
|
||||
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
try_get,
|
||||
int_or_none,
|
||||
url_or_none,
|
||||
float_or_none,
|
||||
int_or_none,
|
||||
try_get,
|
||||
unified_timestamp,
|
||||
url_or_none,
|
||||
)
|
||||
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
from .common import InfoExtractor
|
||||
|
||||
from ..utils import (
|
||||
int_or_none,
|
||||
str_or_none,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
from .common import InfoExtractor
|
||||
from .amp import AMPIE
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
ExtractorError,
|
||||
int_or_none,
|
||||
|
@@ -1,3 +1,4 @@
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
mimetype2ext,
|
||||
parse_duration,
|
||||
@@ -5,7 +6,6 @@ from ..utils import (
|
||||
str_or_none,
|
||||
traverse_obj,
|
||||
)
|
||||
from .common import InfoExtractor
|
||||
|
||||
|
||||
class BloggerIE(InfoExtractor):
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import re
|
||||
|
||||
from .common import InfoExtractor
|
||||
|
||||
from ..utils import (
|
||||
extract_attributes,
|
||||
)
|
||||
|
@@ -1,9 +1,5 @@
|
||||
from .common import InfoExtractor
|
||||
from ..utils import (
|
||||
js_to_json,
|
||||
traverse_obj,
|
||||
unified_timestamp
|
||||
)
|
||||
from ..utils import js_to_json, traverse_obj, unified_timestamp
|
||||
|
||||
|
||||
class BoxCastVideoIE(InfoExtractor):
|
||||
|
@@ -6,7 +6,7 @@ from ..utils import (
|
||||
classproperty,
|
||||
int_or_none,
|
||||
traverse_obj,
|
||||
urljoin
|
||||
urljoin,
|
||||
)
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user