mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-06-28 18:51:25 +08:00
feat: add preset rule import functionality and update related messages
This commit is contained in:
55
pkg/rule/preset.go
Normal file
55
pkg/rule/preset.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package rule
|
||||
|
||||
import "path"
|
||||
|
||||
// PresetCategory describes a built-in filetype classification: files whose name
|
||||
// matches Regex are routed into the Dir subdirectory (joined with a user base path).
|
||||
type PresetCategory struct {
|
||||
// Name is a stable identifier for the category (used in logs/messages).
|
||||
Name string
|
||||
// Regex is a FILENAME-REGEX rule data string matching this category's extensions.
|
||||
Regex string
|
||||
// Dir is the default subdirectory name for this category.
|
||||
Dir string
|
||||
}
|
||||
|
||||
// presetCategories holds the default filetype classification rules.
|
||||
// Regexes are case-insensitive and match common file extensions.
|
||||
var presetCategories = []PresetCategory{
|
||||
{
|
||||
Name: "video",
|
||||
Regex: `(?i)\.(mp4|mkv|ts|avi|flv|mov|webm|wmv|rmvb|m2ts)$`,
|
||||
Dir: "视频",
|
||||
},
|
||||
{
|
||||
Name: "image",
|
||||
Regex: `(?i)\.(jpg|jpeg|png|gif|webp|bmp)$`,
|
||||
Dir: "图片",
|
||||
},
|
||||
{
|
||||
Name: "audio",
|
||||
Regex: `(?i)\.(mp3|flac|wav|aac|m4a|ogg)$`,
|
||||
Dir: "音频",
|
||||
},
|
||||
{
|
||||
Name: "document",
|
||||
Regex: `(?i)\.(pdf|doc|docx|xls|xlsx|ppt|pptx|txt|md|csv|epub|mobi|azw3|chm)$`,
|
||||
Dir: "文档",
|
||||
},
|
||||
{
|
||||
Name: "archive",
|
||||
Regex: `(?i)\.(zip|rar|7z|tar|gz|bz2|xz|r\d{1,3}|z\d{1,3}|\d{3}|part\d+\.rar|7z\.\d{3})$`,
|
||||
Dir: "压缩包",
|
||||
},
|
||||
}
|
||||
|
||||
// PresetCategories returns the built-in filetype classification rules with each
|
||||
// category's directory joined under basePath. basePath may be empty.
|
||||
func PresetCategories(basePath string) []PresetCategory {
|
||||
out := make([]PresetCategory, len(presetCategories))
|
||||
for i, c := range presetCategories {
|
||||
c.Dir = path.Join(basePath, c.Dir)
|
||||
out[i] = c
|
||||
}
|
||||
return out
|
||||
}
|
||||
55
pkg/rule/preset_test.go
Normal file
55
pkg/rule/preset_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package rule
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPresetCategoriesCompile(t *testing.T) {
|
||||
for _, c := range PresetCategories("") {
|
||||
if _, err := regexp.Compile(c.Regex); err != nil {
|
||||
t.Errorf("preset %q has invalid regex %q: %v", c.Name, c.Regex, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPresetCategoriesMatch(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"video": "movie.MP4",
|
||||
"image": "photo.jpg",
|
||||
"audio": "song.flac",
|
||||
"document": "report.pdf",
|
||||
"archive": "backup.zip",
|
||||
}
|
||||
|
||||
byName := make(map[string]*regexp.Regexp)
|
||||
for _, c := range PresetCategories("") {
|
||||
byName[c.Name] = regexp.MustCompile(c.Regex)
|
||||
}
|
||||
|
||||
for name, filename := range cases {
|
||||
re, ok := byName[name]
|
||||
if !ok {
|
||||
t.Errorf("missing preset category %q", name)
|
||||
continue
|
||||
}
|
||||
if !re.MatchString(filename) {
|
||||
t.Errorf("preset %q did not match %q", name, filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPresetCategoriesBasePath(t *testing.T) {
|
||||
presets := PresetCategories("/media")
|
||||
for _, c := range presets {
|
||||
if c.Dir == "" || c.Dir[0] != '/' {
|
||||
t.Errorf("preset %q dir %q not joined under base path", c.Name, c.Dir)
|
||||
}
|
||||
}
|
||||
// Empty base path must not prefix a separator.
|
||||
for _, c := range PresetCategories("") {
|
||||
if c.Dir == "" || c.Dir[0] == '/' {
|
||||
t.Errorf("preset %q dir %q should be relative when base path empty", c.Name, c.Dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user