diff --git a/Loon/Loon_Google_CAPTCHA.plugin b/Loon/Loon_Google_CAPTCHA.plugin new file mode 100644 index 0000000..7baec65 --- /dev/null +++ b/Loon/Loon_Google_CAPTCHA.plugin @@ -0,0 +1,14 @@ +#!name = Google人机验证 +#!desc = Google搜索内容时并发使用多个策略/策略组,以避免可能出现的人机验证。注意:需要在插件参数填写策略/策略组名的正则表达式。 +#!author = NobyDa +#!input = GOOGLE_CAPTCHA_REGEX +#!homepage = https://github.com/NobyDa/Script/tree/master +#!icon = https://cdn.jsdelivr.net/gh/NobyDa/mini@master/Color/Google.png +#!date = 2024-05-19 12:00:00 + + +[Script] +http-response ^https:\/\/www\.google\.com(?:\.[a-z]+|)\/(?:search\?(?:|.+?&)q=|$) requires-body=1,timeout=30,script-path=https://raw.githubusercontent.com/NobyDa/Script/master/Surge/JS/Google_CAPTCHA.js,tag=Google人机验证 + +[MITM] +hostname = www.google.com* \ No newline at end of file diff --git a/NobyDa_BoxJs.json b/NobyDa_BoxJs.json index 26c427c..f162ecf 100644 --- a/NobyDa_BoxJs.json +++ b/NobyDa_BoxJs.json @@ -682,6 +682,20 @@ "type": "text", "placeholder": "^(🇸🇬|🇭🇰)\\s.*\\d+$", "desc": "筛选的代理策略/策略组, 限制20个, 留空则表示随机使用。" + }, + { + "id": "@GOOGLE_CAPTCHA.RegexTest", + "name": "正则表达式测试", + "val": "", + "type": "text", + "placeholder": "(🇸🇬|🇭🇰)", + "desc": "填写并保存后可在右上角测试匹配的策略/策略组。" + } + ], + "scripts": [ + { + "name": "测试匹配的策略/策略组", + "script": "https://gist.githubusercontent.com/NobyDa/830932e4526c9c84169020a56c3ef199/raw/GOOGLE_CAPTCHA_TEST_POLICY.js" } ], "author": "@NobyDa", diff --git a/Surge/JS/Google_CAPTCHA.js b/Surge/JS/Google_CAPTCHA.js index 630e57a..4b96ec1 100644 --- a/Surge/JS/Google_CAPTCHA.js +++ b/Surge/JS/Google_CAPTCHA.js @@ -3,14 +3,14 @@ Google搜索人机验证解决方案 搜索内容时遇到人机验证立即并发使用多个代理策略、策略组尝试搜索内容,并返回最优结果。 脚本作者:@NobyDa -更新时间:2024/05/16 -平台兼容:Surge(iOS4.9.3+/macOS4.2.3+) / QuantumultX(1.0.26+) +更新时间:2024/05/19 +平台兼容:Surge(iOS4.9.3+/macOS4.2.3+) / QuantumultX(1.0.26+) / Loon(3.1.9[694]+) -可在BoxJs或Surge脚本配置参数(argument)填写筛选的代理策略、策略组的正则表达式。 -所有代理策略、策略组至多筛选、使用20个,不筛选则表示随机使用。 +可在 BoxJs(低优先级)、Surge模块参数、Loon插件参数中填写筛选的代理策略、策略组的正则表达式。 +所有代理策略、策略组至多筛选、使用20个,可在BoxJs中测试匹配的策略,不筛选则表示随机使用。 注意:Surge由于策略架构问题,正则表达式筛选的"代理策略"不包含"外部代理策略"; -QuantumultX无此限制,正则表达式可筛选所有"策略组"内的"代理策略"。 +QuantumultX、Loon则无此限制,正则表达式可筛选所有"策略组"内的"代理策略"。 ********************************* Surge(iOS 5.9.0+/macOS 5.5.0+) 模块: @@ -20,6 +20,14 @@ https://raw.githubusercontent.com/NobyDa/Script/master/Surge/Module/GoogleCAPTCH QuantumultX(1.0.26+) 重写资源引用: https://raw.githubusercontent.com/NobyDa/Script/master/QuantumultX/Snippet/GoogleCAPTCHA.snippet +********************************* +Loon(3.1.9[694]+) 插件: +https://raw.githubusercontent.com/NobyDa/Script/master/Loon/Loon_Google_CAPTCHA.plugin + +********************************* +BoxJs 订阅地址: +https://raw.githubusercontent.com/NobyDa/Script/master/NobyDa_BoxJs.json + *********************************/ const $ = new NobyDa_Tools(); @@ -30,6 +38,7 @@ $.ret = {}; const req = JSON.parse(JSON.stringify($request)); const policy = await $.policy(); const regexText = (typeof $argument == 'string' && $argument) || + $.data.read('GOOGLE_CAPTCHA_REGEX') || // loon plugin args. JSON.parse($.data.read('GOOGLE_CAPTCHA') || '{}').Regex || ''; // empty = all const selected = [...policy.group, ...policy.proxy] .filter((n) => n && new RegExp(regexText).test(n)) @@ -67,7 +76,7 @@ function NobyDa_Tools() { this.isLoon = typeof $loon !== "undefined"; this.isQuanX = typeof $configuration !== 'undefined'; this.isSurge = typeof $environment !== 'undefined' && $environment['surge-version']; - this.isNode = typeof module !== 'undefined'&& !!module.exports; + this.isNode = typeof module !== 'undefined' && !!module.exports; this.http = Object.fromEntries( ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS", "PATCH"].map( (m) => [m.toLowerCase(), (opts) => { @@ -104,13 +113,18 @@ function NobyDa_Tools() { group: Object.keys(b.ret) }), () => r({})); }); - // if (this.isLoon) { - // const config = JSON.parse($config.getConfig()); - // const proxy = config['all_policy_groups'] - // .reduce((t, i) => [...new Set([...t, ...JSON.parse($config.getSubPolicies(i) || '[]').map(n => n.name)])], []) - // .filter((v) => ![...config['all_policy_groups'], ...config['all_buildin_nodes']].includes(v)); - // return { proxy, group: config['all_policy_groups'] } - // }; + if (this.isLoon) return new Promise(async (r1) => { + const config = JSON.parse($config.getConfig()); + const groupData = await Promise.all(config['all_policy_groups'].map((i) => new Promise((r2) => { + $config.getSubPolicies(i, (b) => { r2(JSON.parse(b || '[]')) }) + }))); + r1({ + proxy: groupData.reduce((t, i) => [...new Set([...t, ...i.filter((v) => { + return v.type == 'node' && !config['all_buildin_nodes'].includes(v.name) + }).map((n) => n.name)])], []), + group: config['all_policy_groups'] + }) + }); }; this.data = Object.fromEntries(['read', 'write'].map( (i) => [i, (v1, v2) => {