mirror of
https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-10 00:52:40 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
876d2e92ca | ||
|
|
63064bc596 | ||
|
|
e81245a5bb | ||
|
|
217fdae7f1 | ||
|
|
ef4d0a228b | ||
|
|
e816e5b3c0 | ||
|
|
005051c4ac | ||
|
|
61078b10f3 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sub-store",
|
"name": "sub-store",
|
||||||
"version": "2.19.77",
|
"version": "2.19.87",
|
||||||
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.",
|
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.",
|
||||||
"main": "src/main.js",
|
"main": "src/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
"dns-packet": "^5.6.1",
|
"dns-packet": "^5.6.1",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
|
"fetch-socks": "^1.3.2",
|
||||||
"http-proxy-middleware": "^3.0.3",
|
"http-proxy-middleware": "^3.0.3",
|
||||||
"ip-address": "^9.0.5",
|
"ip-address": "^9.0.5",
|
||||||
"js-base64": "^3.7.2",
|
"js-base64": "^3.7.2",
|
||||||
|
|||||||
26
backend/pnpm-lock.yaml
generated
26
backend/pnpm-lock.yaml
generated
@@ -40,6 +40,9 @@ importers:
|
|||||||
express:
|
express:
|
||||||
specifier: ^4.17.1
|
specifier: ^4.17.1
|
||||||
version: 4.21.2
|
version: 4.21.2
|
||||||
|
fetch-socks:
|
||||||
|
specifier: ^1.3.2
|
||||||
|
version: 1.3.2
|
||||||
http-proxy-middleware:
|
http-proxy-middleware:
|
||||||
specifier: ^3.0.3
|
specifier: ^3.0.3
|
||||||
version: 3.0.3
|
version: 3.0.3
|
||||||
@@ -1974,6 +1977,9 @@ packages:
|
|||||||
fastq@1.18.0:
|
fastq@1.18.0:
|
||||||
resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==}
|
resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==}
|
||||||
|
|
||||||
|
fetch-socks@1.3.2:
|
||||||
|
resolution: {integrity: sha512-vkH5+Zgj2yEbU57Cei0iyLgTZ4OkEKJj56Xu3ViB5dpsl599JgEooQ3x6NVagIFRHWnWJ+7K0MO0aIV1TMgvnw==}
|
||||||
|
|
||||||
file-entry-cache@6.0.1:
|
file-entry-cache@6.0.1:
|
||||||
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
|
||||||
engines: {node: ^10.12.0 || >=12.0.0}
|
engines: {node: ^10.12.0 || >=12.0.0}
|
||||||
@@ -3636,6 +3642,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==}
|
resolution: {integrity: sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
smart-buffer@4.2.0:
|
||||||
|
resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
|
||||||
|
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
|
||||||
|
|
||||||
snapdragon-node@2.1.1:
|
snapdragon-node@2.1.1:
|
||||||
resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==}
|
resolution: {integrity: sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -3648,6 +3658,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==}
|
resolution: {integrity: sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
socks@2.8.6:
|
||||||
|
resolution: {integrity: sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==}
|
||||||
|
engines: {node: '>= 10.0.0', npm: '>= 3.0.0'}
|
||||||
|
|
||||||
source-map-generator@0.8.0:
|
source-map-generator@0.8.0:
|
||||||
resolution: {integrity: sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA==}
|
resolution: {integrity: sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
@@ -6553,6 +6567,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
reusify: 1.0.4
|
reusify: 1.0.4
|
||||||
|
|
||||||
|
fetch-socks@1.3.2:
|
||||||
|
dependencies:
|
||||||
|
socks: 2.8.6
|
||||||
|
undici: 7.4.0
|
||||||
|
|
||||||
file-entry-cache@6.0.1:
|
file-entry-cache@6.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
flat-cache: 3.2.0
|
flat-cache: 3.2.0
|
||||||
@@ -8424,6 +8443,8 @@ snapshots:
|
|||||||
|
|
||||||
slash@1.0.0: {}
|
slash@1.0.0: {}
|
||||||
|
|
||||||
|
smart-buffer@4.2.0: {}
|
||||||
|
|
||||||
snapdragon-node@2.1.1:
|
snapdragon-node@2.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
define-property: 1.0.0
|
define-property: 1.0.0
|
||||||
@@ -8447,6 +8468,11 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
socks@2.8.6:
|
||||||
|
dependencies:
|
||||||
|
ip-address: 9.0.5
|
||||||
|
smart-buffer: 4.2.0
|
||||||
|
|
||||||
source-map-generator@0.8.0: {}
|
source-map-generator@0.8.0: {}
|
||||||
|
|
||||||
source-map-resolve@0.5.3:
|
source-map-resolve@0.5.3:
|
||||||
|
|||||||
@@ -134,6 +134,18 @@ export default function Clash_Producer() {
|
|||||||
proxy['h2-opts'].headers.host = [host];
|
proxy['h2-opts'].headers.host = [host];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (proxy.network === 'ws') {
|
||||||
|
const wsPath = proxy['ws-opts']?.path;
|
||||||
|
const reg = /^(.*?)(?:\?ed=(\d+))?$/;
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const [_, path = '', ed = ''] = reg.exec(wsPath);
|
||||||
|
proxy['ws-opts'].path = path;
|
||||||
|
if (ed !== '') {
|
||||||
|
proxy['ws-opts']['early-data-header-name'] =
|
||||||
|
'Sec-WebSocket-Protocol';
|
||||||
|
proxy['ws-opts']['max-early-data'] = parseInt(ed, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (proxy['plugin-opts']?.tls) {
|
if (proxy['plugin-opts']?.tls) {
|
||||||
if (isPresent(proxy, 'skip-cert-verify')) {
|
if (isPresent(proxy, 'skip-cert-verify')) {
|
||||||
proxy['plugin-opts']['skip-cert-verify'] =
|
proxy['plugin-opts']['skip-cert-verify'] =
|
||||||
|
|||||||
@@ -198,6 +198,18 @@ export default function ClashMeta_Producer() {
|
|||||||
proxy['h2-opts'].headers.host = [host];
|
proxy['h2-opts'].headers.host = [host];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (proxy.network === 'ws') {
|
||||||
|
const wsPath = proxy['ws-opts']?.path;
|
||||||
|
const reg = /^(.*?)(?:\?ed=(\d+))?$/;
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const [_, path = '', ed = ''] = reg.exec(wsPath);
|
||||||
|
proxy['ws-opts'].path = path;
|
||||||
|
if (ed !== '') {
|
||||||
|
proxy['ws-opts']['early-data-header-name'] =
|
||||||
|
'Sec-WebSocket-Protocol';
|
||||||
|
proxy['ws-opts']['max-early-data'] = parseInt(ed, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (proxy['plugin-opts']?.tls) {
|
if (proxy['plugin-opts']?.tls) {
|
||||||
if (isPresent(proxy, 'skip-cert-verify')) {
|
if (isPresent(proxy, 'skip-cert-verify')) {
|
||||||
|
|||||||
@@ -166,6 +166,18 @@ export default function Shadowrocket_Producer() {
|
|||||||
proxy['h2-opts'].headers.host = [host];
|
proxy['h2-opts'].headers.host = [host];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (proxy.network === 'ws') {
|
||||||
|
const wsPath = proxy['ws-opts']?.path;
|
||||||
|
const reg = /^(.*?)(?:\?ed=(\d+))?$/;
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const [_, path = '', ed = ''] = reg.exec(wsPath);
|
||||||
|
proxy['ws-opts'].path = path;
|
||||||
|
if (ed !== '') {
|
||||||
|
proxy['ws-opts']['early-data-header-name'] =
|
||||||
|
'Sec-WebSocket-Protocol';
|
||||||
|
proxy['ws-opts']['max-early-data'] = parseInt(ed, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (proxy['plugin-opts']?.tls) {
|
if (proxy['plugin-opts']?.tls) {
|
||||||
if (isPresent(proxy, 'skip-cert-verify')) {
|
if (isPresent(proxy, 'skip-cert-verify')) {
|
||||||
proxy['plugin-opts']['skip-cert-verify'] =
|
proxy['plugin-opts']['skip-cert-verify'] =
|
||||||
|
|||||||
@@ -71,7 +71,14 @@ const smuxParser = (smux, proxy) => {
|
|||||||
const wsParser = (proxy, parsedProxy) => {
|
const wsParser = (proxy, parsedProxy) => {
|
||||||
const transport = { type: 'ws', headers: {} };
|
const transport = { type: 'ws', headers: {} };
|
||||||
if (proxy['ws-opts']) {
|
if (proxy['ws-opts']) {
|
||||||
const { path: wsPath = '', headers: wsHeaders = {} } = proxy['ws-opts'];
|
const {
|
||||||
|
path: wsPath = '',
|
||||||
|
headers: wsHeaders = {},
|
||||||
|
'max-early-data': max_early_data,
|
||||||
|
'early-data-header-name': early_data_header_name,
|
||||||
|
} = proxy['ws-opts'];
|
||||||
|
transport.early_data_header_name = early_data_header_name;
|
||||||
|
transport.max_early_data = parseInt(max_early_data, 10);
|
||||||
if (wsPath !== '') transport.path = `${wsPath}`;
|
if (wsPath !== '') transport.path = `${wsPath}`;
|
||||||
if (Object.keys(wsHeaders).length > 0) {
|
if (Object.keys(wsHeaders).length > 0) {
|
||||||
const headers = {};
|
const headers = {};
|
||||||
|
|||||||
@@ -238,6 +238,18 @@ export default function Stash_Producer() {
|
|||||||
proxy['h2-opts'].headers.host = [host];
|
proxy['h2-opts'].headers.host = [host];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (proxy.network === 'ws') {
|
||||||
|
const wsPath = proxy['ws-opts']?.path;
|
||||||
|
const reg = /^(.*?)(?:\?ed=(\d+))?$/;
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const [_, path = '', ed = ''] = reg.exec(wsPath);
|
||||||
|
proxy['ws-opts'].path = path;
|
||||||
|
if (ed !== '') {
|
||||||
|
proxy['ws-opts']['early-data-header-name'] =
|
||||||
|
'Sec-WebSocket-Protocol';
|
||||||
|
proxy['ws-opts']['max-early-data'] = parseInt(ed, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (proxy['plugin-opts']?.tls) {
|
if (proxy['plugin-opts']?.tls) {
|
||||||
if (isPresent(proxy, 'skip-cert-verify')) {
|
if (isPresent(proxy, 'skip-cert-verify')) {
|
||||||
proxy['plugin-opts']['skip-cert-verify'] =
|
proxy['plugin-opts']['skip-cert-verify'] =
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Base64 } from 'js-base64';
|
||||||
|
import _ from 'lodash';
|
||||||
import express from '@/vendor/express';
|
import express from '@/vendor/express';
|
||||||
import $ from '@/core/app';
|
import $ from '@/core/app';
|
||||||
import migrate from '@/utils/migration';
|
import migrate from '@/utils/migration';
|
||||||
@@ -304,6 +306,7 @@ export default function serve() {
|
|||||||
const path = eval(`require("path")`);
|
const path = eval(`require("path")`);
|
||||||
const fs = eval(`require("fs")`);
|
const fs = eval(`require("fs")`);
|
||||||
const data_url = eval('process.env.SUB_STORE_DATA_URL');
|
const data_url = eval('process.env.SUB_STORE_DATA_URL');
|
||||||
|
const data_url_post = eval('process.env.SUB_STORE_DATA_URL_POST');
|
||||||
const fe_be_path = eval('process.env.SUB_STORE_FRONTEND_BACKEND_PATH');
|
const fe_be_path = eval('process.env.SUB_STORE_FRONTEND_BACKEND_PATH');
|
||||||
const fe_port = eval('process.env.SUB_STORE_FRONTEND_PORT') || 3001;
|
const fe_port = eval('process.env.SUB_STORE_FRONTEND_PORT') || 3001;
|
||||||
const fe_host =
|
const fe_host =
|
||||||
@@ -424,10 +427,39 @@ export default function serve() {
|
|||||||
if (data_url) {
|
if (data_url) {
|
||||||
$.info(`[BACKEND] downloading data from ${data_url}`);
|
$.info(`[BACKEND] downloading data from ${data_url}`);
|
||||||
download(data_url)
|
download(data_url)
|
||||||
.then((content) => {
|
.then(async (content) => {
|
||||||
$.write(content, '#sub-store');
|
try {
|
||||||
|
content = JSON.parse(Base64.decode(content));
|
||||||
|
if (Object.keys(content.settings).length === 0) {
|
||||||
|
throw new Error(
|
||||||
|
'备份文件应该至少包含 settings 字段',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
try {
|
||||||
|
content = JSON.parse(content);
|
||||||
|
if (Object.keys(content.settings).length === 0) {
|
||||||
|
throw new Error(
|
||||||
|
'备份文件应该至少包含 settings 字段',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
$.error(
|
||||||
|
`Gist 备份文件校验失败, 无法还原\nReason: ${
|
||||||
|
err.message ?? err
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
throw new Error('Gist 备份文件校验失败, 无法还原');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data_url_post) {
|
||||||
|
$.info('[BACKEND] executing post-processing script');
|
||||||
|
eval(data_url_post);
|
||||||
|
}
|
||||||
|
|
||||||
$.cache = JSON.parse(content);
|
$.write(JSON.stringify(content, null, ` `), '#sub-store');
|
||||||
|
|
||||||
|
$.cache = content;
|
||||||
$.persistCache();
|
$.persistCache();
|
||||||
|
|
||||||
migrate();
|
migrate();
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Base64 } from 'js-base64';
|
||||||
|
import _ from 'lodash';
|
||||||
import $ from '@/core/app';
|
import $ from '@/core/app';
|
||||||
import { ENV } from '@/vendor/open-api';
|
import { ENV } from '@/vendor/open-api';
|
||||||
import { failed, success } from '@/restful/response';
|
import { failed, success } from '@/restful/response';
|
||||||
@@ -104,7 +106,7 @@ async function refresh(_, res) {
|
|||||||
success(res);
|
success(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function gistBackupAction(action) {
|
async function gistBackupAction(action, keep, encode) {
|
||||||
// read token
|
// read token
|
||||||
const { gistToken, syncPlatform } = $.read(SETTINGS_KEY);
|
const { gistToken, syncPlatform } = $.read(SETTINGS_KEY);
|
||||||
if (!gistToken) throw new Error('GitHub Token is required for backup!');
|
if (!gistToken) throw new Error('GitHub Token is required for backup!');
|
||||||
@@ -114,6 +116,9 @@ async function gistBackupAction(action) {
|
|||||||
key: GIST_BACKUP_KEY,
|
key: GIST_BACKUP_KEY,
|
||||||
syncPlatform,
|
syncPlatform,
|
||||||
});
|
});
|
||||||
|
let currentContent = $.read('#sub-store');
|
||||||
|
currentContent = currentContent ? JSON.parse(currentContent) : {};
|
||||||
|
if ($.env.isNode) currentContent = JSON.parse(JSON.stringify($.cache));
|
||||||
let content;
|
let content;
|
||||||
const settings = $.read(SETTINGS_KEY);
|
const settings = $.read(SETTINGS_KEY);
|
||||||
const updated = settings.syncTime;
|
const updated = settings.syncTime;
|
||||||
@@ -121,7 +126,18 @@ async function gistBackupAction(action) {
|
|||||||
case 'upload':
|
case 'upload':
|
||||||
try {
|
try {
|
||||||
content = $.read('#sub-store');
|
content = $.read('#sub-store');
|
||||||
if ($.env.isNode) content = JSON.stringify($.cache, null, ` `);
|
content = content ? JSON.parse(content) : {};
|
||||||
|
if ($.env.isNode) content = JSON.parse(JSON.stringify($.cache));
|
||||||
|
if (encode === 'plaintext') {
|
||||||
|
content.settings.gistToken =
|
||||||
|
'恢复后请重新设置 GitHub Token';
|
||||||
|
content = JSON.stringify(content, null, ` `);
|
||||||
|
} else {
|
||||||
|
content = Base64.encode(
|
||||||
|
JSON.stringify(content, null, ` `),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$.info(`下载备份, 与本地内容对比...`);
|
$.info(`下载备份, 与本地内容对比...`);
|
||||||
const onlineContent = await gist.download(
|
const onlineContent = await gist.download(
|
||||||
GIST_BACKUP_FILE_NAME,
|
GIST_BACKUP_FILE_NAME,
|
||||||
@@ -138,7 +154,14 @@ async function gistBackupAction(action) {
|
|||||||
settings.syncTime = new Date().getTime();
|
settings.syncTime = new Date().getTime();
|
||||||
$.write(settings, SETTINGS_KEY);
|
$.write(settings, SETTINGS_KEY);
|
||||||
content = $.read('#sub-store');
|
content = $.read('#sub-store');
|
||||||
if ($.env.isNode) content = JSON.stringify($.cache, null, ` `);
|
content = content ? JSON.parse(content) : {};
|
||||||
|
if ($.env.isNode) content = JSON.parse(JSON.stringify($.cache));
|
||||||
|
if (encode === 'plaintext') {
|
||||||
|
content.settings.gistToken = '恢复后请重新设置 GitHub Token';
|
||||||
|
content = JSON.stringify(content, null, ` `);
|
||||||
|
} else {
|
||||||
|
content = Base64.encode(JSON.stringify(content, null, ` `));
|
||||||
|
}
|
||||||
$.info(`上传备份中...`);
|
$.info(`上传备份中...`);
|
||||||
try {
|
try {
|
||||||
await gist.upload({
|
await gist.upload({
|
||||||
@@ -156,21 +179,34 @@ async function gistBackupAction(action) {
|
|||||||
$.info(`还原备份中...`);
|
$.info(`还原备份中...`);
|
||||||
content = await gist.download(GIST_BACKUP_FILE_NAME);
|
content = await gist.download(GIST_BACKUP_FILE_NAME);
|
||||||
try {
|
try {
|
||||||
if (Object.keys(JSON.parse(content).settings).length === 0) {
|
content = JSON.parse(Base64.decode(content));
|
||||||
|
if (Object.keys(content.settings).length === 0) {
|
||||||
throw new Error('备份文件应该至少包含 settings 字段');
|
throw new Error('备份文件应该至少包含 settings 字段');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
$.error(
|
try {
|
||||||
`Gist 备份文件校验失败, 无法还原\nReason: ${
|
content = JSON.parse(content);
|
||||||
err.message ?? err
|
if (Object.keys(content.settings).length === 0) {
|
||||||
}`,
|
throw new Error('备份文件应该至少包含 settings 字段');
|
||||||
);
|
}
|
||||||
throw new Error('Gist 备份文件校验失败, 无法还原');
|
} catch (err) {
|
||||||
|
$.error(
|
||||||
|
`Gist 备份文件校验失败, 无法还原\nReason: ${
|
||||||
|
err.message ?? err
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
throw new Error('Gist 备份文件校验失败, 无法还原');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keep) {
|
||||||
|
$.info(`保留原有设置 ${keep}`);
|
||||||
|
keep.split(',').forEach((path) => {
|
||||||
|
_.set(content, path, _.get(currentContent, path));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// restore settings
|
// restore settings
|
||||||
$.write(content, '#sub-store');
|
$.write(JSON.stringify(content, null, ` `), '#sub-store');
|
||||||
if ($.env.isNode) {
|
if ($.env.isNode) {
|
||||||
content = JSON.parse(content);
|
|
||||||
$.cache = content;
|
$.cache = content;
|
||||||
$.persistCache();
|
$.persistCache();
|
||||||
}
|
}
|
||||||
@@ -182,7 +218,7 @@ async function gistBackupAction(action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function gistBackup(req, res) {
|
async function gistBackup(req, res) {
|
||||||
const { action } = req.query;
|
const { action, keep, encode } = req.query;
|
||||||
// read token
|
// read token
|
||||||
const { gistToken } = $.read(SETTINGS_KEY);
|
const { gistToken } = $.read(SETTINGS_KEY);
|
||||||
if (!gistToken) {
|
if (!gistToken) {
|
||||||
@@ -195,7 +231,7 @@ async function gistBackup(req, res) {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
await gistBackupAction(action);
|
await gistBackupAction(action, keep, encode);
|
||||||
success(res);
|
success(res);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
$.error(
|
$.error(
|
||||||
|
|||||||
53
backend/src/vendor/open-api.js
vendored
53
backend/src/vendor/open-api.js
vendored
@@ -18,6 +18,26 @@ function isPlainObject(obj) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseSocks5Uri(uri) {
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
let [__, username, password, server, port, query, name] = uri.match(
|
||||||
|
/^socks5:\/\/(?:(.*?):(.*?)@)?(.*?)(?::(\d+?))?(\?.*?)?(?:#(.*?))?$/,
|
||||||
|
);
|
||||||
|
if (port) {
|
||||||
|
port = parseInt(port, 10);
|
||||||
|
} else {
|
||||||
|
$.error(`port is not present in line: ${uri}`);
|
||||||
|
throw new Error(`port is not present in line: ${uri}`);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
type: 5,
|
||||||
|
host: server,
|
||||||
|
port,
|
||||||
|
|
||||||
|
userId: username != null ? decodeURIComponent(username) : undefined,
|
||||||
|
password: password != null ? decodeURIComponent(password) : undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
export class OpenAPI {
|
export class OpenAPI {
|
||||||
constructor(name = 'untitled', debug = false) {
|
constructor(name = 'untitled', debug = false) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -393,6 +413,7 @@ export function HTTP(defaultOptions = { baseURL: '' }) {
|
|||||||
}
|
}
|
||||||
if (isNode) {
|
if (isNode) {
|
||||||
const undici = eval("require('undici')");
|
const undici = eval("require('undici')");
|
||||||
|
const { socksDispatcher } = eval("require('fetch-socks')");
|
||||||
const {
|
const {
|
||||||
ProxyAgent,
|
ProxyAgent,
|
||||||
EnvHttpProxyAgent,
|
EnvHttpProxyAgent,
|
||||||
@@ -422,16 +443,34 @@ export function HTTP(defaultOptions = { baseURL: '' }) {
|
|||||||
).toString('base64')}`,
|
).toString('base64')}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
let dispatcher;
|
||||||
|
if (!opts.proxy) {
|
||||||
|
const allProxy =
|
||||||
|
eval('process.env.all_proxy') ||
|
||||||
|
eval('process.env.ALL_PROXY');
|
||||||
|
if (allProxy && /^socks5:\/\//.test(allProxy)) {
|
||||||
|
opts.proxy = allProxy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opts.proxy) {
|
||||||
|
if (/^socks5:\/\//.test(opts.proxy)) {
|
||||||
|
dispatcher = socksDispatcher(
|
||||||
|
parseSocks5Uri(opts.proxy),
|
||||||
|
agentOpts,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dispatcher = new ProxyAgent({
|
||||||
|
...agentOpts,
|
||||||
|
uri: opts.proxy,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dispatcher = new EnvHttpProxyAgent(agentOpts);
|
||||||
|
}
|
||||||
const response = await request(opts.url, {
|
const response = await request(opts.url, {
|
||||||
...opts,
|
...opts,
|
||||||
method: method.toUpperCase(),
|
method: method.toUpperCase(),
|
||||||
dispatcher: (opts.proxy
|
dispatcher: dispatcher.compose(
|
||||||
? new ProxyAgent({
|
|
||||||
...agentOpts,
|
|
||||||
uri: opts.proxy,
|
|
||||||
})
|
|
||||||
: new EnvHttpProxyAgent(agentOpts)
|
|
||||||
).compose(
|
|
||||||
interceptors.redirect({
|
interceptors.redirect({
|
||||||
maxRedirections: 3,
|
maxRedirections: 3,
|
||||||
throwOnMaxRedirects: true,
|
throwOnMaxRedirects: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user