fix: 修复当订阅链接有多个 clash 配置时丢失节点的问题
update: 增加检测更新
modify: 修改数据库路径
modify: 修改短链生成逻辑
modify: 统一输出信息
This commit is contained in:
Nite07
2023-09-21 09:08:02 +08:00
committed by GitHub
parent f166c6a54a
commit 8d06ab3175
27 changed files with 588 additions and 349 deletions

View File

@ -7,6 +7,7 @@ import (
"gopkg.in/yaml.v3"
"net/url"
"regexp"
"sort"
"strings"
"sub2clash/model"
"sub2clash/parser"
@ -43,6 +44,7 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template
if err != nil {
return nil, errors.New("解析模板失败: " + err.Error())
}
var proxyList []model.Proxy
// 加载订阅
for i := range query.Subs {
data, err := utils.LoadSubscription(query.Subs[i], query.Refresh)
@ -50,31 +52,49 @@ func BuildSub(clashType model.ClashType, query validator.SubValidator, template
return nil, errors.New("加载订阅失败: " + err.Error())
}
// 解析订阅
var proxyList []model.Proxy
err = yaml.Unmarshal(data, &sub)
if err != nil {
reg, _ := regexp.Compile("(ssr|ss|vmess|trojan|http|https)://")
if reg.Match(data) {
proxyList = utils.ParseProxy(strings.Split(string(data), "\n")...)
p := utils.ParseProxy(strings.Split(string(data), "\n")...)
proxyList = append(proxyList, p...)
} else {
// 如果无法直接解析尝试Base64解码
base64, err := parser.DecodeBase64(string(data))
if err != nil {
return nil, errors.New("加载订阅失败: " + err.Error())
}
proxyList = utils.ParseProxy(strings.Split(base64, "\n")...)
p := utils.ParseProxy(strings.Split(base64, "\n")...)
proxyList = append(proxyList, p...)
}
} else {
proxyList = sub.Proxies
proxyList = append(proxyList, sub.Proxies...)
}
utils.AddProxy(sub, query.AutoTest, query.Lazy, query.Sort, clashType, proxyList...)
}
// 将新增节点都添加到临时变量 t 中,防止策略组排序错乱
var t = &model.Subscription{}
utils.AddProxy(t, query.AutoTest, query.Lazy, clashType, proxyList...)
// 处理自定义代理
utils.AddProxy(
sub, query.AutoTest, query.Lazy, query.Sort, clashType,
t, query.AutoTest, query.Lazy, clashType,
utils.ParseProxy(query.Proxies...)...,
)
MergeSubAndTemplate(temp, sub)
// 排序策略组
switch query.Sort {
case "sizeasc":
sort.Sort(model.ProxyGroupsSortBySize(t.ProxyGroups))
case "sizedesc":
sort.Sort(sort.Reverse(model.ProxyGroupsSortBySize(t.ProxyGroups)))
case "nameasc":
sort.Sort(model.ProxyGroupsSortByName(t.ProxyGroups))
case "namedesc":
sort.Sort(sort.Reverse(model.ProxyGroupsSortByName(t.ProxyGroups)))
default:
sort.Sort(model.ProxyGroupsSortByName(t.ProxyGroups))
}
// 合并新节点和模板
MergeSubAndTemplate(temp, t)
// 处理自定义规则
for _, v := range query.Rules {
if v.Prepend {

View File

@ -1,12 +1,14 @@
package controller
import (
"crypto/sha256"
"encoding/hex"
"errors"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"net/http"
"strings"
"sub2clash/config"
"sub2clash/model"
"sub2clash/utils"
"sub2clash/utils/database"
"sub2clash/validator"
"time"
@ -18,12 +20,32 @@ func ShortLinkGenHandler(c *gin.Context) {
if err := c.ShouldBind(&params); err != nil {
c.String(400, "参数错误: "+err.Error())
}
// 生成短链接
//hash := utils.RandomString(6)
shortLink := sha256.Sum224([]byte(params.Url))
hash := hex.EncodeToString(shortLink[:])
if strings.TrimSpace(params.Url) == "" {
c.String(400, "参数错误")
return
}
// 生成hash
hash := utils.RandomString(config.Default.ShortLinkLength)
// 存入数据库
database.DB.FirstOrCreate(
var item model.ShortLink
result := database.FindShortLinkByUrl(params.Url, &item)
if result.Error == nil {
c.String(200, item.Hash)
return
} else {
if !errors.Is(result.Error, gorm.ErrRecordNotFound) {
c.String(500, "数据库错误: "+result.Error.Error())
return
}
}
// 如果记录存在则重新生成hash直到记录不存在
result = database.FindShortLinkByHash(hash, &item)
for result.Error == nil {
hash = utils.RandomString(config.Default.ShortLinkLength)
result = database.FindShortLinkByHash(hash, &item)
}
// 创建记录
database.FirstOrCreateShortLink(
&model.ShortLink{
Hash: hash,
Url: params.Url,
@ -37,17 +59,21 @@ func ShortLinkGenHandler(c *gin.Context) {
func ShortLinkGetHandler(c *gin.Context) {
// 获取动态路由
hash := c.Param("hash")
if strings.TrimSpace(hash) == "" {
c.String(400, "参数错误")
return
}
// 查询数据库
var shortLink model.ShortLink
result := database.DB.Where("hash = ?", hash).First(&shortLink)
// 更新最后访问时间
shortLink.LastRequestTime = time.Now().Unix()
database.DB.Save(&shortLink)
result := database.FindShortLinkByHash(hash, &shortLink)
// 重定向
if result.Error != nil {
c.String(404, "未找到短链接")
return
}
// 更新最后访问时间
shortLink.LastRequestTime = time.Now().Unix()
database.SaveShortLink(&shortLink)
uri := config.Default.BasePath + shortLink.Url
c.Redirect(http.StatusTemporaryRedirect, uri)
}