Skip to content

Instantly share code, notes, and snippets.

@ty4z2008
Last active May 21, 2023 03:59
Show Gist options
  • Save ty4z2008/e752ec5ed4796e7687edc9b5953e2832 to your computer and use it in GitHub Desktop.
Save ty4z2008/e752ec5ed4796e7687edc9b5953e2832 to your computer and use it in GitHub Desktop.
获取ss订阅地址为surge 配置
/**
* Usage :
*
* node > 12.13
*
* npm install pinyin request
*
* export SSR_URL=xxxxx
*
* node surge.js
*
*/
const fs = require("fs");
const pinyin = require("pinyin");
const request = require("request");
let tpl = `
[General]
loglevel = notify
bypass-system = true
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, localhost, *.local, ::ffff:0:0/96
proxy-settings-interface = Primary Interface (Auto)
external-controller-access = 1@0.0.0.0:6170
bypass-tun = 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12
ipv6 = true
use-default-policy-if-wifi-not-primary = true
allow-wifi-access = true
dns-server = 223.5.5.5, 114.114.114.114, 119.29.29.29, 8.8.8.8, system
enhanced-mode-by-rule = true
show-error-page-for-reject = true
test-timeout = 5
http-listen = 0.0.0.0
socks5-listen = 0.0.0.0
exclude-simple-hostnames = true
[Replica]
hide-apple-request=true
hide-crashlytics-request=true
use-keyword-filter=false
[Proxy]
{{PROXY_LIST}}
[Proxy Group]
{{PROXY_NAME_LIST}}
`;
const subscribeUrl = process.env.SSR_URL || '';
const base64decode = cipher => {
if (cipher) {
try {
let buff = Buffer.from(cipher, "base64");
return buff.toString("utf8");
} catch (e) {
return cipher;
}
} else {
return cipher;
}
};
const start = async () => {
let plain = await getSubscribe().catch(err => {
console.trace(err)
console.log('请求订阅地址失败,请检查地址是否有效.')
process.exit()
});
let buff = Buffer.from(plain, "base64");
let txtTemp = buff.toString("utf8");
let ssrList = txtTemp.split("\n");
console.log(`共找到${ssrList.length}个订阅`);
let plainList = ssrList
.map(conf => {
// decode
let base64 = conf.replace("ssr://", "");
return base64decode(base64);
})
.map(conf => {
// convert
let arr = conf.split("?");
let [
server,
server_port,
protocol,
method,
obfs,
password
] = arr[0].split(":");
let {
obfsparam = "",
protoparam = "",
remarks = "",
group = ""
} = Object.fromEntries(new URLSearchParams(arr[1]));
[password, obfsparam, protoparam, remarks, group] = [
password,
obfsparam,
protoparam,
remarks,
group
].map(base64decode);
return {
server,
server_port,
protocol,
method,
obfs,
password,
obfsparam,
protoparam,
remarks,
group
};
});
let proxies = [];
let proxyList = plainList
.filter(({
obfs,
protocol
}) => obfs === "plain" && protocol === "origin")
.map(({
server,
password,
method,
server_port,
remarks
}) => {
remarks = [].concat(...pinyin(remarks, {
style: pinyin.STYLE_INITIALS, // 设置拼音风格
heteronym: true
})).join('').replace(/\[|\s|\]|\/|,/g, '');
proxies.push(remarks);
return `${remarks} = ss,${server}, ${server_port}, encrypt-method=${method}, password=${password.replace(/[^\w]/g,'')},udp-relay=true, tfo=true`;
});
let output = tpl
.replace("{{PROXY_LIST}}", proxyList.join("\n"))
.replace("{{PROXY_NAME_LIST}}", proxies.join(','));
fs.writeFileSync("./surge.conf", output, "utf8");
console.log(`已将${proxies.length}个订阅转换为Surge可用配置`)
console.log("转换完成,请查看surge.conf文件是否ok。现在可以将文件复制到Surge配置目录,并重新载入配置");
};
const getSubscribe = async() => {
return new Promise((resolve, reject) => {
if (!subscribeUrl) {
console.log('please set SSR_URL env. example: export SSR_URL=your_url')
process.exit()
return
}
request({
url: subscribeUrl,
method: 'get'
}, function(err, response, body) {
if (err) return reject(err)
resolve(body)
})
});
}
start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment