Skip to content

Commit

Permalink
feat: implement ApplyApiPathRule and update path handling in artwork …
Browse files Browse the repository at this point in the history
…and picture routes
  • Loading branch information
krau committed Jan 26, 2025
1 parent c8d46ab commit 81a54f9
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 16 deletions.
2 changes: 1 addition & 1 deletion adapter/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func ConvertToFeedItems(ctx context.Context, artworks []*types.Artwork) []*feeds
</article>
`,
html.EscapeString(artwork.Title),
html.EscapeString(common.ApplyPathRule(artwork.Pictures[0].StorageInfo.Regular.Path)),
html.EscapeString(common.ApplyApiPathRule(artwork.Pictures[0].StorageInfo.Regular.Path)),
html.EscapeString(artwork.Title),
html.EscapeString(artwork.Description),
html.EscapeString(artwork.Artist.Name),
Expand Down
2 changes: 1 addition & 1 deletion api/restful/routers/artwork/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func RandomArtworkPreview(ctx *gin.Context) {
case types.StorageTypeLocal:
ctx.File(picture.StorageInfo.Regular.Path)
case types.StorageTypeAlist:
ctx.Redirect(http.StatusFound, common.ApplyPathRule(picture.StorageInfo.Regular.Path))
ctx.Redirect(http.StatusFound, common.ApplyApiPathRule(picture.StorageInfo.Regular.Path))
default:
data, err := storage.GetFile(ctx, picture.StorageInfo.Regular)
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions api/restful/routers/artwork/response_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ func ResponseDataFromArtwork(artwork *types.Artwork) *ArtworkResponseData {
for i, picture := range artwork.Pictures {
var thumbnail, regular string
if picture.StorageInfo.Thumb.Type == types.StorageTypeAlist {
thumbnail = common.ApplyPathRule(picture.StorageInfo.Thumb.Path)
thumbnail = common.ApplyApiPathRule(picture.StorageInfo.Thumb.Path)
} else {
thumbnail = picture.Thumbnail
}
if picture.StorageInfo.Regular.Type == types.StorageTypeAlist {
regular = common.ApplyPathRule(picture.StorageInfo.Regular.Path)
regular = common.ApplyApiPathRule(picture.StorageInfo.Regular.Path)
} else {
regular = picture.Thumbnail
}
Expand Down
2 changes: 1 addition & 1 deletion api/restful/routers/picture/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func RandomPicture(ctx *gin.Context) {
case types.StorageTypeLocal:
ctx.File(picture.StorageInfo.Regular.Path)
case types.StorageTypeAlist:
ctx.Redirect(http.StatusFound, common.ApplyPathRule(picture.StorageInfo.Regular.Path))
ctx.Redirect(http.StatusFound, common.ApplyApiPathRule(picture.StorageInfo.Regular.Path))
default:
data, err := storage.GetFile(ctx, picture.StorageInfo.Regular)
if err != nil {
Expand Down
14 changes: 5 additions & 9 deletions common/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"encoding/hex"
"html"
"math/rand"
"net/url"
"path"
"regexp"
"strings"

Expand Down Expand Up @@ -125,16 +125,12 @@ func ExtractTagsFromText(text string) []string {
return tags
}

func ApplyPathRule(path string) string {
func ApplyApiPathRule(originPath string) string {
for _, rule := range config.Cfg.API.PathRules {
if strings.HasPrefix(path, rule.Path) {
parsedUrl, err := url.JoinPath(rule.JoinPrefix, strings.TrimPrefix(path, rule.TrimPrefix))
if err != nil {
Logger.Errorf("Failed to parse url: %s", err)
return rule.JoinPrefix + strings.TrimPrefix(path, rule.TrimPrefix)
}
if strings.HasPrefix(originPath, rule.Path) {
parsedUrl := path.Join(rule.JoinPrefix, strings.TrimPrefix(originPath, rule.TrimPrefix))
return parsedUrl
}
}
return path
return originPath
}
4 changes: 2 additions & 2 deletions config/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ type apiConfig struct {
TokenExpire int `toml:"token_expire" mapstructure:"token_expire" json:"token_expire" yaml:"token_expire"`
RefreshTokenExpire int `toml:"refresh_token_expire" mapstructure:"refresh_token_expire" json:"refresh_token_expire" yaml:"refresh_token_expire"`

PathRules []PathRule `toml:"path_rules" mapstructure:"path_rules" json:"path_rules" yaml:"path_rules"`
PathRules []ApiPathRule `toml:"path_rules" mapstructure:"path_rules" json:"path_rules" yaml:"path_rules"`

Cache apiCacheConfig `toml:"cache" mapstructure:"cache" json:"cache" yaml:"cache"`
}

type PathRule struct {
type ApiPathRule struct {
Path string `toml:"path" mapstructure:"path" json:"path" yaml:"path"`
TrimPrefix string `toml:"trim_prefix" mapstructure:"trim_prefix" json:"trim_prefix" yaml:"trim_prefix"`
JoinPrefix string `toml:"join_prefix" mapstructure:"join_prefix" json:"join_prefix" yaml:"join_prefix"`
Expand Down
21 changes: 21 additions & 0 deletions config/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,32 @@ type storageConfigs struct {
ThumbFormat string `toml:"thumb_format" mapstructure:"thumb_format" json:"thumb_format" yaml:"thumb_format"`
CacheDir string `toml:"cache_dir" mapstructure:"cache_dir" json:"cache_dir" yaml:"cache_dir"`
CacheTTL uint `toml:"cache_ttl" mapstructure:"cache_ttl" json:"cache_ttl" yaml:"cache_ttl"`
Rules []storageRuleConfig `toml:"rules" mapstructure:"rules" json:"rules" yaml:"rules"`
Webdav StorageWebdavConfig `toml:"webdav" mapstructure:"webdav" json:"webdav" yaml:"webdav"`
Local StorageLocalConfig `toml:"local" mapstructure:"local" json:"local" yaml:"local"`
Alist StorageAlistConfig `toml:"alist" mapstructure:"alist" json:"alist" yaml:"alist"`
}

type storageRuleConfig struct {
/*
Match: 进行 与 匹配
Replace: 依次进行替换
example:
match: {storage_type: "webdav", path_prefix: "/onedrive"}
replace: {rewrite_storage: "local", trim_prefix: "/onedrive", join_prefix: "/local/manyacg"}
此规则被应用后, storage 在获取 webdav 存储驱动下的以 /onedrive 开头的图片时, 会去寻找 local 存储驱动下的以 /local/manyacg 开头的图片(路径前缀被替换)
*/

// Match
StorageType string `toml:"storage_type" mapstructure:"storage_type" json:"storage_type" yaml:"storage_type"`
PathPrefix string `toml:"path_prefix" mapstructure:"path_prefix" json:"path_prefix" yaml:"path_prefix"`

// Replace
RewriteStorage string `toml:"rewrite_storage" mapstructure:"rewrite_storage" json:"rewrite_storage" yaml:"rewrite_storage"`
TrimPrefix string `toml:"trim_prefix" mapstructure:"trim_prefix" json:"trim_prefix" yaml:"trim_prefix"`
JoinPrefix string `toml:"join_prefix" mapstructure:"join_prefix" json:"join_prefix" yaml:"join_prefix"`
}

type StorageWebdavConfig struct {
Enable bool `toml:"enable" mapstructure:"enable" json:"enable" yaml:"enable"`
URL string `toml:"url" mapstructure:"url" json:"url" yaml:"url"`
Expand Down
2 changes: 2 additions & 0 deletions storage/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func (l *Local) Save(ctx context.Context, filePath string, storagePath string) (
}

func (l *Local) GetFile(ctx context.Context, detail *types.StorageDetail) ([]byte, error) {
common.Logger.Debugf("getting file %s", detail.Path)
return os.ReadFile(detail.Path)
}

Expand All @@ -58,5 +59,6 @@ func (l *Local) GetFileStream(ctx context.Context, detail *types.StorageDetail)
}

func (l *Local) Delete(ctx context.Context, detail *types.StorageDetail) error {
common.Logger.Debugf("deleting file %s", detail.Path)
return common.PurgeFile(detail.Path)
}
4 changes: 4 additions & 0 deletions storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ func Save(ctx context.Context, filePath string, storagePath string, storageType
var storageLocks sync.Map

func GetFile(ctx context.Context, detail *types.StorageDetail) ([]byte, error) {
detail, err := applyRule(detail)
if err != nil {
return nil, err
}
if detail.Type != types.StorageTypeLocal {
lock, _ := storageLocks.LoadOrStore(detail.String(), &sync.Mutex{})
lock.(*sync.Mutex).Lock()
Expand Down
44 changes: 44 additions & 0 deletions storage/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package storage

import (
"errors"
"path"
"strings"

"github.com/krau/ManyACG/config"
"github.com/krau/ManyACG/types"
)

var (
ErrNilStorageDetail = errors.New("storage detail is nil")
ErrStorageNotFound = errors.New("storage not found")
)

func applyRule(detail *types.StorageDetail) (*types.StorageDetail, error) {
if detail == nil {
return nil, ErrNilStorageDetail
}

currentType := detail.Type.String()
currentPath := detail.Path

if currentType == "" || currentPath == "" {
return detail, nil
}

for _, rule := range config.Cfg.Storage.Rules {
if !(currentType == rule.StorageType && strings.HasPrefix(currentPath, rule.PathPrefix)) {
continue
}
if rule.RewriteStorage == "" {
continue
}
_, ok := Storages[types.StorageType(rule.RewriteStorage)]
if !ok {
return nil, ErrStorageNotFound
}
detail.Type = types.StorageType(rule.RewriteStorage)
detail.Path = path.Join(rule.JoinPrefix, strings.TrimPrefix(currentPath, rule.TrimPrefix))
}
return detail, nil
}
1 change: 1 addition & 0 deletions telegram/handlers/admin_edit_artwork.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ func AutoTaggingArtwork(ctx context.Context, bot *telego.Bot, message telego.Mes
}
}())
if err != nil {
common.Logger.Errorf("Get picture file from storage failed: %s", err)
file, err = common.DownloadWithCache(ctx, picture.Original, nil)
}
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions types/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package types

type StorageType string

func (s StorageType) String() string {
return string(s)
}

const (
StorageTypeWebdav StorageType = "webdav"
StorageTypeLocal StorageType = "local"
Expand Down

0 comments on commit 81a54f9

Please sign in to comment.