mirror of
https://github.com/sub-store-org/Sub-Store.git
synced 2025-08-10 00:52:40 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc0aed052c | ||
|
|
6efb19c856 | ||
|
|
2cd30dfe68 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sub-store",
|
||||
"version": "2.16.55",
|
||||
"version": "2.16.58",
|
||||
"description": "Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket.",
|
||||
"main": "src/main.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
validCheck,
|
||||
flowTransfer,
|
||||
getRmainingDays,
|
||||
normalizeFlowHeader,
|
||||
} from '@/utils/flow';
|
||||
|
||||
function isObject(item) {
|
||||
@@ -1083,6 +1084,7 @@ function createDynamicFunction(name, script, $arguments, $options) {
|
||||
flowTransfer,
|
||||
validCheck,
|
||||
getRmainingDays,
|
||||
normalizeFlowHeader,
|
||||
};
|
||||
if ($.env.isLoon) {
|
||||
return new Function(
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
import { ProxyUtils } from '@/core/proxy-utils';
|
||||
import { COLLECTIONS_KEY, SUBS_KEY } from '@/constants';
|
||||
import { findByName } from '@/utils/database';
|
||||
import { getFlowHeaders } from '@/utils/flow';
|
||||
import { getFlowHeaders, normalizeFlowHeader } from '@/utils/flow';
|
||||
import $ from '@/core/app';
|
||||
import { failed } from '@/restful/response';
|
||||
import { InternalServerError, ResourceNotFoundError } from '@/restful/errors';
|
||||
@@ -259,7 +259,10 @@ async function downloadSubscription(req, res) {
|
||||
$arguments.flowUrl,
|
||||
);
|
||||
if (flowInfo) {
|
||||
res.set('subscription-userinfo', flowInfo);
|
||||
res.set(
|
||||
'subscription-userinfo',
|
||||
normalizeFlowHeader(flowInfo),
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -293,10 +296,9 @@ async function downloadSubscription(req, res) {
|
||||
}
|
||||
res.set(
|
||||
'subscription-userinfo',
|
||||
[subUserInfo, flowInfo]
|
||||
.filter((i) => i)
|
||||
.join('; ')
|
||||
.replace(/\s*;\s*;\s*/g, ';'),
|
||||
normalizeFlowHeader(
|
||||
[subUserInfo, flowInfo].filter((i) => i).join(';'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -556,7 +558,7 @@ async function downloadCollection(req, res) {
|
||||
if (subUserInfo) {
|
||||
res.set(
|
||||
'subscription-userinfo',
|
||||
subUserInfo.replace(/\s*;\s*;\s*/g, ';'),
|
||||
normalizeFlowHeader(subUserInfo),
|
||||
);
|
||||
}
|
||||
if (platform === 'JSON') {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { deleteByName, findByName, updateByName } from '@/utils/database';
|
||||
import { getFlowHeaders } from '@/utils/flow';
|
||||
import { getFlowHeaders, normalizeFlowHeader } from '@/utils/flow';
|
||||
import { FILES_KEY } from '@/constants';
|
||||
import { failed, success } from '@/restful/response';
|
||||
import $ from '@/core/app';
|
||||
@@ -148,7 +148,7 @@ async function getFile(req, res) {
|
||||
if (flowInfo) {
|
||||
res.set(
|
||||
'subscription-userinfo',
|
||||
flowInfo.replace(/\s*;\s*;\s*/g, ';'),
|
||||
normalizeFlowHeader(flowInfo),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,21 @@ async function gistBackupAction(action) {
|
||||
const updated = settings.syncTime;
|
||||
switch (action) {
|
||||
case 'upload':
|
||||
try {
|
||||
content = $.read('#sub-store');
|
||||
if ($.env.isNode) content = JSON.stringify($.cache, null, ` `);
|
||||
$.info(`下载备份, 与本地内容对比...`);
|
||||
const onlineContent = await gist.download(
|
||||
GIST_BACKUP_FILE_NAME,
|
||||
);
|
||||
if (onlineContent === content) {
|
||||
$.info(`内容一致, 无需上传备份`);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
$.error(`${error.message ?? error}`);
|
||||
}
|
||||
|
||||
// update syncTime
|
||||
settings.syncTime = new Date().getTime();
|
||||
$.write(settings, SETTINGS_KEY);
|
||||
|
||||
@@ -313,3 +313,41 @@ export function getRmainingDays(opt = {}) {
|
||||
$.error(`getRmainingDays failed: ${e.message ?? e}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeFlowHeader(flowHeaders) {
|
||||
try {
|
||||
// 使用 Map 保持顺序并处理重复键
|
||||
const kvMap = new Map();
|
||||
|
||||
flowHeaders
|
||||
.split(';')
|
||||
.map((p) => p.trim())
|
||||
.filter(Boolean)
|
||||
.forEach((pair) => {
|
||||
const eqIndex = pair.indexOf('=');
|
||||
if (eqIndex === -1) return;
|
||||
|
||||
const key = pair.slice(0, eqIndex).trim();
|
||||
const encodedValue = pair.slice(eqIndex + 1).trim();
|
||||
|
||||
// 只保留第一个出现的 key
|
||||
if (!kvMap.has(key)) {
|
||||
try {
|
||||
// 解码 URI 组件并保留原始值作为 fallback
|
||||
const decodedValue = decodeURIComponent(encodedValue);
|
||||
kvMap.set(key, decodedValue);
|
||||
} catch (e) {
|
||||
kvMap.set(key, encodedValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 拼接标准化字符串
|
||||
return Array.from(kvMap.entries())
|
||||
.map(([k, v]) => `${k}=${encodeURIComponent(v)}`) // 重新编码保持兼容性
|
||||
.join(';');
|
||||
} catch (e) {
|
||||
$.error(`normalizeFlowHeader failed: ${e.message ?? e}`);
|
||||
return flowHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ const ISOFlags = {
|
||||
'🇧🇬': ['BG', 'BGR'],
|
||||
'🇧🇭': ['BH', 'BHR'],
|
||||
'🇧🇴': ['BO', 'BOL'],
|
||||
'🇧🇳': ['BN', 'BRN'],
|
||||
'🇧🇷': ['BR', 'BRA'],
|
||||
'🇧🇹': ['BT', 'BTN'],
|
||||
'🇧🇾': ['BY', 'BLR'],
|
||||
'🇨🇦': ['CA', 'CAN'],
|
||||
'🇨🇭': ['CH', 'CHE'],
|
||||
@@ -40,6 +42,7 @@ const ISOFlags = {
|
||||
'🇬🇪': ['GE', 'GEO'],
|
||||
'🇬🇷': ['GR', 'GRC'],
|
||||
'🇬🇹': ['GT', 'GTM'],
|
||||
'🇬🇺': ['GU', 'GUM'],
|
||||
'🇭🇰': ['HK', 'HKG', 'HKT', 'HKBN', 'HGC', 'WTT', 'CMI'],
|
||||
'🇭🇷': ['HR', 'HRV'],
|
||||
'🇭🇺': ['HU', 'HUN'],
|
||||
@@ -59,12 +62,15 @@ const ISOFlags = {
|
||||
'🇮🇷': ['IR', 'IRN'],
|
||||
'🇮🇸': ['IS', 'ISL'],
|
||||
'🇮🇹': ['IT', 'ITA'],
|
||||
'🇱🇦': ['LA', 'LAO'],
|
||||
'🇱🇰': ['LK', 'LKA'],
|
||||
'🇱🇹': ['LT', 'LTU'],
|
||||
'🇱🇺': ['LU', 'LUX'],
|
||||
'🇱🇻': ['LV', 'LVA'],
|
||||
'🇲🇦': ['MA', 'MAR'],
|
||||
'🇲🇩': ['MD', 'MDA'],
|
||||
'🇳🇬': ['NG', 'NGA'],
|
||||
'🇲🇲': ['MM', 'MMR'],
|
||||
'🇲🇰': ['MK', 'MKD'],
|
||||
'🇲🇳': ['MN', 'MNG'],
|
||||
'🇲🇴': ['MO', 'MAC', 'CTM'],
|
||||
@@ -83,6 +89,7 @@ const ISOFlags = {
|
||||
'🇵🇷': ['PR', 'PRI'],
|
||||
'🇵🇹': ['PT', 'PRT'],
|
||||
'🇵🇾': ['PY', 'PRY'],
|
||||
'🇵🇬': ['PG', 'PNG'],
|
||||
'🇷🇴': ['RO', 'ROU'],
|
||||
'🇷🇸': ['RS', 'SRB'],
|
||||
'🇷🇪': ['RE', 'REU'],
|
||||
@@ -142,8 +149,10 @@ export function getFlag(name) {
|
||||
'🇧🇬': ['Bulgaria', '保加利亚', '保加利亞'],
|
||||
'🇧🇭': ['Bahrain', '巴林'],
|
||||
'🇧🇷': ['Brazil', '巴西', '圣保罗'],
|
||||
'🇧🇳': ['Brunei', '文莱', '汶萊'],
|
||||
'🇧🇾': ['Belarus', '白俄罗斯', '白俄'],
|
||||
'🇧🇴': ['Bolivia', '玻利维亚'],
|
||||
'🇧🇹': ['Bhutan', '不丹', '不丹王国'],
|
||||
'🇨🇦': [
|
||||
'Canada',
|
||||
'加拿大',
|
||||
@@ -194,6 +203,7 @@ export function getFlag(name) {
|
||||
],
|
||||
'🇬🇪': ['Georgia', '格鲁吉亚', '格魯吉亞'],
|
||||
'🇬🇷': ['Greece', '希腊', '希臘'],
|
||||
'🇬🇺': ['Guam', '关岛', '關島'],
|
||||
'🇬🇹': ['Guatemala', '危地马拉'],
|
||||
'🇭🇰': [
|
||||
'Hongkong',
|
||||
@@ -254,11 +264,14 @@ export function getFlag(name) {
|
||||
'🇮🇷': ['Iran', '伊朗'],
|
||||
'🇮🇸': ['Iceland', '冰岛', '冰島'],
|
||||
'🇮🇹': ['Italy', '意大利', '義大利', '米兰', 'Nachash'],
|
||||
'🇱🇰': ['Sri Lanka', '斯里兰卡', '斯里蘭卡'],
|
||||
'🇱🇦': ['Laos', '老挝', '老撾'],
|
||||
'🇱🇹': ['Lithuania', '立陶宛'],
|
||||
'🇱🇺': ['Luxembourg', '卢森堡'],
|
||||
'🇱🇻': ['Latvia', '拉脱维亚', 'Latvija'],
|
||||
'🇲🇦': ['Morocco', '摩洛哥'],
|
||||
'🇲🇩': ['Moldova', '摩尔多瓦', '摩爾多瓦'],
|
||||
'🇲🇲': ['Myanmar', '缅甸', '緬甸'],
|
||||
'🇳🇬': ['Nigeria', '尼日利亚', '尼日利亞'],
|
||||
'🇲🇰': ['Macedonia', '马其顿', '馬其頓'],
|
||||
'🇲🇳': ['Mongolia', '蒙古'],
|
||||
@@ -284,6 +297,7 @@ export function getFlag(name) {
|
||||
'🇵🇱': ['Poland', '波兰', '波蘭', '华沙', 'Warsaw'],
|
||||
'🇵🇷': ['Puerto Rico', '波多黎各'],
|
||||
'🇵🇹': ['Portugal', '葡萄牙'],
|
||||
'🇵🇬': ['Papua New Guinea', '巴布亚新几内亚'],
|
||||
'🇵🇾': ['Paraguay', '巴拉圭'],
|
||||
'🇷🇴': ['Romania', '罗马尼亚'],
|
||||
'🇷🇸': ['Serbia', '塞尔维亚'],
|
||||
|
||||
@@ -118,6 +118,7 @@ export default class Gist {
|
||||
.get('/gists?per_page=100&page=1')
|
||||
.then((response) => {
|
||||
const gists = JSON.parse(response.body);
|
||||
$.info(`获取到当前 GitHub 用户的 gist: ${gists.length} 个`);
|
||||
for (let g of gists) {
|
||||
if (g.description === this.key) {
|
||||
return g;
|
||||
|
||||
Reference in New Issue
Block a user