diff --git a/backend/.idea/workspace.xml b/backend/.idea/workspace.xml
index 7887c97..1ee79b4 100644
--- a/backend/.idea/workspace.xml
+++ b/backend/.idea/workspace.xml
@@ -22,6 +22,9 @@
+
+
+
@@ -87,6 +90,8 @@
+
+
@@ -106,182 +111,182 @@
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
diff --git a/backend/sub-store.js b/backend/sub-store.js
index 9455b68..fb10f45 100644
--- a/backend/sub-store.js
+++ b/backend/sub-store.js
@@ -119,7 +119,9 @@ async function downloadSub(req, res) {
const sub = allSubs[name];
try {
const output = await parseSub(sub, platform);
- res.send(output);
+ const {key, value} = getFlowHeaders(output.headers, []);
+ res.set(key, value)
+ res.send(output.proxies);
} catch (err) {
res.status(500).json({
status: "failed",
@@ -136,7 +138,12 @@ async function downloadSub(req, res) {
async function parseSub(sub, platform) {
// always download from url
- const raw = await $.http.get(sub.url).then(resp => resp.body).catch(err => {
+ const {raw, headers} = await $.http.get(sub.url).then(resp => {
+ return {
+ raw: resp.body,
+ headers: resp.headers
+ }
+ }).catch(err => {
throw new Error(err);
});
@@ -196,7 +203,42 @@ async function parseSub(sub, platform) {
$parser.addProducers([
QX_Producer, Loon_Producer, Surge_Producer, Raw_Producer
]);
- return $parser.produce(proxies);
+ return {
+ proxies: $parser.produce(proxies),
+ headers
+ };
+}
+
+function getFlowHeaders(headers, proxies) {
+ const subkey = Object.keys(headers).filter(k => /SUBSCRIPTION-USERINFO/i.test(k))[0];
+ if (subkey) {
+ // from headers
+ const userinfo = headers[subkey];
+ const upload = Number(userinfo.match(/upload=(\d+)/)[1]);
+ const download = Number(userinfo.match(/download=(\d+)/)[1]);
+ const total = Number(userinfo.match(/total=(\d+)/)[1]);
+ const expire = (userinfo.match(/expire=(\d+)/) || [])[1];
+ return {
+ key: "Subscription-Userinfo",
+ value: `${upload ? "upload=" + upload + ";" : ""}${download ? "download=" + download + ";" : ""}${total ? "total=" + total + ";" : ""}${expire ? "expire=" + expire + ";" : ""}`
+ }
+ } else {
+ let remains, expire;
+ // from fake nodes
+ for (const p of proxies) {
+ if (p.name.indexOf("剩余流量") !== -1) {
+ remains = p.name;
+ }
+ if (p.name.indexOf("过期时间") !== -1) {
+ expire = p.name;
+ }
+ }
+ return {
+ key: "Raw-Subscription-Userinfo",
+ value: `${remains ? "remains=" + remains + ";" : ""}${expire ? "expire=" + expire + ";" : ""}`
+ }
+ }
+
}
// Subscriptions
@@ -321,7 +363,7 @@ async function downloadCollection(req, res) {
const output = await Promise.all(subs.map(async id => {
const sub = $.read(SUBS_KEY)[id];
try {
- return parseSub(sub, platform);
+ return parseSub(sub, platform).then(res => res.proxies);
} catch (err) {
console.log(`ERROR when process subscription: ${id}`);
return "";
@@ -1633,7 +1675,7 @@ function ScriptOperator(script) {
/**************************** Filters ***************************************/
// filter by keywords
-function KeywordFilter({keywords=[], keep = true}) {
+function KeywordFilter({keywords = [], keep = true}) {
return {
name: "Keyword Filter",
func: (proxies) => {
@@ -1680,7 +1722,7 @@ function RegionFilter(regions) {
}
// filter by regex
-function RegexFilter({regex=[], keep = true}) {
+function RegexFilter({regex = [], keep = true}) {
return {
name: "Regex Filter",
func: (proxies) => {
diff --git a/web/src/components/KeywordFilter.vue b/web/src/components/KeywordFilter.vue
index ce21399..adb1a22 100644
--- a/web/src/components/KeywordFilter.vue
+++ b/web/src/components/KeywordFilter.vue
@@ -83,6 +83,15 @@ export default {
},
remove(idx) {
this.keywords.splice(idx, 1);
+ },
+ save() {
+ this.$emit("dataChanged", {
+ idx: this.idx,
+ args: {
+ keywords: this.keywords,
+ keep: this.mode === 'IN'
+ }
+ });
}
},
created() {
@@ -93,17 +102,13 @@ export default {
}
},
watch: {
+ mode() {
+ this.save();
+ },
keywords() {
- this.$emit("dataChanged", {
- idx: this.idx,
- type: "Keyword Filter",
- args: {
- keywords: this.keywords,
- keep: this.mode === 'IN'
- }
- })
+ this.save();
}
- }
+ },
}
diff --git a/web/src/components/RegexFilter.vue b/web/src/components/RegexFilter.vue
index f9dff8f..b474db5 100644
--- a/web/src/components/RegexFilter.vue
+++ b/web/src/components/RegexFilter.vue
@@ -87,18 +87,23 @@ export default {
},
remove(idx) {
this.regexps.splice(idx, 1);
- }
- },
- watch: {
- regexps() {
+ },
+ save() {
this.$emit("dataChanged", {
idx: this.idx,
- type: "Regex Filter",
args: {
regex: this.regexps,
keep: this.mode === 'IN'
}
- })
+ });
+ }
+ },
+ watch: {
+ regexps() {
+ this.save();
+ },
+ mode() {
+ this.save();
}
},
created() {
diff --git a/web/src/config.js b/web/src/config.js
index e770cfa..77f362b 100644
--- a/web/src/config.js
+++ b/web/src/config.js
@@ -1,3 +1,3 @@
-const DEBUG = false;
+const DEBUG = true;
export const BACKEND_BASE = DEBUG ? `http://192.168.1.134:3000` : `https://sub.store`;
\ No newline at end of file
diff --git a/web/src/views/SubEditor.vue b/web/src/views/SubEditor.vue
index a15d73a..6cd5a42 100644
--- a/web/src/views/SubEditor.vue
+++ b/web/src/views/SubEditor.vue
@@ -274,6 +274,7 @@ export default {
},
dataChanged(content) {
+ console.log(`${JSON.stringify(content)}`);
this.options.process[content.idx].args = content.args;
},