summaryrefslogtreecommitdiff
path: root/internal/service
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-02 09:33:22 +0300
committerPaul Buetow <paul@buetow.org>2026-05-02 09:33:22 +0300
commit95c6ce72bdf16ead39d0df1ee27b0474441fbe4f (patch)
treef6823246f8e7f85db2233fec461159005ffadc41 /internal/service
parent4dd62a8b61c56ef28f5f0cab58b8c2da94806717 (diff)
fix:x
Diffstat (limited to 'internal/service')
-rw-r--r--internal/service/media.go4
-rw-r--r--internal/service/media_share.go23
-rw-r--r--internal/service/mock.go7
-rw-r--r--internal/service/service.go23
4 files changed, 49 insertions, 8 deletions
diff --git a/internal/service/media.go b/internal/service/media.go
index 1856592..a617a29 100644
--- a/internal/service/media.go
+++ b/internal/service/media.go
@@ -73,6 +73,8 @@ var supportedExtensions = map[string]struct{}{
".ogg": {},
".m4a": {},
".wma": {},
+ ".m4b": {},
+ ".opus": {},
}
func isSupportedExtension(name string) bool {
@@ -86,7 +88,7 @@ func guessMediaType(name string) model.MediaType {
switch ext {
case ".mp4", ".mkv", ".avi", ".mov", ".wmv", ".flv", ".webm":
return model.MediaTypeVideo
- case ".mp3", ".wav", ".flac", ".aac", ".ogg", ".m4a", ".wma":
+ case ".mp3", ".wav", ".flac", ".aac", ".ogg", ".m4a", ".wma", ".m4b", ".opus":
return model.MediaTypeAudio
default:
return model.MediaTypeVideo
diff --git a/internal/service/media_share.go b/internal/service/media_share.go
index 0a96f85..3decf96 100644
--- a/internal/service/media_share.go
+++ b/internal/service/media_share.go
@@ -112,3 +112,26 @@ func (s *mediaService) StreamSharedMedia(ctx context.Context, token string) (*Fi
FileSize: media.FileSizeBytes,
}, nil
}
+
+func (s *mediaService) GetSharedMedia(ctx context.Context, token string) (*GetSharedMediaResult, error) {
+ share, err := s.ValidateShareToken(ctx, token)
+ if err != nil {
+ return nil, err
+ }
+
+ media, err := s.store.GetMediaByID(ctx, share.MediaID)
+ if err != nil {
+ return nil, fmt.Errorf("get media: %w", err)
+ }
+ if media == nil {
+ return nil, ErrMediaNotFound
+ }
+
+ res := &GetSharedMediaResult{
+ Media: media,
+ StreamURL: fmt.Sprintf("/s/%s/stream", token),
+ HasThumb: media.ThumbnailPath != "",
+ ThumbURL: fmt.Sprintf("/s/%s/thumbnail", token),
+ }
+ return res, nil
+}
diff --git a/internal/service/mock.go b/internal/service/mock.go
index c6c2301..82a25de 100644
--- a/internal/service/mock.go
+++ b/internal/service/mock.go
@@ -42,6 +42,7 @@ type MockMediaService struct {
RevokeShareFunc func(ctx context.Context, token string, userID int64) error
ValidateShareTokenFunc func(ctx context.Context, token string) (*model.Share, error)
StreamSharedMediaFunc func(ctx context.Context, token string) (*FileResult, error)
+ GetSharedMediaFunc func(ctx context.Context, token string) (*GetSharedMediaResult, error)
GetNoteFunc func(ctx context.Context, mediaID, userID int64) (*model.Note, error)
UpsertNoteFunc func(ctx context.Context, note *model.Note) error
DeleteNoteFunc func(ctx context.Context, mediaID, userID int64) error
@@ -161,6 +162,12 @@ func (m *MockMediaService) StreamSharedMedia(ctx context.Context, token string)
}
return nil, errors.New("not implemented")
}
+func (m *MockMediaService) GetSharedMedia(ctx context.Context, token string) (*GetSharedMediaResult, error) {
+ if m.GetSharedMediaFunc != nil {
+ return m.GetSharedMediaFunc(ctx, token)
+ }
+ return nil, errors.New("not implemented")
+}
func (m *MockMediaService) GetNote(ctx context.Context, mediaID, userID int64) (*model.Note, error) {
if m.GetNoteFunc != nil {
return m.GetNoteFunc(ctx, mediaID, userID)
diff --git a/internal/service/service.go b/internal/service/service.go
index 1ed1443..fd96b25 100644
--- a/internal/service/service.go
+++ b/internal/service/service.go
@@ -29,14 +29,23 @@ type MediaWriteService interface {
UploadMedia(ctx context.Context, setID, userID int64, filename string, data io.Reader, size int64) (*model.Media, error)
}
+// GetSharedMediaResult wraps media metadata needed to render a share page.
+ type GetSharedMediaResult struct {
+ Media *model.Media `json:"media"`
+ HasThumb bool `json:"has_thumb"`
+ StreamURL string `json:"stream_url"`
+ ThumbURL string `json:"thumb_url"`
+ }
+
// MediaShareService handles creation, validation and revocation of share links.
-type MediaShareService interface {
- CreateShare(ctx context.Context, userID, mediaID int64, expiresAt time.Time) (*model.Share, error)
- ListShares(ctx context.Context, mediaID, userID int64) ([]model.Share, error)
- RevokeShare(ctx context.Context, token string, userID int64) error
- ValidateShareToken(ctx context.Context, token string) (*model.Share, error)
- StreamSharedMedia(ctx context.Context, token string) (*FileResult, error)
-}
+ type MediaShareService interface {
+ CreateShare(ctx context.Context, userID, mediaID int64, expiresAt time.Time) (*model.Share, error)
+ ListShares(ctx context.Context, mediaID, userID int64) ([]model.Share, error)
+ RevokeShare(ctx context.Context, token string, userID int64) error
+ ValidateShareToken(ctx context.Context, token string) (*model.Share, error)
+ StreamSharedMedia(ctx context.Context, token string) (*FileResult, error)
+ GetSharedMedia(ctx context.Context, token string) (*GetSharedMediaResult, error)
+ }
// MediaTagService handles tagging of media items.
type MediaTagService interface {