mirror of
https://git.mirrors.martin98.com/https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-22 17:39:05 +08:00
feat: 实验性支持本地脚本复用
This commit is contained in:
parent
2c89a0ddbd
commit
9e5a1adb12
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sub-store",
|
"name": "sub-store",
|
||||||
"version": "2.14.52",
|
"version": "2.14.53",
|
||||||
"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": {
|
||||||
|
@ -2,6 +2,7 @@ export const SCHEMA_VERSION_KEY = 'schemaVersion';
|
|||||||
export const SETTINGS_KEY = 'settings';
|
export const SETTINGS_KEY = 'settings';
|
||||||
export const SUBS_KEY = 'subs';
|
export const SUBS_KEY = 'subs';
|
||||||
export const COLLECTIONS_KEY = 'collections';
|
export const COLLECTIONS_KEY = 'collections';
|
||||||
|
export const FILES_KEY = 'files';
|
||||||
export const ARTIFACTS_KEY = 'artifacts';
|
export const ARTIFACTS_KEY = 'artifacts';
|
||||||
export const RULES_KEY = 'rules';
|
export const RULES_KEY = 'rules';
|
||||||
export const GIST_BACKUP_KEY = 'Auto Generated Sub-Store Backup';
|
export const GIST_BACKUP_KEY = 'Auto Generated Sub-Store Backup';
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import download from '@/utils/download';
|
import download from '@/utils/download';
|
||||||
import { isIPv4, isIPv6 } from '@/utils';
|
import { isIPv4, isIPv6 } from '@/utils';
|
||||||
|
import { FILES_KEY } from '@/constants';
|
||||||
import PROXY_PROCESSORS, { ApplyProcessor } from './processors';
|
import PROXY_PROCESSORS, { ApplyProcessor } from './processors';
|
||||||
import PROXY_PREPROCESSORS from './preprocessors';
|
import PROXY_PREPROCESSORS from './preprocessors';
|
||||||
import PROXY_PRODUCERS from './producers';
|
import PROXY_PRODUCERS from './producers';
|
||||||
@ -84,7 +85,29 @@ async function process(proxies, operators = [], targetPlatform) {
|
|||||||
|
|
||||||
// if this is a remote script, download it
|
// if this is a remote script, download it
|
||||||
try {
|
try {
|
||||||
script = await download(url.split('#')[0]);
|
const downloadUrl = url.split('#')[0];
|
||||||
|
const downloadUrlMatch =
|
||||||
|
downloadUrl.match(/^\/api\/file\/(.+)/);
|
||||||
|
if (downloadUrlMatch) {
|
||||||
|
let fileName = downloadUrlMatch?.[1];
|
||||||
|
if (fileName == null) {
|
||||||
|
throw new Error(`本地脚本 URL 无效: ${url}`);
|
||||||
|
}
|
||||||
|
fileName = decodeURIComponent(fileName);
|
||||||
|
const allFiles = $.read(FILES_KEY);
|
||||||
|
const file = allFiles.find(
|
||||||
|
(i) => i.name === fileName && i.type === item.type,
|
||||||
|
);
|
||||||
|
if (!file) {
|
||||||
|
throw new Error(
|
||||||
|
`找不到类型为 ${item.type} 的本地脚本: ${fileName}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
script = file.content;
|
||||||
|
} else {
|
||||||
|
script = await download(downloadUrl);
|
||||||
|
}
|
||||||
|
|
||||||
// $.info(`Script loaded: >>>\n ${script}`);
|
// $.info(`Script loaded: >>>\n ${script}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
$.error(
|
$.error(
|
||||||
|
103
backend/src/restful/file.js
Normal file
103
backend/src/restful/file.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import { deleteByName, findByName, updateByName } from '@/utils/database';
|
||||||
|
import { FILES_KEY } from '@/constants';
|
||||||
|
import { failed, success } from '@/restful/response';
|
||||||
|
import $ from '@/core/app';
|
||||||
|
import { RequestInvalidError, ResourceNotFoundError } from '@/restful/errors';
|
||||||
|
|
||||||
|
export default function register($app) {
|
||||||
|
if (!$.read(FILES_KEY)) $.write([], FILES_KEY);
|
||||||
|
|
||||||
|
$app.route('/api/file/:name')
|
||||||
|
.get(getFile)
|
||||||
|
.patch(updateFile)
|
||||||
|
.delete(deleteFile);
|
||||||
|
|
||||||
|
$app.route('/api/files').get(getAllFiles).post(createFile).put(replaceFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// file API
|
||||||
|
function createFile(req, res) {
|
||||||
|
const file = req.body;
|
||||||
|
$.info(`正在创建文件:${file.name}`);
|
||||||
|
const allFiles = $.read(FILES_KEY);
|
||||||
|
if (findByName(allFiles, file.name)) {
|
||||||
|
failed(
|
||||||
|
res,
|
||||||
|
new RequestInvalidError(
|
||||||
|
'DUPLICATE_KEY',
|
||||||
|
`File ${file.name} already exists.`,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
allFiles.push(file);
|
||||||
|
$.write(allFiles, FILES_KEY);
|
||||||
|
success(res, file, 201);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFile(req, res) {
|
||||||
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
|
const allFiles = $.read(FILES_KEY);
|
||||||
|
const file = findByName(allFiles, name);
|
||||||
|
if (file) {
|
||||||
|
success(res, file);
|
||||||
|
} else {
|
||||||
|
failed(
|
||||||
|
res,
|
||||||
|
new ResourceNotFoundError(
|
||||||
|
`FILE_NOT_FOUND`,
|
||||||
|
`File ${name} does not exist`,
|
||||||
|
404,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFile(req, res) {
|
||||||
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
|
let file = req.body;
|
||||||
|
const allFiles = $.read(FILES_KEY);
|
||||||
|
const oldFile = findByName(allFiles, name);
|
||||||
|
if (oldFile) {
|
||||||
|
const newFile = {
|
||||||
|
...oldFile,
|
||||||
|
...file,
|
||||||
|
};
|
||||||
|
$.info(`正在更新文件:${name}...`);
|
||||||
|
|
||||||
|
updateByName(allFiles, name, newFile);
|
||||||
|
$.write(allFiles, FILES_KEY);
|
||||||
|
success(res, newFile);
|
||||||
|
} else {
|
||||||
|
failed(
|
||||||
|
res,
|
||||||
|
new ResourceNotFoundError(
|
||||||
|
'RESOURCE_NOT_FOUND',
|
||||||
|
`File ${name} does not exist!`,
|
||||||
|
),
|
||||||
|
404,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteFile(req, res) {
|
||||||
|
let { name } = req.params;
|
||||||
|
name = decodeURIComponent(name);
|
||||||
|
$.info(`正在删除文件:${name}`);
|
||||||
|
let allFiles = $.read(FILES_KEY);
|
||||||
|
deleteByName(allFiles, name);
|
||||||
|
$.write(allFiles, FILES_KEY);
|
||||||
|
success(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAllFiles(req, res) {
|
||||||
|
const allFiles = $.read(FILES_KEY);
|
||||||
|
success(res, allFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replaceFile(req, res) {
|
||||||
|
const allFiles = req.body;
|
||||||
|
$.write(allFiles, FILES_KEY);
|
||||||
|
success(res);
|
||||||
|
}
|
@ -4,6 +4,7 @@ import $ from '@/core/app';
|
|||||||
import registerSubscriptionRoutes from './subscriptions';
|
import registerSubscriptionRoutes from './subscriptions';
|
||||||
import registerCollectionRoutes from './collections';
|
import registerCollectionRoutes from './collections';
|
||||||
import registerArtifactRoutes from './artifacts';
|
import registerArtifactRoutes from './artifacts';
|
||||||
|
import registerFileRoutes from './file';
|
||||||
import registerSyncRoutes from './sync';
|
import registerSyncRoutes from './sync';
|
||||||
import registerDownloadRoutes from './download';
|
import registerDownloadRoutes from './download';
|
||||||
import registerSettingRoutes from './settings';
|
import registerSettingRoutes from './settings';
|
||||||
@ -23,6 +24,7 @@ export default function serve() {
|
|||||||
registerSortingRoutes($app);
|
registerSortingRoutes($app);
|
||||||
registerSettingRoutes($app);
|
registerSettingRoutes($app);
|
||||||
registerArtifactRoutes($app);
|
registerArtifactRoutes($app);
|
||||||
|
registerFileRoutes($app);
|
||||||
registerSyncRoutes($app);
|
registerSyncRoutes($app);
|
||||||
registerNodeInfoRoutes($app);
|
registerNodeInfoRoutes($app);
|
||||||
registerMiscRoutes($app);
|
registerMiscRoutes($app);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user