Skip to content

Commit 7d030b0

Browse files
committed
🐛 修复GM_info的兼容问题
1 parent 75bc958 commit 7d030b0

File tree

13 files changed

+210
-760
lines changed

13 files changed

+210
-760
lines changed

jest.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module.exports = {
2323
},
2424

2525
"jest.autoRun": {
26-
"watch": true,
26+
"watch": false,
2727
"onStartup": ["all-tests"]
2828
}
2929
};

package-lock.json

Lines changed: 39 additions & 627 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "scriptcat",
3-
"version": "0.9.1",
3+
"version": "0.9.2",
44
"description": "脚本猫,一个可以执行用户脚本的浏览器扩展,万物皆可脚本化,让你的浏览器可以做更多的事情!",
55
"scripts": {
66
"lint": "eslint --ext .js,.ts,.tsx tests/ src/",
@@ -50,7 +50,7 @@
5050
"@types/cron": "^1.7.2",
5151
"@types/crypto-js": "^4.0.1",
5252
"@types/file-saver": "^2.0.3",
53-
"@types/jest": "^26.0.22",
53+
"@types/jest": "^27.0.0",
5454
"@types/sortablejs": "^1.10.7",
5555
"@types/uuid": "^8.3.0",
5656
"@typescript-deploys/monaco-editor": "^4.2.0-pr-42612-2",

src/apps/grant/frontend.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { addStyle } from '@App/pkg/frontend';
44
import { blobToBase64, randomInt, randomString } from '@App/pkg/utils/utils';
55
import { BrowserMsg } from '../msg-center/browser';
66
import { AppEvent, ScriptValueChange } from '../msg-center/event';
7+
import { getMetadataStr } from '../script/utils';
78
import { Grant } from './interface';
89

910
type Callback = (grant: Grant) => void;
@@ -24,7 +25,7 @@ export interface ScriptContext {
2425

2526
getApi(grant: string): FrontenApiValue | undefined;
2627
ValueChange(name: string, value: Value): void;
27-
GM_info(): any;
28+
// GM_info(): any;
2829
}
2930

3031
export class FrontendGrant implements ScriptContext {
@@ -79,17 +80,23 @@ export class FrontendGrant implements ScriptContext {
7980
};
8081
}
8182

82-
public GM_info() {
83+
static GM_info(script: ScriptCache) {
84+
const metadataStr = getMetadataStr(script.sourceCode);
8385
return {
86+
// downloadMode
87+
// isIncognito
8488
scriptWillUpdate: false,
8589
scriptHandler: 'ScriptCat',
86-
scriptUpdateURL: this.script.checkupdate_url,
87-
scriptSource: this.script.code,
90+
scriptUpdateURL: script.checkupdate_url,
91+
scriptMetaStr: metadataStr,
92+
scriptSource: script.code,
93+
version: script.metadata['version'] && script.metadata['version'][0],
8894
script: {
89-
name: this.script.name,
90-
namespace: this.script.namespace,
91-
version: this.script.metadata['version'] && this.script.metadata['version'][0],
92-
author: this.script.author,
95+
// TODO: 更多完整的信息(为了兼容Tampermonkey,后续待定)
96+
name: script.name,
97+
namespace: script.namespace,
98+
version: script.metadata['version'] && script.metadata['version'][0],
99+
author: script.author,
93100
},
94101
};
95102
}
@@ -774,5 +781,4 @@ export class SandboxContext extends FrontendGrant {
774781
this.end();
775782
this.postRequest('CAT_runComplete', []);
776783
};
777-
778784
}

src/apps/script/controller.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,8 +515,9 @@ export class ScriptController {
515515

516516
ret.resource = await this.getResources(ret);
517517

518-
ret.flag = randomString(16);
519-
ret.code = compileScriptCode(ret);
518+
ret.flag = randomString(16);
519+
ret.sourceCode = ret.code;
520+
ret.code = compileScriptCode(ret);
520521

521522
ret.grantMap = {};
522523

@@ -585,4 +586,4 @@ export class ScriptController {
585586
});
586587
});
587588
}
588-
}
589+
}

src/apps/script/manager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,7 @@ export class ScriptManager extends Manager {
607607
return;
608608
}
609609
const cache = await this.controller.buildScriptCache(script);
610-
cache.code = dealScript(`window['${cache.flag}']=function(context){\n` + cache.code + '\n}');
610+
cache.code = dealScript(`window['${cache.flag}']=function(GM_info, context){\n` + cache.code + '\n}');
611611
script.metadata['match']?.forEach(val => {
612612
this.match.add(val, cache);
613613
});
@@ -1249,4 +1249,4 @@ export class ScriptManager extends Manager {
12491249
});
12501250
}
12511251

1252-
}
1252+
}

src/apps/script/utils.ts

Lines changed: 107 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -5,115 +5,127 @@ import axios from 'axios';
55
import { ScriptUrlInfo } from '../msg-center/structs';
66
import { Subscribe } from '@App/model/do/subscribe';
77

8+
export function getMetadataStr(code: string): string | null {
9+
const start = code.indexOf('==UserScript==');
10+
const end = code.indexOf('==/UserScript==');
11+
if (start === -1 || end === -1) {
12+
return null;
13+
}
14+
return '// ' + code.substring(start, end + 14);
15+
}
16+
817
export function parseMetadata(code: string): Metadata | null {
9-
let issub = false;
10-
let regex = /\/\/\s*==UserScript==([\s\S]+?)\/\/\s*==\/UserScript==/m;
11-
let header = regex.exec(code)
12-
if (!header) {
13-
regex = /\/\/\s*==UserSubscribe==([\s\S]+?)\/\/\s*==\/UserSubscribe==/m;
14-
header = regex.exec(code)
15-
if (!header) {
16-
return null;
17-
}
18-
issub = true
19-
}
20-
regex = /\/\/\s*@([\S]+)((.+?)$|$)/gm;
21-
const ret: Metadata = {};
22-
let meta: RegExpExecArray | null;
23-
while (meta = regex.exec(header[1])) {
24-
const [key, val] = [meta[1].toLowerCase().trim(), meta[2].trim()];
25-
let values = ret[key]
26-
if (values == null) {
27-
values = [];
28-
}
29-
values.push(val);
30-
ret[key] = values;
31-
}
32-
if (ret['name'] == undefined) {
33-
return null;
34-
}
35-
if (issub) {
36-
ret['usersubscribe'] = [];
37-
}
38-
return ret;
18+
let issub = false;
19+
let regex = /\/\/\s*==UserScript==([\s\S]+?)\/\/\s*==\/UserScript==/m;
20+
let header = regex.exec(code);
21+
if (!header) {
22+
regex = /\/\/\s*==UserSubscribe==([\s\S]+?)\/\/\s*==\/UserSubscribe==/m;
23+
header = regex.exec(code);
24+
if (!header) {
25+
return null;
26+
}
27+
issub = true;
28+
}
29+
regex = /\/\/\s*@([\S]+)((.+?)$|$)/gm;
30+
const ret: Metadata = {};
31+
let meta: RegExpExecArray | null;
32+
while ((meta = regex.exec(header[1]))) {
33+
const [key, val] = [meta[1].toLowerCase().trim(), meta[2].trim()];
34+
let values = ret[key];
35+
if (values == null) {
36+
values = [];
37+
}
38+
values.push(val);
39+
ret[key] = values;
40+
}
41+
if (ret['name'] == undefined) {
42+
return null;
43+
}
44+
if (issub) {
45+
ret['usersubscribe'] = [];
46+
}
47+
return ret;
3948
}
4049

4150
export function parseUserConfig(code: string): UserConfig | undefined {
42-
const regex = /\/\*\s*==UserConfig==([\s\S]+?)\s*==\/UserConfig==\s*\*\//m;
43-
const config = regex.exec(code)
44-
if (!config) {
45-
return undefined;
46-
}
47-
const configs = config[1].trim().split(/[-]{3,}/);
48-
const ret: UserConfig = {};
49-
configs.forEach(val => {
50-
const obj = YAML.parse(val);
51-
for (const key in obj) {
52-
ret[key] = obj[key];
53-
}
54-
});
55-
return ret;
51+
const regex = /\/\*\s*==UserConfig==([\s\S]+?)\s*==\/UserConfig==\s*\*\//m;
52+
const config = regex.exec(code);
53+
if (!config) {
54+
return undefined;
55+
}
56+
const configs = config[1].trim().split(/[-]{3,}/);
57+
const ret: UserConfig = {};
58+
configs.forEach((val) => {
59+
const obj = YAML.parse(val);
60+
for (const key in obj) {
61+
ret[key] = obj[key];
62+
}
63+
});
64+
return ret;
5665
}
5766

5867
export function validMetadata(metadata: Metadata | null): Metadata | null {
59-
if (metadata == null) {
60-
return null;
61-
}
68+
if (metadata == null) {
69+
return null;
70+
}
6271

63-
return metadata;
72+
return metadata;
6473
}
6574

6675
export function loadScriptByUrl(url: string): Promise<ScriptUrlInfo | undefined> {
67-
return new Promise(resolve => {
68-
axios.get(url, {
69-
headers: {
70-
'Cache-Control': 'no-cache'
71-
}
72-
}).then((response): ScriptUrlInfo | undefined => {
73-
if (response.status != 200) {
74-
return undefined;
75-
}
76-
const ok = parseMetadata(response.data);
77-
if (!ok) {
78-
return undefined;
79-
}
80-
const uuid = uuidv5(url, uuidv5.URL);
81-
const ret = {
82-
url: url,
83-
code: response.data,
84-
uuid: uuid,
85-
issub: false,
86-
};
87-
if (ok['usersubscribe']) {
88-
ret.issub = true;
89-
}
90-
resolve(ret);
91-
}).catch((e) => {
92-
resolve(undefined);
93-
});
94-
});
76+
return new Promise((resolve) => {
77+
axios
78+
.get(url, {
79+
headers: {
80+
'Cache-Control': 'no-cache',
81+
},
82+
})
83+
.then((response): ScriptUrlInfo | undefined => {
84+
if (response.status != 200) {
85+
return undefined;
86+
}
87+
const ok = parseMetadata(response.data);
88+
if (!ok) {
89+
return undefined;
90+
}
91+
const uuid = uuidv5(url, uuidv5.URL);
92+
const ret = {
93+
url: url,
94+
code: response.data,
95+
uuid: uuid,
96+
issub: false,
97+
};
98+
if (ok['usersubscribe']) {
99+
ret.issub = true;
100+
}
101+
resolve(ret);
102+
})
103+
.catch((e) => {
104+
resolve(undefined);
105+
});
106+
});
95107
}
96108

97109
export function copyScript(script: Script, old: Script) {
98-
script.id = old.id;
99-
script.uuid = old.uuid;
100-
script.createtime = old.createtime;
101-
script.checktime = old.checktime;
102-
script.lastruntime = old.lastruntime;
103-
script.delayruntime = old.delayruntime;
104-
script.error = old.error;
105-
script.sort = old.sort;
106-
if (!script.selfMetadata) {
107-
script.selfMetadata = old.selfMetadata || {};
108-
}
109-
script.subscribeUrl = old.subscribeUrl;
110-
script.status = old.status;
110+
script.id = old.id;
111+
script.uuid = old.uuid;
112+
script.createtime = old.createtime;
113+
script.checktime = old.checktime;
114+
script.lastruntime = old.lastruntime;
115+
script.delayruntime = old.delayruntime;
116+
script.error = old.error;
117+
script.sort = old.sort;
118+
if (!script.selfMetadata) {
119+
script.selfMetadata = old.selfMetadata || {};
120+
}
121+
script.subscribeUrl = old.subscribeUrl;
122+
script.status = old.status;
111123
}
112124

113125
export function copySubscribe(sub: Subscribe, old: Subscribe) {
114-
sub.id = old.id;
115-
sub.createtime = old.createtime;
116-
sub.status = old.status;
117-
sub.checktime = old.checktime;
118-
sub.error = old.error;
119-
}
126+
sub.id = old.id;
127+
sub.createtime = old.createtime;
128+
sub.status = old.status;
129+
sub.checktime = old.checktime;
130+
sub.error = old.error;
131+
}

src/background.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,14 @@ get(Server + 'api/v1/system/version', (str) => {
143143
});
144144
});
145145

146-
// 半小时同步一次数据和检查更新
146+
// 半小时同步一次数据
147+
setInterval(() => {
148+
if (SystemConfig.enable_auto_sync) {
149+
void user.sync();
150+
}
151+
}, 1800 * 1000);
152+
153+
// 两小时检查一次更新
147154
setInterval(() => {
148155
get(Server + 'api/v1/system/version', (str) => {
149156
chrome.storage.local.get(['oldNotice'], (items) => {
@@ -158,10 +165,7 @@ setInterval(() => {
158165
});
159166
});
160167
});
161-
if (SystemConfig.enable_auto_sync) {
162-
void user.sync();
163-
}
164-
}, 1800000);
168+
}, 7200 * 1000);
165169

166170
if (process.env.NODE_ENV == 'production') {
167171
chrome.runtime.onInstalled.addListener((details) => {

src/injected.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ browserMsg.listen('scripts', (msg) => {
5050
scripts.forEach(script => {
5151
// 构建沙盒
5252
let context: ScriptContext;
53+
const GMInfo = FrontendGrant.GM_info(script);
5354
if (script.grantMap['none']) {
5455
context = <any>window;
5556
} else {
@@ -67,8 +68,8 @@ browserMsg.listen('scripts', (msg) => {
6768
}
6869
Object.defineProperty(window, script.flag, {
6970
get: () => { return undefined; },
70-
set: (val: (context: ScriptContext) => void) => {
71-
val.apply(context, [context]);
71+
set: (val: (GM_Info:any, context: ScriptContext) => void) => {
72+
val.apply(context, [GMInfo, context]);
7273
}
7374
});
7475
// 注入css
@@ -87,8 +88,8 @@ browserMsg.listen('scripts', (msg) => {
8788
}
8889
Object.defineProperty(window, script.flag, {
8990
get: () => { return undefined; },
90-
set: (val: (context: ScriptContext) => void) => {
91-
val.apply(context, [context]);
91+
set: (val: (GM_Info:any, context: ScriptContext) => void) => {
92+
val.apply(context, [GMInfo, context]);
9293
}
9394
});
9495
// 注入css

0 commit comments

Comments
 (0)