1
0
mirror of https://github.com/nitezs/sub2clash.git synced 2024-12-23 21:54:42 -05:00

feat: 增加不输出国家策略组功能

This commit is contained in:
Nite07 2024-03-10 13:26:35 +08:00
parent 65dccc3b51
commit 94a320a682
7 changed files with 175 additions and 295 deletions

View File

@ -74,7 +74,7 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template
} }
// 解析订阅 // 解析订阅
err = yaml.Unmarshal(data, &sub) err = yaml.Unmarshal(data, &sub)
newProxies := make([]model.Proxy, 0) var newProxies []model.Proxy
if err != nil { if err != nil {
reg, _ := regexp.Compile("(ssr|ss|vmess|trojan|vless|hysteria)://") reg, _ := regexp.Compile("(ssr|ss|vmess|trojan|vless|hysteria)://")
if reg.Match(data) { if reg.Match(data) {
@ -157,10 +157,6 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template
for i := range proxyList { for i := range proxyList {
// 重命名匹配到的节点 // 重命名匹配到的节点
for j, v := range replaceRegs { for j, v := range replaceRegs {
if err != nil {
logger.Logger.Debug("replace regexp compile failed", zap.Error(err))
return nil, errors.New("replaceName 参数非法: " + err.Error())
}
if v.MatchString(proxyList[i].Name) { if v.MatchString(proxyList[i].Name) {
proxyList[i].Name = v.ReplaceAllString( proxyList[i].Name = v.ReplaceAllString(
proxyList[i].Name, query.ReplaceTo[j], proxyList[i].Name, query.ReplaceTo[j],
@ -200,7 +196,7 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template
sort.Sort(model.ProxyGroupsSortByName(t.ProxyGroups)) sort.Sort(model.ProxyGroupsSortByName(t.ProxyGroups))
} }
// 合并新节点和模板 // 合并新节点和模板
MergeSubAndTemplate(temp, t) MergeSubAndTemplate(temp, t, query.IgnoreCountryGrooup)
// 处理自定义规则 // 处理自定义规则
for _, v := range query.Rules { for _, v := range query.Rules {
if v.Prepend { if v.Prepend {
@ -233,7 +229,7 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template
return temp, nil return temp, nil
} }
func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription) { func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription, igcg bool) {
// 只合并节点、策略组 // 只合并节点、策略组
// 统计所有国家策略组名称 // 统计所有国家策略组名称
var countryGroupNames []string var countryGroupNames []string
@ -284,5 +280,7 @@ func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription) {
} }
temp.ProxyGroups[i].Proxies = newProxies temp.ProxyGroups[i].Proxies = newProxies
} }
temp.ProxyGroups = append(temp.ProxyGroups, sub.ProxyGroups...) if !igcg {
temp.ProxyGroups = append(temp.ProxyGroups, sub.ProxyGroups...)
}
} }

View File

@ -1,22 +1,16 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh-CN"> <html lang="zh-CN">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8" />
<meta content="width=device-width, initial-scale=1.0" name="viewport"/> <meta content="width=device-width, initial-scale=1.0" name="viewport" />
<title>sub2clash</title> <title>sub2clash</title>
<!-- Bootstrap CSS --> <!-- Bootstrap CSS -->
<link <link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
crossorigin="anonymous" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" rel="stylesheet" />
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
rel="stylesheet"
/>
<!-- Bootstrap JS --> <!-- Bootstrap JS -->
<script <script crossorigin="anonymous" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
></script>
<!-- Axios --> <!-- Axios -->
<script src="https://cdn.jsdelivr.net/npm/axios@latest/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios@latest/dist/axios.min.js"></script>
<script src="./static/index.js"></script> <script src="./static/index.js"></script>
@ -26,260 +20,156 @@
} }
.btn-xs { .btn-xs {
padding: 2px 2px; /* 调整内边距以减小按钮大小 */ padding: 2px 2px;
font-size: 10px; /* 设置字体大小 */ /* 调整内边距以减小按钮大小 */
line-height: 1.2; /* 调整行高 */ font-size: 10px;
border-radius: 3px; /* 可选的边框半径调整 */ /* 设置字体大小 */
line-height: 1.2;
/* 调整行高 */
border-radius: 3px;
/* 可选的边框半径调整 */
height: 25px; height: 25px;
width: 25px; width: 25px;
} }
</style> </style>
</head> </head>
<body class="bg-light"> <body class="bg-light">
<div class="container mt-5"> <div class="container mt-5">
<div class="mb-4"> <div class="mb-4">
<h2>sub2clash</h2> <h2>sub2clash</h2>
<span class="text-muted fst-italic" <span class="text-muted fst-italic">通用订阅链接转 Clash(Meta) 配置工具
>通用订阅链接转 Clash(Meta) 配置工具 <a href="https://github.com/nitezs/sub2clash#clash-meta" target="_blank">使用文档</a></span><br /><span
<a class="text-muted fst-italic">注意:本程序非纯前端程序,输入的订阅将被后端缓存,请确保您信任当前站点</span>
href="https://github.com/nitezs/sub2clash#clash-meta" </div>
target="_blank"
>使用文档</a
></span
><br><span class="text-muted fst-italic"
>注意:本程序非纯前端程序,输入的订阅将被后端缓存,请确保您信任当前站点</span
>
</div>
<!-- Input URL --> <!-- Input URL -->
<div class="form-group mb-5"> <div class="form-group mb-5">
<label for="apiLink">解析链接:</label> <label for="apiLink">解析链接:</label>
<div class="input-group mb-2"> <div class="input-group mb-2">
<input <input class="form-control" id="urlInput" type="text" placeholder="通过生成的链接重新填写下方设置" />
class="form-control" <button class="btn btn-primary" onclick="parseInputURL()" type="button">
id="urlInput" 解析
type="text" </button>
placeholder="通过生成的链接重新填写下方设置" </div>
/> </div>
<button <!-- API Endpoint -->
class="btn btn-primary" <div class="form-group mb-3">
onclick="parseInputURL()" <label for="endpoint">客户端类型:</label>
type="button" <select class="form-control" id="endpoint" name="endpoint">
> <option value="clash">Clash</option>
解析 <option value="meta">Clash.Meta</option>
</select>
</div>
<!-- Template -->
<div class="form-group mb-3">
<label for="template">模板链接或名称:</label>
<input class="form-control" id="template" name="template" placeholder="输入外部模板链接或内部模板名称(可选)" type="text" />
</div>
<!-- Subscription Link -->
<div class="form-group mb-3">
<label for="sub">订阅链接:</label>
<textarea class="form-control" id="sub" name="sub" placeholder="每行输入一个订阅链接" rows="5"></textarea>
</div>
<!-- Proxy Link -->
<div class="form-group mb-3">
<label for="proxy">节点分享链接:</label>
<textarea class="form-control" id="proxy" name="proxy" placeholder="每行输入一个节点分享链接" rows="5"></textarea>
</div>
<!-- Refresh -->
<div class="form-check mb-3">
<input class="form-check-input" id="refresh" name="refresh" type="checkbox" />
<label class="form-check-label" for="refresh">强制重新获取订阅</label>
</div>
<!-- Node List -->
<div class="form-check mb-3">
<input class="form-check-input" id="nodeList" name="nodeList" type="checkbox" />
<label class="form-check-label" for="nodeList">输出为 Node List</label>
</div>
<!-- Auto Test -->
<div class="form-check mb-3">
<input class="form-check-input" id="autoTest" name="autoTest" type="checkbox" />
<label class="form-check-label" for="autoTest">国家策略组自动测速</label>
</div>
<!-- Lazy -->
<div class="form-check mb-3">
<input class="form-check-input" id="lazy" name="lazy" type="checkbox" />
<label class="form-check-label" for="lazy">自动测速启用 lazy 模式</label>
</div>
<!-- IgnoreCountryGroup -->
<div class="form-check mb-3">
<input class="form-check-input" id="igcg" name="igcg" type="checkbox" />
<label class="form-check-label" for="igcg">不输出国家策略组</label>
</div>
<!-- Rule Provider -->
<div class="form-group mb-3" id="ruleProviderGroup">
<label>Rule Provider:</label>
<button class="btn btn-primary mb-1 btn-xs" onclick="addRuleProvider()" type="button">
+
</button>
</div>
<!-- Rule -->
<div class="form-group mb-3" id="ruleGroup">
<label>规则:</label>
<button class="btn btn-primary mb-1 btn-xs" onclick="addRule()" type="button">
+
</button>
</div>
<!-- Sort -->
<div class="form-group mb-3">
<label for="sort">国家策略组排序规则:</label>
<select class="form-control" id="sort" name="sort">
<option value="nameasc">名称(升序)</option>
<option value="namedesc">名称(降序)</option>
<option value="sizeasc">节点数量(升序)</option>
<option value="sizedesc">节点数量(降序)</option>
</select>
</div>
<!-- Remove -->
<div class="form-group mb-3">
<label for="remove">排除节点:</label>
<input class="form-control" type="text" name="remove" id="remove" placeholder="正则表达式" />
</div>
<!-- Rename -->
<div class="form-group mb-3" id="replaceGroup">
<label>节点名称替换:</label>
<button class="btn btn-primary mb-1 btn-xs" onclick="addReplace()" type="button">
+
</button> </button>
</div> </div>
</div>
<!-- API Endpoint -->
<div class="form-group mb-3">
<label for="endpoint">客户端类型:</label>
<select class="form-control" id="endpoint" name="endpoint">
<option value="clash">Clash</option>
<option value="meta">Clash.Meta</option>
</select>
</div>
<!-- Template -->
<div class="form-group mb-3">
<label for="template">模板链接或名称:</label>
<input
class="form-control"
id="template"
name="template"
placeholder="输入外部模板链接或内部模板名称(可选)"
type="text"
/>
</div>
<!-- Subscription Link -->
<div class="form-group mb-3">
<label for="sub">订阅链接:</label>
<textarea
class="form-control"
id="sub"
name="sub"
placeholder="每行输入一个订阅链接"
rows="5"
></textarea>
</div>
<!-- Proxy Link -->
<div class="form-group mb-3">
<label for="proxy">节点分享链接:</label>
<textarea
class="form-control"
id="proxy"
name="proxy"
placeholder="每行输入一个节点分享链接"
rows="5"
></textarea>
</div>
<!-- Refresh -->
<div class="form-check mb-3">
<input
class="form-check-input"
id="refresh"
name="refresh"
type="checkbox"
/>
<label class="form-check-label" for="refresh"
>强制重新获取订阅</label
>
</div>
<!-- Node List -->
<div class="form-check mb-3">
<input
class="form-check-input"
id="nodeList"
name="nodeList"
type="checkbox"
/>
<label class="form-check-label" for="nodeList"
>输出为 Node List</label
>
</div>
<!-- Auto Test -->
<div class="form-check mb-3">
<input
class="form-check-input"
id="autoTest"
name="autoTest"
type="checkbox"
/>
<label class="form-check-label" for="autoTest"
>国家策略组自动测速</label
>
</div>
<!-- Lazy -->
<div class="form-check mb-3">
<input
class="form-check-input"
id="lazy"
name="lazy"
type="checkbox"
/>
<label class="form-check-label" for="lazy"
>自动测速启用 lazy 模式</label
>
</div>
<!-- Rule Provider -->
<div class="form-group mb-3" id="ruleProviderGroup">
<label>Rule Provider:</label>
<button
class="btn btn-primary mb-1 btn-xs"
onclick="addRuleProvider()"
type="button"
>
+
</button>
</div>
<!-- Rule -->
<div class="form-group mb-3" id="ruleGroup">
<label>规则:</label>
<button
class="btn btn-primary mb-1 btn-xs"
onclick="addRule()"
type="button"
>
+
</button>
</div>
<!-- Sort -->
<div class="form-group mb-3">
<label for="sort">国家策略组排序规则:</label>
<select class="form-control" id="sort" name="sort">
<option value="nameasc">名称(升序)</option>
<option value="namedesc">名称(降序)</option>
<option value="sizeasc">节点数量(升序)</option>
<option value="sizedesc">节点数量(降序)</option>
</select>
</div>
<!-- Remove -->
<div class="form-group mb-3">
<label for="remove">排除节点:</label>
<input
class="form-control"
type="text"
name="remove"
id="remove"
placeholder="正则表达式"
/>
</div>
<!-- Rename -->
<div class="form-group mb-3" id="replaceGroup">
<label>节点名称替换:</label>
<button
class="btn btn-primary mb-1 btn-xs"
onclick="addReplace()"
type="button"
>
+
</button>
</div>
<!-- Display the API Link --> <!-- Display the API Link -->
<div class="form-group mb-5"> <div class="form-group mb-5">
<label for="apiLink">配置链接:</label> <label for="apiLink">配置链接:</label>
<div class="input-group mb-2"> <div class="input-group mb-2">
<input <input class="form-control" id="apiLink" readonly type="text" />
class="form-control" <button class="btn btn-primary" onclick="generateURL()" type="button">
id="apiLink" 生成链接
readonly </button>
type="text" <button class="btn btn-primary" onclick="copyToClipboard('apiLink',this)" type="button">
/> 复制链接
<button </button>
class="btn btn-primary" </div>
onclick="generateURL()" <div class="input-group">
type="button" <input class="form-control" id="apiShortLink" readonly type="text" />
> <input class="form-control" id="password" type="text" placeholder="密码" />
生成链接 <button class="btn btn-primary" onclick="generateShortLink()" type="button">
</button> 生成短链
<button </button>
class="btn btn-primary" <button class="btn btn-primary" onclick="copyToClipboard('apiShortLink',this)" type="button">
onclick="copyToClipboard('apiLink',this)" 复制短链
type="button" </button>
> </div>
复制链接
</button>
</div>
<div class="input-group">
<input
class="form-control"
id="apiShortLink"
readonly
type="text"
/>
<input
class="form-control"
id="password"
type="text"
placeholder="密码"
/>
<button
class="btn btn-primary"
onclick="generateShortLink()"
type="button"
>
生成短链
</button>
<button
class="btn btn-primary"
onclick="copyToClipboard('apiShortLink',this)"
type="button"
>
复制短链
</button>
</div> </div>
<!-- footer-->
<footer>
<p class="text-center">
Powered by
<a class="link-primary" href="https://github.com/nitezs/sub2clash">sub2clash</a>
</p>
<p class="text-center">Version {{.Version}}</p>
</footer>
</div> </div>
<!-- footer-->
<footer>
<p class="text-center">
Powered by
<a
class="link-primary"
href="https://github.com/nitezs/sub2clash"
>sub2clash</a
>
</p>
<p class="text-center">Version {{.Version}}</p>
</footer>
</div>
</body> </body>
</html> </html>

View File

@ -6,6 +6,7 @@ function clearExistingValues() {
document.getElementById("refresh").checked = false; document.getElementById("refresh").checked = false;
document.getElementById("autoTest").checked = false; document.getElementById("autoTest").checked = false;
document.getElementById("lazy").checked = false; document.getElementById("lazy").checked = false;
document.getElementById("igcg").checked = false;
document.getElementById("template").value = ""; document.getElementById("template").value = "";
document.getElementById("sort").value = "nameasc"; document.getElementById("sort").value = "nameasc";
document.getElementById("remove").value = ""; document.getElementById("remove").value = "";
@ -74,6 +75,8 @@ function generateURI() {
queryParams.push(`lazy=${lazy ? "true" : "false"}`); queryParams.push(`lazy=${lazy ? "true" : "false"}`);
const nodeList = document.getElementById("nodeList").checked; const nodeList = document.getElementById("nodeList").checked;
queryParams.push(`nodeList=${nodeList ? "true" : "false"}`); queryParams.push(`nodeList=${nodeList ? "true" : "false"}`);
const igcg = document.getElementById("igcg").checked;
queryParams.push(`ignoreCountryGroup=${igcg ? "true" : "false"}`);
// 获取模板链接或名称(如果存在) // 获取模板链接或名称(如果存在)
const template = document.getElementById("template").value; const template = document.getElementById("template").value;

View File

@ -65,17 +65,11 @@ func AddProxy(
countryName := GetContryName(proxy.Name) countryName := GetContryName(proxy.Name)
for i := range sub.ProxyGroups { for i := range sub.ProxyGroups {
group := &sub.ProxyGroups[i] group := &sub.ProxyGroups[i]
if group.Name == countryName { if group.Name == countryName {
group.Proxies = append(group.Proxies, proxy.Name) group.Proxies = append(group.Proxies, proxy.Name)
group.Size++ group.Size++
haveProxyGroup = true haveProxyGroup = true
} }
if group.Name == "手动切换" {
group.Proxies = append(group.Proxies, proxy.Name)
group.Size++
}
} }
if !haveProxyGroup { if !haveProxyGroup {
var newGroup model.ProxyGroup var newGroup model.ProxyGroup

View File

@ -81,8 +81,5 @@ func FetchSubscriptionFromAPI(url string) ([]byte, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to write to sub.yaml: %w", err) return nil, fmt.Errorf("failed to write to sub.yaml: %w", err)
} }
if err != nil {
return nil, fmt.Errorf("failed to unmarshal yaml: %w", err)
}
return data, nil return data, nil
} }

View File

@ -25,9 +25,6 @@ func LoadTemplate(template string) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err != nil {
return nil, err
}
return result, nil return result, nil
} }
return nil, errors.New("模板文件不存在") return nil, errors.New("模板文件不存在")

View File

@ -12,24 +12,25 @@ import (
) )
type SubValidator struct { type SubValidator struct {
Sub string `form:"sub" binding:""` Sub string `form:"sub" binding:""`
Subs []string `form:"-" binding:""` Subs []string `form:"-" binding:""`
Proxy string `form:"proxy" binding:""` Proxy string `form:"proxy" binding:""`
Proxies []string `form:"-" binding:""` Proxies []string `form:"-" binding:""`
Refresh bool `form:"refresh,default=false" binding:""` Refresh bool `form:"refresh,default=false" binding:""`
Template string `form:"template" binding:""` Template string `form:"template" binding:""`
RuleProvider string `form:"ruleProvider" binding:""` RuleProvider string `form:"ruleProvider" binding:""`
RuleProviders []RuleProviderStruct `form:"-" binding:""` RuleProviders []RuleProviderStruct `form:"-" binding:""`
Rule string `form:"rule" binding:""` Rule string `form:"rule" binding:""`
Rules []RuleStruct `form:"-" binding:""` Rules []RuleStruct `form:"-" binding:""`
AutoTest bool `form:"autoTest,default=false" binding:""` AutoTest bool `form:"autoTest,default=false" binding:""`
Lazy bool `form:"lazy,default=false" binding:""` Lazy bool `form:"lazy,default=false" binding:""`
Sort string `form:"sort" binding:""` Sort string `form:"sort" binding:""`
Remove string `form:"remove" binding:""` Remove string `form:"remove" binding:""`
Replace string `form:"replace" binding:""` Replace string `form:"replace" binding:""`
ReplaceKeys []string `form:"-" binding:""` ReplaceKeys []string `form:"-" binding:""`
ReplaceTo []string `form:"-" binding:""` ReplaceTo []string `form:"-" binding:""`
NodeListMode bool `form:"nodeList,default=false" binding:""` NodeListMode bool `form:"nodeList,default=false" binding:""`
IgnoreCountryGrooup bool `form:"ignoreCountryGroup,default=false" binding:""`
} }
type RuleProviderStruct struct { type RuleProviderStruct struct {