Skip to content

Commit

Permalink
fix: 修复当订阅链接有多个 clash 配置时丢失节点的问题
Browse files Browse the repository at this point in the history
modify: 修改数据库路径
modify: 修改短链生成逻辑
update: 增加检测更新

modify: 统一输出信息为英文
update: 修改 Dockerfile

fix: 修改 docker.yml

modify: 调整代码结构
  • Loading branch information
nitezs committed Sep 20, 2023
1 parent be9bdd2 commit fce2d2e
Show file tree
Hide file tree
Showing 29 changed files with 307 additions and 206 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ CLASH_TEMPLATE=clash_template.json
REQUEST_RETRY_TIMES=3
REQUEST_MAX_FILE_SIZE=1048576
CACHE_EXPIRE=300
LOG_LEVEL=info
LOG_LEVEL=info
BASE_PATH=/
6 changes: 6 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ jobs:
with:
context: .
file: ./Dockerfile
build-args: |
dev=true
version=${{ github.sha }}
push: true
tags: ghcr.io/${{ github.repository }}:${{ steps.set_tag.outputs.tag }}

Expand All @@ -56,6 +59,9 @@ jobs:
with:
context: .
file: ./Dockerfile
build-args: |
dev=false
version=${{ steps.set_tag.outputs.tag }}
push: true
tags: |
ghcr.io/${{ github.repository }}:${{ steps.set_tag.outputs.tag }}
Expand Down
46 changes: 1 addition & 45 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,18 @@ jobs:

- name: Build
run: |
LDFLAGS="-s -w"
LDFLAGS="-s -w -X config.Version=${{ github.ref_name }}"
# Linux
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags="$LDFLAGS" -o output/sub2clash-linux-386 main.go
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="$LDFLAGS" -o output/sub2clash-linux-amd64 main.go
CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags="$LDFLAGS" -o output/sub2clash-linux-arm main.go
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="$LDFLAGS" -o output/sub2clash-linux-arm64 main.go
# Darwin
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="$LDFLAGS" -o output/sub2clash-darwin-amd64 main.go
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="$LDFLAGS" -o output/sub2clash-darwin-arm64 main.go
# Windows
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="$LDFLAGS" -o output/sub2clash-windows-386.exe main.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="$LDFLAGS" -o output/sub2clash-windows-amd64.exe main.go
CGO_ENABLED=0 GOOS=windows GOARCH=arm go build -ldflags="$LDFLAGS" -o output/sub2clash-windows-arm.exe main.go
CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -ldflags="$LDFLAGS" -o output/sub2clash-windows-arm64.exe main.go
- name: Create Release
Expand All @@ -52,16 +48,6 @@ jobs:
draft: false
prerelease: false

- name: Upload Release Asset (Linux 386)
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/sub2clash-linux-386
asset_name: sub2clash-linux-386
asset_content_type: application/octet-stream

- name: Upload Release Asset (Linux amd64)
uses: actions/upload-release-asset@v1
env:
Expand All @@ -72,16 +58,6 @@ jobs:
asset_name: sub2clash-linux-amd64
asset_content_type: application/octet-stream

- name: Upload Release Asset (Linux arm)
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/sub2clash-linux-arm
asset_name: sub2clash-linux-arm
asset_content_type: application/octet-stream

- name: Upload Release Asset (Linux arm64)
uses: actions/upload-release-asset@v1
env:
Expand Down Expand Up @@ -112,16 +88,6 @@ jobs:
asset_name: sub2clash-darwin-arm64
asset_content_type: application/octet-stream

- name: Upload Release Asset (Windows 386)
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/sub2clash-windows-386.exe
asset_name: sub2clash-windows-386.exe
asset_content_type: application/octet-stream

- name: Upload Release Asset (Windows amd64)
uses: actions/upload-release-asset@v1
env:
Expand All @@ -132,16 +98,6 @@ jobs:
asset_name: sub2clash-windows-amd64.exe
asset_content_type: application/octet-stream

- name: Upload Release Asset (Windows arm)
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./output/sub2clash-windows-arm.exe
asset_name: sub2clash-windows-arm.exe
asset_content_type: application/octet-stream

- name: Upload Release Asset (Windows arm64)
uses: actions/upload-release-asset@v1
env:
Expand Down
4 changes: 1 addition & 3 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ builds:
- darwin
goarch:
- amd64
- arm
- arm64
- 386
ldflags:
- -s -w
- -s -w -X sub2clash/config.Version={{ .Version }}
no_unique_dist_dir: true
binary: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}"
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ WORKDIR /app
COPY . .
RUN go mod download

# 获取参数
ARG version
ARG dev

# 使用 -ldflags 参数进行编译
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o sub2clash main.go
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X sub2clash/config.Version=${version} -X sub2clash/config.Dev=${dev}" -o sub2clash main.go

FROM alpine:latest

Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@

可以通过编辑 .env 文件来修改默认配置,docker 直接添加环境变量

| 变量名 | 说明 | 默认值 |
|-----------------------|----------------------------------------|-----------------------|
| PORT | 端口 | `8011` |
| META_TEMPLATE | meta 模板文件名 | `template_meta.yaml` |
| CLASH_TEMPLATE | clash 模板文件名 | `template_clash.yaml` |
| REQUEST_RETRY_TIMES | Get 请求重试次数 | `3` |
| REQUEST_MAX_FILE_SIZE | Get 请求订阅文件最大大小(byte) | `1048576` |
| CACHE_EXPIRE | 订阅缓存时间(秒) | `300` |
| LOG_LEVEL | 日志等级,可选值 `debug`,`info`,`warn`,`error` | `info` |
| 变量名 | 说明 | 默认值 |
|-----------------------|-----------------------------------------------------------|-----------------------|
| BASE_PATH | 程序运行子路径,例如将服务反代在 `https://example.com/sub` 则此变量值应为 `/sub` | `/` |
| PORT | 端口 | `8011` |
| META_TEMPLATE | meta 模板文件名 | `template_meta.yaml` |
| CLASH_TEMPLATE | clash 模板文件名 | `template_clash.yaml` |
| REQUEST_RETRY_TIMES | Get 请求重试次数 | `3` |
| REQUEST_MAX_FILE_SIZE | Get 请求订阅文件最大大小(byte) | `1048576` |
| CACHE_EXPIRE | 订阅缓存时间(秒) | `300` |
| LOG_LEVEL | 日志等级,可选值 `debug`,`info`,`warn`,`error` | `info` |
| SHORT_LINK_LENGTH | 短链长度 | `6` |

### API

Expand Down Expand Up @@ -63,5 +65,3 @@
[代理链接解析](./parser)还没有经过严格测试,可能会出现解析错误的情况,如果出现问题请提交 issue

## TODO

- [x] 可视化面板
34 changes: 27 additions & 7 deletions api/controller/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"gopkg.in/yaml.v3"
"net/url"
"regexp"
"sort"
"strings"
"sub2clash/model"
"sub2clash/parser"
Expand Down Expand Up @@ -43,38 +44,57 @@ 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)
if err != nil {
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 {
Expand Down
40 changes: 30 additions & 10 deletions api/controller/short_link.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package controller

import (
"crypto/sha256"
"encoding/hex"
"errors"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"net/http"
"sub2clash/config"
"sub2clash/model"
"sub2clash/utils"
"sub2clash/utils/database"
"sub2clash/validator"
"time"
Expand All @@ -16,11 +19,27 @@ 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[:])
// 生成hash
hash := utils.RandomString(config.Default.ShortLinkLength)
// 存入数据库
var item model.ShortLink
result := database.DB.Model(&model.ShortLink{}).Where("url = ?", params.Url).First(&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.DB.Model(&model.ShortLink{}).Where("hash = ?", hash).First(&item)
for result.Error == nil {
hash = utils.RandomString(config.Default.ShortLinkLength)
result = database.DB.Model(&model.ShortLink{}).Where("hash = ?", hash).First(&item)
}
// 创建记录
database.DB.FirstOrCreate(
&model.ShortLink{
Hash: hash,
Expand All @@ -38,13 +57,14 @@ func ShortLinkGetHandler(c *gin.Context) {
// 查询数据库
var shortLink model.ShortLink
result := database.DB.Where("hash = ?", hash).First(&shortLink)
// 更新最后访问时间
shortLink.LastRequestTime = time.Now().Unix()
database.DB.Save(&shortLink)
// 重定向
if result.Error != nil {
c.String(404, "未找到短链接")
return
}
c.Redirect(302, "/"+shortLink.Url)
// 更新最后访问时间
shortLink.LastRequestTime = time.Now().Unix()
database.DB.Save(&shortLink)
uri := config.Default.BasePath + shortLink.Url
c.Redirect(http.StatusTemporaryRedirect, uri)
}
7 changes: 6 additions & 1 deletion api/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/gin-gonic/gin"
"html/template"
"sub2clash/api/controller"
"sub2clash/config"
"sub2clash/middleware"
)

Expand All @@ -17,7 +18,11 @@ func SetRoute(r *gin.Engine) {
r.SetHTMLTemplate(template.Must(template.New("").ParseFS(templates, "templates/*")))
r.GET(
"/", func(c *gin.Context) {
c.HTML(200, "index.html", nil)
c.HTML(
200, "index.html", gin.H{
"Version": config.Version,
},
)
},
)
r.GET(
Expand Down
7 changes: 4 additions & 3 deletions api/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ <h2>sub2clash</h2>
<!-- Auto Test -->
<div class="form-check mb-3">
<input type="checkbox" class="form-check-input" id="autoTest" name="autoTest">
<label class="form-check-label" for="autoTest">指定国家策略组是否自动测速</label>
<label class="form-check-label" for="autoTest">国家策略组自动测速</label>
</div>

<!-- Lazy -->
<div class="form-check mb-3">
<input type="checkbox" class="form-check-input" id="lazy" name="lazy">
<label class="form-check-label" for="lazy">自动测速是否启用 lazy</label>
<label class="form-check-label" for="lazy">自动测速启用 lazy</label>
</div>

<!-- Sort -->
Expand Down Expand Up @@ -136,6 +136,7 @@ <h2>sub2clash</h2>
<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>
Expand Down Expand Up @@ -298,7 +299,7 @@ <h2>sub2clash</h2>
function generateShortLink() {
const apiShortLink = document.getElementById("apiShortLink");

axios.post("/short", {
axios.post("./short", {
"url": generateURI()
}, {
headers: {
Expand Down
Loading

0 comments on commit fce2d2e

Please sign in to comment.