Compare commits

..

20 Commits

Author SHA1 Message Date
Tindy X
5eb54b4a46 Fix build script 2020-01-08 00:40:07 +08:00
Tindy X
8af22aceb1 Bump version to v0.2.5 2020-01-08 00:23:32 +08:00
Tindy X
3f4d764e42 Update build script 2020-01-07 23:36:21 +08:00
Tindy X
e6a5e55a69 Update build scripts 2020-01-07 23:30:34 +08:00
Tindy X
f2e12f1e4b Fix build error 2020-01-07 15:57:15 +08:00
Tindy X
bebefd9511 Fix build error on some platform 2020-01-07 15:48:39 +08:00
Tindy X
b94dce44ed Fix support for parsing some Shadowsocks/R subscriptions 2020-01-07 15:39:06 +08:00
Tindy X
d1bf8a13f2 Enhancements
Fix dependency bug for compiling on some platforms.
Add specifying port via environment variable.
Add BacktoCN.list extracted from ConnersHua's original BakctoCN configuration.
2020-01-07 11:39:18 +08:00
Tindy X
6a61f29cf2 Update local rulesets 2020-01-07 10:17:26 +08:00
MelosBot
48568a950f Update README-cn.md (#33)
Makes creating token faster and fixes a few things
2020-01-05 21:35:11 +08:00
Tindy X
46a58f4394 Bump version to v0.2.4 2020-01-05 20:37:58 +08:00
Tindy X
2f44a216b5 Add ARM64 build to Travis CI script 2020-01-05 18:58:37 +08:00
Tindy X
15fab8f324 Add filter_deprecated_nodes flag to filter out nodes that are no longer supported by latest clients 2020-01-05 18:54:00 +08:00
Tindy X
5870ab2386 Enhancements
Add skip-cert-verify flag for HTTPS / Socks 5 nodes in Clash / Surge subscriptions.
Tweaked keys order in Clash subscriptions.
Optimize codes.
2020-01-04 17:29:44 +08:00
Tindy X
215c467f2a Enhancements
Add auto filtering for nodes that are not supported by Clash/R core.
Add skip_cert_verify for Surge, Quantumult and Quantumult X subscription.
Add "separate links" option for exporting SIP002 subscriptions.
Optimize codes.
2020-01-04 15:22:12 +08:00
Tindy X
a775c69121 Enhancements
Fix crash when parsing HTTP nodes in Surge subscriptions.
Fix section order problem for various subscriptions.
Add more custom settings in external configuration file.
Add no-resolve to LAN rules.
Update README-cn.md.
2020-01-03 14:29:40 +08:00
Tindy X
9094270b65 Bug fixes
Fix incorrect parameters for simple interface.
Fix group generation support for Surge.
Change default skip_cert_verify flag to false.
Optimize codes.
2020-01-03 00:15:34 +08:00
MelosBot
24f5dc40d0 Update README-cn.md (#30)
Update README-cn.md

Modify the description and add updated parameters.
2020-01-03 00:13:38 +08:00
Tindy X
3077a7ca40 Revert Travis CI script 2020-01-01 22:39:16 +08:00
Tindy X
144725213f Add support for adding skip-cert-verify flag to Clash/R subscription 2020-01-01 22:38:21 +08:00
29 changed files with 862 additions and 388 deletions

View File

@@ -7,31 +7,58 @@ stages:
if: branch = master
matrix:
include:
- os: osx
- name: "macOS Build"
os: osx
compiler: clang
osx_image: xcode10.3
script:
- bash scripts/build.macos.release.sh
- 'export VERSION=`cat src/version.h | grep " VERSION " | sed "s/.*\"v\(.*\)\"/\1/g"`'
- mv subconverter_darwin64.tar.gz subconverter_$VERSION_darwin64.tar.gz
deploy:
provider: releases
api_key: "$GITHUB_OAUTH_TOKEN"
file: "subconverter_$VERSION_darwin64.tar.gz"
file: "subconverter_darwin64.tar.gz"
skip_cleanup: true
draft: true
on:
tags: true
- services: docker
- name: "Linux x86_64 Build"
services: docker
script:
- docker pull alpine:latest
- docker run -v $TRAVIS_BUILD_DIR:/root/workdir alpine:latest /bin/sh -c "apk add bash git && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
- 'export VERSION=`cat src/version.h | grep " VERSION " | sed "s/.*\"v\(.*\)\"/\1/g"`'
- mv subconverter_linux64.tar.gz subconverter_$VERSION_linux64.tar.gz
deploy:
provider: releases
api_key: "$GITHUB_OAUTH_TOKEN"
file: "subconverter_$VERSION_linux64.tar.gz"
file: "subconverter_linux64.tar.gz"
skip_cleanup: true
draft: true
on:
tags: true
- name: "Linux ARMHF Build"
services: docker
script:
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
- docker run --rm -v $TRAVIS_BUILD_DIR:/root/workdir multiarch/alpine:armhf-edge /bin/sh -c "apk add bash git && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
before_deploy:
- mv subconverter_linux64.tar.gz subconverter_armhf.tar.gz
deploy:
provider: releases
api_key: "$GITHUB_OAUTH_TOKEN"
file: "subconverter_armhf.tar.gz"
skip_cleanup: true
draft: true
on:
tags: true
- name: "Linux ARM64 Build"
services: docker
arch: arm64
script:
- docker run -v $TRAVIS_BUILD_DIR:/root/workdir alpine:latest /bin/sh -c "apk add bash git && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
before_deploy:
- mv subconverter_linux64.tar.gz subconverter_aarch64.tar.gz
deploy:
provider: releases
api_key: "$GITHUB_OAUTH_TOKEN"
file: "subconverter_aarch64.tar.gz"
skip_cleanup: true
draft: true
on:

View File

@@ -10,9 +10,21 @@ ADD_DEFINITIONS(-Wall -Wextra -Wno-unused-parameter -Wno-unused-result)
OPTION(USING_STD_REGEX "Use std::regex from C++ library instead of PCRECPP." OFF)
OPTION(USING_MALLOC_TRIM "Call malloc_trim after processing request to lower memory usage (Your system must support malloc_trim)." OFF)
IF(MACOS)
INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES(
"
#include<string>
int main(){std::to_string(0);return 0;}
" HAVE_TO_STRING)
IF(APPLE)
ADD_DEFINITIONS(-D_MACOS)
ENDIF()
IF(HAVE_TO_STRING)
ADD_DEFINITIONS(-DHAVE_TO_STRING)
ENDIF()
IF(USING_MALLOC_TRIM)
ADD_DEFINITIONS(-DMALLOC_TRIM)
ENDIF()

View File

@@ -4,286 +4,435 @@
[![Build Status](https://travis-ci.com/tindy2013/subconverter.svg?branch=master)](https://travis-ci.com/tindy2013/subconverter)
- [subconverter](#subconverter)
- [支持类型](#支持类型)
- [用法](#用法)
- [旧接口](#旧接口)
- [**推荐阅读**](#推荐阅读)
- [pref.ini](#prefini)
- [common](#common)
- [api_mode](#api_mode)
- [default_url](#default_url)
- [exclude_remarks](#exclude_remarks)
- [include_remarks](#include_remarks)
- [clash_rule_base](#clash_rule_base)
- [surge_rule_base](#surge_rule_base)
- [surfboard_rule_base](#surfboard_rule_base)
- [rename_node](#rename_node)
- [managed_config](#managed_config)
- [emojis](#emojis)
- [ruleset](#ruleset)
- [clash_proxy_group](#clash_proxy_group)
- [server](#server)
- [listen](#listen)
- [port](#port)
- [advanced](#advanced)
- [gist](#gist)
- [支持类型](#支持类型)
- [简易用法](#简易用法)
- [调用地址](#调用地址)
- [调用说明](#调用说明)
- [进阶用法](#进阶用法)
- [阅前提示](#阅前提示)
- [进阶地址](#进阶地址)
- [配置文件](#配置文件)
- [自动上传](#自动上传)
## 支持类型
| 类型 | 作为源类型 | 作为目标类型 | 参数 |
| ------------ | :--------: | :----------: | ----------- |
| clash | ✔ | ✔ | clash |
| clashr | ✔ | ✔ | clashr |
| surge2 | ✔ | ✔ | surge?ver=2 |
| surge3 | ✔ | ✔ | surge?ver=3 |
| surge4 | ✔ | ✔ | surge?ver=4 |
| quantumult | ✔ | ✔ | quan |
| quantumult X | ✔ | ✔ | quanx |
| surfboard | ✔ | ✔ | surfboard |
| ss | ✔ | ✔ | ss |
| ssr | ✔ | ✔ | ssr |
| ssd | ✔ | ✔ | ssd |
| v2ray | ✔ | ✔ | v2ray |
| Clash | ✔ | ✔ | clash |
| ClashR | ✔ | ✔ | clashr |
| Quantumult | ✔ | ✔ | quan |
| Quantumult X | ✔ | ✔ | quanx |
| SS (SIP002) | ✔ | ✔ | ss |
| SSD | ✔ | ✔ | ssd |
| SSR | ✔ | ✔ | ssr |
| Surfboard | ✔ | ✔ | surfboard |
| Surge 2 | ✔ | ✔ | surge&ver=2 |
| Surge 3 | ✔ | ✔ | surge&ver=3 |
| Surge 4 | ✔ | ✔ | surge&ver=4 |
| V2Ray | ✔ | ✔ | v2ray |
**注意**Shadowrocket 用户可以使用 `ss``ssr`以及 `v2ray`参数
---
## 用法
## 简易用法
```
http://127.0.0.1:25500/sub?target=clash&url=%URL_ENCODED_LINKS%
> 即生成的配置文件默认套用 **神机规则**
http://127.0.0.1:25500/sub?target=surge&ver=4&url=%URL_ENCODED_LINKS%
### 调用地址
http://127.0.0.1:25500/sub?target=v2ray&url=%URL_ENCODED_LINKS%
```TXT
http://127.0.0.1:25500/sub?target=%TARGET%&url=%URL%&config=%CONFIG%
```
#### 旧接口
### 调用说明
```
http://127.0.0.1:25500/clash?url=%URL_ENCODED_LINKS%
| 调用参数 | 必要性 | 示例 | 解释 |
| ------- | :----: | :------------------- | ---------------- |
| target | 必要 | surge&ver=4 | 指想要生成的配置类型,详见上方 [支持类型](#支持类型) 中的参数 |
| url | 必要 | https%3A%2F%2Fwww.xxx.com | 指机场所提供的订阅链接,需要经过 [URLEncode](https://www.urlencoder.org/) 处理 |
| config | 可选 | https%3A%2F%2Fwww.xxx.com | 指远程 `pref.ini` (包含分组和规则部分),需要经过 [URLEncode](https://www.urlencoder.org/) 处理,可查看 [示例仓库](https://github.com/lzdnico/subconverteriniexample) 寻找灵感,默认加载本地设置文件 |
运行 subconverter 主程序后,按照 [调用说明](###调用说明) 的对应内容替换即可得到一份使用**神机规则**的配置文件。
此外,如果你需要将多个订阅合成一份, 则要在上方所提及的 URLEncode 之前使用 '|' 来分隔链接。
举个例子:
```TXT
有以下两个订阅,且想合并转换成 Clash 的订阅:
1. https://dler.cloud/subscribe/ABCDE?clash=vmess
2. https://rich.cloud/subscribe/ABCDE?clash=vmess
首先使用 '|' 将两个订阅分隔开:
https://dler.cloud/subscribe/ABCDE?clash=vmess|https://rich.cloud/subscribe/ABCDE?clash=vmess
接着通过 URLEncode 后可以得到:
https%3A%2F%2Fdler.cloud%2Fsubscribe%2FABCDE%3Fclash%3Dvmess%7Chttps%3A%2F%2Frich.cloud%2Fsubscribe%2FABCDE%3Fclash%3Dvmess
然后将想要的 %TARGET% (即 clash) 和上一步所得到的 %URL% 填入调用地址中:
http://127.0.0.1:25500/sub?target=clash&url=https%3A%2F%2Fdler.cloud%2Fsubscribe%2FABCDE%3Fclash%3Dvmess%7Chttps%3A%2F%2Frich.cloud%2Fsubscribe%2FABCDE%3Fclash%3Dvmess
最后将该链接填写至 Clash 的订阅处就大功告成了。
```
如果你有多个订阅, 在url encode之前使用 '|' 来分隔链接. <br>
---
e.g. <br>
> 我有以下两个订阅: <br>
`https://dler.cloud/subscribe/ABCDE?clash=vmess`
`https://rich.cloud/subscribe/ABCDE?clash=vmess`
<br> <br>
使用'|'分隔: <br>
`https://dler.cloud/subscribe/ABCDE?clash=vmess|https://rich.cloud/subscribe/ABCDE?clash=vmess`
<br> <br>
url encode后: <br>
`https%3A//dler.cloud/subscribe/ABCDE%3Fclash%3Dvmess%7Chttps%3A//rich.cloud/subscribe/ABCDE%3Fclash%3Dvmess`
<br> <br>
添加到链接后面: <br>
`http://127.0.0.1:25500/sub?target=clash&url=https%3A//dler.cloud/subscribe/ABCDE%3Fclash%3Dvmess%7Chttps%3A//rich.cloud/subscribe/ABCDE%3Fclash%3Dvmess`
<br> <br>
&nbsp;&nbsp;&#127830; 食用 &#127830;
<br> <br>
## 进阶用法
> 在不满足于本程序所提供的神机规则或者对应的分组时,可以考虑尝试进阶用法
>
> 即 对 `调用地址` 甚至程序目录下的 `pref.ini` 进行个性化的编辑以满足不同的需求
- 想学更多姿势? 来瞅瞅[pref.ini](./pref.ini).
### 阅前提示
在进行下一步操作前,十分推荐您阅读以下内容:
1.`pref.ini` 相关的:[INI 语法介绍](https://zh.wikipedia.org/wiki/INI%E6%96%87%E4%BB%B6)
1.`Clash` 配置相关的: [YAML 语法介绍](https://zh.wikipedia.org/wiki/YAML#%E8%AA%9E%E6%B3%95)
1. 会经常涉及到的: [正则表达式入门](https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md)
1. 当遇到问题需要提交 ISSUE 时的: [提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)
## **推荐阅读**
当您尝试进行进阶操作时,即默认您有相关的操作能力,本程序仅保证在默认配置文件下能够正常运行。
> - [&#128220; 正则表达式 &#128220;](https://zh.wikipedia.org/zh-hans/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F)
> - [&#128221; yaml语法介绍 &#128221;](https://zh.wikipedia.org/wiki/YAML#%E8%AA%9E%E6%B3%95)
> - [&#10068; 提问的智慧 &#10068;](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)
### 进阶地址
#### 调用地址 (进阶)
## pref.ini
### common
#### api_mode
> API模式设置为true以防止直接加载本地订阅或直接提供本地文件.
当值为`false`时, 每次更新配置都会读取`pref.ini`, 为`true`时则仅启动时读取.
#### default_url
> 无url参数时默认链接,不需要encode. 如果有多个链接, 使用 "|" 分隔, 支持`文件`/`url`.
e.g.
```ini
default_url=https://dler.cloud/subscribe/ABCDE?clash=vmess
```txt
http://127.0.0.1:25500/sub?target=%TARGET%&url=%URL%&emoji=%EMOJI%····
```
此时订阅
`http://127.0.0.1:25500/clash`
#### 调用说明 (进阶)
相当于:
<br>
`http://127.0.0.1:25500/sub?target=clash&url=https%3A//dler.cloud/subscribe/ABCDE%3Fclash%3Dvmess`
| 调用参数 | 必要性 | 示例 | 解释 |
| -------- | :----: | :--------------- | :------------------------ |
| target | 必要 | surge&ver=4 | 指想要生成的配置类型,详见上方 [支持类型](#支持类型) 中的参数 |
| url | 可选 | https%3A%2F%2Fwww.xxx.com | 指机场所提供的订阅链接,需要经过 [URLEncode](https://www.urlencoder.org/) 处理,**可选的前提是在 `default_url` 中进行指定** |
| config | 可选 | https%3A%2F%2Fwww.xxx.com | 指远程 `pref.ini` (包含分组和规则部分),需要经过 [URLEncode](https://www.urlencoder.org/) 处理,可查看 [示例仓库](https://github.com/lzdnico/subconverteriniexample) 寻找灵感,默认加载本地设置文件 |
| upload | 可选 | true / false | 指将生成的订阅文件上传至 `Gist`,需要填写`gistconf.ini`,默认为 false (即不上传) |
| emoji | 可选 | true / false | 指在节点名称前加入 Emoji默认为 true |
| group | 可选 | MySS | 指设置该订阅的组名,多用于 SSD/SSR |
| tfo | 可选 | true / false | 指开启该订阅链接的 TCP Fast Open默认为 false |
| udp | 可选 | true / false | 指开启该订阅链接的 UDP默认为 false |
| scv | 可选 | true / false | 指关闭 TLS 节点的证书检查,默认为 false |
| list | 可选 | true / false | 指输出 Surge nodelist 或者 Clash proxy provider |
| sort | 可选 | true / false | 指对输出的节点或策略组进行再次排序,默认为 false |
| include | 可选 | 详见下文中 `include_remarks` | 指仅保留匹配到的节点,支持正则匹配,需要经过 [URLEncode](https://www.urlencoder.org/) 处理,会覆盖配置文件里的设置 |
| exclude | 可选 | 详见下文中 `exclude_remarks` | 指排除匹配到的节点,支持正则匹配,需要经过 [URLEncode](https://www.urlencoder.org/) 处理,会覆盖配置文件里的设置 |
举个例子:
```TXT
有订阅 `https://dler.cloud/subscribe/ABCDE?clash=vmess`,想转换成 Surge 4 的订阅,且需要开启 TFO 和 UDP
顺便再给节点名加上 EMOJI 同时排除掉订阅中显示流量和官网的节点(节点名为"剩余流量1024G""官网地址dler.cloud"
#### exclude_remarks
首先确认需要用到的参数:
target=surge&ver=4 、 tfo=true 、 udp=true 、 emoji=true 、exclude=(流量|官网)
url=https://dler.cloud/subscribe/ABCDE?clash=vmess
> 排除匹配到的节点, 支持正则.
然后将需要 URLEncode 的部分进行处理:
exclude=%28%E6%B5%81%E9%87%8F%7C%E5%AE%98%E7%BD%91%29
url=https%3A%2F%2Fdler.cloud%2Fsubscribe%2FABCDE%3Fclash%3Dvmess
e.g.
```ini
exclude_remarks=(流量|时间|官网|产品)
接着将所有元素进行拼接:
http://127.0.0.1:25500/sub?target=surge&ver=4&tfo=true&udp=true&emoji=true&exclude=%28%E6%B5%81%E9%87%8F%7C%E5%AE%98%E7%BD%91%29&url=https%3A%2F%2Fdler.cloud%2Fsubscribe%2FABCDE%3Fclash%3Dvmess
最后将该链接填写至 Surge 的订阅处就大功告成了。
```
### 配置文件
> 关于 subconverter.exe 目录中 `pref.ini` 文件的解释
#### include_remarks
#### [common] 部分
> 仅保留匹配到的节点, 支持正则.
> 该部分主要涉及到的内容为 **全局的节点排除或保留** 、**节点的重命名**
>
> 其他设置项目可以保持默认或者在知晓作用的前提下进行修改
e.g.
```ini
include_remarks=(?<=美).*(BGP|GIA|IPLC)
```
1. **api_mode**
> API 模式,设置为 true 以防止直接加载本地订阅或直接提供本地文件。(多用于架设于服务器上)
- 当值为 `false` 时, 每次更新配置都会读取 `pref.ini` , 为 `true` 时则仅启动时读取。
#### clash_rule_base
1. **default_url**
> 生成的clash配置文件基础. 支持`文件`/`url`.
> 无 %URL% 参数时,默认加载的订阅链接, **不需要 URLEncode**。 如果有多个链接,仍然需要使用 "|" 分隔,支持`文件`/`url`
e.g.
```ini
clash_rule_base=clash.yaml
- 例如:
clash_rule_base=https://raw.githubusercontent.com/ConnersHua/Profiles/master/Clash/Pro.yaml
```
```ini
default_url='https://dler.cloud/subscribe/ABCDE?clash=vmess'
```
- 解释:
```TXT
此时订阅链接:
http://127.0.0.1:25500/sub?target=clash
等同于:
http://127.0.0.1:25500/sub?target=clash&url=https%3A%2F%2Fdler.cloud%2Fsubscribe%2FABCDE%3Fclash%3Dvmess
```
#### surge_rule_base
1. **exclude_remarks**
> 生成的surge配置文件基础. 用法同上.
> 排除匹配到的节点,支持正则匹配
- 例如:
```ini
exclude_remarks=(流量|时间|官网|产品)
```
#### surfboard_rule_base
1. **include_remarks**
> 生成的surfboard配置文件基础. 用法同上.
> 仅保留匹配到的节点,支持正则匹配
- 例如:
```ini
include_remarks=(?<=美).*(BGP|GIA|IPLC)
```
#### mellow_rule_base
1. **clash_rule_base**
> 生成的mellow配置文件基础. 用法同上.
> 生成的 Clash 配置文件基础。支持 `本地文件` 和 `在线URL`
- 例如:
```ini
clash_rule_base=clash.yaml # 加载本地的 clash.yaml 文件作为基础
# 或者
clash_rule_base=https://raw.githubusercontent.com/ConnersHua/Profiles/master/Clash/Pro.yaml
# 加载神机的 Github 中相关文件作为基础
```
#### rename_node
1. **surge_rule_base**
> 重命名节点, 支持正则.
> 生成的 Surge 配置文件基础,用法同上
e.g.
```ini
rename_node=中国@中
rename_node=深圳@深
```
1. **surfboard_rule_base**
> 生成的 Surfboard 配置文件基础,用法同上
1. **mellow_rule_base**
### managed_config
> 生成的 Mellow 配置文件基础,用法同上
> 将'MANAGED-CONFIG'信息附加到Surge配置.
1. **proxy_ruleset**
> 更新 RuleSet 时是否使用代理
>
> 填写 `NONE` 或者空白禁用,或者填写 `SYSTEM` 使用系统代理
>
> 也可填写如同 `socks5://127.0.0.1:1080` 的 HTTP 或 SOCKS 代理
- 例如:
### emojis
```ini
proxy_ruleset=SYSTEM # 使用系统代理
# 或者
proxy_ruleset=socks5://127.0.0.1:1080 # 使用本地的 1080 端口进行 SOCKS5 代理
```
> 在匹配到的节点前添加自定义emojis, 支持正则.
1. **proxy_subscription**
e.g.
```ini
rule=(流量|时间|应急),⌛time
rule=(美|美国|United States),🇺🇸
```
> 更新 原始订阅 时是否使用代理,用法同上
1. **append_proxy_type**
> 节点名称是否需要加入属性,设置为 true 时在节点名称前加入 \[SS\] \[SSR\] \[VMess\] 以作区别,
>
> 默认为 false
### ruleset
> 如果你对原本订阅自带的规则不满意可以使用如下配置
- 例如(设置为 true时
> 启用自定义规则集
`enabled=true`
> 覆盖原有规则
`overwrite_original_rules=true`
> 当其他程序更新订阅时更新规则集
`update_ruleset_on_request=false`
```txt
[SS] 香港中转
[VMess] 美国 GIA
```
> 从本地或url获取规则片段.
> []前缀后的文字将被当作规则而不是链接或路径
1. **rename_node**
e.g.
<img src="./doc/imgs/Snipaste_2019-11-18_14-11-52.png">
> 重命名节点,支持正则匹配
>
> 使用方式:原始命名@重命名
- 例如:
```ini
rename_node=中国@中
rename_node=\(?((x|X)?(\d+)(\.?\d+)?)((\s?倍率?:?)|(x|X))\)?@(倍率:$1)
```
#### [node_pref] 部分
> 该部分主要涉及到的内容为 **开启节点的UDP及TCP** 、**重命名节点后的排序**
>
> 相关设置项目建议保持默认或者在知晓作用的前提下进行修改
1. **udp_flag**
> 为节点打开 UDP 模式,设置为 true 时打开,默认为 false
- 当不清楚机场的设置时**请勿调整此项**。
1. **tcp_fast_open_flag**
> 为节点打开 TFO (TCP Fast Open) 模式,设置为 true 时打开,默认为 false
- 当不清楚机场的设置时**请勿调整此项**。
1. **sort_flag**
> 对生成的订阅中的节点进行 A-Z 的排序,设置为 true 时打开,默认为 false
1. **skip_cert_verify_flag**
> 关闭 TLS 节点的证书检查。设置为 true 时打开,默认为 false
- **请勿随意将此设置修改为 true**
#### [managed_config] 部分
> 该部分主要涉及到的内容为 **订阅文件的更新地址**
1. **write_managed_config**
> 是否将'!MANAGED-CONFIG'信息附加到 Surge 或 Surfboard 配置,设置为 true 时打开,默认为 true
1. **managed_config_prefix**
> 具体的 '#!MANAGED-CONFIG' 信息,地址前缀不用添加 "/"。Surge 或 Surfboard 会向此地址发出更新请求
>
> 局域网用户需要将此处改为本程序运行设备的局域网 ip
- 例如:
```ini
managed_config_prefix = http://192.168.1.5:25500
```
#### [surge_external_proxy] 部分
> 为 Surge 添加 SSR 的支持路径
#### [emojis] 部分
1. add_emoji
> 是否在节点名称前加入下面自定义的 Emoji设置为 true 时打开,默认为 true
1. remove_old_emoji
> 是否移除原有订阅中存在的 Emoji设置为 true 时打开,默认为 true
1. rule
> 在匹配到的节点前添加自定义 emojis支持正则匹配
- 例如:
```ini
rule=(流量|时间|应急),⌛time
rule=(美|美国|United States),🇺🇸
```
#### [ruleset] 部分
> 如果你对原本订阅自带的规则不满意时,可以使用如下配置
1. **enabled**
> 启用自定义规则集的**总开关**,设置为 true 时打开,默认为 true
1. **overwrite_original_rules**
> 覆盖原有规则,即 [common] 中 xxx_rule_base 中的内容,设置为 true 时打开,默认为 false
1. **update_ruleset_on_request**
> 根据请求执行规则集更新,设置为 true 时打开,默认为 false
1. **surge_ruleset**
> 从本地或 url 获取规则片段
>
> [] 前缀后的文字将被当作规则,而不是链接或路径,主要包含 `[]GEOIP` 和 `[]MATCH`(等同于 `[]FINAL`)。
- 例如:
```ini
surge_ruleset=🍎 苹果服务,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Apple.list
# 表示引用 https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Apple.list 规则
# 且将此规则指向 [clash_proxy_group] 所设置 🍎 苹果服务 策略组
surge_ruleset=🎯 全球直连,rules/NobyDa/Surge/Download.list
# 表示引用本地 rules/NobyDa/Surge/Download.list 规则
# 且将此规则指向 [clash_proxy_group] 所设置 🎯 全球直连 策略组
surge_ruleset=🎯 全球直连,[]GEOIP,CN
# 表示引用 GEOIP 中关于中国的所有 IP
# 且将此规则指向 [clash_proxy_group] 所设置 🎯 全球直连 策略组
```
#### [clash_proxy_group] 部分
> 为 Clash 、Mellow 、Surge 以及 Surfboard 等程序创建策略组, 可用正则来筛选节点
>
> [] 前缀后的文字将被当作引用策略组
```ini
surge_ruleset=🍎 苹果服务,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Apple.list
surge_ruleset=🎯 全球直连,rules/NobyDa/Surge/Download.list
surge_ruleset=🎯 全球直连,[]GEOIP,CN
custom_proxy_group=🍎 苹果服务`url-test`(美国|US)`http://www.gstatic.com/generate_204`300
# 表示创建一个叫 🍎 苹果服务 的 url-test 策略组,并向其中添加名字含'美国','US'的节点每隔300秒测试一次
custom_proxy_group=🇯🇵 日本延迟最低`url-test`(日|JP)`http://www.gstatic.com/generate_204`300
# 表示创建一个叫 🇯🇵 日本延迟最低 的 url-test 策略组,并向其中添加名字含'日','JP'的节点每隔300秒测试一次
custom_proxy_group=🇯🇵 JP`select`沪日`日本`[]🇯🇵 日本延迟最低
# 表示创建一个叫 🇯🇵 JP 的 select 策略组,并向其中**依次**添加名字含'沪日','日本'的节点,以及引用上述所创建的 🇯🇵 日本延迟最低 策略组
```
效果图:
- ssr/v2 订阅默认没有组名, 可以使用这个方法来添加组名
<img src="./doc/imgs/ruleset.png">
```ini
custom_proxy_group=g1`select`!!GROUPID=0
# 指订阅链接中的第一条订阅
custom_proxy_group=g2`select`!!GROUPID=1
# 指订阅链接中的第二条订阅
custom_proxy_group=v2ray`select`!!GROUP=V2RayProvider
```
- 现在也可以使用双条件进行筛选
```ini
custom_proxy_group=g1hk`select`!!GROUPID=0!!(HGC|HKBN|PCCW|HKT|hk|港)
# 订阅链接中的第一条订阅内名字含 HGC、HKBN、PCCW、HKT、hk、港 的节点
```
### clash_proxy_group
#### [server] 部分
> clash的策略组, 可用正则来筛选节点.
> 此部分通常**保持默认**即可
e.g.
```ini
custom_proxy_group=🇺🇸US`url-test`(美|美国|United States)`http://www.gstatic.com/generate_204`300
```
表示创建一个叫 usUS的url-test策略组,并向其中添加名字包含'美','美国','United States'的节点~每隔300秒测试一次~(目前硬编码固定为300)
1. **listen**
> 绑定到 Web 服务器的地址,将地址设为 0.0.0.0,则局域网内设备均可使用。
效果图:
1. **port**
<img src="./doc/imgs/Snipaste_2019-11-18_14-47-30.png">
> 绑定到 Web 服务器地址的端口,默认为 25500
#### [advanced] 部分
ssr/v2订阅默认没有组名, 可以使用这个方法来添加组名.
> 此部分通常**保持默认**即可
## 自动上传
> 自动上传 gist ,可以用于 Clash For Android / Surge 等进行远程订阅
在程序目录内的 [gistconf.ini](./base/gistconf.ini) 中添加 `Personal Access Token`[在此创建](https://github.com/settings/tokens/new?scopes=gist&description=Subconverter)),在链接后加上 `&upload=true` 就会在更新好后自动上传 gist。
例如:
```ini
custom_proxy_group=g1`select`!!GROUPID=0
custom_proxy_group=g2`select`!!GROUPID=1
custom_proxy_group=v2ray`select`!!GROUP=V2RayProvider
[common]
;uncomment the following line and enter your token to enable upload function
token = xxxxxxxxxxxxxxxxxxxxxxxx(所生成的 Personal Access Token)
```
### server
#### listen
> 绑定到Web服务器的地址, 将地址设为0.0.0.0, 则局域网内设备均可使用.
`listen=0.0.0.0`
#### port
> 绑定到Web服务器地址的端口.
`port=25500`
### advanced
> 无需描述.
## gist
> 自动上传gist.
在[gistconf.ini](./gistconf.ini)中添加personal access token, 在链接后加上`upload=true`就会在更新好后自动上传gist.

View File

@@ -0,0 +1,35 @@
[custom]
custom_proxy_group=Proxy`select`.*`[]AUTO`[]DIRECT`.*
custom_proxy_group=AUTO`url-test`.*`http://www.gstatic.com/generate_204`300
custom_proxy_group=google`select`.*
custom_proxy_group=netflix`select`.*
custom_proxy_group=动画疯`select`(深台|彰化|新北|台)
custom_proxy_group=fox+`select`(HGC|HKBN|PCCW|HKT|深台|彰化|新北|台|新加坡|sg|hk|tw)
custom_proxy_group=美区影视`select`(美|美国)
custom_proxy_group=Global_media`select`.*
custom_proxy_group=Domestic`select`[]DIRECT`[]Proxy
custom_proxy_group=Apple`select`[]DIRECT`[]Proxy
custom_proxy_group=Final`select`[]Proxy`[]DIRECT
custom_proxy_group=屏蔽广告`select`[]REJECT`[]DIRECT
custom_proxy_group=UnblockNeteaseMusic`select`云音乐解锁`[]DIRECT
custom_proxy_group=Telegram`select`新加坡`[]Proxy
enable_rule_generator=false
;surge_ruleset=DIRECT,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Unbreak.list
;surge_ruleset=⛔️ 广告拦截,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Advertising.list
;surge_ruleset=🚫 运营劫持,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Hijacking.list
;surge_ruleset=🌌 YouTube,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Media/YouTube.list
;surge_ruleset=🎥 NETFLIX,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Media/Netflix.list
;surge_ruleset=HBO,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Media/HBO.list
;surge_ruleset=Fox,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Media/Fox.list
;surge_ruleset=🌍 国外媒体,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/GlobalMedia.list
;surge_ruleset=🌏 港台媒体,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/HKMTMedia.list
;surge_ruleset=📲 电报信息,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Telegram.list
;surge_ruleset=🔰 节点选择,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Global.list
;surge_ruleset=🍎 苹果服务,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/Apple.list
;surge_ruleset=DIRECT,https://raw.githubusercontent.com/ConnersHua/Profiles/master/Surge/Ruleset/China.list
clash_rule_base=forcerule.yml
;surge_rule_base=surge.conf
;surfboard_rule_base=surfboard.conf
;mellow_rule_base=mellow.conf

View File

@@ -93,6 +93,8 @@ rename_node=\(?((x|X)?(\d+)(\.?\d+)?)((\s?倍率?)|(x|X))\)?@$1x
udp_flag=false
tcp_fast_open_flag=false
sort_flag=false
skip_cert_verify_flag=false
filter_deprecated_nodes=false
[managed_config]
;Append a '#!MANAGED-CONFIG' info to Surge configurations

View File

@@ -0,0 +1,75 @@
# (Video)
# AcFun
USER-AGENT,AcFun*
DOMAIN-SUFFIX,acfun.cn
DOMAIN-SUFFIX,acfun.com
DOMAIN-SUFFIX,aixifan.com
# > bilibili
USER-AGENT,bili-universal
USER-AGENT,Bilibili*
DOMAIN-SUFFIX,acgvideo.com
DOMAIN-SUFFIX,bilibili.com
DOMAIN-SUFFIX,hdslb.com
# > HunanTV
USER-AGENT,MGTV*
DOMAIN-SUFFIX,hitv.com
DOMAIN-SUFFIX,hunantv.com
DOMAIN-SUFFIX,mgtv.com
# > Migu
USER-AGENT,MiguVideo*
USER-AGENT,%E5%92%AA%E5%92%95%E8%A7%86%E9%A2%91
DOMAIN-SUFFIX,cmvideo.cn
DOMAIN-SUFFIX,migu.cn
DOMAIN-SUFFIX,miguvideo.com
# > iQiyi
USER-AGENT,iQiYi*
USER-AGENT,PPStream*
USER-AGENT,QIYI*
USER-AGENT,QYPlayer*
DOMAIN-SUFFIX,iqiyi.com
DOMAIN-SUFFIX,iqiyipic.com
DOMAIN-SUFFIX,qy.net
DOMAIN-SUFFIX,71.am
# > Sohu
DOMAIN-SUFFIX,56.com
DOMAIN-SUFFIX,sohu.com
DOMAIN-SUFFIX,sohu.com.cn
DOMAIN-SUFFIX,itc.cn
DOMAIN-SUFFIX,v-56.com
# > Tencent
USER-AGENT,live4iphone*
USER-AGENT,qqlive4iphone*
USER-AGENT,TencentMidasConnect*
DOMAIN-SUFFIX,video.qq.com
# > Youku
USER-AGENT,Youku*
USER-AGENT,%E4%BC%98%E9%85%B7*
DOMAIN-SUFFIX,soku.com
DOMAIN-SUFFIX,youku.com
DOMAIN-SUFFIX,ykimg.com
# (Music)
# > Alibaba
USER-AGENT,walkman*
USER-AGENT,xiami*
DOMAIN-SUFFIX,xiami.com
DOMAIN-SUFFIX,xiami.net
# > Netease
USER-AGENT,NeteaseMusic*
USER-AGENT,%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90*
DOMAIN-SUFFIX,music.126.net
DOMAIN-SUFFIX,music.163.com
# > Tencent
USER-AGENT,MOO%E9%9F%B3%E4%B9%90*
USER-AGENT,QQ%E9%9F%B3%E4%B9%90
DOMAIN-SUFFIX,qqmusic.qq.com
DOMAIN-SUFFIX,y.qq.com
DOMAIN,aqqmusic.tc.qq.com
# Kugou and Kuwo
DOMAIN-SUFFIX,kugou.com
USER-AGENT,%E9%85%B7%E6%88%91%E9%9F%B3%E4%B9%90*
DOMAIN-SUFFIX,kuwo.cn
DOMAIN-SUFFIX,koowo.com
# > Baidu
USER-AGENT,baiduyinyue
DOMAIN-SUFFIX,qianqian.com

View File

@@ -1,10 +1,10 @@
DOMAIN-SUFFIX,local
IP-CIDR,192.168.0.0/16
IP-CIDR,10.0.0.0/8
IP-CIDR,172.16.0.0/12
IP-CIDR,127.0.0.0/8
IP-CIDR,100.64.0.0/10
IP-CIDR6,::1/128
IP-CIDR6,fc00::/7
IP-CIDR6,fe80::/10
IP-CIDR6,fd00::/8
IP-CIDR,192.168.0.0/16,no-resolve
IP-CIDR,10.0.0.0/8,no-resolve
IP-CIDR,172.16.0.0/12,no-resolve
IP-CIDR,127.0.0.0/8,no-resolve
IP-CIDR,100.64.0.0/10,no-resolve
IP-CIDR6,::1/128,no-resolve
IP-CIDR6,fc00::/7,no-resolve
IP-CIDR6,fe80::/10,no-resolve
IP-CIDR6,fd00::/8,no-resolve

File diff suppressed because one or more lines are too long

View File

@@ -1,12 +1,13 @@
PROCESS-NAME,trustd
USER-AGENT,*com.apple.mobileme.fmip1
USER-AGENT,*WeatherFoundation*
USER-AGENT,%E5%9C%B0%E5%9B%BE*
USER-AGENT,%E8%AE%BE%E7%BD%AE*
USER-AGENT,*com.apple.mobileme.fmip1
USER-AGENT,*WeatherFoundation*
USER-AGENT,AppleNews*
USER-AGENT,AppStore*
USER-AGENT,com.apple.appstored*
USER-AGENT,com.apple.geod*
USER-AGENT,com.apple.Maps
USER-AGENT,com.apple.news*
USER-AGENT,FindMyFriends*
USER-AGENT,FindMyiPhone*
USER-AGENT,FMDClient*
@@ -16,10 +17,12 @@ USER-AGENT,geod*
USER-AGENT,locationd*
USER-AGENT,Maps*
USER-AGENT,TestFlight*
DOMAIN,apple.comscoreresearch.com
DOMAIN-SUFFIX,apple.cn
DOMAIN-SUFFIX,apple.com
DOMAIN-SUFFIX,apple.news
DOMAIN-SUFFIX,icloud.com
DOMAIN-SUFFIX,icloud-content.com
DOMAIN-SUFFIX,itunes.com
DOMAIN-SUFFIX,me.com
DOMAIN-SUFFIX,mzstatic.com
DOMAIN,api.smoot.apple.cn
DOMAIN-SUFFIX,mzstatic.com

View File

@@ -1,6 +1,3 @@
# > Client
PROCESS-NAME,ss-local
# > UA
USER-AGENT,hide*
USER-AGENT,MicroMessenger*
@@ -129,7 +126,6 @@ DOMAIN-SUFFIX,fresh-ideas.cc
DOMAIN-SUFFIX,geetest.com
DOMAIN-SUFFIX,godic.net
DOMAIN-SUFFIX,goodread.com
DOMAIN-SUFFIX,google.cn
DOMAIN-SUFFIX,gtimg.com
DOMAIN-SUFFIX,haibian.com
DOMAIN-SUFFIX,hao123.com

View File

@@ -0,0 +1,6 @@
# > BBC iPlayer
USER-AGENT,BBCiPlayer*
DOMAIN-SUFFIX,bbc.co.uk
DOMAIN-SUFFIX,bbci.co.uk
DOMAIN-KEYWORD,bbcfmt
DOMAIN-KEYWORD,uk-live

View File

@@ -0,0 +1,3 @@
# > Hulu(フールー)
DOMAIN-SUFFIX,happyon.jp
DOMAIN-SUFFIX,hulu.jp

View File

@@ -0,0 +1,5 @@
# > NeteaseMusic
USER-AGENT,%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90
USER-AGENT,NeteaseMusic*
DOMAIN-SUFFIX,music.126.net
DOMAIN-SUFFIX,music.163.com

View File

@@ -0,0 +1,3 @@
# > Youtube_Music
USER-AGENT,*YouTubeMusic*
USER-AGENT,*com.google.ios.youtubemusic*

View File

@@ -1,4 +1,3 @@
# > Youtube_Music
USER-AGENT,*YouTubeMusic*
USER-AGENT,*com.google.ios.youtubemusic*
PROCESS-NAME,YT Music
USER-AGENT,*com.google.ios.youtubemusic*

View File

@@ -0,0 +1,4 @@
# > myTV_SUPER
USER-AGENT,mytv*
DOMAIN-SUFFIX,mytvsuper.com
DOMAIN-SUFFIX,tvb.com

View File

@@ -1,14 +1,3 @@
# > Client
PROCESS-NAME,Backup and Sync
PROCESS-NAME,Day One
PROCESS-NAME,Dropbox
PROCESS-NAME,LINE
PROCESS-NAME,node-webkit
PROCESS-NAME,Resilio Sync
PROCESS-NAME,Tweetbot
PROCESS-NAME,Twitter
PROCESS-NAME,Twitterrific
# > UA
USER-AGENT,%E7%BA%BD%E7%BA%A6%E6%97%B6%E6%8A%A5*
USER-AGENT,AwemeI18n*
@@ -455,7 +444,6 @@ DOMAIN-SUFFIX,sydneytoday.com
DOMAIN-SUFFIX,symauth.com
DOMAIN-SUFFIX,symcb.com
DOMAIN-SUFFIX,symcd.com
DOMAIN-SUFFIX,t.me
DOMAIN-SUFFIX,t66y.com
DOMAIN-SUFFIX,tablesgenerator.com
DOMAIN-SUFFIX,tabtter.jp
@@ -464,12 +452,10 @@ DOMAIN-SUFFIX,talkboxapp.com
DOMAIN-SUFFIX,talkonly.net
DOMAIN-SUFFIX,tapbots.com
DOMAIN-SUFFIX,tapbots.net
DOMAIN-SUFFIX,tdesktop.com
DOMAIN-SUFFIX,techcrunch.com
DOMAIN-SUFFIX,technorati.com
DOMAIN-SUFFIX,techsmith.com
DOMAIN-SUFFIX,teddysun.com
DOMAIN-SUFFIX,telegra.ph
DOMAIN-SUFFIX,textnow.me
DOMAIN-SUFFIX,thebobs.com
DOMAIN-SUFFIX,theinitium.com
@@ -639,7 +625,6 @@ DOMAIN-KEYWORD,facebook
DOMAIN-KEYWORD,github
DOMAIN-KEYWORD,instagram
DOMAIN-KEYWORD,porn
DOMAIN-KEYWORD,telegram
DOMAIN-KEYWORD,twitter
DOMAIN-KEYWORD,whatsapp
DOMAIN-KEYWORD,google
@@ -767,10 +752,3 @@ IP-CIDR,74.86.0.0/16,no-resolve
IP-CIDR,75.126.0.0/16,no-resolve
IP-CIDR,174.37.0.0/16,no-resolve
IP-CIDR,208.43.0.0/16,no-resolve
# > Telegram
IP-CIDR,91.108.4.0/22,no-resolve
IP-CIDR,91.108.8.0/22,no-resolve
IP-CIDR,91.108.56.0/22,no-resolve
IP-CIDR,149.154.160.0/20,no-resolve
IP-CIDR,149.154.164.0/22,no-resolve

View File

@@ -262,8 +262,6 @@ DOMAIN-SUFFIX,bfshan.cn
# REJECT
# > Client
PROCESS-NAME,Jietu
DOMAIN-KEYWORD,admaster
DOMAIN-KEYWORD,admdfs
DOMAIN-KEYWORD,adnewnc
@@ -4802,7 +4800,6 @@ DOMAIN-SUFFIX,liangao.com
DOMAIN-SUFFIX,liangziweixg.com
DOMAIN-SUFFIX,lib.haotv8.com
DOMAIN-SUFFIX,liba.haotv8.com
DOMAIN-SUFFIX,libs.baidu.com
DOMAIN-SUFFIX,libs.tvmao.cn
DOMAIN-SUFFIX,license.lumion3d.com
DOMAIN-SUFFIX,license.lumion3d.net

View File

@@ -0,0 +1,17 @@
# > Telegram
DOMAIN-SUFFIX,t.me
DOMAIN-SUFFIX,tdesktop.com
DOMAIN-SUFFIX,telegra.ph
DOMAIN-SUFFIX,telegram.me
DOMAIN-SUFFIX,telegram.org
IP-CIDR,91.108.4.0/22,no-resolve
IP-CIDR,91.108.56.0/22,no-resolve
IP-CIDR,91.108.56.0/23,no-resolve
IP-CIDR,109.239.140.0/24,no-resolve
IP-CIDR,149.154.160.0/22,no-resolve
IP-CIDR,149.154.164.0/22,no-resolve
IP-CIDR,149.154.168.0/22,no-resolve
IP-CIDR,149.154.172.0/22,no-resolve
IP-CIDR6,2001:67c:4e8::/48,no-resolve
IP-CIDR6,2001:b28:f23d::/48,no-resolve
IP-CIDR6,2001:b28:f23f::/48,no-resolve

View File

@@ -3,14 +3,7 @@ mkdir obj
set -xe
apk add gcc g++ build-base linux-headers cmake make autoconf automake libtool
apk add libressl-dev zlib-dev rapidjson-dev libevent-dev libevent-static zlib-static pcre-dev bzip2-static
git clone https://github.com/curl/curl
cd curl
./buildconf
./configure --with-ssl --disable-ldap --disable-ldaps --disable-rtsp --without-libidn2 > /dev/null
make install -j4 > /dev/null
cd ..
apk add openssl-dev openssl-libs-static curl-dev curl-static nghttp2-static zlib-dev rapidjson-dev libevent-dev libevent-static zlib-static pcre-dev bzip2-static
git clone https://github.com/jbeder/yaml-cpp
cd yaml-cpp
@@ -20,7 +13,7 @@ cd ..
cmake .
make -j4
g++ -o base/subconverter CMakeFiles/subconverter.dir/src/*.o -static -lpcrecpp -lpcre -levent -lyaml-cpp -lcurl -lssl -lcrypto -lz -lbz2 -ldl -lpthread -O3 -s
g++ -o base/subconverter CMakeFiles/subconverter.dir/src/*.o -static -lpcrecpp -lpcre -levent -lyaml-cpp -lcurl -lnghttp2 -lssl -lcrypto -lz -lbz2 -ldl -lpthread -O3 -s
cd base
chmod +rx subconverter

View File

@@ -123,7 +123,7 @@ public:
if(parsed)
return GetErrorString(last_error);
else
return "line " + std::__cxx11::to_string(last_error_index) + ": " + GetErrorString(last_error);
return "line " + std::to_string(last_error_index) + ": " + GetErrorString(last_error);
}
/**
@@ -202,7 +202,7 @@ public:
{
last_error_index++;
lineSize = strLine.size();
if(!lineSize || strLine[0] == ';' || strLine[0] == '#') //empty lines and comments are ignored
if(!lineSize || strLine[0] == ';' || strLine[0] == '#' || (lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored
continue;
if(strLine[lineSize - 1] == '\r') //remove line break
{
@@ -240,8 +240,11 @@ public:
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_DUPLICATE); //not allowed, stop
}
ini_content.emplace(curSection, itemGroup); //insert previous section to content map
read_sections.emplace_back(curSection); //add to read sections list
read_sections.push_back(curSection); //add to read sections list
if(std::count(section_order.cbegin(), section_order.cend(), curSection) == 0)
section_order.emplace_back(curSection);
}
eraseElements(itemGroup); //reset section storage
curSection = thisSection; //start a new section
}
@@ -269,6 +272,8 @@ public:
}
ini_content.emplace(curSection, itemGroup); //insert this section to content map
read_sections.emplace_back(curSection); //add to read sections list
if(std::count(section_order.cbegin(), section_order.cend(), curSection) == 0)
section_order.emplace_back(curSection);
}
parsed = true;
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE); //all done
@@ -409,6 +414,7 @@ public:
void EraseAll()
{
eraseElements(ini_content);
eraseElements(section_order);
parsed = false;
}
@@ -596,6 +602,7 @@ public:
string_multimap mapTemp;
mapTemp.insert(std::pair<std::string, std::string>(itemName, itemVal));
ini_content.insert(std::pair<std::string, std::multimap<std::string, std::string>>(section, mapTemp));
section_order.emplace_back(section);
}
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE);
@@ -632,7 +639,7 @@ public:
*/
int SetDouble(std::string section, std::string itemName, double itemVal)
{
return Set(section, itemName, std::__cxx11::to_string(itemVal));
return Set(section, itemName, std::to_string(itemVal));
}
/**
@@ -648,7 +655,7 @@ public:
*/
int SetLong(std::string section, std::string itemName, long itemVal)
{
return Set(section, itemName, std::__cxx11::to_string(itemVal));
return Set(section, itemName, std::to_string(itemVal));
}
/**
@@ -666,7 +673,7 @@ public:
{
std::string data;
for(auto &x : Array)
data += std::__cxx11::to_string(x) + separator;
data += std::to_string(x) + separator;
data = data.substr(0, data.size() - separator.size());
return Set(section, itemName, data);
}
@@ -690,6 +697,7 @@ public:
*/
ini_content[newName] = std::move(ini_content[oldName]);
ini_content.erase(oldName);
std::replace(section_order.begin(), section_order.end(), oldName, newName);
__SAVE_ERROR_AND_RETURN(INIREADER_EXCEPTION_NONE);
}
@@ -758,6 +766,7 @@ public:
eraseElements(ini_content.at(section));
if(cached_section == section)
eraseElements(cached_section_content);
//section_order.erase(std::find(section_order.begin(), section_order.end(), section));
}
/**
@@ -779,14 +788,17 @@ public:
if(!parsed)
return std::string();
for(auto &x : ini_content)
for(auto &x : section_order)
{
content += "[" + x.first + "]\n";
for(auto &y : x.second)
content += "[" + x + "]\n";
if(ini_content.find(x) != ini_content.end())
{
if(y.first != "{NONAME}")
content += y.first + "=";
content += y.second + "\n";
for(auto &y : ini_content.at(x))
{
if(y.first != "{NONAME}")
content += y.first + "=";
content += y.second + "\n";
}
}
content += "\n";
}

View File

@@ -19,6 +19,7 @@
//common settings
std::string pref_path = "pref.ini";
bool generator_mode = false;
string_array def_exclude_remarks, def_include_remarks, rulesets;
std::vector<ruleset_content> ruleset_content_array;
std::string listen_address = "127.0.0.1", default_url, managed_config_prefix;
@@ -33,8 +34,8 @@ extern std::mutex on_configuring;
//preferences
string_array renames, emojis;
bool add_emoji = false, remove_old_emoji = false, append_proxy_type = true;
bool udp_flag = false, tfo_flag = false, do_sort = false;
bool add_emoji = false, remove_old_emoji = false, append_proxy_type = false, filter_deprecated = true;
bool udp_flag = false, tfo_flag = false, scv_flag = false, do_sort = false;
std::string proxy_ruleset, proxy_subscription;
std::string clash_rule_base;
@@ -197,6 +198,10 @@ void readConf()
tfo_flag = ini.GetBool("tcp_fast_open_flag");
if(ini.ItemExist("sort_flag"))
do_sort = ini.GetBool("sort_flag");
if(ini.ItemExist("skip_cert_verify_flag"))
scv_flag = ini.GetBool("skip_cert_verify_flag");
if(ini.ItemExist("filter_deprecated_nodes"))
filter_deprecated = ini.GetBool("filter_deprecated_nodes");
}
ini.EnterSection("managed_config");
@@ -253,7 +258,19 @@ void readConf()
std::cerr<<"Read preference settings completed."<<std::endl;
}
int loadExternalConfig(std::string &path, string_array &custom_proxy_group, string_array &surge_ruleset, std::string proxy)
struct ExternalConfig
{
string_array custom_proxy_group;
string_array surge_ruleset;
std::string clash_rule_base;
std::string surge_rule_base;
std::string surfboard_rule_base;
std::string mellow_rule_base;
bool overwrite_original_rules = true;
bool enable_rule_generator = true;
};
int loadExternalConfig(std::string &path, ExternalConfig &ext, std::string proxy)
{
std::string base_content;
if(fileExist(path))
@@ -272,15 +289,23 @@ int loadExternalConfig(std::string &path, string_array &custom_proxy_group, stri
ini.EnterSection("custom");
if(ini.ItemPrefixExist("custom_proxy_group"))
{
eraseElements(custom_proxy_group);
ini.GetAll("custom_proxy_group", custom_proxy_group);
}
ini.GetAll("custom_proxy_group", ext.custom_proxy_group);
if(ini.ItemPrefixExist("surge_ruleset"))
{
eraseElements(surge_ruleset);
ini.GetAll("surge_ruleset", surge_ruleset);
}
ini.GetAll("surge_ruleset", ext.surge_ruleset);
if(ini.ItemExist("clash_rule_base"))
ext.clash_rule_base = ini.Get("clash_rule_base");
if(ini.ItemExist("surge_rule_base"))
ext.surge_rule_base = ini.Get("surge_rule_base");
if(ini.ItemExist("surfboard_rule_base"))
ext.surfboard_rule_base = ini.Get("surfboard_rule_base");
if(ini.ItemExist("mellow_rule_base"))
ext.mellow_rule_base = ini.Get("mellow_rule_base");
if(ini.ItemExist("overwrite_original_rules"))
ext.overwrite_original_rules = ini.GetBool("overwrite_original_rules");
if(ini.ItemExist("enable_rule_generator"))
ext.enable_rule_generator = ini.GetBool("enable_rule_generator");
return 0;
}
@@ -321,18 +346,27 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
std::string group = UrlDecode(getUrlArg(argument, "group")), upload = getUrlArg(argument, "upload"), upload_path = getUrlArg(argument, "upload_path"), version = getUrlArg(argument, "ver");
std::string append_type = getUrlArg(argument, "append_type"), tfo = getUrlArg(argument, "tfo"), udp = getUrlArg(argument, "udp"), nodelist = getUrlArg(argument, "list");
std::string include = UrlDecode(getUrlArg(argument, "include")), exclude = UrlDecode(getUrlArg(argument, "exclude")), sort_flag = getUrlArg(argument, "sort");
std::string scv = getUrlArg(argument, "scv"), fdn = getUrlArg(argument, "fdn");
std::string base_content, output_content;
string_array extra_group, extra_ruleset, include_remarks, exclude_remarks;
std::string groups = urlsafe_base64_decode(getUrlArg(argument, "groups")), ruleset = urlsafe_base64_decode(getUrlArg(argument, "ruleset")), config = UrlDecode(getUrlArg(argument, "config"));
std::vector<ruleset_content> rca;
extra_settings ext;
//for external configuration
std::string ext_clash_base = clash_rule_base, ext_surge_base = surge_rule_base, ext_mellow_base = mellow_rule_base, ext_surfboard_base = surfboard_rule_base;
//validate urls
if(!url.size())
url = default_url;
if(!url.size() || !target.size())
return "Invalid request!";
//check if we need to read configuration
if(!api_mode || cfw_child_process)
readConf();
//check for proxy settings
std::string proxy;
if(proxy_subscription == "SYSTEM")
proxy = getSystemProxy();
@@ -341,16 +375,38 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
proxy = proxy_subscription;
//load external configuration
if(config.size())
{
std::cerr<<"External configuration file provided. Loading...\n";
//read predefined data first
extra_group = clash_extra_group;
extra_ruleset = rulesets;
loadExternalConfig(config, extra_group, extra_ruleset, proxy);
refreshRulesets(extra_ruleset, rca);
//then load external configuration
ExternalConfig extconf;
loadExternalConfig(config, extconf, proxy);
if(extconf.clash_rule_base.size())
ext_clash_base = extconf.clash_rule_base;
if(extconf.surge_rule_base.size())
ext_surge_base = extconf.surge_rule_base;
if(extconf.surfboard_rule_base.size())
ext_surfboard_base = extconf.surfboard_rule_base;
if(extconf.mellow_rule_base.size())
ext_mellow_base = extconf.mellow_rule_base;
ext.enable_rule_generator = extconf.enable_rule_generator;
//load custom group
if(extconf.custom_proxy_group.size())
extra_group = extconf.custom_proxy_group;
//load custom rules
if(extconf.overwrite_original_rules)
{
extra_ruleset = extconf.surge_ruleset;
refreshRulesets(extra_ruleset, rca);
}
}
else
{
//loading custom groups
if(groups.size())
{
extra_group = split(groups, "@");
@@ -360,6 +416,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
extra_group = clash_extra_group;
//loading custom rulesets
if(ruleset.size())
{
extra_ruleset = split(ruleset, "@");
@@ -382,7 +439,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
}
}
extra_settings ext;
//check other flags
if(emoji.size())
{
ext.add_emoji = ext.remove_emoji = emoji == "true";
@@ -400,14 +457,18 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
ext.tfo = tfo.size() ? tfo == "true" : tfo_flag;
ext.udp = udp.size() ? udp == "true" : udp_flag;
ext.sort_flag = sort_flag.size() ? sort_flag == "true" : do_sort;
ext.skip_cert_verify = scv.size() ? scv == "true" : scv_flag;
ext.filter_deprecated = fdn.size() ? fdn == "true" : filter_deprecated;
ext.nodelist = nodelist == "true";
ext.surge_ssr_path = surge_ssr_path;
//loading urls
string_array urls = split(url, "|");
std::vector<nodeInfo> nodes;
int groupID = 0;
//check custom include/exclude settings
if(include.size() && regValid(include))
include_remarks.emplace_back(include);
else
@@ -417,8 +478,11 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else
exclude_remarks = def_exclude_remarks;
//check custom group name
if(group.size())
custom_group = group;
//start parsing urls
for(std::string &x : urls)
{
x = trim(x);
@@ -426,6 +490,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
addNodes(x, nodes, groupID, proxy, exclude_remarks, include_remarks);
groupID++;
}
//exit if found nothing
if(!nodes.size())
return "No nodes were found!";
@@ -433,17 +498,21 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
if(target == "clash" || target == "clashr")
{
std::cerr<<"Clash"<<((target == "clashr") ? "R" : "")<<std::endl;
if(rca.size() || extra_group.size() || update_ruleset_on_request)
if(rca.size() || extra_group.size() || update_ruleset_on_request || ext_clash_base != clash_rule_base)
{
if(fileExist(clash_rule_base))
base_content = fileGet(clash_rule_base, false);
if(fileExist(ext_clash_base))
base_content = fileGet(ext_clash_base, false);
else
base_content = webGet(clash_rule_base, getSystemProxy());
base_content = webGet(ext_clash_base, getSystemProxy());
output_content = netchToClash(nodes, base_content, rca, extra_group, target == "clashr", ext);
}
else
output_content = YAML::Dump(netchToClash(nodes, clash_base, extra_group, target == "clashr", ext));
{
YAML::Node yamlnode = clash_base;
netchToClash(nodes, yamlnode, extra_group, target == "clashr", ext);
output_content = YAML::Dump(yamlnode);
}
if(upload == "true")
uploadGist(target, upload_path, output_content, false);
@@ -454,10 +523,10 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
int surge_ver = version.size() ? to_int(version, 3) : 3;
std::cerr<<"Surge "<<surge_ver<<std::endl;
if(fileExist(surge_rule_base))
base_content = fileGet(surge_rule_base, false);
if(fileExist(ext_surge_base))
base_content = fileGet(ext_surge_base, false);
else
base_content = webGet(surge_rule_base, getSystemProxy());
base_content = webGet(ext_surge_base, getSystemProxy());
output_content = netchToSurge(nodes, base_content, rca, extra_group, surge_ver, ext);
if(upload == "true")
@@ -470,10 +539,10 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else if(target == "surfboard")
{
std::cerr<<"Surfboard"<<std::endl;
if(fileExist(surfboard_rule_base))
base_content = fileGet(surfboard_rule_base, false);
if(fileExist(ext_surfboard_base))
base_content = fileGet(ext_surfboard_base, false);
else
base_content = webGet(surfboard_rule_base, getSystemProxy());
base_content = webGet(ext_surfboard_base, getSystemProxy());
output_content = netchToSurge(nodes, base_content, rca, extra_group, 2, ext);
if(upload == "true")
@@ -486,12 +555,12 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS)
else if(target == "mellow")
{
std::cerr<<"Mellow"<<std::endl;
if(rca.size() || extra_group.size() || update_ruleset_on_request)
if(rca.size() || extra_group.size() || update_ruleset_on_request || ext_mellow_base != mellow_rule_base)
{
if(fileExist(mellow_rule_base))
base_content = fileGet(mellow_rule_base, false);
if(fileExist(ext_mellow_base))
base_content = fileGet(ext_mellow_base, false);
else
base_content = webGet(mellow_rule_base, getSystemProxy());
base_content = webGet(ext_mellow_base, getSystemProxy());
output_content = netchToMellow(nodes, base_content, rca, extra_group, ext);
}
@@ -586,7 +655,7 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
refreshRulesets(rulesets, ruleset_content_array);
rca = ruleset_content_array;
extra_settings ext = {add_emoji, remove_old_emoji, append_proxy_type, udp_flag, tfo_flag, false, do_sort, ""};
extra_settings ext = {true, add_emoji, remove_old_emoji, append_proxy_type, udp_flag, tfo_flag, false, do_sort, scv_flag, filter_deprecated, ""};
std::string proxy;
if(proxy_subscription == "SYSTEM")
@@ -607,7 +676,9 @@ std::string simpleToClashR(RESPONSE_CALLBACK_ARGS)
std::cerr<<"Generate target: ClashR\n";
return YAML::Dump(netchToClash(nodes, clash_base, extra_group, true, ext));
YAML::Node yamlnode = clash_base;
netchToClash(nodes, yamlnode, extra_group, true, ext);
return YAML::Dump(yamlnode);
}
void chkArg(int argc, char *argv[])
@@ -769,6 +840,9 @@ int main(int argc, char *argv[])
});
}
std::string env_port = GetEnv("PORT");
if(env_port.size())
listen_port = to_int(env_port, listen_port);
listener_args args = {listen_address, listen_port, max_pending_connections, max_concurrent_threads};
std::cout<<"Serving HTTP @ http://"<<listen_address<<":"<<listen_port<<std::endl;
start_web_server_multi(&args);

View File

@@ -33,8 +33,6 @@
#include <sys/socket.h>
#endif // _WIN32
using namespace std::__cxx11;
void sleep(int interval)
{
/*
@@ -320,6 +318,21 @@ std::vector<std::string> split(const std::string &s, const std::string &seperato
return result;
}
std::string GetEnv(std::string name)
{
std::string retVal;
#ifdef _WIN32
char chrData[1024] = {};
if(GetEnvironmentVariable(name.c_str(), chrData, 1023))
retVal.assign(chrData);
#else
char *env = getenv(name.c_str());
if(env != NULL)
retVal.assign(env);
#endif // _WIN32
return retVal;
}
std::string getSystemProxy()
{
#ifdef _WIN32
@@ -689,12 +702,12 @@ int fileWrite(std::string path, std::string content, bool overwrite)
return 0;
}
bool isIPv4(std::string address)
bool isIPv4(std::string &address)
{
return regMatch(address, "^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
}
bool isIPv6(std::string address)
bool isIPv6(std::string &address)
{
std::vector<std::string> regLists = {"^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$", "^((?:[0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4})*)?)::((?:([0-9A-Fa-f]{1,4}:)*[0-9A-Fa-f]{1,4})?)$", "^(::(?:[0-9A-Fa-f]{1,4})(?::[0-9A-Fa-f]{1,4}){5})|((?:[0-9A-Fa-f]{1,4})(?::[0-9A-Fa-f]{1,4}){5}::)$"};
for(unsigned int i = 0; i < regLists.size(); i++)

View File

@@ -46,14 +46,15 @@ std::string regReplace(std::string src, std::string match, std::string rep);
bool regMatch(std::string src, std::string match);
std::string speedCalc(double speed);
std::string getMD5(std::string data);
bool isIPv4(std::string address);
bool isIPv6(std::string address);
bool isIPv4(std::string &address);
bool isIPv6(std::string &address);
void urlParse(std::string url, std::string &host, std::string &path, int &port, bool &isTLS);
void removeUTF8BOM(std::string &data);
int shortAssemble(unsigned short num_a, unsigned short num_b);
void shortDisassemble(int source, unsigned short &num_a, unsigned short &num_b);
int to_int(std::string &s, int def_vaule = 0);
std::string UTF8ToCodePoint(std::string data);
std::string GetEnv(std::string name);
std::string fileGet(std::string path, bool binary = true);
int fileWrite(std::string path, std::string content, bool overwrite);
@@ -78,20 +79,17 @@ template <typename T> static inline void eraseElements(T &target)
T().swap(target);
}
#ifdef _MACOS
#ifndef HAVE_TO_STRING
namespace std
{
namespace __cxx11
template <typename T> std::string to_string(const T& n)
{
template <typename T> std::string to_string(const T& n)
{
std::ostringstream ss;
ss << n;
return ss.str();
}
std::ostringstream ss;
ss << n;
return ss.str();
}
}
#endif // _MACOS
#endif // HAVE_TO_STRING
#ifdef _WIN32
void StringToWstring(std::wstring& szDst, std::string str);

View File

@@ -11,7 +11,6 @@
#include "rapidjson_extra.h"
#include "ini_reader.h"
using namespace std::__cxx11;
using namespace rapidjson;
using namespace YAML;
/*
@@ -245,7 +244,7 @@ void explodeVmessConf(std::string content, std::string custom_port, int local_po
node.group = V2RAY_DEFAULT_GROUP;
node.remarks = add + ":" + port;
node.server = add;
node.port = stoi(port);
node.port = to_int(port);
nodes.push_back(node);
}
return;
@@ -320,7 +319,7 @@ void explodeVmessConf(std::string content, std::string custom_port, int local_po
node.remarks = ps;
node.id = index;
node.server = add;
node.port = stoi(port);
node.port = to_int(port);
nodes.push_back(node);
}
return;
@@ -349,8 +348,8 @@ void explodeSS(std::string ss, bool libev, std::string custom_port, int local_po
}
if(strFind(ss, "@"))
{
ss = regReplace(ss, "(.*?)@(.*):(.*)", "$1,$2,$3");
args = split(ss, ",");
ss = regReplace(ss, "(.*?)@(.*):(.*)", "$1|$2|$3");
args = split(ss, "|");
secret = split(urlsafe_base64_decode(args[0]), ":");
method = secret[0];
password = secret[1];
@@ -359,8 +358,8 @@ void explodeSS(std::string ss, bool libev, std::string custom_port, int local_po
}
else
{
ss = regReplace(urlsafe_base64_decode(ss), "(.*?):(.*?)@(.*):(.*)", "$1,$2,$3,$4");
args = split(ss, ",");
ss = regReplace(urlsafe_base64_decode(ss), "(.*?):(.*?)@(.*):(.*)", "$1|$2|$3|$4");
args = split(ss, "|");
method = args[0];
password = args[1];
server = args[2];
@@ -416,7 +415,7 @@ void explodeSSD(std::string link, bool libev, std::string custom_port, int local
node.group = group;
node.remarks = remarks;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
node.proxyStr = ssConstruct(server, port, password, method, plugin, pluginopts, remarks, local_port, libev);
node.id = index;
nodes.push_back(node);
@@ -455,7 +454,7 @@ void explodeSSAndroid(std::string ss, bool libev, std::string custom_port, int l
node.group = group;
node.remarks = ps;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
node.proxyStr = ssConstruct(server, port, password, method, "", "", ps, local_port, libev);
nodes.push_back(node);
index++;
@@ -482,7 +481,7 @@ void explodeSSConf(std::string content, std::string custom_port, int local_port,
node.group = SS_DEFAULT_GROUP;
node.remarks = server + ":" + port;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
node.proxyStr = SerializeObject(json);
nodes.push_back(node);
return;
@@ -510,7 +509,7 @@ void explodeSSConf(std::string content, std::string custom_port, int local_port,
node.remarks = ps;
node.id = index;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
node.proxyStr = ssConstruct(server, port, password, method, plugin, pluginopts, ps, local_port, libev);
nodes.push_back(node);
index++;
@@ -536,8 +535,8 @@ void explodeSSR(std::string ssr, bool ss_libev, bool ssr_libev, std::string cust
protoparam = regReplace(urlsafe_base64_decode(getUrlArg(strobfs, "protoparam")), "\\s", "");
}
ssr = regReplace(ssr, "(.*):(.*?):(.*?):(.*?):(.*?):(.*)", "$1,$2,$3,$4,$5,$6");
strcfg = split(ssr, ",");
ssr = regReplace(ssr, "(.*):(.*?):(.*?):(.*?):(.*?):(.*)", "$1|$2|$3|$4|$5|$6");
strcfg = split(ssr, "|");
if(strcfg.size() != 6)
return;
@@ -601,7 +600,7 @@ void explodeSSRConf(std::string content, std::string custom_port, int local_port
node.group = SSR_DEFAULT_GROUP;
node.remarks = server + ":" + port;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
node.proxyStr = SerializeObject(json);
nodes.push_back(node);
return;
@@ -634,7 +633,7 @@ void explodeSSRConf(std::string content, std::string custom_port, int local_port
node.remarks = remarks;
node.id = index;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
node.proxyStr = ssrConstruct(group, remarks, remarks_base64, server, port, protocol, method, obfs, password, obfsparam, protoparam, local_port, ssr_libev);
nodes.push_back(node);
index++;
@@ -840,11 +839,11 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
if(singleproxy["tls"].IsDefined())
tls = singleproxy["tls"].as<std::string>() == "true" ? "tls" : "";
else
tls = "";
tls.clear();
if(singleproxy["ws-headers"].IsDefined())
singleproxy["ws-headers"]["Host"] >> host;
else
host = "";
host.clear();
node.linkType = SPEEDTEST_MESSAGE_FOUNDVMESS;
@@ -867,7 +866,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
if(singleproxy["plugin-opts"]["host"].IsDefined())
singleproxy["plugin-opts"]["host"] >> pluginopts_host;
else
pluginopts_host = "";
pluginopts_host.clear();
}
}
else if(singleproxy["plugin"].as<std::string>() == "v2ray-plugin")
@@ -879,19 +878,19 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
if(singleproxy["plugin-opts"]["host"].IsDefined())
singleproxy["plugin-opts"]["host"] >> pluginopts_host;
else
pluginopts_host = "";
pluginopts_host.clear();
if(singleproxy["plugin-opts"]["tls"].IsDefined())
tls = singleproxy["plugin-opts"]["tls"].as<bool>() ? "tls;" : "";
else
tls = "";
tls.clear();
if(singleproxy["plugin-opts"]["path"].IsDefined())
singleproxy["plugin-opts"]["path"] >> path;
else
path = "";
path.clear();
if(singleproxy["plugin-opts"]["mux"].IsDefined())
pluginopts_mux = singleproxy["plugin-opts"]["mux"].as<bool>() ? "mux=4;" : "";
else
pluginopts_mux = "";
pluginopts_mux.clear();
}
}
}
@@ -903,7 +902,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
singleproxy["obfs-host"] >> pluginopts_host;
}
else
plugin = "";
plugin.clear();
if(plugin == "simple-obfs")
{
@@ -921,7 +920,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
pluginopts += "mux=" + pluginopts_mux + ";";
}
else
pluginopts = "";
pluginopts.clear();
//support for go-shadowsocks2
if(cipher == "AEAD_CHACHA20_POLY1305")
@@ -944,6 +943,11 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
singleproxy["username"] >> user;
singleproxy["password"] >> password;
}
else
{
user.clear();
password.clear();
}
node.linkType = SPEEDTEST_MESSAGE_FOUNDSOCKS;
node.proxyStr = socksConstruct(ps, server, port, user, password);
@@ -971,6 +975,11 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
singleproxy["username"] >> user;
singleproxy["password"] >> password;
}
else
{
user.clear();
password.clear();
}
node.linkType = SPEEDTEST_MESSAGE_FOUNDHTTP;
node.proxyStr = httpConstruct(ps, server, port, user, password);
@@ -981,7 +990,7 @@ void explodeClash(Node yamlnode, std::string custom_port, int local_port, std::v
node.group = group;
node.remarks = ps;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
node.id = index;
nodes.push_back(node);
index++;
@@ -1140,7 +1149,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
port = custom_port == "" ? trim(configs[2]) : custom_port;
method = trim(configs[3]);
password = trim(configs[4]);
plugin = "";
plugin.clear();
for(i = 6; i < configs.size(); i++)
{
@@ -1174,7 +1183,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
{
server = trim(configs[1]);
port = custom_port == "" ? trim(configs[2]) : custom_port;
plugin = "";
plugin.clear();
for(i = 3; i < configs.size(); i++)
{
@@ -1209,6 +1218,8 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
{
node.linkType = SPEEDTEST_MESSAGE_FOUNDSOCKS;
node.group = SOCKS_DEFAULT_GROUP;
server = trim(configs[1]);
port = custom_port == "" ? trim(configs[2]) : custom_port;
if(configs.size() >= 5)
{
username = trim(configs[2]);
@@ -1266,6 +1277,8 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
{
node.linkType = SPEEDTEST_MESSAGE_FOUNDHTTP;
node.group = HTTP_DEFAULT_GROUP;
server = trim(configs[1]);
port = custom_port == "" ? trim(configs[2]) : custom_port;
if(configs.size() >= 5)
{
username = trim(configs[2]);
@@ -1330,7 +1343,7 @@ bool explodeSurge(std::string surge, std::string custom_port, int local_port, st
node.remarks = remarks;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
node.id = index;
nodes.push_back(node);
index++;
@@ -1394,7 +1407,7 @@ void explodeSSTap(std::string sstap, std::string custom_port, int local_port, st
node.remarks = remarks;
node.id = index;
node.server = server;
node.port = stoi(port);
node.port = to_int(port);
nodes.push_back(node);
}
}

View File

@@ -21,6 +21,9 @@ extern bool add_emoji, remove_old_emoji;
extern bool api_mode;
extern string_array ss_ciphers, ssr_ciphers;
string_array clashr_protocols = {"auth_aes128_md5", "auth_aes128_sha1"};
string_array clashr_obfs = {"plain", "http_simple", "http_post", "tls1.2_ticket_auth"};
/*
std::string hostnameToIPAddr(std::string host)
{
@@ -482,7 +485,7 @@ void groupGenerate(std::string &rule, std::vector<nodeInfo> &nodelist, std::vect
}
}
YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_array &extra_proxy_group, bool clashR, extra_settings &ext)
void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, string_array &extra_proxy_group, bool clashR, extra_settings &ext)
{
try_config_lock();
YAML::Node proxies, singleproxy, singlegroup, original_groups;
@@ -532,12 +535,20 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
password = GetMember(json, "Password");
method = GetMember(json, "EncryptMethod");
singleproxy["name"] = remark;
singleproxy["server"] = hostname;
singleproxy["port"] = (unsigned short)stoi(port);
if(x.linkType == SPEEDTEST_MESSAGE_FOUNDSS)
{
//latest clash core removed support for chacha20 encryption
if(ext.filter_deprecated && method == "chacha20")
continue;
plugin = GetMember(json, "Plugin");
pluginopts = replace_all_distinct(GetMember(json, "PluginOption"), ";", "&");
singleproxy["type"] = "ss";
singleproxy["cipher"] = method;
singleproxy["password"] = password;
if(plugin == "simple-obfs" || plugin == "obfs-local")
{
singleproxy["plugin"] = "obfs";
@@ -552,6 +563,8 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
singleproxy["plugin-opts"]["path"] = getUrlArg(pluginopts, "path");
singleproxy["plugin-opts"]["tls"] = pluginopts.find("tls") != pluginopts.npos;
singleproxy["plugin-opts"]["mux"] = pluginopts.find("mux") != pluginopts.npos;
if(ext.skip_cert_verify)
singleproxy["plugin-opts"]["skip-cert-verify"] = true;
}
}
else if(x.linkType == SPEEDTEST_MESSAGE_FOUNDVMESS)
@@ -567,6 +580,8 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
singleproxy["alterId"] = stoi(aid);
singleproxy["cipher"] = method;
singleproxy["tls"] = tlssecure;
if(ext.skip_cert_verify)
singleproxy["skip-cert-verify"] = true;
if(transproto == "ws")
{
singleproxy["network"] = transproto;
@@ -578,12 +593,21 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
}
else if(x.linkType == SPEEDTEST_MESSAGE_FOUNDSSR && clashR)
{
//latest clash core removed support for chacha20 encryption
if(ext.filter_deprecated && method == "chacha20")
continue;
//ignoring all nodes with unsupported obfs and protocols
protocol = GetMember(json, "Protocol");
protoparam = GetMember(json, "ProtocolParam");
if(std::find(clashr_protocols.cbegin(), clashr_protocols.cend(), protocol) == clashr_protocols.cend())
continue;
obfs = GetMember(json, "OBFS");
if(std::find(clashr_obfs.cbegin(), clashr_obfs.cend(), obfs) == clashr_obfs.cend())
continue;
protoparam = GetMember(json, "ProtocolParam");
obfsparam = GetMember(json, "OBFSParam");
singleproxy["type"] = "ssr";
singleproxy["cipher"] = method;
singleproxy["password"] = password;
singleproxy["protocol"] = protocol;
singleproxy["protocolparam"] = protoparam;
singleproxy["obfs"] = obfs;
@@ -593,19 +617,22 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
{
singleproxy["type"] = "socks5";
singleproxy["username"] = username;
singleproxy["password"] = password;
if(ext.skip_cert_verify)
singleproxy["skip-cert-verify"] = true;
}
else if(x.linkType == SPEEDTEST_MESSAGE_FOUNDHTTP)
{
singleproxy["type"] = "http";
singleproxy["username"] = username;
singleproxy["password"] = password;
singleproxy["tls"] = type == "HTTPS";
if(ext.skip_cert_verify)
singleproxy["skip-cert-verify"] = true;
}
else
continue;
singleproxy["password"] = password;
singleproxy["name"] = remark;
singleproxy["server"] = hostname;
singleproxy["port"] = (unsigned short)stoi(port);
if(ext.udp)
singleproxy["udp"] = true;
singleproxy.SetStyle(YAML::EmitterStyle::Flow);
@@ -618,7 +645,8 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
{
YAML::Node provider;
provider["proxies"] = proxies;
return provider;
yamlnode = provider;
return;
}
yamlnode["Proxy"] = proxies;
@@ -635,6 +663,9 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
if(vArray.size() < 3)
continue;
singlegroup["name"] = vArray[0];
singlegroup["type"] = vArray[1];
if(vArray[1] == "select")
{
rules_upper_bound = vArray.size();
@@ -656,8 +687,6 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
if(!filtered_nodelist.size())
filtered_nodelist.emplace_back("DIRECT");
singlegroup["name"] = vArray[0];
singlegroup["type"] = vArray[1];
singlegroup["proxies"] = filtered_nodelist;
//singlegroup.SetStyle(YAML::EmitterStyle::Flow);
@@ -675,8 +704,6 @@ YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &yamlnode, stri
}
yamlnode["Proxy Group"] = original_groups;
return yamlnode;
}
std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, bool clashR, extra_settings &ext)
@@ -692,12 +719,13 @@ std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, s
return std::string();
}
yamlnode = netchToClash(nodes, yamlnode, extra_proxy_group, clashR, ext);
netchToClash(nodes, yamlnode, extra_proxy_group, clashR, ext);
if(ext.nodelist)
return YAML::Dump(yamlnode);
rulesetToClash(yamlnode, ruleset_content_array);
if(ext.enable_rule_generator)
rulesetToClash(yamlnode, ruleset_content_array);
return YAML::Dump(yamlnode);
}
@@ -712,11 +740,15 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam;
std::string id, aid, transproto, faketype, host, path, quicsecure, quicsecret;
std::string url;
std::string output_nodelist;
std::vector<nodeInfo> nodelist;
unsigned short local_port = 1080;
bool tlssecure;
//group pref
std::string url;
int interval = 0;
std::string ssid_default;
string_array vArray, remarks_list, filtered_nodelist;
ini.store_any_line = true;
@@ -757,11 +789,11 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
remark = x.remarks = x.remarks + "$";
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
username = GetMember(json, "Username");
password = GetMember(json, "Password");
method = GetMember(json, "EncryptMethod");
proxy = "";
proxy.clear();
if(x.linkType == SPEEDTEST_MESSAGE_FOUNDSS)
{
@@ -793,6 +825,8 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
{
proxy += ", ws=true, ws-path=" + path + ", ws-headers=Host:" + host;
}
if(ext.skip_cert_verify)
proxy += ", skip-cert-verify=1";
else if(transproto == "kcp" || transproto == "h2" || transproto == "quic")
continue;
}
@@ -805,7 +839,7 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
obfs = GetMember(json, "OBFS");
obfsparam = GetMember(json, "OBFSParam");
proxy = "external, exec=\"" + ext.surge_ssr_path + "\", args=\"";
string_array args = {"-l", std::__cxx11::to_string(local_port), "-s", hostname, "-p", port, "-m", method, "-k", password, "-o", obfs, "-O", protocol};
string_array args = {"-l", std::to_string(local_port), "-s", hostname, "-p", port, "-m", method, "-k", password, "-o", obfs, "-O", protocol};
if(obfsparam.size())
{
args.emplace_back("-g");
@@ -821,22 +855,22 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
return std::move(a) + "\", args=\"" + std::move(b);
});
//std::string ipaddr = (isIPv4(hostname) || isIPv6(hostname)) ? hostname : hostnameToIPAddr(hostname);
//proxy += "\", local-port=" + std::__cxx11::to_string(local_port) + ", addresses=" + ipaddr;
proxy += "\", local-port=" + std::__cxx11::to_string(local_port);
//proxy += "\", local-port=" + std::to_string(local_port) + ", addresses=" + ipaddr;
proxy += "\", local-port=" + std::to_string(local_port);
local_port++;
}
else if(x.linkType == SPEEDTEST_MESSAGE_FOUNDSOCKS)
{
proxy = "socks5, " + hostname + ", " + port;
if(username.size() && password.size())
proxy += ", " + username + ", " + password;
proxy = "socks5, " + hostname + ", " + port + ", " + username + ", " + password;
if(ext.skip_cert_verify)
proxy += ", skip-cert-verify=1";
}
else if(type == "HTTP" || type == "HTTPS")
{
proxy = "http," + hostname + "," + port;
if(username != "" && password != "")
proxy += ", " + username + ", " + password;
proxy = "http," + hostname + "," + port + ", " + username + ", " + password;
proxy += std::string(", tls=") + (type == "HTTPS" ? "true" : "false");
if(ext.skip_cert_verify)
proxy += ", skip-cert-verify=1";
}
else
continue;
@@ -858,12 +892,13 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
return output_nodelist;
ini.SetCurrentSection("Proxy Group");
ini.EraseSection();
for(std::string &x : extra_proxy_group)
{
eraseElements(filtered_nodelist);
unsigned int rules_upper_bound = 0;
url = "";
proxy = "";
url.clear();
proxy.clear();
vArray = split(x, "`");
if(vArray.size() < 3)
@@ -873,12 +908,25 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
{
rules_upper_bound = vArray.size();
}
else if(vArray[1] == "url-test" || vArray[1] == "fallback" || vArray[1] == "load-balance")
else if(vArray[1] == "url-test" || vArray[1] == "fallback")
{
if(vArray.size() < 5)
continue;
rules_upper_bound = vArray.size() - 2;
url = vArray[vArray.size() - 2];
interval = to_int(vArray[vArray.size() - 1]);
}
else if(vArray[1] == "ssid")
{
if(vArray.size() < 4)
continue;
proxy = vArray[1] + ",default=" + vArray[2];
proxy += std::accumulate(vArray.begin() + 3, vArray.end(), vArray[3], [](std::string a, std::string b)
{
return std::move(a) + "," + std::move(b);
});
ini.Set("{NONAME}", vArray[0] + " = " + proxy); //insert order
continue;
}
else
continue;
@@ -898,13 +946,14 @@ std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, s
{
return std::move(a) + "," + std::move(b);
});
if(vArray[1] == "url-test" || vArray[1] == "fallback" || vArray[1] == "load-balance")
proxy += ",url=" + url;
if(vArray[1] == "url-test" || vArray[1] == "fallback")
proxy += ",url=" + url + ",interval=" + std::to_string(interval);
ini.Set("{NONAME}", vArray[0] + " = " + proxy); //insert order
}
rulesetToSurge(ini, ruleset_content_array, surge_ver);
if(ext.enable_rule_generator)
rulesetToSurge(ini, ruleset_content_array, surge_ver);
return ini.ToString();
}
@@ -941,7 +990,7 @@ std::string netchToSS(std::vector<nodeInfo> &nodes, extra_settings &ext)
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
password = GetMember(json, "Password");
method = GetMember(json, "EncryptMethod");
plugin = GetMember(json, "Plugin");
@@ -971,7 +1020,10 @@ std::string netchToSS(std::vector<nodeInfo> &nodes, extra_settings &ext)
allLinks += proxyStr + "\n";
}
return base64_encode(allLinks);
if(ext.nodelist)
return allLinks;
else
return base64_encode(allLinks);
}
std::string netchToSSR(std::vector<nodeInfo> &nodes, extra_settings &ext)
@@ -1005,7 +1057,7 @@ std::string netchToSSR(std::vector<nodeInfo> &nodes, extra_settings &ext)
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
password = GetMember(json, "Password");
method = GetMember(json, "EncryptMethod");
protocol = GetMember(json, "Protocol");
@@ -1066,7 +1118,7 @@ std::string netchToVMess(std::vector<nodeInfo> &nodes, extra_settings &ext)
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
method = GetMember(json, "EncryptMethod");
id = GetMember(json, "UserID");
aid = GetMember(json, "AlterID");
@@ -1129,7 +1181,7 @@ std::string netchToQuan(std::vector<nodeInfo> &nodes, extra_settings &ext)
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
method = GetMember(json, "EncryptMethod");
password = GetMember(json, "Password");
@@ -1151,6 +1203,8 @@ std::string netchToQuan(std::vector<nodeInfo> &nodes, extra_settings &ext)
proxyStr += ", obfs=ws, obfs-path=" + path + ", obfs-header=\"Host: " + host + "\"";
if(tlssecure)
proxyStr += ", over-tls=true, tls-host=" + host;
if(ext.skip_cert_verify)
proxyStr += ", certificate=0";
proxyStr = "vmess://" + urlsafe_base64_encode(proxyStr);
break;
case SPEEDTEST_MESSAGE_FOUNDSSR:
@@ -1220,7 +1274,7 @@ std::string netchToQuanX(std::vector<nodeInfo> &nodes, extra_settings &ext)
remark = x.remarks;
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
method = GetMember(json, "EncryptMethod");
switch(x.linkType)
@@ -1235,6 +1289,8 @@ std::string netchToQuanX(std::vector<nodeInfo> &nodes, extra_settings &ext)
proxyStr = "vmess = " + hostname + ":" + port + ", method=" + method + ", password=" + id;
if(transproto == "ws")
proxyStr += ", obfs=ws, obfs-host=" + host + ", obfs-uri=" + path;
if(ext.skip_cert_verify)
proxyStr += ", certificate=0";
break;
case SPEEDTEST_MESSAGE_FOUNDSS:
password = GetMember(json, "Password");
@@ -1280,6 +1336,7 @@ std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, extra_s
std::string plugin, pluginopts;
std::string protocol, protoparam, obfs, obfsparam;
int port, index = 0;
if(!group.size())
group = "SSD";
@@ -1317,7 +1374,7 @@ std::string netchToSSD(std::vector<nodeInfo> &nodes, std::string &group, extra_s
{
json.Parse(x.proxyStr.data());
remark = "\"" + replace_all_distinct(UTF8ToCodePoint(x.remarks), "\\u1f1", "\\ud83c\\udd") + "\"";
remark = "\"" + replace_all_distinct(UTF8ToCodePoint(x.remarks), "\\u1f1", "\\ud83c\\udd") + "\""; //convert UTF-8 characters to code points
hostname = GetMember(json, "Hostname");
port = (unsigned short)stoi(GetMember(json, "Port"));
password = GetMember(json, "Password");
@@ -1441,7 +1498,7 @@ void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rul
while(std::count(remarks_list.begin(), remarks_list.end(), remark) > 0)
remark = x.remarks = x.remarks + "$";
hostname = GetMember(json, "Hostname");
port = std::__cxx11::to_string((unsigned short)stoi(GetMember(json, "Port")));
port = std::to_string((unsigned short)stoi(GetMember(json, "Port")));
username = GetMember(json, "Username");
password = GetMember(json, "Password");
method = GetMember(json, "EncryptMethod");
@@ -1492,8 +1549,8 @@ void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rul
{
eraseElements(filtered_nodelist);
unsigned int rules_upper_bound = 0;
url = "";
proxy = "";
url.clear();
proxy.clear();
vArray = split(x, "`");
if(vArray.size() < 3)
@@ -1548,7 +1605,8 @@ void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<rul
ini.Set("{NONAME}", proxy); //insert order
}
rulesetToSurge(ini, ruleset_content_array, 2);
if(ext.enable_rule_generator)
rulesetToSurge(ini, ruleset_content_array, 2);
ini.RenameSection("Rule", "RoutingRule");
}

View File

@@ -12,20 +12,23 @@ struct ruleset_content
struct extra_settings
{
bool enable_rule_generator = true;
bool add_emoji = false;
bool remove_emoji = false;
bool append_proxy_type = true;
bool append_proxy_type = false;
bool udp = false;
bool tfo = false;
bool nodelist = false;
bool sort_flag = false;
bool skip_cert_verify = false;
bool filter_deprecated = false;
std::string surge_ssr_path;
};
void rulesetToClash(YAML::Node &base_rule, std::vector<ruleset_content> &ruleset_content_array);
void rulesetToSurge(INIReader &base_rule, std::vector<ruleset_content> &ruleset_content_array, int surge_ver);
std::string netchToClash(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, bool clashR, extra_settings &ext);
YAML::Node netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &base, string_array &extra_proxy_group, bool clashR, extra_settings &ext);
void netchToClash(std::vector<nodeInfo> &nodes, YAML::Node &base, string_array &extra_proxy_group, bool clashR, extra_settings &ext);
std::string netchToSurge(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, int surge_ver, extra_settings &ext);
std::string netchToMellow(std::vector<nodeInfo> &nodes, std::string &base_conf, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext);
void netchToMellow(std::vector<nodeInfo> &nodes, INIReader &ini, std::vector<ruleset_content> &ruleset_content_array, string_array &extra_proxy_group, extra_settings &ext);

View File

@@ -1,6 +1,6 @@
#ifndef VERSION_H_INCLUDED
#define VERSION_H_INCLUDED
#define VERSION "v0.2.3"
#define VERSION "v0.2.5"
#endif // VERSION_H_INCLUDED

View File

@@ -49,7 +49,7 @@ std::string curlGet(std::string url, std::string proxy)
std::string buildSocks5ProxyString(std::string addr, int port, std::string username, std::string password)
{
std::string authstr = username != "" && password != "" ? username + ":" + password + "@" : "";
std::string proxystr = "socks5://" + authstr + addr + ":" + std::__cxx11::to_string(port);
std::string proxystr = "socks5://" + authstr + addr + ":" + std::to_string(port);
return proxystr;
}