138 lines
4.0 KiB
Go
138 lines
4.0 KiB
Go
package useCases
|
|
|
|
import (
|
|
"RenewCMS/internal/domain/article"
|
|
"RenewCMS/internal/domain/author"
|
|
"RenewCMS/internal/domain/image"
|
|
"RenewCMS/internal/domain/site"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
UsageTypeArticle = "article"
|
|
UsageTypeAuthor = "author"
|
|
UsageTypeSite = "site"
|
|
|
|
UsageFieldBody = "body"
|
|
UsageFieldCover = "cover"
|
|
UsageFieldSocial = "social"
|
|
UsageFieldAvatar = "avatar"
|
|
UsageFieldDefaultSocialImage = "default_social_image"
|
|
)
|
|
|
|
type MediaUsage struct {
|
|
Type string
|
|
ID uint32
|
|
Title string
|
|
Published *bool
|
|
Fields []string
|
|
}
|
|
|
|
type GetMediaUsageUseCase struct {
|
|
imageRepository image.Repository
|
|
articleRepository article.Repository
|
|
sites site.Repository
|
|
authors author.Repository
|
|
}
|
|
|
|
func NewGetMediaUsageUseCase(imageRepository image.Repository, articleRepository article.Repository, sites site.Repository, authors author.Repository) *GetMediaUsageUseCase {
|
|
return &GetMediaUsageUseCase{imageRepository: imageRepository, articleRepository: articleRepository, sites: sites, authors: authors}
|
|
}
|
|
|
|
func (u *GetMediaUsageUseCase) Usage(id uint32) ([]MediaUsage, error) {
|
|
img, err := u.imageRepository.Get(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usages, err := u.articleUsages(img)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
authorUsages, err := u.authorUsages(img)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
siteUsages, err := u.siteUsages(img)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return slices.Concat(usages, authorUsages, siteUsages), nil
|
|
}
|
|
|
|
func (u *GetMediaUsageUseCase) articleUsages(img image.Image) ([]MediaUsage, error) {
|
|
storedName := image.StoredName(img.Path)
|
|
inBody, err := u.articleRepository.FindByBodyContaining(storedName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
referencing, err := u.articleRepository.FindByImage(img.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
byID := map[uint32]*MediaUsage{}
|
|
for _, found := range inBody {
|
|
if !strings.Contains(found.Body, storedName) {
|
|
continue
|
|
}
|
|
entry := usageFor(byID, found)
|
|
entry.Fields = append(entry.Fields, UsageFieldBody)
|
|
}
|
|
for _, found := range referencing {
|
|
entry := usageFor(byID, found)
|
|
if found.CoverImageID != nil && *found.CoverImageID == img.ID {
|
|
entry.Fields = append(entry.Fields, UsageFieldCover)
|
|
}
|
|
if found.SocialImageID != nil && *found.SocialImageID == img.ID {
|
|
entry.Fields = append(entry.Fields, UsageFieldSocial)
|
|
}
|
|
}
|
|
usages := make([]MediaUsage, 0, len(byID))
|
|
for _, entry := range byID {
|
|
usages = append(usages, *entry)
|
|
}
|
|
slices.SortFunc(usages, func(a, b MediaUsage) int { return int(a.ID) - int(b.ID) })
|
|
return usages, nil
|
|
}
|
|
|
|
func usageFor(byID map[uint32]*MediaUsage, found article.Article) *MediaUsage {
|
|
if entry, ok := byID[found.ID]; ok {
|
|
return entry
|
|
}
|
|
published := found.IsOnline
|
|
entry := &MediaUsage{Type: UsageTypeArticle, ID: found.ID, Title: found.Title, Published: &published, Fields: []string{}}
|
|
byID[found.ID] = entry
|
|
return entry
|
|
}
|
|
|
|
func (u *GetMediaUsageUseCase) authorUsages(img image.Image) ([]MediaUsage, error) {
|
|
found, err := u.authors.FindByAvatar(img.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usages := make([]MediaUsage, 0, len(found))
|
|
for _, a := range found {
|
|
usages = append(usages, MediaUsage{Type: UsageTypeAuthor, ID: a.ID, Title: a.Name, Fields: []string{UsageFieldAvatar}})
|
|
}
|
|
return usages, nil
|
|
}
|
|
|
|
func (u *GetMediaUsageUseCase) siteUsages(img image.Image) ([]MediaUsage, error) {
|
|
all, err := u.sites.List()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
usages := []MediaUsage{}
|
|
for _, s := range all {
|
|
if s.DefaultSocialImageID != nil && *s.DefaultSocialImageID == img.ID {
|
|
usages = append(usages, MediaUsage{Type: UsageTypeSite, ID: s.ID, Title: s.Name, Fields: []string{UsageFieldDefaultSocialImage}})
|
|
}
|
|
}
|
|
slices.SortFunc(usages, func(a, b MediaUsage) int { return int(a.ID) - int(b.ID) })
|
|
return usages, nil
|
|
}
|
|
|
|
func articleMentionsImage(a article.Article, img image.Image) bool {
|
|
return strings.Contains(a.Body, image.StoredName(img.Path)) || a.UsesImage(img.ID)
|
|
}
|