Files
RenewCMS/internal/infrastructure/useCases/GetMediaUsage.go
T

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)
}