Compare commits

...

7 Commits

13 changed files with 121 additions and 12 deletions

2
.gitignore vendored
View File

@@ -133,3 +133,5 @@ out
backend/dist/*
!backend/dist/.gitkeep
backend/sub-store.min.js
CHANGELOG.md

View File

@@ -32,7 +32,7 @@ Core functionalities:
- [x] V2RayN URI
- [x] QX (SS, SSR, VMess, Trojan, HTTP)
- [x] Loon (SS, SSR, VMess, Trojan, HTTP, WireGuard, VLESS)
- [x] Surge (SS, VMess, Trojan, HTTP, TUIC, Snell)
- [x] Surge (SS, VMess, Trojan, HTTP, TUIC, Snell, SSR(external, only for macOS))
- [x] ShadowRocket (SS, SSR, VMess, Trojan, HTTP, Snell, VLESS, WireGuard, Hysteria)
- [x] Clash.Meta (SS, SSR, VMess, Trojan, HTTP, Snell, VLESS, WireGuard, Hysteria)
- [x] Stash (SS, SSR, VMess, Trojan, HTTP, Snell, VLESS, WireGuard, Hysteria)

View File

@@ -1,6 +1,6 @@
{
"name": "sub-store",
"version": "2.14.41",
"version": "2.14.45",
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
"main": "src/main.js",
"scripts": {
@@ -10,7 +10,7 @@
"start": "nodemon -w src -w package.json --exec babel-node src/main.js",
"build": "gulp",
"bundle": "node bundle.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s"
"changelog": "conventional-changelog -p cli -i CHANGELOG.md -s"
},
"author": "Peng-YM",
"license": "GPL-3.0",

View File

@@ -136,10 +136,21 @@ function produce(proxies, targetPlatform) {
$.info(`Producing proxies for target: ${targetPlatform}`);
if (typeof producer.type === 'undefined' || producer.type === 'SINGLE') {
let localPort = 10000;
return proxies
.map((proxy) => {
try {
return producer.produce(proxy);
let line = producer.produce(proxy);
if (
line.length > 0 &&
line.includes('__SubStoreLocalPort__')
) {
line = line.replace(
/__SubStoreLocalPort__/g,
localPort++,
);
}
return line;
} catch (err) {
$.error(
`Cannot produce proxy: ${JSON.stringify(
@@ -216,7 +227,20 @@ function lastParse(proxy) {
proxy[`${proxy.network}-opts`].headers =
proxy[`${proxy.network}-opts`].headers || {};
proxy[`${proxy.network}-opts`].headers.Host =
proxy.network === 'http' ? [proxy.server] : proxy.server;
['vmess', 'vless'].includes(proxy.type) && proxy.network === 'http'
? [proxy.server]
: proxy.server;
}
// 统一将 VMess 和 VLESS 的 http 传输层的 path 和 Host 处理为数组
if (['vmess', 'vless'].includes(proxy.type) && proxy.network === 'http') {
let transportPath = proxy[`${proxy.network}-opts`]?.path;
let transportHost = proxy[`${proxy.network}-opts`]?.headers?.Host;
if (transportHost && !Array.isArray(transportHost)) {
proxy[`${proxy.network}-opts`].headers.Host = [transportHost];
}
if (transportPath && !Array.isArray(transportPath)) {
proxy[`${proxy.network}-opts`].path = [transportPath];
}
}
return proxy;
}

View File

@@ -215,7 +215,6 @@ function URI_VMess() {
// V2rayN URI format
params = JSON.parse(content);
} catch (e) {
// console.error(e);
// Shadowrocket URI format
// eslint-disable-next-line no-unused-vars
let [__, base64Line, qs] = /(^[^?]+?)\/?\?(.*)$/.exec(line);

View File

@@ -411,7 +411,6 @@ const DOMAIN_RESOLVERS = {
},
});
const answers = resp.body.split(';').map((i) => i.split(',')[0]);
console.log(`answers`, answers);
if (answers.length === 0) {
throw new Error('No answers');
}

View File

@@ -1,4 +1,5 @@
import Surge_Producer from './surge';
import SurgeMac_Producer from './surgemac';
import Clash_Producer from './clash';
import ClashMeta_Producer from './clashmeta';
import Stash_Producer from './stash';
@@ -17,6 +18,7 @@ function JSON_Producer() {
export default {
QX: QX_Producer(),
Surge: Surge_Producer(),
SurgeMac: SurgeMac_Producer(),
Loon: Loon_Producer(),
Clash: Clash_Producer(),
ClashMeta: ClashMeta_Producer(),

View File

@@ -0,0 +1,65 @@
import { Result } from './utils';
import Surge_Producer from './surge';
const targetPlatform = 'SurgeMac';
const surge_Producer = Surge_Producer();
export default function SurgeMac_Producer() {
const produce = (proxy) => {
switch (proxy.type) {
case 'ssr':
return shadowsocksr(proxy);
case 'ss':
return surge_Producer.produce(proxy);
case 'trojan':
return surge_Producer.produce(proxy);
case 'vmess':
return surge_Producer.produce(proxy);
case 'http':
return surge_Producer.produce(proxy);
case 'socks5':
return surge_Producer.produce(proxy);
case 'snell':
return surge_Producer.produce(proxy);
case 'tuic':
return surge_Producer.produce(proxy);
}
throw new Error(
`Platform ${targetPlatform} does not support proxy type: ${proxy.type}`,
);
};
return { produce };
}
function shadowsocksr(proxy) {
const result = new Result(proxy);
proxy.local_port = '__SubStoreLocalPort__';
proxy.local_address = proxy.local_address ?? '127.0.0.1';
result.append(
`${proxy.name} = external, exec = "${
proxy.exec || '/usr/local/bin/ssr-local'
}", address = "${proxy.server}", local-port = ${proxy.local_port}`,
);
for (const [key, value] of Object.entries({
cipher: '-m',
obfs: '-o',
password: '-k',
port: '-p',
protocol: '-O',
'protocol-param': '-G',
server: '-s',
local_port: '-l',
local_address: '-b',
})) {
result.appendIfPresent(
`, args = "${value}", args = "${proxy[key]}"`,
key,
);
}
return result.toString();
}

View File

@@ -47,7 +47,7 @@ function AllRuleParser() {
}
if (!matched) throw new Error('Invalid rule type: ' + rawType);
} catch (e) {
console.error(`Failed to parse line: ${line}\n Reason: ${e}`);
console.log(`Failed to parse line: ${line}\n Reason: ${e}`);
}
}
return result;

View File

@@ -125,8 +125,10 @@ async function gistBackup(req, res) {
$.cache = content;
$.persistCache();
}
// perform migration after restoring from gist
$.info(`perform migration after restoring from gist...`);
migrate();
$.info(`migration completed`);
$.info(`还原备份完成`);
break;
}
success(res);

View File

@@ -44,8 +44,12 @@ export async function updateGitHubAvatar() {
.then((resp) => JSON.parse(resp.body));
settings.avatarUrl = data['avatar_url'];
$.write(settings, SETTINGS_KEY);
} catch (e) {
$.error('Failed to fetch GitHub avatar for User: ' + username);
} catch (err) {
$.error(
`Failed to fetch GitHub avatar for User: ${username}. Reason: ${
err.message ?? err
}`,
);
}
}
}
@@ -67,7 +71,11 @@ export async function updateArtifactStore() {
$.write(settings, SETTINGS_KEY);
}
} catch (err) {
$.error('Failed to fetch artifact store for User: ' + githubUser);
$.error(
`Failed to fetch artifact store for User: ${githubUser}. Reason: ${
err.message ?? err
}`,
);
}
}
}

View File

@@ -11,6 +11,8 @@ export function getPlatformFromHeaders(headers) {
}
if (UA.indexOf('Quantumult%20X') !== -1) {
return 'QX';
} else if (UA.indexOf('Surge Mac') !== -1) {
return 'SurgeMac';
} else if (UA.indexOf('Surge') !== -1) {
return 'Surge';
} else if (UA.indexOf('Decar') !== -1 || UA.indexOf('Loon') !== -1) {

View File

@@ -1,5 +1,11 @@
# Sub-Store 配置指南
## 查看更新说明:
[Sub-Store Releases](https://github.com/sub-store-org/Sub-Store/releases)
[Telegram 频道](https://t.me/cool_scripts)
## 脚本配置:
### 1. Loon