feat: 增加重复节点检测

feat: 增加节点名称字符串替换
feat: 增加节点删除
feat: 增加短链密码设定
modify: 修改模板解析逻辑
This commit is contained in:
2023-09-22 23:43:26 +08:00
parent 06c9858866
commit 2339b7d256
12 changed files with 225 additions and 39 deletions

View File

@ -9,6 +9,7 @@ import (
"net/url"
"regexp"
"sort"
"strconv"
"strings"
"sub2clash/logger"
"sub2clash/model"
@ -88,6 +89,46 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template
proxyList = append(proxyList, sub.Proxies...)
}
}
// 去重
proxies := make(map[string]*model.Proxy)
for i := range proxyList {
key := proxyList[i].Server + ":" + strconv.Itoa(proxyList[i].Port) + ":" + proxyList[i].Type
if _, exist := proxies[key]; exist {
proxyList = append(proxyList[:i], proxyList[i+1:]...)
}
}
// 重名检测
names := make(map[string]bool)
for i := range proxyList {
if _, exist := names[proxyList[i].Name]; exist {
proxyList[i].Name = proxyList[i].Name + "@" + proxyList[i].Server + ":" + strconv.Itoa(proxyList[i].Port)
}
names[proxyList[i].Name] = true
}
// 删除节点、改名
if strings.TrimSpace(query.Remove) != "" {
removeReg, err := regexp.Compile(query.Remove)
if err != nil {
logger.Logger.Debug("remove regexp compile failed", zap.Error(err))
return nil, errors.New("remove 参数非法: " + err.Error())
}
replaceReg, err := regexp.Compile(query.ReplaceKey)
if err != nil {
logger.Logger.Debug("replace regexp compile failed", zap.Error(err))
return nil, errors.New("replaceName 参数非法: " + err.Error())
}
newProxyList := make([]model.Proxy, 0, len(proxyList))
for i := range proxyList {
if removeReg.MatchString(proxyList[i].Name) {
continue // 如果匹配到要删除的元素,跳过该元素,不添加到新切片中
}
if replaceReg.MatchString(proxyList[i].Name) {
proxyList[i].Name = replaceReg.ReplaceAllString(proxyList[i].Name, query.ReplaceTo)
}
newProxyList = append(newProxyList, proxyList[i]) // 将要保留的元素添加到新切片中
}
proxyList = newProxyList
}
// 将新增节点都添加到临时变量 t 中,防止策略组排序错乱
var t = &model.Subscription{}
utils.AddProxy(t, query.AutoTest, query.Lazy, clashType, proxyList...)
@ -154,28 +195,28 @@ func MergeSubAndTemplate(temp *model.Subscription, sub *model.Subscription) {
)
}
}
var proxyNames []string
for _, proxy := range sub.Proxies {
proxyNames = append(proxyNames, proxy.Name)
}
// 将订阅中的节点添加到模板中
temp.Proxies = append(temp.Proxies, sub.Proxies...)
// 将订阅中的策略组添加到模板中
skipGroups := []string{"全球直连", "广告拦截", "手动切换"}
for i := range temp.ProxyGroups {
skip := false
for _, v := range skipGroups {
if strings.Contains(temp.ProxyGroups[i].Name, v) {
if v == "手动切换" {
proxies := make([]string, 0, len(sub.Proxies))
for _, p := range sub.Proxies {
proxies = append(proxies, p.Name)
}
temp.ProxyGroups[i].Proxies = proxies
}
skip = true
continue
if temp.ProxyGroups[i].IsCountryGrop {
continue
}
newProxies := make([]string, 0, len(temp.ProxyGroups[i].Proxies))
for j := range temp.ProxyGroups[i].Proxies {
if temp.ProxyGroups[i].Proxies[j] == "<all>" {
newProxies = append(newProxies, proxyNames...)
} else if temp.ProxyGroups[i].Proxies[j] == "<countries>" {
newProxies = append(newProxies, countryGroupNames...)
} else {
newProxies = append(newProxies, temp.ProxyGroups[i].Proxies[j])
}
}
if !skip {
temp.ProxyGroups[i].Proxies = append(temp.ProxyGroups[i].Proxies, countryGroupNames...)
}
temp.ProxyGroups[i].Proxies = newProxies
}
temp.ProxyGroups = append(temp.ProxyGroups, sub.ProxyGroups...)
}

View File

@ -50,15 +50,20 @@ func ShortLinkGenHandler(c *gin.Context) {
Hash: hash,
Url: params.Url,
LastRequestTime: -1,
Password: params.Password,
},
)
// 返回短链接
if params.Password != "" {
hash += "/?password=" + params.Password
}
c.String(200, hash)
}
func ShortLinkGetHandler(c *gin.Context) {
// 获取动态路由
hash := c.Param("hash")
password := c.Query("password")
if strings.TrimSpace(hash) == "" {
c.String(400, "参数错误")
return
@ -71,6 +76,10 @@ func ShortLinkGetHandler(c *gin.Context) {
c.String(404, "未找到短链接")
return
}
if shortLink.Password != "" && shortLink.Password != password {
c.String(403, "密码错误")
return
}
// 更新最后访问时间
shortLink.LastRequestTime = time.Now().Unix()
database.SaveShortLink(&shortLink)

View File

@ -168,6 +168,39 @@
<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">
<label for="replaceKey">替换节点名称:</label>
<div class="input-group mb-2">
<input
class="form-control"
type="text"
name="replace"
id="replaceKey"
placeholder="原字符串(正则表达式)"
/>
<input
class="form-control"
type="text"
name="replace"
id="replaceTo"
placeholder="替换为"
/>
</div>
</div>
</form>
<!-- Display the API Link -->
@ -188,6 +221,12 @@
</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()"
@ -382,6 +421,24 @@
// 获取排序策略
const sort = document.getElementById("sort").value;
queryParams.push(`sort=${sort}`);
// 获取删除节点的正则表达式
const remove = document.getElementById("remove").value;
if (remove.trim() !== "") {
queryParams.push(`remove=${encodeURIComponent(remove)}`);
}
// 获取替换节点名称的正则表达式
const replaceKey = document.getElementById("replaceKey").value;
const replaceTo = document.getElementById("replaceTo").value;
if (replaceKey.trim() !== "" && replaceTo.trim() !== "") {
queryParams.push(
`replace=[${encodeURIComponent(replaceKey)},${encodeURIComponent(
replaceTo,
)}]`,
);
}
return `${endpoint}?${queryParams.join("&")}`;
}
@ -396,6 +453,7 @@
function generateShortLink() {
const apiShortLink = document.getElementById("apiShortLink");
const password = document.getElementById("password");
let uri = generateURI();
if (uri === "") {
return;
@ -405,6 +463,7 @@
"./short",
{
url: uri,
password: password.value.trim(),
},
{
headers: {