Skip to content

Commit e234d1f

Browse files
committed
feat(scripts): 添加脚本和模板使用情况检查功能防止误删
1 parent d22b0f5 commit e234d1f

File tree

8 files changed

+347
-16
lines changed

8 files changed

+347
-16
lines changed

api/script.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package api
22

33
import (
44
"strconv"
5+
"sublink/database"
56
"sublink/models"
67
"sublink/utils"
78

@@ -49,6 +50,55 @@ func ScriptDel(c *gin.Context) {
4950
utils.OkWithMsg(c, "删除成功")
5051
}
5152

53+
func GetScriptUsage(c *gin.Context) {
54+
scriptIDStr := c.Query("id")
55+
if scriptIDStr == "" {
56+
utils.FailWithMsg(c, "脚本ID不能为空")
57+
return
58+
}
59+
60+
scriptID, err := strconv.Atoi(scriptIDStr)
61+
if err != nil || scriptID <= 0 {
62+
utils.FailWithMsg(c, "脚本ID非法")
63+
return
64+
}
65+
66+
var subScripts []models.SubcriptionScript
67+
if err := database.DB.Where("script_id = ?", scriptID).Find(&subScripts).Error; err != nil {
68+
utils.FailWithMsg(c, "获取脚本使用情况失败")
69+
return
70+
}
71+
72+
if len(subScripts) == 0 {
73+
utils.OkWithData(c, gin.H{
74+
"subscriptions": []string{},
75+
"count": 0,
76+
})
77+
return
78+
}
79+
80+
subIDs := make([]int, 0, len(subScripts))
81+
for _, subScript := range subScripts {
82+
subIDs = append(subIDs, subScript.SubcriptionID)
83+
}
84+
85+
var subs []models.Subcription
86+
if err := database.DB.Where("id IN ?", subIDs).Find(&subs).Error; err != nil {
87+
utils.FailWithMsg(c, "获取脚本使用情况失败")
88+
return
89+
}
90+
91+
usedBy := make([]string, 0, len(subs))
92+
for _, sub := range subs {
93+
usedBy = append(usedBy, sub.Name)
94+
}
95+
96+
utils.OkWithData(c, gin.H{
97+
"subscriptions": usedBy,
98+
"count": len(usedBy),
99+
})
100+
}
101+
52102
// ScriptUpdate 更新脚本
53103
func ScriptUpdate(c *gin.Context) {
54104
var data models.Script

api/template.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package api
22

33
import (
4+
"encoding/json"
45
"errors"
56
"os"
67
"path/filepath"
78
"strconv"
89
"strings"
910
"sublink/cache"
11+
"sublink/database"
1012
"sublink/models"
1113
"sublink/utils"
1214

@@ -459,6 +461,79 @@ func DelTemp(c *gin.Context) {
459461
utils.OkWithMsg(c, "删除成功")
460462
}
461463

464+
func normalizeTemplateUsageValue(value string) string {
465+
return strings.ReplaceAll(strings.TrimSpace(value), "\\", "/")
466+
}
467+
468+
func buildTemplateMatchValues(filename string) map[string]struct{} {
469+
normalizedFile := normalizeTemplateUsageValue(filename)
470+
fileName := filepath.Base(normalizedFile)
471+
values := []string{normalizedFile, fileName, "./template/" + fileName, "/template/" + fileName}
472+
matchValues := make(map[string]struct{}, len(values))
473+
for _, value := range values {
474+
value = normalizeTemplateUsageValue(value)
475+
if value == "" {
476+
continue
477+
}
478+
matchValues[value] = struct{}{}
479+
}
480+
return matchValues
481+
}
482+
483+
func getTemplateUsageSubscriptions(filename string) ([]string, error) {
484+
var subs []models.Subcription
485+
if err := database.DB.Find(&subs).Error; err != nil {
486+
return nil, err
487+
}
488+
489+
matchValues := buildTemplateMatchValues(filename)
490+
usedBy := make([]string, 0)
491+
492+
for _, sub := range subs {
493+
var config struct {
494+
Clash string `json:"clash"`
495+
Surge string `json:"surge"`
496+
}
497+
498+
if sub.Config != "" {
499+
if err := json.Unmarshal([]byte(sub.Config), &config); err != nil {
500+
continue
501+
}
502+
}
503+
504+
clashValue := normalizeTemplateUsageValue(config.Clash)
505+
surgeValue := normalizeTemplateUsageValue(config.Surge)
506+
if _, ok := matchValues[clashValue]; ok {
507+
usedBy = append(usedBy, sub.Name)
508+
continue
509+
}
510+
if _, ok := matchValues[surgeValue]; ok {
511+
usedBy = append(usedBy, sub.Name)
512+
}
513+
}
514+
515+
return usedBy, nil
516+
}
517+
518+
func GetTemplateUsage(c *gin.Context) {
519+
filename := c.Query("filename")
520+
if filename == "" {
521+
utils.FailWithMsg(c, "文件名不能为空")
522+
return
523+
}
524+
525+
usedBy, err := getTemplateUsageSubscriptions(filename)
526+
if err != nil {
527+
utils.FailWithMsg(c, "获取模板使用情况失败")
528+
return
529+
}
530+
531+
utils.OkWithData(c, gin.H{
532+
"subscriptions": usedBy,
533+
"count": len(usedBy),
534+
})
535+
}
536+
462537
// ACL4SSRPreset ACL4SSR 规则预设
463538
type ACL4SSRPreset struct {
464539
Name string `json:"name"`

routers/script.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func Script(r *gin.Engine) {
1515
ScriptGroup.POST("/add", middlewares.DemoModeRestrict, api.ScriptAdd)
1616
ScriptGroup.DELETE("/delete", middlewares.DemoModeRestrict, api.ScriptDel)
1717
ScriptGroup.POST("/update", middlewares.DemoModeRestrict, api.ScriptUpdate)
18+
ScriptGroup.GET("/usage", api.GetScriptUsage)
1819
ScriptGroup.GET("/list", api.ScriptList)
1920
}
2021
}

routers/template.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ func Templates(r *gin.Engine) {
1313
{
1414
TempsGroup.POST("/add", api.AddTemp)
1515
TempsGroup.POST("/delete", api.DelTemp)
16+
TempsGroup.GET("/usage", api.GetTemplateUsage)
1617
TempsGroup.GET("/get", api.GetTempS)
1718
TempsGroup.POST("/update", api.UpdateTemp)
1819
TempsGroup.GET("/presets", api.GetACL4SSRPresets)

webs/src/api/scripts.js

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webs/src/api/templates.js

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webs/src/views/scripts/index.jsx

Lines changed: 102 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)