mirror of
https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-10 00:52:40 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e61baf69a0 | ||
|
|
ea7a3d752c | ||
|
|
eef4fa0751 | ||
|
|
84dc0d63f2 | ||
|
|
9ce14351c5 | ||
|
|
76e781c711 | ||
|
|
f0acf4a2a7 | ||
|
|
9abeb4ce7b | ||
|
|
153802c7c4 | ||
|
|
19418b631f | ||
|
|
97caeed208 | ||
|
|
dd8d1d85e8 | ||
|
|
14ed56b5d5 | ||
|
|
9785271c5b | ||
|
|
05bdf95a29 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sub-store",
|
||||
"version": "2.14.353",
|
||||
"version": "2.14.367",
|
||||
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
isValidPortNumber,
|
||||
isNotBlank,
|
||||
ipAddress,
|
||||
getRandomPort,
|
||||
} from '@/utils';
|
||||
import PROXY_PROCESSORS, { ApplyProcessor } from './processors';
|
||||
import PROXY_PREPROCESSORS from './preprocessors';
|
||||
@@ -220,6 +221,17 @@ function produce(proxies, targetPlatform, type, opts = {}) {
|
||||
delete proxy['tls-fingerprint'];
|
||||
}
|
||||
}
|
||||
|
||||
// 处理 端口跳跃
|
||||
if (proxy.ports) {
|
||||
if (!['ClashMeta'].includes(targetPlatform)) {
|
||||
proxy.ports = proxy.ports.replace(/\//g, ',');
|
||||
}
|
||||
if (!proxy.port) {
|
||||
proxy.port = getRandomPort(proxy.ports);
|
||||
}
|
||||
}
|
||||
|
||||
return proxy;
|
||||
});
|
||||
|
||||
@@ -274,6 +286,7 @@ export const ProxyUtils = {
|
||||
process: processFn,
|
||||
produce,
|
||||
ipAddress,
|
||||
getRandomPort,
|
||||
isIPv4,
|
||||
isIPv6,
|
||||
isIP,
|
||||
|
||||
@@ -158,7 +158,7 @@ function URI_SSR() {
|
||||
for (const item of line) {
|
||||
let [key, val] = item.split('=');
|
||||
val = val.trim();
|
||||
if (val.length > 0) {
|
||||
if (val.length > 0 && val !== '(null)') {
|
||||
other_params[key] = val;
|
||||
}
|
||||
}
|
||||
@@ -296,6 +296,11 @@ function URI_VMess() {
|
||||
? !params.verify_cert
|
||||
: undefined,
|
||||
};
|
||||
if (!proxy['skip-cert-verify'] && isPresent(params.allowInsecure)) {
|
||||
proxy['skip-cert-verify'] = /(TRUE)|1/i.test(
|
||||
params.allowInsecure,
|
||||
);
|
||||
}
|
||||
// https://github.com/2dust/v2rayN/wiki/%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E6%A0%BC%E5%BC%8F%E8%AF%B4%E6%98%8E(ver-2)
|
||||
if (proxy.tls && proxy.sni) {
|
||||
proxy.sni = params.sni;
|
||||
@@ -351,6 +356,7 @@ function URI_VMess() {
|
||||
transportPath = '/';
|
||||
}
|
||||
}
|
||||
// 传输层应该有配置, 暂时不考虑兼容不给配置的节点
|
||||
if (transportPath || transportHost) {
|
||||
if (['grpc'].includes(proxy.network)) {
|
||||
proxy[`${proxy.network}-opts`] = {
|
||||
|
||||
@@ -54,31 +54,31 @@ shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs
|
||||
$set(proxy, "plugin-opts.path", obfs.path);
|
||||
}
|
||||
}
|
||||
vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/vmess_alterId/fast_open/udp_relay/others)* {
|
||||
vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/vmess_alterId/fast_open/udp_relay/others)* {
|
||||
proxy.type = "vmess";
|
||||
proxy.cipher = proxy.cipher || "none";
|
||||
proxy.alterId = proxy.alterId || 0;
|
||||
handleTransport();
|
||||
}
|
||||
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
|
||||
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
|
||||
proxy.type = "vless";
|
||||
handleTransport();
|
||||
}
|
||||
trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
|
||||
trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
|
||||
proxy.type = "trojan";
|
||||
handleTransport();
|
||||
}
|
||||
hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* {
|
||||
hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* {
|
||||
proxy.type = "hysteria2";
|
||||
}
|
||||
https = tag equals "https"i address (username password)? (tls_host/tls_verification/fast_open/udp_relay/others)* {
|
||||
https = tag equals "https"i address (username password)? (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
|
||||
proxy.type = "http";
|
||||
proxy.tls = true;
|
||||
}
|
||||
http = tag equals "http"i address (username password)? (fast_open/udp_relay/others)* {
|
||||
proxy.type = "http";
|
||||
}
|
||||
socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
|
||||
socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
|
||||
proxy.type = "socks5";
|
||||
}
|
||||
|
||||
@@ -172,6 +172,8 @@ vmess_alterId = comma "alterId" equals alterId:$[0-9]+ { proxy.alterId = parseIn
|
||||
over_tls = comma "over-tls" equals flag:bool { proxy.tls = flag; }
|
||||
tls_host = comma sni:("tls-name"/"sni") equals host:domain { proxy.sni = host; }
|
||||
tls_verification = comma "skip-cert-verify" equals flag:bool { proxy["skip-cert-verify"] = flag; }
|
||||
tls_cert_sha256 = comma "tls-cert-sha256" equals match:[^,]+ { proxy["tls-fingerprint"] = match.join("").replace(/^"(.*)"$/, '$1'); }
|
||||
tls_pubkey_sha256 = comma "tls-pubkey-sha256" equals match:[^,]+ { proxy["tls-pubkey-sha256"] = match.join("").replace(/^"(.*)"$/, '$1'); }
|
||||
|
||||
fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; }
|
||||
udp_relay = comma "udp" equals flag:bool { proxy.udp = flag; }
|
||||
@@ -180,6 +182,7 @@ ecn = comma "ecn" equals flag:bool { proxy.ecn = flag; }
|
||||
download_bandwidth = comma "download-bandwidth" equals match:[^,]+ { proxy.down = match.join(""); }
|
||||
salamander_password = comma "salamander-password" equals match:[^,]+ { proxy['obfs-password'] = match.join(""); proxy.obfs = 'salamander'; }
|
||||
|
||||
|
||||
tag = match:[^=,]* { proxy.name = match.join("").trim(); }
|
||||
comma = _ "," _
|
||||
equals = _ "=" _
|
||||
|
||||
@@ -52,31 +52,31 @@ shadowsocks = tag equals "shadowsocks"i address method password (obfs_typev obfs
|
||||
$set(proxy, "plugin-opts.path", obfs.path);
|
||||
}
|
||||
}
|
||||
vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/vmess_alterId/fast_open/udp_relay/others)* {
|
||||
vmess = tag equals "vmess"i address method uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/vmess_alterId/fast_open/udp_relay/others)* {
|
||||
proxy.type = "vmess";
|
||||
proxy.cipher = proxy.cipher || "none";
|
||||
proxy.alterId = proxy.alterId || 0;
|
||||
handleTransport();
|
||||
}
|
||||
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
|
||||
vless = tag equals "vless"i address uuid (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
|
||||
proxy.type = "vless";
|
||||
handleTransport();
|
||||
}
|
||||
trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
|
||||
trojan = tag equals "trojan"i address password (transport/transport_host/transport_path/over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
|
||||
proxy.type = "trojan";
|
||||
handleTransport();
|
||||
}
|
||||
hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* {
|
||||
hysteria2 = tag equals "hysteria2"i address password (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/udp_relay/fast_open/download_bandwidth/salamander_password/ecn/others)* {
|
||||
proxy.type = "hysteria2";
|
||||
}
|
||||
https = tag equals "https"i address (username password)? (tls_host/tls_verification/fast_open/udp_relay/others)* {
|
||||
https = tag equals "https"i address (username password)? (tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
|
||||
proxy.type = "http";
|
||||
proxy.tls = true;
|
||||
}
|
||||
http = tag equals "http"i address (username password)? (fast_open/udp_relay/others)* {
|
||||
proxy.type = "http";
|
||||
}
|
||||
socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/fast_open/udp_relay/others)* {
|
||||
socks5 = tag equals "socks5"i address (username password)? (over_tls/tls_host/tls_verification/tls_cert_sha256/tls_pubkey_sha256/fast_open/udp_relay/others)* {
|
||||
proxy.type = "socks5";
|
||||
}
|
||||
|
||||
@@ -170,6 +170,8 @@ vmess_alterId = comma "alterId" equals alterId:$[0-9]+ { proxy.alterId = parseIn
|
||||
over_tls = comma "over-tls" equals flag:bool { proxy.tls = flag; }
|
||||
tls_host = comma sni:("tls-name"/"sni") equals host:domain { proxy.sni = host; }
|
||||
tls_verification = comma "skip-cert-verify" equals flag:bool { proxy["skip-cert-verify"] = flag; }
|
||||
tls_cert_sha256 = comma "tls-cert-sha256" equals match:[^,]+ { proxy["tls-fingerprint"] = match.join("").replace(/^"(.*)"$/, '$1'); }
|
||||
tls_pubkey_sha256 = comma "tls-pubkey-sha256" equals match:[^,]+ { proxy["tls-pubkey-sha256"] = match.join("").replace(/^"(.*)"$/, '$1'); }
|
||||
|
||||
fast_open = comma "fast-open" equals flag:bool { proxy.tfo = flag; }
|
||||
udp_relay = comma "udp" equals flag:bool { proxy.udp = flag; }
|
||||
|
||||
@@ -392,18 +392,23 @@ const DOMAIN_RESOLVERS = {
|
||||
const id = hex_md5(`CUSTOM:${url}:${domain}:${type}`);
|
||||
const cached = resourceCache.get(id);
|
||||
if (!noCache && cached) return cached;
|
||||
const answerType = type === 'IPv6' ? 'AAAA' : 'A';
|
||||
const res = await doh({
|
||||
url,
|
||||
domain,
|
||||
type: type === 'IPv6' ? 'AAAA' : 'A',
|
||||
type: answerType,
|
||||
timeout,
|
||||
edns,
|
||||
});
|
||||
|
||||
const { answers } = res;
|
||||
if (!Array.isArray(answers) || answers.length === 0) {
|
||||
throw new Error('No answers');
|
||||
}
|
||||
const result = answers.map((i) => i?.data).filter((i) => i);
|
||||
const result = answers
|
||||
.filter((i) => i?.type === answerType)
|
||||
.map((i) => i?.data)
|
||||
.filter((i) => i);
|
||||
if (result.length === 0) {
|
||||
throw new Error('No answers');
|
||||
}
|
||||
|
||||
@@ -153,6 +153,14 @@ function trojan(proxy) {
|
||||
|
||||
// sni
|
||||
result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni');
|
||||
result.appendIfPresent(
|
||||
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
|
||||
'tls-fingerprint',
|
||||
);
|
||||
result.appendIfPresent(
|
||||
`,tls-pubkey-sha256=${proxy['tls-pubkey-sha256']}`,
|
||||
'tls-pubkey-sha256',
|
||||
);
|
||||
|
||||
// tfo
|
||||
result.appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
|
||||
@@ -215,6 +223,14 @@ function vmess(proxy) {
|
||||
|
||||
// sni
|
||||
result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni');
|
||||
result.appendIfPresent(
|
||||
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
|
||||
'tls-fingerprint',
|
||||
);
|
||||
result.appendIfPresent(
|
||||
`,tls-pubkey-sha256=${proxy['tls-pubkey-sha256']}`,
|
||||
'tls-pubkey-sha256',
|
||||
);
|
||||
|
||||
// AEAD
|
||||
if (isPresent(proxy, 'aead')) {
|
||||
@@ -286,6 +302,14 @@ function vless(proxy) {
|
||||
|
||||
// sni
|
||||
result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni');
|
||||
result.appendIfPresent(
|
||||
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
|
||||
'tls-fingerprint',
|
||||
);
|
||||
result.appendIfPresent(
|
||||
`,tls-pubkey-sha256=${proxy['tls-pubkey-sha256']}`,
|
||||
'tls-pubkey-sha256',
|
||||
);
|
||||
|
||||
// tfo
|
||||
result.appendIfPresent(`,fast-open=${proxy.tfo}`, 'tfo');
|
||||
@@ -339,6 +363,11 @@ function socks5(proxy) {
|
||||
// tfo
|
||||
result.appendIfPresent(`,tfo=${proxy.tfo}`, 'tfo');
|
||||
|
||||
// udp
|
||||
if (proxy.udp) {
|
||||
result.append(`,udp=true`);
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@@ -418,6 +447,14 @@ function hysteria2(proxy) {
|
||||
|
||||
// sni
|
||||
result.appendIfPresent(`,tls-name=${proxy.sni}`, 'sni');
|
||||
result.appendIfPresent(
|
||||
`,tls-cert-sha256=${proxy['tls-fingerprint']}`,
|
||||
'tls-fingerprint',
|
||||
);
|
||||
result.appendIfPresent(
|
||||
`,tls-pubkey-sha256=${proxy['tls-pubkey-sha256']}`,
|
||||
'tls-pubkey-sha256',
|
||||
);
|
||||
result.appendIfPresent(
|
||||
`,skip-cert-verify=${proxy['skip-cert-verify']}`,
|
||||
'skip-cert-verify',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Result } from './utils';
|
||||
import { Result, isPresent } from './utils';
|
||||
import Surge_Producer from './surge';
|
||||
import { isIPv4, isIPv6, isPresent } from '@/utils';
|
||||
import { isIPv4, isIPv6 } from '@/utils';
|
||||
import $ from '@/core/app';
|
||||
|
||||
const targetPlatform = 'SurgeMac';
|
||||
@@ -84,6 +84,7 @@ function shadowsocksr(proxy) {
|
||||
for (const [key, value] of Object.entries({
|
||||
cipher: '-m',
|
||||
obfs: '-o',
|
||||
'obfs-param': '-g',
|
||||
password: '-k',
|
||||
port: '-p',
|
||||
protocol: '-O',
|
||||
@@ -92,8 +93,10 @@ function shadowsocksr(proxy) {
|
||||
'local-port': '-l',
|
||||
'local-address': '-b',
|
||||
})) {
|
||||
external_proxy.args.push(value);
|
||||
external_proxy.args.push(external_proxy[key]);
|
||||
if (external_proxy[key] != null) {
|
||||
external_proxy.args.push(value);
|
||||
external_proxy.args.push(external_proxy[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return external(external_proxy);
|
||||
|
||||
@@ -293,7 +293,7 @@ export function getFlag(name) {
|
||||
'沪俄',
|
||||
'Moscow',
|
||||
],
|
||||
'🇸🇦': ['Saudi', '沙特阿拉伯', '沙特'],
|
||||
'🇸🇦': ['Saudi', '沙特阿拉伯', '沙特', 'Riyadh', '利雅得'],
|
||||
'🇸🇪': ['Sweden', '瑞典'],
|
||||
'🇸🇬': [
|
||||
'Singapore',
|
||||
|
||||
@@ -94,6 +94,23 @@ function getPolicyDescriptor(str) {
|
||||
// };
|
||||
// })();
|
||||
|
||||
function getRandomInt(min, max) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
function getRandomPort(portString) {
|
||||
let portParts = portString.split(/,|\//);
|
||||
let randomPart = portParts[Math.floor(Math.random() * portParts.length)];
|
||||
if (randomPart.includes('-')) {
|
||||
let [min, max] = randomPart.split('-').map(Number);
|
||||
return getRandomInt(min, max);
|
||||
} else {
|
||||
return Number(randomPart);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
ipAddress,
|
||||
isIPv4,
|
||||
@@ -105,4 +122,5 @@ export {
|
||||
getIfPresent,
|
||||
// utf8ArrayToStr,
|
||||
getPolicyDescriptor,
|
||||
getRandomPort,
|
||||
};
|
||||
|
||||
@@ -28,7 +28,9 @@ export function getPlatformFromUserAgent({ ua, UA }) {
|
||||
return 'Stash';
|
||||
} else if (
|
||||
ua === 'meta' ||
|
||||
(ua.indexOf('clash') !== -1 && ua.indexOf('meta') !== -1)
|
||||
(ua.indexOf('clash') !== -1 && ua.indexOf('meta') !== -1) ||
|
||||
ua.indexOf('clash-verge') !== -1 ||
|
||||
ua.indexOf('flclash') !== -1
|
||||
) {
|
||||
return 'ClashMeta';
|
||||
} else if (ua.indexOf('clash') !== -1) {
|
||||
|
||||
37
config/Egern.yaml
Normal file
37
config/Egern.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Sub-Store
|
||||
description: '支持 Surge 正式版的参数设置功能. 测落地功能 ability: http-client-policy, 同步配置的定时 cronexp: 55 23 * * *'
|
||||
compat_arguments:
|
||||
ability: http-client-policy
|
||||
cronexp: 55 23 * * *
|
||||
sync: '"Sub-Store Sync"'
|
||||
timeout: '120'
|
||||
engine: auto
|
||||
produce: '"# Sub-Store Produce"'
|
||||
produce_cronexp: 50 */6 * * *
|
||||
produce_sub: '"sub1,sub2"'
|
||||
produce_col: '"col1,col2"'
|
||||
compat_arguments_desc: '\n1️⃣ ability\n\n默认已开启测落地能力\n需要配合脚本操作\n如 https://raw.githubusercontent.com/Keywos/rule/main/cname.js\n填写任意其他值关闭\n\n2️⃣ cronexp\n\n同步配置定时任务\n默认为每天 23 点 55 分\n\n定时任务指定时将订阅/文件上传到私有 Gist. 在前端, 叫做 ''同步'' 或 ''同步配置''\n\n3️⃣ sync\n\n自定义定时任务名\n便于在脚本编辑器中选择\n若设为 # 可取消定时任务\n\n4️⃣ timeout\n\n脚本超时, 单位为秒\n\n5️⃣ engine\n\n默认为自动使用 webview 引擎, 可设为指定 jsc, 但 jsc 容易爆内存\n\n6️⃣ produce\n\n自定义处理订阅的定时任务名\n一般用于定时处理耗时较长的订阅, 以更新缓存\n这样 Surge 中拉取的时候就能用到缓存, 不至于总是超时\n若设为 # 可取消此定时任务\n默认不开启\n\n7️⃣ produce_cronexp\n\n配置处理订阅的定时任务\n\n默认为每 6 小时\n\n9️⃣ produce_sub\n\n自定义需定时处理的单条订阅名\n多个用 , 连接\n\n🔟 produce_col\n\n自定义需定时处理的组合订阅名\n多个用 , 连接\n\n⚠️ 注意: 是 名称(name) 不是 显示名称(displayName)\n如果名称需要编码, 请编码后再用 , 连接\n顺序: 并发执行单条订阅, 然后并发执行组合订阅'
|
||||
scriptings:
|
||||
- http_request:
|
||||
name: Sub-Store Core
|
||||
match: ^https?:\/\/sub\.store\/((download)|api\/(preview|sync|(utils\/node-info)))
|
||||
script_url: https://github.com/sub-store-org/Sub-Store/releases/latest/download/sub-store-1.min.js
|
||||
body_required: true
|
||||
- http_request:
|
||||
name: Sub-Store Simple
|
||||
match: ^https?:\/\/sub\.store
|
||||
script_url: https://github.com/sub-store-org/Sub-Store/releases/latest/download/sub-store-0.min.js
|
||||
body_required: true
|
||||
- schedule:
|
||||
name: '{{{sync}}}'
|
||||
cron: '{{{cronexp}}}'
|
||||
script_url: https://github.com/sub-store-org/Sub-Store/releases/latest/download/cron-sync-artifacts.min.js
|
||||
- schedule:
|
||||
name: '{{{produce}}}'
|
||||
cron: '{{{produce_cronexp}}}'
|
||||
script_url: https://github.com/sub-store-org/Sub-Store/releases/latest/download/cron-sync-artifacts.min.js
|
||||
arguments:
|
||||
_compat.$argument: '"sub={{{produce_sub}}}&col={{{produce_col}}}"'
|
||||
mitm:
|
||||
hostnames:
|
||||
- sub.store
|
||||
@@ -45,6 +45,9 @@ Surge Mac 版如何支持 SSR, 如何去除 HTTP 传输层以支持 类似 VMess
|
||||
### 5. Shadowrocket
|
||||
安装使用 模块 [`https://raw.githubusercontent.com/sub-store-org/Sub-Store/master/config/Surge-Noability.sgmodule`](https://raw.githubusercontent.com/sub-store-org/Sub-Store/master/config/Surge-Noability.sgmodule) 即可。
|
||||
|
||||
### 6. Egern
|
||||
安装使用 模块 [`https://raw.githubusercontent.com/sub-store-org/Sub-Store/master/config/Egern.yaml`](https://raw.githubusercontent.com/sub-store-org/Sub-Store/master/config/Egern.yaml) 即可。
|
||||
|
||||
## 使用 Sub-Store
|
||||
1. 使用 Safari 打开这个 https://sub.store 如网页正常打开并且未弹出任何错误提示,说明 Sub-Store 已经配置成功。
|
||||
2. 可以把 Sub-Store 添加到主屏幕,即可获得类似于 APP 的使用体验。
|
||||
@@ -56,4 +59,4 @@ https://github.com/sub-store-org/Sub-Store/wiki/%E9%93%BE%E6%8E%A5%E5%8F%82%E6%9
|
||||
|
||||
## 脚本使用说明
|
||||
|
||||
https://github.com/sub-store-org/Sub-Store/wiki/%E8%84%9A%E6%9C%AC%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E
|
||||
https://github.com/sub-store-org/Sub-Store/wiki/%E8%84%9A%E6%9C%AC%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E
|
||||
|
||||
@@ -42,6 +42,7 @@ function operator(proxies = [], targetPlatform, context) {
|
||||
// parse, // 订阅解析
|
||||
// process, // 节点操作/文件操作
|
||||
// produce, // 输出订阅
|
||||
// getRandomPort, // 获取随机端口(参考 ports 端口跳跃的格式 443,8443,5000-6000)
|
||||
// ipAddress, // https://github.com/beaugunderson/ip-address
|
||||
// isIPv4,
|
||||
// isIPv6,
|
||||
|
||||
Reference in New Issue
Block a user