Compare commits

..

1 Commits

Author SHA1 Message Date
QuentinHsu
bac04587b8 🐞 fix(subscriptions): negative usage flow 2022-10-23 13:36:01 +08:00
11 changed files with 4286 additions and 4449 deletions

View File

@@ -21,7 +21,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: "16"
node-version: "14"
- name: Install dependencies
run: |
npm install -g pnpm

View File

@@ -1,6 +1,6 @@
{
"name": "sub-store",
"version": "2.14.0",
"version": "2.13.5",
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and ShadowRocket.",
"main": "src/main.js",
"scripts": {
@@ -30,7 +30,7 @@
"@babel/preset-env": "^7.18.0",
"@babel/register": "^7.17.7",
"@types/gulp": "^4.0.9",
"axios": "^0.21.2",
"axios": "^0.20.0",
"babel-plugin-relative-path-import": "^2.0.1",
"babelify": "^10.0.0",
"browser-pack-flat": "^3.4.2",

8544
backend/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,5 +9,3 @@ export const GIST_BACKUP_FILE_NAME = 'Sub-Store';
export const ARTIFACT_REPOSITORY_KEY = 'Sub-Store Artifacts Repository';
export const RESOURCE_CACHE_KEY = '#sub-store-cached-resource';
export const CACHE_EXPIRATION_TIME_MS = 60 * 60 * 1000; // 1 hour
export const SCRIPT_RESOURCE_CACHE_KEY = '#sub-store-cached-script-resource'; // cached-script-resource CSR
export const CSR_EXPIRATION_TIME_KEY = '#sub-store-csr-expiration-time'; // Custom expiration time key; (Loon|Surge) Default write 48 hour

View File

@@ -1,5 +1,4 @@
import resourceCache from '@/utils/resource-cache';
import scriptResourceCache from '@/utils/script-resource-cache';
import { isIPv4, isIPv6 } from '@/utils';
import { FULL } from '@/utils/logical';
import { getFlag } from '@/utils/geo';
@@ -634,7 +633,6 @@ function createDynamicFunction(name, script, $arguments) {
'$httpClient',
'$notification',
'ProxyUtils',
'scriptResourceCache',
`${script}\n return ${name}`,
)(
$arguments,
@@ -647,7 +645,6 @@ function createDynamicFunction(name, script, $arguments) {
// eslint-disable-next-line no-undef
$notification,
ProxyUtils,
scriptResourceCache,
);
} else {
return new Function(
@@ -655,8 +652,7 @@ function createDynamicFunction(name, script, $arguments) {
'$substore',
'lodash',
'ProxyUtils',
'scriptResourceCache',
`${script}\n return ${name}`,
)($arguments, $, lodash, ProxyUtils, scriptResourceCache);
)($arguments, $, lodash, ProxyUtils);
}
}

View File

@@ -55,10 +55,6 @@ function shadowsocks(proxy) {
// udp
result.appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// test-url
result.appendIfPresent(`,test-url=${proxy['test-url']}`, 'test-url');
return result.toString();
}
@@ -91,10 +87,6 @@ function trojan(proxy) {
// udp
result.appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// test-url
result.appendIfPresent(`,test-url=${proxy['test-url']}`, 'test-url');
return result.toString();
}
@@ -135,9 +127,6 @@ function vmess(proxy) {
// udp
result.appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// test-url
result.appendIfPresent(`,test-url=${proxy['test-url']}`, 'test-url');
return result.toString();
}
@@ -166,10 +155,6 @@ function http(proxy) {
// udp
result.appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// test-url
result.appendIfPresent(`,test-url=${proxy['test-url']}`, 'test-url');
return result.toString();
}
@@ -200,10 +185,6 @@ function socks5(proxy) {
// udp
result.appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// test-url
result.appendIfPresent(`,test-url=${proxy['test-url']}`, 'test-url');
return result.toString();
}
@@ -229,10 +210,6 @@ function snell(proxy) {
// udp
result.appendIfPresent(`,udp-relay=${proxy.udp}`, 'udp');
// test-url
result.appendIfPresent(`,test-url=${proxy['test-url']}`, 'test-url');
return result.toString();
}

View File

@@ -1,14 +1,13 @@
import { HTTP, ENV } from '@/vendor/open-api';
import { HTTP } from '@/vendor/open-api';
import { hex_md5 } from '@/vendor/md5';
import resourceCache from '@/utils/resource-cache';
const tasks = new Map();
export default async function download(url, ua) {
const { isNode } = ENV();
ua = ua || 'Quantumult%20X/1.0.29 (iPhone14,5; iOS 15.4.1)';
const id = hex_md5(ua + url);
if (!isNode && tasks.has(id)) {
if (tasks.has(id)) {
return tasks.get(id);
}
@@ -40,8 +39,6 @@ export default async function download(url, ua) {
}
});
if (!isNode) {
tasks.set(id, result);
}
tasks.set(id, result);
return result;
}

View File

@@ -16,13 +16,8 @@ class ResourceCache {
let clear = false;
Object.entries(this.resourceCache).forEach((entry) => {
const [id, updated] = entry;
if (!updated.time) {
// clear old version cache
delete this.resourceCache[id];
if (new Date().getTime() - updated > this.expires) {
$.delete(`#${id}`);
clear = true;
}
if (new Date().getTime() - updated.time > this.expires) {
delete this.resourceCache[id];
clear = true;
}
@@ -31,6 +26,9 @@ class ResourceCache {
}
revokeAll() {
Object.keys(this.resourceCache).forEach((id) => {
$.delete(`#${id}`);
});
this.resourceCache = {};
this._persist();
}
@@ -40,16 +38,17 @@ class ResourceCache {
}
get(id) {
const updated = this.resourceCache[id] && this.resourceCache[id].time;
const updated = this.resourceCache[id];
if (updated && new Date().getTime() - updated <= this.expires) {
return this.resourceCache[id].data;
return $.read(`#${id}`);
}
return null;
}
set(id, value) {
this.resourceCache[id] = { time: new Date().getTime(), data: value }
this.resourceCache[id] = new Date().getTime();
this._persist();
$.write(value, `#${id}`);
}
}

View File

@@ -1,105 +0,0 @@
import $ from '@/core/app';
import {
SCRIPT_RESOURCE_CACHE_KEY,
CSR_EXPIRATION_TIME_KEY,
} from '@/constants';
class ResourceCache {
constructor() {
this.expires = getExpiredTime();
if (!$.read(SCRIPT_RESOURCE_CACHE_KEY)) {
$.write('{}', SCRIPT_RESOURCE_CACHE_KEY);
}
this.resourceCache = JSON.parse($.read(SCRIPT_RESOURCE_CACHE_KEY));
this._cleanup();
}
_cleanup() {
// clear obsolete cached resource
let clear = false;
Object.entries(this.resourceCache).forEach((entry) => {
const [id, updated] = entry;
if (!updated.time) {
// clear old version cache
delete this.resourceCache[id];
$.delete(`#${id}`);
clear = true;
}
if (new Date().getTime() - updated.time > this.expires) {
delete this.resourceCache[id];
clear = true;
}
});
if (clear) this._persist();
}
revokeAll() {
this.resourceCache = {};
this._persist();
}
_persist() {
$.write(JSON.stringify(this.resourceCache), SCRIPT_RESOURCE_CACHE_KEY);
}
get(id) {
const updated = this.resourceCache[id] && this.resourceCache[id].time;
if (updated && new Date().getTime() - updated <= this.expires) {
return this.resourceCache[id].data;
}
return null;
}
gettime(id) {
const updated = this.resourceCache[id] && this.resourceCache[id].time;
if (updated && new Date().getTime() - updated <= this.expires) {
return this.resourceCache[id].time;
}
return null;
}
set(id, value) {
this.resourceCache[id] = { time: new Date().getTime(), data: value };
this._persist();
}
}
function getExpiredTime() {
console.log($.read(CSR_EXPIRATION_TIME_KEY));
if (!$.read(CSR_EXPIRATION_TIME_KEY)) {
$.write('1728e5', CSR_EXPIRATION_TIME_KEY); // 48 * 3600 * 1000
}
let expiration = 1728e5;
if ($.env.isLoon) {
const loont = {
// Loon 插件自义定
'1\u5206\u949f': 6e4,
'5\u5206\u949f': 3e5,
'10\u5206\u949f': 6e5,
'30\u5206\u949f': 18e5, // "30分钟"
'1\u5c0f\u65f6': 36e5,
'2\u5c0f\u65f6': 72e5,
'3\u5c0f\u65f6': 108e5,
'6\u5c0f\u65f6': 216e5,
'12\u5c0f\u65f6': 432e5,
'24\u5c0f\u65f6': 864e5,
'48\u5c0f\u65f6': 1728e5,
'72\u5c0f\u65f6': 2592e5, // "72小时"
'\u53c2\u6570\u4f20\u5165': 'readcachets', // "参数输入"
};
let intimed = $.read('#\u8282\u70b9\u7f13\u5b58\u6709\u6548\u671f'); // Loon #节点缓存有效期
console.log(intimed);
if (intimed in loont) {
expiration = loont[intimed];
if (expiration === 'readcachets') {
expiration = intimed;
}
}
return expiration;
} else {
expiration = $.read(CSR_EXPIRATION_TIME_KEY);
return expiration;
}
}
export default new ResourceCache();

View File

@@ -4,16 +4,12 @@
#!author=Peng-YM
#!homepage=https://github.com/Peng-YM/Sub-Store
#!icon=https://raw.githubusercontent.com/58xinian/icon/master/Sub-Store1.png
#!select = 节点缓存有效期,1分钟,5分钟,10分钟,30分钟,1小时,2小时,3小时,6小时,12小时,24小时,48小时,72小时,参数传入
[Rule]
DOMAIN,sub-store.vercel.app,PROXY
[MITM]
hostname=sub.store
[Script]
http-request ^https?:\/\/sub\.store\/((download)|api\/(preview|sync|(utils\/node-info))) script-path=https://github.com/sub-store-org/Sub-Store/releases/latest/download/sub-store-1.min.js, requires-body=true, timeout=120, tag=Sub-Store Core
http-request ^https?:\/\/sub\.store script-path=https://github.com/sub-store-org/Sub-Store/releases/latest/download/sub-store-0.min.js, requires-body=true, timeout=120, tag=Sub-Store Simple
http-request https?:\/\/sub\.store script-path=https://github.com/sub-store-org/Sub-Store/releases/latest/download/sub-store-0.min.js, requires-body=true, timeout=120, tag=Sub-Store Simple
cron "0 0 * * *" script-path=https://github.com/sub-store-org/Sub-Store/releases/latest/download/cron-sync-artifacts.min.js, tag=Sub-Store Sync

View File

@@ -17,13 +17,8 @@ class ResourceCache {
let clear = false;
Object.entries(this.resourceCache).forEach((entry) => {
const [id, updated] = entry;
if (!updated.time) {
// clear old version cache
delete this.resourceCache[id];
if (new Date().getTime() - updated > this.expires) {
$.delete(`#${id}`);
clear = true;
}
if (new Date().getTime() - updated.time > this.expires) {
delete this.resourceCache[id];
clear = true;
}
@@ -32,6 +27,9 @@ class ResourceCache {
}
revokeAll() {
Object.keys(this.resourceCache).forEach((id) => {
$.delete(`#${id}`);
});
this.resourceCache = {};
this._persist();
}
@@ -41,16 +39,17 @@ class ResourceCache {
}
get(id) {
const updated = this.resourceCache[id] && this.resourceCache[id].time;
const updated = this.resourceCache[id];
if (updated && new Date().getTime() - updated <= this.expires) {
return this.resourceCache[id].data;
return $.read(`#${id}`);
}
return null;
}
set(id, value) {
this.resourceCache[id] = { time: new Date().getTime(), data: value }
this.resourceCache[id] = new Date().getTime();
this._persist();
$.write(value, `#${id}`);
}
}