Documentation
¶
Overview ¶
Package publishing owns Album import, curation, access and publication.
Index ¶
- func RegisterAccessRoutes(e *echo.Echo, module AccessUseCases, requireCurator echo.MiddlewareFunc)
- func RegisterPublicationRoutes(e *echo.Echo, module PublicationUseCases, requireCurator echo.MiddlewareFunc)
- func RegisterRoutes(e *echo.Echo, module *Module, requireCurator echo.MiddlewareFunc)
- func RegisterViewerRoutes(e *echo.Echo, module ViewerUseCases, ...)
- func SourceAssetThumbnailURL(sourceID string) string
- type AccessConflict
- type AccessPerson
- type AccessResolution
- type AccessUseCases
- type Album
- type AlbumAccessChoice
- type AlbumAccessPreview
- type AlbumDetail
- type AudienceChange
- type Chapter
- type ChapterFailure
- type ChapterService
- type Decision
- type DeleteAlbumRequest
- type EnqueueImport
- type Entry
- type EntryPageRequest
- type ExcludeEntriesRequest
- type ExcludedEntry
- type FaceRecord
- type ImportRequest
- type IncludeEntryRequest
- type MergeMomentsRequest
- type Module
- func (m *Module) ApplySync(ctx context.Context, albumID string, request SyncRequest) (AlbumDetail, error)
- func (m *Module) AuthorizeViewerEntry(ctx context.Context, actorID, previewPersonID, entryID string) error
- func (m *Module) ChapterFailures(ctx context.Context) ([]ChapterFailure, error)
- func (m *Module) CheckSync(ctx context.Context, albumID string, request SyncRequest) (SyncReview, error)
- func (m *Module) DeleteAlbum(ctx context.Context, albumID string, request DeleteAlbumRequest) error
- func (m *Module) ExcludeEntries(ctx context.Context, albumID, momentID string, request ExcludeEntriesRequest) (AlbumDetail, error)
- func (m *Module) ExecuteImport(ctx context.Context, id string, finalAttempt ...bool) (returnErr error)
- func (m *Module) GetAlbum(ctx context.Context, id string) (AlbumDetail, error)
- func (m *Module) IgnoreSource(ctx context.Context, sourceID string) error
- func (m *Module) IncludeEntry(ctx context.Context, albumID, entryID string, request IncludeEntryRequest) (AlbumDetail, error)
- func (m *Module) ListAlbums(ctx context.Context, search string) ([]Album, error)
- func (m *Module) ListSources(ctx context.Context, search string, page int, ignored bool) (SourcePage, error)
- func (m *Module) MergeMoments(ctx context.Context, albumID, sourceMomentID string, ...) (AlbumDetail, error)
- func (m *Module) MoveEntries(ctx context.Context, albumID, sourceMomentID string, ...) (AlbumDetail, error)
- func (m *Module) PreviewAlbumAccess(ctx context.Context, albumID string, request SaveAlbumAccessRequest) (AlbumAccessPreview, error)
- func (m *Module) PreviewExclude(ctx context.Context, albumID, momentID string, request ExcludeEntriesRequest) (StructurePreview, error)
- func (m *Module) PreviewInclude(ctx context.Context, albumID, entryID string, request IncludeEntryRequest) (StructurePreview, error)
- func (m *Module) PreviewMerge(ctx context.Context, albumID, sourceMomentID string, ...) (StructurePreview, error)
- func (m *Module) PreviewMove(ctx context.Context, albumID, sourceMomentID string, ...) (StructurePreview, error)
- func (m *Module) PreviewRemoveAccess(ctx context.Context, albumID string, request RemoveAccessPreviewRequest) (RemoveAccessPreview, error)
- func (m *Module) PreviewSplit(ctx context.Context, albumID, sourceMomentID string, ...) (StructurePreview, error)
- func (m *Module) PublishAlbum(ctx context.Context, albumID string, request PublishRequest) (AlbumDetail, error)
- func (m *Module) RefreshMomentFaces(ctx context.Context, albumID, momentID string) (AlbumDetail, error)
- func (m *Module) RemoveAccess(ctx context.Context, albumID string, request RemoveAccessRequest) (AlbumDetail, error)
- func (m *Module) RestoreSource(ctx context.Context, sourceID string) error
- func (m *Module) RetryChapters(ctx context.Context, albumID, entryID string) (AlbumDetail, error)
- func (m *Module) RetryImport(ctx context.Context, id string) (AlbumDetail, error)
- func (m *Module) ReviewPublication(ctx context.Context, albumID string) (PublicationReview, error)
- func (m *Module) SaveAlbumAccess(ctx context.Context, albumID string, request SaveAlbumAccessRequest) (AlbumDetail, error)
- func (m *Module) SaveCoverOrder(ctx context.Context, albumID string, request SaveCoverOrderRequest) (AlbumDetail, error)
- func (m *Module) SaveEntryRules(ctx context.Context, albumID, entryID string, request SaveRulesRequest) (AlbumDetail, error)
- func (m *Module) SaveMomentRules(ctx context.Context, albumID, momentID string, request SaveRulesRequest) (AlbumDetail, error)
- func (m *Module) SetMomentCover(ctx context.Context, albumID, momentID string, request SetMomentCoverRequest) (AlbumDetail, error)
- func (m *Module) SplitMoment(ctx context.Context, albumID, sourceMomentID string, ...) (AlbumDetail, error)
- func (m *Module) StartImport(ctx context.Context, sourceID string) (AlbumDetail, error)
- func (m *Module) UnpublishAlbum(ctx context.Context, albumID string) (AlbumDetail, error)
- func (m *Module) UpdateAlbum(ctx context.Context, id string, request UpdateAlbumRequest) (AlbumDetail, error)
- func (m *Module) UpdateMoment(ctx context.Context, albumID, momentID string, request UpdateMomentRequest) (AlbumDetail, error)
- func (m *Module) UpdateVideo(ctx context.Context, albumID, entryID string, request UpdateVideoRequest) (AlbumDetail, error)
- func (m *Module) ViewAlbum(ctx context.Context, actorID, previewPersonID, albumID string) (ViewerAlbum, error)
- func (m *Module) ViewAlbums(ctx context.Context, actorID string) ([]ViewerAlbum, error)
- func (m *Module) ViewEntries(ctx context.Context, actorID, previewPersonID, albumID, kind string, ...) (ViewerPage, error)
- func (m *Module) ViewLibrary(ctx context.Context, actorID string) (ViewerLibrary, error)
- func (m *Module) ViewLibraryEntries(ctx context.Context, actorID, kind string, page EntryPageRequest) (ViewerPage, error)
- func (m *Module) ViewingGroups(ctx context.Context, albumID string) (ViewingGroups, error)
- func (m *Module) VisibleEntries(ctx context.Context, db bun.IDB, personID string) ([]notifications.VisibleEntry, error)
- type Moment
- type MomentAccess
- type MoveEntriesRequest
- type PublicationAudience
- type PublicationReview
- type PublicationUseCases
- type PublishRequest
- type RemoveAccessPreview
- type RemoveAccessPreviewRequest
- type RemoveAccessRequest
- type SaveAlbumAccessRequest
- type SaveCoverOrderRequest
- type SaveRulesRequest
- type SetMomentCoverRequest
- type SourceAlbum
- type SourcePage
- type SourceRequest
- type SplitMomentRequest
- type StructurePreview
- type SyncAddition
- type SyncAlbumRef
- type SyncChange
- type SyncCover
- type SyncCoverChoice
- type SyncCoverOption
- type SyncDescription
- type SyncMomentOption
- type SyncPlacement
- type SyncRemoval
- type SyncRequest
- type SyncReview
- type UpdateAlbumRequest
- type UpdateMomentRequest
- type UpdateVideoRequest
- type ViewerAlbum
- type ViewerDay
- type ViewerEntry
- type ViewerLibrary
- type ViewerPage
- type ViewerUseCases
- type ViewingGroup
- type ViewingGroups
- type ViewingPerson
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RegisterAccessRoutes ¶
func RegisterAccessRoutes(e *echo.Echo, module AccessUseCases, requireCurator echo.MiddlewareFunc)
RegisterAccessRoutes keeps every access mutation behind the Curator guard.
func RegisterPublicationRoutes ¶
func RegisterPublicationRoutes(e *echo.Echo, module PublicationUseCases, requireCurator echo.MiddlewareFunc)
func RegisterRoutes ¶
func RegisterRoutes(e *echo.Echo, module *Module, requireCurator echo.MiddlewareFunc)
func RegisterViewerRoutes ¶
func RegisterViewerRoutes(e *echo.Echo, module ViewerUseCases, requirePerson, requireCurator echo.MiddlewareFunc)
RegisterViewerRoutes keeps selected-Person preview behind the Curator guard.
func SourceAssetThumbnailURL ¶
SourceAssetThumbnailURL is the Curator-only preview of an asset that is not yet, or no longer, part of any Album.
Types ¶
type AccessConflict ¶
type AccessPerson ¶
type AccessPerson struct {
PersonID string `json:"person_id"`
DisplayName string `json:"display_name"`
AvatarURL string `json:"avatar_url"`
Decision Decision `json:"decision"`
Detected bool `json:"detected"`
Suggested bool `json:"suggested"`
SupportingEntries int `json:"supporting_entries"`
MomentsDetected int `json:"moments_detected"`
Inherited bool `json:"inherited"`
Effective bool `json:"effective"`
AccessibleCount int `json:"accessible_count"`
Exceptions int `json:"exceptions"`
// Deactivated people appear at Album scope only while they still hold
// rules here, so a Curator can see and remove frozen access.
Deactivated bool `json:"deactivated"`
}
AccessPerson summarizes one Person at one scope. At Album scope Decision is the Album allow, Exceptions counts narrower rules, and MomentsDetected says how many Moments recognized them; at Moment scope Inherited reports an Album allow and Decision the Moment rule.
type AccessResolution ¶
type AccessUseCases ¶
type AccessUseCases interface {
PreviewAlbumAccess(context.Context, string, SaveAlbumAccessRequest) (AlbumAccessPreview, error)
SaveAlbumAccess(context.Context, string, SaveAlbumAccessRequest) (AlbumDetail, error)
SaveMomentRules(context.Context, string, string, SaveRulesRequest) (AlbumDetail, error)
SaveEntryRules(context.Context, string, string, SaveRulesRequest) (AlbumDetail, error)
PreviewRemoveAccess(context.Context, string, RemoveAccessPreviewRequest) (RemoveAccessPreview, error)
RemoveAccess(context.Context, string, RemoveAccessRequest) (AlbumDetail, error)
}
AccessUseCases is the HTTP seam for complete Curator access operations.
type Album ¶
type Album struct {
ID string `json:"id"`
SourceID string `json:"source_id"`
Title string `json:"title"`
Description string `json:"description"`
Published bool `json:"published"`
Ready bool `json:"ready"`
Status string `json:"status"`
Message string `json:"message"`
Processed int `json:"processed"`
Total int `json:"total"`
PhotoCount int `json:"photo_count"`
VideoCount int `json:"video_count"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
CoverURL string `json:"cover_url"`
}
Album is the Curator's view of one import. Status is queued, processing, interrupted, failed, or complete. Ready is true for a complete, unpublished Album that at least one Person could see once published.
type AlbumAccessChoice ¶
type AlbumAccessPreview ¶
type AlbumAccessPreview struct {
Changes []AudienceChange `json:"changes"`
}
type AlbumDetail ¶
type AlbumDetail struct {
Album `tstype:",extends"`
Moments []Moment `json:"moments"`
Access []AccessPerson `json:"access"`
Excluded []ExcludedEntry `json:"excluded"`
}
type AudienceChange ¶
type AudienceChange struct {
PersonID string `json:"person_id"`
DisplayName string `json:"display_name"`
GainedEntryIDs []string `json:"gained_entry_ids"`
LostEntryIDs []string `json:"lost_entry_ids"`
}
AudienceChange describes the Album Entries whose effective access changes.
type Chapter ¶
type Chapter struct {
Title string `json:"title"`
Start float64 `json:"start"`
End float64 `json:"end"`
}
Chapter is one read-only navigation segment, in seconds from the start.
type ChapterFailure ¶
type ChapterFailure struct {
AlbumID string `json:"album_id"`
AlbumTitle string `json:"album_title"`
MomentID string `json:"moment_id"`
EntryID string `json:"entry_id"`
Title string `json:"title"`
Message string `json:"message"`
}
ChapterFailure is one video whose chapter extraction failed, addressed through an Album and Moment so a Curator can open it and retry.
type ChapterService ¶
type ChapterService interface {
RequestChapters(ctx context.Context, tx bun.Tx, mediaItemID models.UUID, checksum string) error
RetryChapters(ctx context.Context, mediaItemID string) error
}
ChapterService is Media's chapter extraction seam. Requests join the import transaction so a committed video always has its committed task.
type Decision ¶
type Decision string
Decision is an explicit access choice. Missing decisions inherit.
type DeleteAlbumRequest ¶
type DeleteAlbumRequest struct {
Title string `json:"title" validate:"required"`
}
func (DeleteAlbumRequest) ValidationMessage ¶
func (DeleteAlbumRequest) ValidationMessage(field, _ string) string
type EnqueueImport ¶
EnqueueImport participates in the caller's transaction. It must not execute work inline.
type Entry ¶
type Entry struct {
ID string `json:"id"`
MediaID string `json:"media_id"`
Filename string `json:"filename"`
Kind string `json:"kind"`
CapturedAt string `json:"captured_at"`
Available bool `json:"available"`
ThumbnailURL string `json:"thumbnail_url"`
// Decisions holds only this entry's explicit rules by Person ID.
Decisions map[string]Decision `json:"decisions"`
// Title is the global video title override, empty when the filename shows.
Title string `json:"title"`
// PlaybackURL streams an available video to the Curator; photos have none.
PlaybackURL string `json:"playback_url"`
// Chapter fields describe the Media Item's extraction: ChapterStatus is
// pending, complete, or failed, and ChapterMessage explains a failure.
Chapters []Chapter `json:"chapters"`
ChapterStatus string `json:"chapter_status"`
ChapterMessage string `json:"chapter_message"`
}
type EntryPageRequest ¶
EntryPageRequest selects one page of a gallery. From and To are local capture days (YYYY-MM-DD) that bound the page, To exclusive, so a browser can load every part of a large Album at once; Cursor continues within those bounds.
type ExcludeEntriesRequest ¶
type ExcludeEntriesRequest struct {
EntryIDs []string `json:"entry_ids" validate:"required,min=1,dive,uuid"`
ReviewToken string `json:"review_token"`
}
ExcludeEntriesRequest keeps selected media of one Moment out of the Album.
type ExcludedEntry ¶
type ExcludedEntry struct {
ID string `json:"id"`
Filename string `json:"filename"`
Kind string `json:"kind"`
Title string `json:"title"`
CapturedAt string `json:"captured_at"`
ThumbnailURL string `json:"thumbnail_url"`
Available bool `json:"available"`
ExcludedAt string `json:"excluded_at"`
}
ExcludedEntry is media the Curator keeps out of this Album while it stays in the Immich album. It keeps its Album Entry identity for Add back.
type FaceRecord ¶
type FaceRecord struct {
SourceID string `json:"source_id"`
SourceName string `json:"source_name"`
ThumbnailURL string `json:"thumbnail_url"`
ImmichURL string `json:"immich_url"`
PersonID string `json:"person_id"`
PersonName string `json:"person_name"`
Ignored bool `json:"ignored"`
Occurrences int `json:"occurrences"`
}
type ImportRequest ¶
type ImportRequest struct {
SourceID string `json:"source_id" validate:"required,max=1024"`
}
type IncludeEntryRequest ¶
type IncludeEntryRequest struct {
MomentID string `json:"moment_id" validate:"required,max=64"`
ReviewToken string `json:"review_token"`
}
IncludeEntryRequest returns excluded media to an existing Moment or to a new Moment for its capture day, keyed "new:YYYY-MM-DD".
type MergeMomentsRequest ¶
type MergeMomentsRequest struct {
TargetMomentID string `json:"target_moment_id" validate:"required,uuid"`
Title string `json:"title" mod:"trim" validate:"max=200"`
CoverEntryID string `json:"cover_entry_id" validate:"required,uuid"`
Resolutions []AccessResolution `json:"resolutions" validate:"dive"`
ReviewToken string `json:"review_token"`
}
func (MergeMomentsRequest) ValidationMessage ¶
func (MergeMomentsRequest) ValidationMessage(field, rule string) string
type Module ¶
type Module struct {
// ImmichURL is the browser-reachable Immich origin used for "Open in
// Immich" links. Empty hides those links.
ImmichURL string
// Chapters queues extraction for imported videos. Nil, as in tests that
// never look at chapters, imports videos without probing them.
Chapters ChapterService
// contains filtered or unexported fields
}
func (*Module) ApplySync ¶
func (m *Module) ApplySync(ctx context.Context, albumID string, request SyncRequest) (AlbumDetail, error)
ApplySync recomputes the review inside one transaction and commits the approved changes together. Any difference from the reviewed diff, in Immich or in this Album, refuses the apply so nothing unreviewed is committed.
func (*Module) AuthorizeViewerEntry ¶
func (m *Module) AuthorizeViewerEntry(ctx context.Context, actorID, previewPersonID, entryID string) error
AuthorizeViewerEntry is the Media boundary. Every uncached thumbnail request checks current membership and access before resolving an Immich variant.
func (*Module) ChapterFailures ¶
func (m *Module) ChapterFailures(ctx context.Context) ([]ChapterFailure, error)
ChapterFailures lists every failed chapter extraction that a Curator can still reach through a complete Album. Chapter status belongs to Media; this only addresses each failure by its Album Entry.
func (*Module) CheckSync ¶
func (m *Module) CheckSync(ctx context.Context, albumID string, request SyncRequest) (SyncReview, error)
CheckSync compares the Album with its Immich album and returns a temporary review. The opening check, the one without decisions, also refreshes cached faces; otherwise it changes nothing. Cancelling the review discards it and a later check recomputes the source state.
func (*Module) DeleteAlbum ¶
DeleteAlbum permanently removes this Album's curation, never Immich media. Shared Media Items remain intact, including metadata owned by later features.
func (*Module) ExcludeEntries ¶
func (m *Module) ExcludeEntries(ctx context.Context, albumID, momentID string, request ExcludeEntriesRequest) (AlbumDetail, error)
ExcludeEntries keeps the reviewed media out of the Album. A later check never offers it as new, and Add back returns it with its identity.
func (*Module) ExecuteImport ¶
func (m *Module) ExecuteImport(ctx context.Context, id string, finalAttempt ...bool) (returnErr error)
ExecuteImport reads outside transactions, then commits a complete reviewed Album atomically. Repeating a completed import never overwrites Curator edits.
func (*Module) IgnoreSource ¶ added in v0.2.0
IgnoreSource keeps an Immich album off the import list until it is restored. Ignoring an album twice is the same decision, so it is not an error.
func (*Module) IncludeEntry ¶
func (m *Module) IncludeEntry(ctx context.Context, albumID, entryID string, request IncludeEntryRequest) (AlbumDetail, error)
IncludeEntry returns excluded media to the Album in the reviewed Moment. Media Immich reports as missing or trashed waits for a check first. A video that was kept out before it was ever probed gets its extraction now.
func (*Module) ListAlbums ¶
func (*Module) ListSources ¶
func (m *Module) ListSources(ctx context.Context, search string, page int, ignored bool) (SourcePage, error)
ListSources pages locally because Immich's album-list endpoint has no paging or partial-name search. Existing imports remain visible regardless of the gate and are never treated as ignored. Ignored selects the albums a Curator keeps off the import list instead of the ones offered for import.
func (*Module) MergeMoments ¶
func (m *Module) MergeMoments(ctx context.Context, albumID, sourceMomentID string, request MergeMomentsRequest) (AlbumDetail, error)
func (*Module) MoveEntries ¶
func (m *Module) MoveEntries(ctx context.Context, albumID, sourceMomentID string, request MoveEntriesRequest) (AlbumDetail, error)
func (*Module) PreviewAlbumAccess ¶
func (m *Module) PreviewAlbumAccess(ctx context.Context, albumID string, request SaveAlbumAccessRequest) (AlbumAccessPreview, error)
func (*Module) PreviewExclude ¶
func (m *Module) PreviewExclude(ctx context.Context, albumID, momentID string, request ExcludeEntriesRequest) (StructurePreview, error)
func (*Module) PreviewInclude ¶
func (m *Module) PreviewInclude(ctx context.Context, albumID, entryID string, request IncludeEntryRequest) (StructurePreview, error)
func (*Module) PreviewMerge ¶
func (m *Module) PreviewMerge(ctx context.Context, albumID, sourceMomentID string, request MergeMomentsRequest) (StructurePreview, error)
func (*Module) PreviewMove ¶
func (m *Module) PreviewMove(ctx context.Context, albumID, sourceMomentID string, request MoveEntriesRequest) (StructurePreview, error)
func (*Module) PreviewRemoveAccess ¶
func (m *Module) PreviewRemoveAccess(ctx context.Context, albumID string, request RemoveAccessPreviewRequest) (RemoveAccessPreview, error)
func (*Module) PreviewSplit ¶
func (m *Module) PreviewSplit(ctx context.Context, albumID, sourceMomentID string, request SplitMomentRequest) (StructurePreview, error)
func (*Module) PublishAlbum ¶
func (m *Module) PublishAlbum(ctx context.Context, albumID string, request PublishRequest) (AlbumDetail, error)
PublishAlbum confirms the reviewed audience and commits publication alone.
func (*Module) RefreshMomentFaces ¶
func (m *Module) RefreshMomentFaces(ctx context.Context, albumID, momentID string) (AlbumDetail, error)
RefreshMomentFaces reads Immich before opening a transaction. Cached face associations are replaced only after every source read succeeds, so a temporary Immich failure cannot erase the last usable recommendations.
func (*Module) RemoveAccess ¶
func (m *Module) RemoveAccess(ctx context.Context, albumID string, request RemoveAccessRequest) (AlbumDetail, error)
func (*Module) RestoreSource ¶ added in v0.2.0
RestoreSource offers an ignored Immich album for import again.
func (*Module) RetryChapters ¶
RetryChapters requeues extraction for one video after a failure. Playback and publication never wait for it.
func (*Module) RetryImport ¶
func (*Module) ReviewPublication ¶
ReviewPublication reports blockers and the current ordinary audience. It does not publish, enqueue work, or record a notification baseline.
func (*Module) SaveAlbumAccess ¶
func (m *Module) SaveAlbumAccess(ctx context.Context, albumID string, request SaveAlbumAccessRequest) (AlbumDetail, error)
SaveAlbumAccess replaces only the Album-wide allows named in the request. Unchecking removes the Album allow and leaves narrower decisions alone.
func (*Module) SaveCoverOrder ¶
func (m *Module) SaveCoverOrder(ctx context.Context, albumID string, request SaveCoverOrderRequest) (AlbumDetail, error)
SaveCoverOrder replaces the Album's Cover Order. Every listed Moment must belong to the Album and appear once; Moments left out fall back to capture order. Positions are cleared first so the unique place constraint never trips while the order is rewritten.
func (*Module) SaveEntryRules ¶
func (m *Module) SaveEntryRules(ctx context.Context, albumID, entryID string, request SaveRulesRequest) (AlbumDetail, error)
func (*Module) SaveMomentRules ¶
func (m *Module) SaveMomentRules(ctx context.Context, albumID, momentID string, request SaveRulesRequest) (AlbumDetail, error)
func (*Module) SetMomentCover ¶
func (m *Module) SetMomentCover(ctx context.Context, albumID, momentID string, request SetMomentCoverRequest) (AlbumDetail, error)
func (*Module) SplitMoment ¶
func (m *Module) SplitMoment(ctx context.Context, albumID, sourceMomentID string, request SplitMomentRequest) (AlbumDetail, error)
func (*Module) StartImport ¶
StartImport commits source identity and durable enqueueing together. Existing Albums can be reopened even when Immich is unavailable or its version is unsupported.
func (*Module) UnpublishAlbum ¶
UnpublishAlbum retains all curation and history while hiding ordinary access.
func (*Module) UpdateAlbum ¶
func (m *Module) UpdateAlbum(ctx context.Context, id string, request UpdateAlbumRequest) (AlbumDetail, error)
func (*Module) UpdateMoment ¶
func (m *Module) UpdateMoment(ctx context.Context, albumID, momentID string, request UpdateMomentRequest) (AlbumDetail, error)
func (*Module) UpdateVideo ¶
func (m *Module) UpdateVideo(ctx context.Context, albumID, entryID string, request UpdateVideoRequest) (AlbumDetail, error)
UpdateVideo sets or clears the Media Item's global video title. The title belongs to the Media Item, so every Album showing that video changes.
func (*Module) ViewAlbum ¶
func (m *Module) ViewAlbum(ctx context.Context, actorID, previewPersonID, albumID string) (ViewerAlbum, error)
ViewAlbum uses one snapshot for identity, effective counts and configured cover.
func (*Module) ViewAlbums ¶
func (*Module) ViewEntries ¶
func (m *Module) ViewEntries(ctx context.Context, actorID, previewPersonID, albumID, kind string, page EntryPageRequest) (ViewerPage, error)
ViewEntries returns separate cursor-paginated galleries without Curator metadata.
func (*Module) ViewLibrary ¶
ViewLibrary summarizes accessible media across Albums in newest-first order.
func (*Module) ViewLibraryEntries ¶
func (m *Module) ViewLibraryEntries(ctx context.Context, actorID, kind string, page EntryPageRequest) (ViewerPage, error)
ViewLibraryEntries returns newest-first media with one accessible Entry per item.
func (*Module) ViewingGroups ¶
ViewingGroups derives who will see which cover from the same saved rules the viewer uses. Publication state is ignored: the Curator is preparing the Album, and the groups describe the view after publication.
func (*Module) VisibleEntries ¶
func (m *Module) VisibleEntries(ctx context.Context, db bun.IDB, personID string) ([]notifications.VisibleEntry, error)
VisibleEntries lists every Album Entry the Person can view as an ordinary viewer: published Albums and allowing Access Decisions only. A Curator's administrative bypass is deliberately excluded so announcement baselines never treat unpublished or otherwise viewer-ineligible content as announced.
type Moment ¶
type Moment struct {
ID string `json:"id"`
Title string `json:"title"`
Label string `json:"label"`
Date string `json:"date"`
EndDate string `json:"end_date"`
CoverEntryID string `json:"cover_entry_id"`
// CoverPosition is the Moment's place in the Album's Cover Order, 0 when
// it only competes in capture order.
CoverPosition int `json:"cover_position"`
Entries []Entry `json:"entries"`
Access MomentAccess `json:"access"`
}
type MomentAccess ¶
type MomentAccess struct {
People []AccessPerson `json:"people"`
Faces []FaceRecord `json:"faces"`
RefreshedAt *time.Time `json:"refreshed_at"`
}
type MoveEntriesRequest ¶
type MoveEntriesRequest struct {
EntryIDs []string `json:"entry_ids" validate:"required,min=1,dive,uuid"`
DestinationMomentID string `json:"destination_moment_id" validate:"required,uuid"`
ReviewToken string `json:"review_token"`
}
Moves and splits pick covers themselves: a Moment that loses its cover, or a Moment created by a split, starts with its earliest item. Curators change covers afterwards from the Moment itself.
func (MoveEntriesRequest) ValidationMessage ¶
func (MoveEntriesRequest) ValidationMessage(field, _ string) string
type PublicationAudience ¶
type PublicationReview ¶
type PublicationReview struct {
Title string `json:"title"`
PhotoCount int `json:"photo_count"`
VideoCount int `json:"video_count"`
MomentCount int `json:"moment_count"`
Audience []PublicationAudience `json:"audience"`
Blockers []string `json:"blockers"`
Warnings []string `json:"warnings"`
ReviewToken string `json:"review_token"`
}
PublicationReview lists what publication would expose and why it may wait. Warnings never block; blockers do.
type PublicationUseCases ¶
type PublicationUseCases interface {
ReviewPublication(context.Context, string) (PublicationReview, error)
PublishAlbum(context.Context, string, PublishRequest) (AlbumDetail, error)
UnpublishAlbum(context.Context, string) (AlbumDetail, error)
DeleteAlbum(context.Context, string, DeleteAlbumRequest) error
}
PublicationUseCases is the HTTP seam for publication and permanent removal.
type PublishRequest ¶
type PublishRequest struct {
ReviewToken string `json:"review_token" validate:"required"`
}
func (PublishRequest) ValidationMessage ¶
func (PublishRequest) ValidationMessage(field, _ string) string
type RemoveAccessPreview ¶
type RemoveAccessPreview struct {
PersonID string `json:"person_id"`
DisplayName string `json:"display_name"`
Changes []AudienceChange `json:"changes"`
ReviewToken string `json:"review_token"`
}
type RemoveAccessPreviewRequest ¶
type RemoveAccessPreviewRequest struct {
PersonID string `json:"person_id" validate:"required,uuid"`
}
type RemoveAccessRequest ¶
type SaveAlbumAccessRequest ¶
type SaveAlbumAccessRequest struct {
People []AlbumAccessChoice `json:"people" validate:"required,dive"`
}
func (SaveAlbumAccessRequest) ValidationMessage ¶
func (SaveAlbumAccessRequest) ValidationMessage(field, _ string) string
type SaveCoverOrderRequest ¶
type SaveCoverOrderRequest struct {
MomentIDs []string `json:"moment_ids" validate:"dive,uuid"`
}
SaveCoverOrderRequest replaces an Album's Cover Order with these Moments in this order. An empty list clears it.
func (SaveCoverOrderRequest) ValidationMessage ¶
func (SaveCoverOrderRequest) ValidationMessage(field, rule string) string
type SaveRulesRequest ¶
type SaveRulesRequest struct {
Decisions []AccessResolution `json:"decisions" validate:"required,dive"`
}
func (SaveRulesRequest) ValidationMessage ¶
func (SaveRulesRequest) ValidationMessage(field, _ string) string
type SetMomentCoverRequest ¶
type SetMomentCoverRequest struct {
EntryID string `json:"entry_id" validate:"required,uuid"`
}
func (SetMomentCoverRequest) ValidationMessage ¶
func (SetMomentCoverRequest) ValidationMessage(field, _ string) string
type SourceAlbum ¶
type SourceAlbum struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
Count int `json:"count"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
CoverURL string `json:"cover_url"`
AlbumID string `json:"album_id"`
}
SourceAlbum describes an Immich Album available for import.
type SourcePage ¶
type SourcePage struct {
Albums []SourceAlbum `json:"albums"`
Page int `json:"page"`
Pages int `json:"pages"`
Total int `json:"total"`
Ignored int `json:"ignored"`
}
SourcePage is one page of Immich albums, either those offered for import or those a Curator ignored. Ignored counts every ignored album Immich still has, whichever side of the list this page shows.
type SourceRequest ¶ added in v0.2.0
type SourceRequest struct {
SourceID string `json:"source_id" validate:"required,max=1024"`
}
SourceRequest names one Immich album to ignore or restore.
type SplitMomentRequest ¶
type SplitMomentRequest struct {
EntryIDs []string `json:"entry_ids" validate:"required,min=1,dive,uuid"`
NewTitle string `json:"new_title" mod:"trim" validate:"max=200"`
ReviewToken string `json:"review_token"`
}
func (SplitMomentRequest) ValidationMessage ¶
func (SplitMomentRequest) ValidationMessage(field, rule string) string
type StructurePreview ¶
type StructurePreview struct {
Ready bool `json:"ready"`
ReviewToken string `json:"review_token"`
RemovesMoment bool `json:"removes_moment"`
Changes []AudienceChange `json:"changes"`
Conflicts []AccessConflict `json:"conflicts"`
}
type SyncAddition ¶
type SyncAddition struct {
SourceID string `json:"source_id"`
Filename string `json:"filename"`
Kind string `json:"kind"`
Title string `json:"title"`
CapturedAt string `json:"captured_at"`
ThumbnailURL string `json:"thumbnail_url"`
Returning bool `json:"returning"`
SuggestedMomentID string `json:"suggested_moment_id"`
MomentID string `json:"moment_id"`
Exclude bool `json:"exclude"`
OtherAlbums []SyncAlbumRef `json:"other_albums"`
}
SyncAddition is a source asset the Album does not currently show. Returning means a removed Album Entry keeps its identity and announcement history. Media the Curator excluded is not listed here; it lives in the Album's Excluded section.
type SyncAlbumRef ¶
type SyncChange ¶
type SyncChange struct {
EntryID string `json:"entry_id"`
Filename string `json:"filename"`
Kind string `json:"kind"`
Title string `json:"title"`
ThumbnailURL string `json:"thumbnail_url"`
Excluded bool `json:"excluded"`
Fields []string `json:"fields"`
CapturedAt string `json:"captured_at"`
NewCapturedAt string `json:"new_captured_at"`
Available bool `json:"available"`
NewAvailable bool `json:"new_available"`
OtherAlbums []SyncAlbumRef `json:"other_albums"`
}
SyncChange is a Media Item whose source facts differ. Fields names what changed: checksum, capture_time, availability, filename, or details. Excluded media is refreshed too so Add back never carries stale facts.
type SyncCover ¶
type SyncCover struct {
MomentID string `json:"moment_id" validate:"required,max=64"`
EntryID string `json:"entry_id" validate:"required,max=1100"`
}
SyncCover replaces a Moment cover that the reviewed removals invalidate. EntryID is an Album Entry ID or, for media joining in the same review, the placeholder the review lists, so it is bounded like a source ID.
type SyncCoverChoice ¶
type SyncCoverChoice struct {
MomentID string `json:"moment_id"`
MomentLabel string `json:"moment_label"`
EntryID string `json:"entry_id"`
Options []SyncCoverOption `json:"options"`
}
SyncCoverChoice is a surviving Moment whose configured cover is being removed. EntryID is the Curator's chosen replacement, empty until chosen.
type SyncCoverOption ¶
type SyncDescription ¶
type SyncMomentOption ¶
type SyncMomentOption struct {
ID string `json:"id"`
Label string `json:"label"`
New bool `json:"new"`
}
SyncMomentOption is a destination: an existing Moment or one the apply would create, keyed "new:YYYY-MM-DD".
type SyncPlacement ¶
type SyncPlacement struct {
SourceID string `json:"source_id" validate:"required,max=1024"`
MomentID string `json:"moment_id" validate:"max=64"`
Exclude bool `json:"exclude"`
}
SyncPlacement chooses where one source asset joins the Album. MomentID is an existing Moment or a proposed Moment key from the review. Exclude keeps the asset out of this Album while it remains in the Immich album.
type SyncRemoval ¶
type SyncRemoval struct {
EntryID string `json:"entry_id"`
Filename string `json:"filename"`
Kind string `json:"kind"`
Title string `json:"title"`
CapturedAt string `json:"captured_at"`
ThumbnailURL string `json:"thumbnail_url"`
MomentID string `json:"moment_id"`
MomentLabel string `json:"moment_label"`
Cover bool `json:"cover"`
Excluded bool `json:"excluded"`
Reason string `json:"reason"`
}
SyncRemoval is an Album Entry whose asset is no longer shown by the Immich album. Reason is left_album, trashed, or deleted; a trashed asset returns as a returning addition if it is restored from the Immich trash. Excluded means the entry was in the Excluded section, which it leaves; Moment fields are empty for it.
type SyncRequest ¶
type SyncRequest struct {
Placements []SyncPlacement `json:"placements" validate:"dive"`
Covers []SyncCover `json:"covers" validate:"dive"`
ReviewToken string `json:"review_token"`
}
SyncRequest carries the Curator's review decisions. A check accepts it without a token; apply requires the token from the matching review.
type SyncReview ¶
type SyncReview struct {
Ready bool `json:"ready"`
UpToDate bool `json:"up_to_date"`
ReviewToken string `json:"review_token"`
Description *SyncDescription `json:"description" tstype:"SyncDescription | null"`
Additions []SyncAddition `json:"additions"`
Removals []SyncRemoval `json:"removals"`
Changes []SyncChange `json:"changes"`
CoverChoices []SyncCoverChoice `json:"cover_choices"`
RemovedMoments []SyncMomentOption `json:"removed_moments"`
Moments []SyncMomentOption `json:"moments"`
Audience []AudienceChange `json:"audience"`
Blockers []string `json:"blockers"`
FacesRefreshed bool `json:"faces_refreshed"`
FacesMessage string `json:"faces_message"`
}
SyncReview is the temporary diff between the Album and its Immich album. Nothing about it is stored; leaving the review discards it.
type UpdateAlbumRequest ¶
type UpdateAlbumRequest struct {
Title string `json:"title" mod:"trim" validate:"required,max=200"`
}
type UpdateMomentRequest ¶
type UpdateMomentRequest struct {
Title string `json:"title" mod:"trim" validate:"max=200"`
}
func (UpdateMomentRequest) ValidationMessage ¶
func (UpdateMomentRequest) ValidationMessage(field, rule string) string
type UpdateVideoRequest ¶
type UpdateVideoRequest struct {
Title string `json:"title" mod:"trim" validate:"max=200"`
}
UpdateVideoRequest sets or, when blank, clears a video's global title.
func (UpdateVideoRequest) ValidationMessage ¶
func (UpdateVideoRequest) ValidationMessage(field, rule string) string
type ViewerAlbum ¶
type ViewerAlbum struct {
ID string `json:"id"`
Title string `json:"title"`
Description string `json:"description"`
PhotoCount int `json:"photo_count"`
VideoCount int `json:"video_count"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
CoverURL string `json:"cover_url"`
// CoverPreviewURL is the same cover at Immich's larger variant for the
// Album header; list cards keep the small thumbnail.
CoverPreviewURL string `json:"cover_preview_url"`
Days []ViewerDay `json:"days"`
}
ViewerAlbum contains only the selected Person's accessible presentation.
type ViewerDay ¶
type ViewerDay struct {
Date string `json:"date"`
PhotoCount int `json:"photo_count"`
VideoCount int `json:"video_count"`
PhotoRatios []float64 `json:"photo_ratios" bun:"photo_ratios,array"`
VideoRatios []float64 `json:"video_ratios" bun:"video_ratios,array"`
}
ViewerDay counts one local capture day. PhotoRatios and VideoRatios list each item's width-to-height ratio in gallery order, truncated to three decimals, so the browser can lay out every day before the media arrives.
type ViewerEntry ¶
type ViewerEntry struct {
ID string `json:"id"`
Kind string `json:"kind"`
Title string `json:"title"`
CapturedAt string `json:"captured_at"`
Available bool `json:"available"`
ThumbnailURL string `json:"thumbnail_url"`
PreviewURL string `json:"preview_url"`
// DownloadURL streams the original photo or video. It is empty in Curator
// preview and for unavailable media.
DownloadURL string `json:"download_url"`
// PlaybackURL is the ranged video stream, also in preview. Photos have none.
PlaybackURL string `json:"playback_url"`
Width int `json:"width"`
Height int `json:"height"`
// Chapters are read-only navigation marks. ChapterStatus is pending,
// complete, or failed; photos leave both empty.
Chapters []Chapter `json:"chapters"`
ChapterStatus string `json:"chapter_status"`
}
ViewerEntry is one gallery item. Photos have no title. A video's title is the Curator's title when set, otherwise the original filename without its extension.
type ViewerLibrary ¶
type ViewerLibrary struct {
PhotoCount int `json:"photo_count"`
VideoCount int `json:"video_count"`
Days []ViewerDay `json:"days"`
}
ViewerLibrary counts each accessible media item once across Albums.
type ViewerPage ¶
type ViewerPage struct {
Entries []ViewerEntry `json:"entries"`
NextCursor string `json:"next_cursor"`
}
type ViewerUseCases ¶
type ViewerUseCases interface {
ViewLibrary(ctx context.Context, actorID string) (ViewerLibrary, error)
ViewLibraryEntries(ctx context.Context, actorID, kind string, page EntryPageRequest) (ViewerPage, error)
ViewAlbum(ctx context.Context, actorID, previewPersonID, albumID string) (ViewerAlbum, error)
ViewAlbums(ctx context.Context, actorID string) ([]ViewerAlbum, error)
ViewEntries(ctx context.Context, actorID, previewPersonID, albumID, kind string, page EntryPageRequest) (ViewerPage, error)
}
ViewerUseCases keeps HTTP identity selection separate from viewer projections.
type ViewingGroup ¶
type ViewingGroup struct {
MomentIDs []string `json:"moment_ids"`
People []ViewingPerson `json:"people"`
}
ViewingGroup is one set of People and the Moments whose covers all of them can see, in Album display order. Which of those covers they get follows from the Cover Order, so the frontend can preview an unsaved order.
type ViewingGroups ¶
type ViewingGroups struct {
Groups []ViewingGroup `json:"groups"`
Placeholder []ViewingPerson `json:"placeholder"`
}
ViewingGroups previews who will see which Album cover. People who can see exactly the same Moment covers form one Viewing Group; they are derived on every read and never stored. Placeholder lists People with some access but no visible cover, who see the neutral placeholder instead.