├── .eslintrc.json
├── .gitignore
├── README.md
├── next-env.d.ts
├── next.config.js
├── package.json
├── pages
├── _app.tsx
├── api
│ ├── arg.ts
│ └── temp.ts
└── index.tsx
├── pnpm-lock.yaml
├── public
├── favicon.ico
└── vercel.svg
├── styles
└── globals.css
├── tsconfig.json
└── utils
└── index.ts
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env.local
29 | .env.development.local
30 | .env.test.local
31 | .env.production.local
32 |
33 | # vercel
34 | .vercel
35 |
36 | # typescript
37 | *.tsbuildinfo
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Sgmodule Argument Proxy](https://sgmodule-argument-proxy.vercel.app)
2 |
3 | 用于需要修改 argument 的 sgmodule 模版,无需 fork 修改,直接通过配置即可生成对应的 sgmodule URL
4 |
5 | [立即使用](https://sgmodule-argument-proxy.vercel.app)
6 |
7 | ## 示例
8 |
9 | https://raw.githubusercontent.com/baranwang/Surge-Resources/master/Modules/SubInfoPanel/SubInfoPanel.sgmodule
10 |
11 | 原 sgmodule 模版内容为
12 |
13 | ```properties
14 | #!name=Sub Info Panel
15 | #!desc=build argument use sgmodule-argument-proxy.vercel.app
16 |
17 | [Script]
18 | Sub_info = type=generic,timeout=10,script-path=https://raw.githubusercontent.com/lhie1/Rules/master/Surge/Surge%204/Script/sub_info_panel.js,script-update-interval=0,argument=url=[URL encode 后的机场节点链接]&reset_day=1&title=AmyInfo&icon=bonjour&color=#007aff
19 |
20 | [Panel]
21 | Sub_info = script-name=Sub_info,update-interval=600
22 | ```
23 |
24 | 使用转换工具配置 argument
25 |
26 | ```
27 | url=https%3A%2F%2Fdler.cloud%2Fsubscribe%2Ffoobar&reset_day=1&title=Dlercloud&icon=network&color=#1473e6
28 | ```
29 |
30 | 生成 sgmodule 链接为
31 |
32 | ```
33 | https://sgmodule-argument-proxy.vercel.app/api/temp?url=https%3A%2F%2Fraw.githubusercontent.com%2Fbaranwang%2FSurge-Resources%2Fmaster%2FModules%2FSubInfoPanel%2FSubInfoPanel.sgmodule&arg=url%3Dhttps%253A%252F%252Fdler.cloud%252Fsubscribe%252Ffoobar%26reset_day%3D1%26title%3DDlercloud%26icon%3Dnetwork%26color%3D%231473e6
34 | ```
35 |
36 | 输出内容为
37 |
38 | ```properties
39 | #!name=Sub Info Panel
40 | #!desc=build argument use sgmodule-argument-proxy.vercel.app
41 |
42 | [Script]
43 | Sub_info = type=generic, timeout=10, script-path=https://raw.githubusercontent.com/lhie1/Rules/master/Surge/Surge%204/Script/sub_info_panel.js, script-update-interval=0, argument=url=https%3A%2F%2Fdler.cloud%2Fsubscribe%2Ffoobar&reset_day=1&title=Dlercloud&icon=network&color=#1473e6
44 |
45 | [Panel]
46 | Sub_info = script-name=Sub_info,update-interval=600
47 | ```
48 |
49 | ## 声明
50 |
51 | **纯字符串处理,不储存任何数据** 不放心可自行 [fork](https://github.com/baranwang/sgmodule-argument-proxy/fork?fragment=1) 本仓库搭建
52 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | module.exports = {
3 | reactStrictMode: true,
4 | }
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sgmodule-argument-proxy",
3 | "displayName": "Sgmodule Argument Proxy",
4 | "private": false,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "ahooks": "^3.1.5",
13 | "antd": "^4.18.3",
14 | "next": "12.0.7",
15 | "node-fetch": "^3.1.0",
16 | "react": "17.0.2",
17 | "react-dom": "17.0.2"
18 | },
19 | "devDependencies": {
20 | "@types/node": "17.0.8",
21 | "@types/react": "17.0.38",
22 | "eslint": "8.6.0",
23 | "eslint-config-next": "12.0.7",
24 | "typescript": "4.5.4"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import { Layout, Typography } from "antd";
2 | import { displayName } from "../package.json";
3 | import Head from "next/head";
4 | import type { AppProps } from "next/app";
5 |
6 | import "antd/dist/antd.css";
7 | import "../styles/globals.css";
8 |
9 | function MyApp({ Component, pageProps }: AppProps) {
10 | return (
11 | <>
12 |
13 | {displayName}
14 |
15 |
16 |
17 |
18 | {displayName}
19 |
20 |
21 |
22 |
23 |
24 |
25 | >
26 | );
27 | }
28 |
29 | export default MyApp;
30 |
--------------------------------------------------------------------------------
/pages/api/arg.ts:
--------------------------------------------------------------------------------
1 |
2 | import type { NextApiRequest, NextApiResponse } from 'next'
3 | import { getTemp } from '../../utils'
4 |
5 | export default async function handler(
6 | req: NextApiRequest,
7 | res: NextApiResponse
8 | ) {
9 | let { url } = req.query
10 | if (Array.isArray(url) || !url) {
11 | return res.status(400).json({ error: 'invalid query' })
12 | }
13 |
14 | try {
15 | const temp = await getTemp(url)
16 | const data: string[] = []
17 |
18 | for (let index = 0, isScript = false; index < temp.length; index += 1) {
19 | let line = temp[index];
20 | if (line.startsWith('#')) {
21 | continue
22 | }
23 | if (isScript && /^\[/.test(line)) {
24 | isScript = false
25 | }
26 | if (line.includes('[Script]')) {
27 | isScript = true
28 | }
29 | if (!isScript) {
30 | continue
31 | }
32 |
33 | const argument = line.split(',').find(item => item.trim().startsWith('argument='))
34 | if (argument) {
35 | data.push(argument.trim().replace(/^argument=/, ''))
36 | }
37 | }
38 |
39 | res.status(200).json({ data })
40 | } catch (e) {
41 | const error = (e as Error).toString()
42 | return res.status(400).json({ error })
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pages/api/temp.ts:
--------------------------------------------------------------------------------
1 | import type { NextApiRequest, NextApiResponse } from 'next'
2 | import { getTemp } from '../../utils'
3 |
4 | export default async function handler(
5 | req: NextApiRequest,
6 | res: NextApiResponse
7 | ) {
8 | let { url, arg } = req.query
9 | if (Array.isArray(url) || !url) {
10 | return res.status(400).send('invalid query')
11 | }
12 | if (arg && !Array.isArray(arg)) {
13 | arg = [arg]
14 | }
15 | try {
16 | const temp = await getTemp(url)
17 | const result: string[] = []
18 |
19 | for (let index = 0, isScript = false, argIndex = 0; index < temp.length; index += 1) {
20 | let line = temp[index];
21 | if (line.startsWith('#')) {
22 | result.push(line)
23 | continue
24 | }
25 |
26 | if (isScript && /^\[/.test(line)) {
27 | isScript = false
28 | }
29 | if (line.includes('[Script]')) {
30 | isScript = true
31 | }
32 | if (!isScript) {
33 | result.push(line)
34 | continue
35 | }
36 |
37 | line = line.split(',').map(item => {
38 | if (item.trim().startsWith('argument=')) {
39 | const argument = `argument=${arg[argIndex] || arg[0]}`
40 | argIndex += 1
41 | return argument
42 | }
43 | return item.trim()
44 | }).join(', ')
45 |
46 | result.push(line)
47 | }
48 |
49 | res.status(200).send(result.join('\n'))
50 | } catch (e) {
51 | const error = (e as Error).toString()
52 | return res.status(400).send(error)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import type { NextPage } from "next";
2 | import { Button, Card, Form, Input, Spin, Typography } from "antd";
3 | import { CSSProperties, useEffect } from "react";
4 | import { useRequest } from "ahooks";
5 |
6 | type Data = {
7 | url: string;
8 | arg: string[];
9 | };
10 |
11 | const Home: NextPage = () => {
12 | const [form] = Form.useForm();
13 |
14 | const {
15 | data: tempArgs,
16 | run: getTempArgs,
17 | loading,
18 | } = useRequest(
19 | (url) =>
20 | fetch(`/api/arg?url=${encodeURIComponent(url)}`)
21 | .then((res) => res.json())
22 | .then((res) => res.data),
23 | { manual: true }
24 | );
25 |
26 | useEffect(() => {
27 | if (!tempArgs) return;
28 | let arg = tempArgs;
29 | if (arg.every((item) => item === arg[0])) {
30 | arg = [arg[0]];
31 | }
32 | form.setFieldsValue({ arg });
33 | }, [form, tempArgs]);
34 |
35 | return (
36 |
37 |
39 | {
43 | try {
44 | getTempArgs(new URL(e.target.value).toString());
45 | } catch (error) {}
46 | }}
47 | />
48 |
49 |
50 |
51 |
52 | {(fields) => (
53 | <>
54 | {fields.map((field, index) => (
55 |
59 |
60 |
61 | ))}
62 | >
63 | )}
64 |
65 |
66 | shouldUpdate noStyle>
67 | {({ getFieldsValue }) => {
68 | if (!process.browser) return <>>;
69 | const { url, arg } = getFieldsValue();
70 | if (!url) return <>>;
71 | const result = new URL("/api/temp", window.location.origin);
72 | result.searchParams.set("url", url);
73 | arg?.forEach((item) => result.searchParams.append("arg", item));
74 | return (
75 |
76 |
80 | {
82 | const style: CSSProperties = {
83 | marginTop: "8px",
84 | marginBottom: "8px",
85 | marginLeft: "-4px",
86 | };
87 | return {
88 | text: result.toString(),
89 | tooltips: "",
90 | icon: [
91 | ,
94 | ,
97 | ],
98 | };
99 | })()}
100 | />
101 |
102 | );
103 | }}
104 |
105 |
106 |
107 |
108 | );
109 | };
110 |
111 | export default Home;
112 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/baranwang/sgmodule-argument-proxy/40b5827200b91d9a12311735777882e1943a9b4f/public/favicon.ico
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | html,
2 | body,
3 | #__next {
4 | min-height: 100%;
5 | }
6 |
7 | #__next {
8 | display: flex;
9 | flex-direction: column;
10 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true
17 | },
18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
19 | "exclude": ["node_modules"]
20 | }
21 |
--------------------------------------------------------------------------------
/utils/index.ts:
--------------------------------------------------------------------------------
1 | import fetch from 'node-fetch'
2 | import { URL } from 'url'
3 |
4 | export const getTemp = async (url: string) => {
5 | const temp = await fetch(new URL(url).toString()).then(response => response.text())
6 | return temp.split('\n')
7 | }
--------------------------------------------------------------------------------