pull/30/head
lhie1 7 years ago
parent fd679b6652
commit 166eb58100

@ -0,0 +1,409 @@
/*
surge conf builder
作者https://t.me/miniers
修改lhie1
*/
const _ = require('lodash');
$app.autoKeyboardEnabled = true;
$app.keyboardToolbarEnabled = true;
let baseUrl = "https://raw.githubusercontent.com/lhie1/Rules/master/",
surgeList = [
'Apple',
'DIRECT',
'HOST',
'Hostname',
'PROXY',
'REJECT',
'URL Rewrite',
'URL REJECT',
'Header Rewrite',
{
name:'TestFlight',
disabled:true,
path:'Surge/TestFlight'
}
];
let remoteIsDone = 0;
let remoteRule = {};
const fields = [{
name: 'filename',
text: '生成的配置文件名(必填)'
},
{
name: 'General',
text: '(必填)'
},
{
name: 'Proxy',
text: '(必填)'
},
{
name: 'Custom',
},
{
name: "ipRule"
},
{
name: 'Delete',
text: '删除所有包含该字符的规则,按行分隔'
},
{
name: 'Rewrite',
},
'Host',
'SSID',
{
name: 'extProxy',
text: '扩展代理,不会增加到自动生成的代理组'
},
{
name: 'hostname',
text: 'MITM中的hostname'
},
{
name: 'extProxyGroup',
text: '自定义代理组'
},
'MITM',
];
let config;
if ($drive.exists("surge.json")) {
try {
let file = $drive.read("surge.json");
config = JSON.parse($drive.read("surge.json").string)
} catch (err) {
initConfig()
}
} else {
initConfig()
}
//初始化配置
function initConfig() {
config = {
filename: 'Surge.conf',
remoteSwitch:{},
'General': `// Auto
loglevel = notify
dns-server = system,1.2.4.8,80.80.80.80,80.80.81.81,1.1.1.1,1.0.0.1
skip-proxy = 127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,100.64.0.0/10,17.0.0.0/8,localhost,*.local,*.crashlytics.com,::ffff:0.0.0.0/1,::ffff:128.0.0.0/1
// iOS
external-controller-access = lhie1@0.0.0.0:6170
allow-wifi-access = true
// macOS
interface = 0.0.0.0
socks-interface = 0.0.0.0
port = 8888
socks-port = 8889
enhanced-mode-by-rule = false
// Auto
exclude-simple-hostnames = true
ipv6 = true
replica = false
[Replica]
hide-apple-request = true
hide-crashlytics-request = true
use-keyword-filter = false`,
'Proxy': `🇺🇸 US = custom,us.com,1234,rc4-md5,password,http://omgib13x8.bkt.clouddn.com/SSEncrypt.module
🇭🇰 HK = custom,hk.com,1234,rc4-md5,password,http://omgib13x8.bkt.clouddn.com/SSEncrypt.module
🇯🇵 JP = custom,jp.com,1234,rc4-md5,password,http://omgib13x8.bkt.clouddn.com/SSEncrypt.module
🇸🇬 SG = custom,sg.com,1234,rc4-md5,password,http://omgib13x8.bkt.clouddn.com/SSEncrypt.module
`,
'Custom': "",
'Rewrite': "",
'Delete': "",
'Host': "",
'SSID': "",
'extProxy': "",
'hostname': "",
'extProxyGroup': "",
'MITM': `skip-server-cert-verify = true
tcp-connection = false
enable = true
ca-passphrase = 4B676386
ca-p12 = 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`,
}
}
function saveConfig() {
var success = $drive.write({
data: $data({
string: JSON.stringify(config)
}),
path: "surge.json"
})
}
function buildFile() {
var ProxyList = getProxyName(config.Proxy).join(',');
var cushostname = config.hostname.split('\n').join(',')
var result = `
[General]
${config.General}
[Proxy]
🚀 Direct = direct
# my Proxy
${config.Proxy}
# my extProxy
${config.extProxy}
[Proxy Group]
🍃 Proxy = select, 🏃 Auto, 🚀 Direct,${ProxyList}
🍂 Domestic = select, 🚀 Direct, 🍃 Proxy
🍎 Only = select, 🚀 Direct,${ProxyList}
Others = select,🚀 Direct,🍃 Proxy
🏃 Auto = url-test,${ProxyList},url = http://www.gstatic.com/generate_204, interval = 1200
# my extProxyGroup
${config.extProxyGroup}
[Rule]
# my custom
${config.Custom}
# remote Apple
${remoteRule.Apple}
# remote REJECT
${remoteRule.REJECT}
# remote PROXY
${remoteRule.PROXY}
# remote DIRECT
${remoteRule.DIRECT}
# my ipRule
${config.ipRule}
// Detect local network
GEOIP,CN,🍂 Domestic
// Use Proxy for all others
FINAL, Others,dns-failed
[Host]
# my host
${config.Host}
# remote HOST
${remoteRule['HOST']}
[URL Rewrite]
# my Rewrite
${config.Rewrite}
# remote URL Rewrite
${remoteRule['URL Rewrite']}
# remote URL REJECT
${remoteRule['URL REJECT']}
[Header Rewrite]
# remote Header Rewrite
${remoteRule['Header Rewrite']}
${remoteRule['TestFlight']}
[SSID Setting]
# my SSID
${config.SSID}
# MITM
${config.MITM?'[MITM]':''}
${config.MITM?`hostname=${cushostname?cushostname+",":""}${remoteRule.Hostname.split('\n').join(',')}`:''}
${config.MITM}`;
$share.sheet([config.filename || "surge.conf", $data({
string: result
})]);
$ui.loading(false)
}
function getProxyName(proxys) {
return proxys.match(/.+(?=\s=\s(custom|http|https|socks5|socks5-tls))/g)
}
function build() {
_.forEach(surgeList, function (name) {
let path,regex;
let disabled;
if(_.isObject(name)){
regex = name.regex;
path = name.path;
name = name.name;
}else{
path = `Auto/${name}`;
}
if(config.remoteSwitch[name]===false){
remoteIsDone++;
remoteRule[name] = '';
return;
}
$console.info(name);
$console.info(encodeURI([baseUrl, path, '.conf'].join('')));
$http.get({
url: encodeURI([baseUrl, path, '.conf'].join('')),
handler: function ({data}) {
if(!data){
$console.warn(`${name}拉取数据失败`)
}
remoteRule[name] = removeDeleteRule(data, name);
if(regex&&remoteRule[name]){
remoteRule[name] = _.get(remoteRule[name].match(new RegExp(regex,'s')),1,remoteRule[name])
}
remoteIsDone++;
if (remoteIsDone >= surgeList.length) {
saveConfig();
buildFile();
}
}
})
})
}
const removeDeleteRule = function(rule,name){
const deleteds = config.Delete.split('\n');
const orgRules = rule.split('\n');
let result = [],
deleted = [];
orgRules.forEach(function(line){
let isDeleted = false;
deleteds.forEach(function(del){
if (del&&line.match(del)) {
isDeleted = true;
}
});
!isDeleted && result.push(line);
});
// $ui.alert(deleted.join('\n'))
return result.join('\n')
};
const changeRemoteSwitch=function(key){
let switchBtn = $(`switch-${key}`);
config.remoteSwitch[key] = !switchBtn.on;
switchBtn.on = config.remoteSwitch[key];
console.log(`${key} = ${switchBtn.on}`)
}
$ui.render({
layout: $layout.fill,
views: [{
type: "button",
props: {
title: "生成配置"
},
layout: function (make) {
make.left.right.top.inset(10)
make.height.equalTo(32)
},
events: {
tapped: function (sender) {
$ui.loading(true)
fields.forEach(function(cus) {
let cfg = cus;
if (typeof cus === 'string') {
cfg = {
name: cus
}
}
config[cfg.name] = $(cfg.name).text
})
build()
// //selectItem()
}
}
}, {
type: "list",
layout: function (make) {
make.left.bottom.right.equalTo(0)
make.top.equalTo($("button").bottom).offset(0)
},
events:{
rowHeight:function(sender,indexPath){
return fields.length === indexPath.section?50:150;
}
},
props: {
data: fields.map(function (cus) {
let cfg = cus;
if (typeof cus === 'string') {
cfg = {
name: cus
}
}
return {
title: `${cfg.name} ${cfg.text?`(${cfg.text})`:''}`,
rows: [{
type: "text",
props: {
id: cfg.name,
text: config[cfg.name] || '',
},
layout: function (make) {
make.edges.inset(5);
}
}]
}
}).concat([{
title:`远程规则开关`,
rows:surgeList.map(function(key){
if(_.isObject(key)){
const disabled = key.disabled;
key = key.name;
if(disabled && _.isUndefined(config.remoteSwitch[key])){
config.remoteSwitch[key] = false;
}
}
return {
type:'view',
props:{},
layout:$layout.fill,
events:{
tapped:function(sender){
changeRemoteSwitch(key);
}
},
views:[
{
type:`switch`,
props:{
id:`switch-${key}`,
on:config.remoteSwitch[key]!==false
},
layout:function(make,view){
make.left.top.equalTo(10)
},
events:{
changed:function(sender){
changeRemoteSwitch(key);
}
}
},
{
type:'label',
props:{
text:key,
align:$align.center
},
layout:function(make){
make.top.equalTo(15);
make.left.equalTo(90)
}
}
]
}
})
}])
}
}]
})
Loading…
Cancel
Save