media

package
v1.6.23 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: AGPL-3.0 Imports: 22 Imported by: 0

Documentation

Overview

Package media provides the core Media Service for the Lesser project's API alignment. This service handles all media operations including file uploads, processing, metadata updates, and storage management. It emits appropriate events for real-time streaming and queues async processing for thumbnails and optimization.

Package media provides streaming pipeline integration

Index

Constants

View Source
const UploadGrantTTL = 15 * time.Minute

UploadGrantTTL bounds every upload grant. The minted presigned PUT URL is a bearer capability for writing unverified bytes into the internal bucket, so the window must be short: fifteen minutes comfortably covers real uploads up to the size cap even on slow links while tightly bounding the exposure of a leaked URL, and it stays on the same order as the existing five-minute read presigns. The DynamoDB TTL attribute self-cleans grant rows after the same bound.

Variables

View Source
var (
	// ErrMediaNotFound is returned when media is not found
	ErrMediaNotFound = errors.NewAppError(errors.CodeNotFound, errors.CategoryMedia, "media not found")

	// ErrMediaCreateFailed is returned when media creation fails
	ErrMediaCreateFailed = errors.FailedToCreate("media", stdErrors.New("failed to create media"))

	// ErrMediaUpdateFailed is returned when media update fails
	ErrMediaUpdateFailed = errors.FailedToUpdate("media", stdErrors.New("failed to update media"))

	// ErrMediaDeleteFailed is returned when media deletion fails
	ErrMediaDeleteFailed = errors.FailedToDelete("media", stdErrors.New("failed to delete media"))

	// ErrMediaAccessDenied is returned when media access is denied
	ErrMediaAccessDenied = errors.AccessDeniedForResource("media", "unknown")

	// ErrMediaProcessingFailed is returned when media processing fails
	ErrMediaProcessingFailed = errors.ProcessingFailed("media processing", stdErrors.New("media processing failed"))

	// ErrDatabaseOperation is returned when database operations fail
	ErrDatabaseOperation = errors.NewStorageError(errors.CodeInternal, "database error")

	// ErrMediaStorageFailed is returned when media storage fails
	ErrMediaStorageFailed = errors.FailedToStore("media record", stdErrors.New("failed to store media record"))

	// ErrMediaRetrievalFailed is returned when media retrieval fails
	ErrMediaRetrievalFailed = errors.FailedToGet("media", stdErrors.New("failed to get media"))

	// ErrMediaFileDataRequired is returned when file data is required but missing
	ErrMediaFileDataRequired = errors.NewValidationError("file_data", "required")

	// ErrMediaFileTooLarge is returned when file size exceeds maximum limit
	ErrMediaFileTooLarge = errors.NewValidationError("file_size", "too large")

	// ErrMediaUnsupportedType is returned when content type is not supported
	ErrMediaUnsupportedType = errors.ContentTypeNotAllowed("unknown")

	// ErrMediaFileExtensionMismatch is returned when file extension doesn't match content type
	ErrMediaFileExtensionMismatch = errors.NewValidationError("file_extension", "does not match content type")

	// ErrMediaUnsafeSVG is returned when SVG content contains active or external content.
	ErrMediaUnsafeSVG = errors.NewValidationError("svg", "unsafe svg content")

	// ErrMediaNotReady is returned when media is not ready for viewing
	ErrMediaNotReady = errors.MediaAttachmentNotReady("unknown")

	// ErrMediaProcessingQueueFailed is returned when media processing queue operation fails
	ErrMediaProcessingQueueFailed = errors.ProcessingFailed("media processing queue", stdErrors.New("media processing queue failed"))

	// ErrMediaNotReadyForStreaming is returned when media is not ready for streaming
	ErrMediaNotReadyForStreaming = errors.NewValidationError("media_streaming", "not ready for streaming")

	// ErrMediaValidationFailed is returned when media validation fails
	ErrMediaValidationFailed = errors.MediaAttachmentValidationFailed("unknown reason")

	// ErrMediaUnauthorizedAccess is returned when user is not authorized to access/modify media
	ErrMediaUnauthorizedAccess = errors.InsufficientPermissions("media access")

	// ErrMediaInUse prevents deletion while a status, draft, or other object still references the media.
	ErrMediaInUse = errors.NewAppError(errors.CodeConflict, errors.CategoryMedia, "media is still referenced")
)

Media service specific errors

View Source
var (
	// ErrTranscodingServiceUnavailable is returned when transcoding service is not available
	ErrTranscodingServiceUnavailable = errors.New("transcoding service unavailable")
	// ErrManifestServiceUnavailable is returned when manifest service is not available
	ErrManifestServiceUnavailable = errors.New("manifest service unavailable")
	// ErrCloudFrontServiceUnavailable is returned when CloudFront service is not available
	ErrCloudFrontServiceUnavailable = errors.New("cloudfront service unavailable")
	// ErrTranscodingJobNotFound is returned when a transcoding job is not found
	ErrTranscodingJobNotFound = errors.New("transcoding job not found")
)
View Source
var (
	// ErrUploadGrantUnavailable reports that the upload grant surface is not
	// wired (missing repository or object-store capability); it fails closed.
	ErrUploadGrantUnavailable = errors.New("upload grant service is unavailable")

	// ErrUploadGrantNotFound reports an unknown grant for the caller; owner
	// scoping is enforced by the repository key construction.
	ErrUploadGrantNotFound = errors.New("upload grant not found")

	// ErrUploadGrantExpired reports a grant past its bounded expiry; finalize
	// fails closed and never admits an asset from an expired grant.
	ErrUploadGrantExpired = errors.New("upload grant has expired")

	// ErrUploadGrantNotMinted reports a finalize attempt on a grant that was
	// already consumed (used or failed digest).
	ErrUploadGrantNotMinted = errors.New("upload grant is not minted")

	// ErrUploadGrantAlreadyConsumed reports that a concurrent finalize won the
	// single-use consume; the caller must not retry against the same grant.
	ErrUploadGrantAlreadyConsumed = errors.New("upload grant was already consumed by another finalize")

	// ErrUploadGrantDigestMismatch reports that the uploaded object's actual
	// bytes (or their size/content type) do not match the grant's declaration.
	// The grant is consumed and the object is deleted.
	ErrUploadGrantDigestMismatch = errors.New("uploaded bytes do not match the declared upload grant")

	// ErrUploadGrantObjectMissing reports a finalize before the caller PUT the
	// declared bytes. The grant is left minted so the PUT can be retried.
	ErrUploadGrantObjectMissing = errors.New("uploaded object not found; PUT the declared bytes before finalizing")

	// ErrUploadGrantObjectEmpty reports an empty uploaded object; the grant is
	// left minted for a retried PUT and the empty object is removed.
	ErrUploadGrantObjectEmpty = errors.New("uploaded object is empty")
)

Functions

func IsNSFWBlocked

func IsNSFWBlocked(err error) bool

IsNSFWBlocked checks if an error is an NSFW blocked error

func ValidateSVGUpload added in v1.2.53

func ValidateSVGUpload(contentType string, data []byte) error

ValidateSVGUpload rejects SVG uploads that contain active content or external references. SVG is XML but browsers execute scripts, event handlers, and CSS URLs in many SVG contexts, so lesser accepts only inert inline SVG markup.

Types

type DeleteMediaCommand added in v1.6.4

type DeleteMediaCommand struct {
	MediaID string `json:"media_id" validate:"required"`
	UserID  string `json:"user_id" validate:"required"`
}

DeleteMediaCommand identifies media and the owner requesting its removal.

type EditorialAccess added in v1.6.23

type EditorialAccess struct {
	URL         string
	ExpiresAt   time.Time
	ContentHash string
}

EditorialAccess is a short-lived, exact-byte read for an internal asset. Authorization of the bound draft is deliberately performed by the CMS service before this storage capability is invoked.

type GetMediaQuery

type GetMediaQuery struct {
	MediaID  string `json:"media_id" validate:"required"`
	ViewerID string `json:"viewer_id"` // User requesting the media (for privacy checks)
}

GetMediaQuery contains parameters for retrieving media

type InternalS3Service added in v1.6.23

type InternalS3Service interface {
	UploadInternalFile(ctx context.Context, bucket, key string, data []byte, contentType, kmsKeyID string) (string, error)
}

InternalS3Service stores an object under the instance KMS key. The public CloudFront origin has no permission to decrypt these objects, while Lesser's authorized Lambda role can presign exact-object reads.

type JobMessage

type JobMessage struct {
	JobID     string `json:"job_id"`
	MediaID   string `json:"media_id"`
	Username  string `json:"username"`
	Timestamp int64  `json:"timestamp"`
}

JobMessage represents a message for media processing

type JobQueueService

type JobQueueService interface {
	QueueMediaJob(ctx context.Context, msg JobMessage) error
}

JobQueueService defines the interface for job queue operations

type ListMediaQuery

type ListMediaQuery struct {
	Owner     string     `json:"owner"`
	Requester string     `json:"requester"`
	MediaType string     `json:"media_type"`
	MimeType  string     `json:"mime_type"`
	Cursor    string     `json:"cursor"`
	Limit     int        `json:"limit"`
	Since     *time.Time `json:"since"`
	Until     *time.Time `json:"until"`
}

ListMediaQuery contains parameters for listing media with filters

type ListMediaResult

type ListMediaResult struct {
	Items      []*models.Media `json:"items"`
	NextCursor string          `json:"next_cursor"`
	HasMore    bool            `json:"has_more"`
	Total      int64           `json:"total"`
}

ListMediaResult contains paginated media results

type MetadataDeleter added in v1.6.4

type MetadataDeleter interface {
	DeleteMediaMetadata(ctx context.Context, mediaID string) error
}

MetadataDeleter removes processor metadata associated with a media ID.

type MintUploadGrantInput added in v1.6.23

type MintUploadGrantInput struct {
	// Owner is the actor who may PUT and finalize; the grant row lives in this
	// actor's partition.
	Owner string
	// ContentType is the declared media type, signed into the presigned PUT.
	ContentType string
	// MaxSizeBytes is the declared size cap; finalize fails closed beyond it.
	MaxSizeBytes int64
	// ContentSHA256 is the hex-encoded sha256 of the exact intended bytes.
	ContentSHA256 string
}

MintUploadGrantInput declares the constraints the minted grant binds.

type NSFWBlockedError

type NSFWBlockedError struct {
	// contains filtered or unexported fields
}

NSFWBlockedError represents an error when NSFW content is blocked

func NewNSFWBlockedError

func NewNSFWBlockedError(message string) *NSFWBlockedError

NewNSFWBlockedError creates a new NSFW blocked error

func (*NSFWBlockedError) Error

func (e *NSFWBlockedError) Error() string

type ObjectDeleter added in v1.6.4

type ObjectDeleter interface {
	DeleteMediaObject(ctx context.Context, bucket, key string) error
}

ObjectDeleter removes one physical media object from its backing store.

type OrphanedPublishedMintSource added in v1.6.23

type OrphanedPublishedMintSource interface {
	ListOrphanedPublishedMintIDs(ctx context.Context) ([]string, error)
	RecheckOrphanedPublishedMint(ctx context.Context, mediaID string) (bool, error)
}

OrphanedPublishedMintSource enumerates durable published mints that no live article references: assets minted by a publish whose draft is terminally failed and whose compensating rollback never ran or failed. The registry wires it from the CMS side; reconciliation is a no-op without it. RecheckOrphanedPublishedMint re-verifies one candidate's orphan premise at unpublish time so the enumerate-then-unpublish window cannot clear an asset a concurrent republish just made live.

type ProcessingQueue

type ProcessingQueue interface {
	QueueMediaProcessing(ctx context.Context, mediaID string, processingType string) error
}

ProcessingQueue defines the interface for async media processing

type PublishedMedia added in v1.6.23

type PublishedMedia struct {
	MediaID     string
	ContentHash string
	ContentType string
	FileSize    int64
	Width       int
	Height      int
	URL         string
	S3Key       string
	PublishedAt time.Time
}

PublishedMedia is the durable public serving minted for one internal editorial asset at the publish transition. The URL serves the exact approved original bytes indefinitely: no expiring presignature, no temporary generator URL, no dependence on the internal KMS-read posture.

type PublishedMediaCopier added in v1.6.23

type PublishedMediaCopier interface {
	CopyFileToPublished(ctx context.Context, bucket, sourceKey, destinationKey, contentType string) (string, error)
}

PublishedMediaCopier copies the exact original bytes of an internal editorial asset to the durable unsigned serving surface at the publish transition. The destination object is SSE-S3 (the CloudFront origin can serve it) while the source remains SSE-KMS under the instance key.

type RenditionVariant

type RenditionVariant struct {
	Quality        string
	Width          int
	Height         int
	Bitrate        int
	Codec          string
	HLSPlaylistURL string
	DASHSegmentURL string
	FileSize       int64
	Format         string
}

RenditionVariant represents a transcoded variant

type Renditions

type Renditions struct {
	MediaID           string
	HLSMasterURL      string
	DASHManifestURL   string
	Variants          []RenditionVariant
	ThumbnailURLs     []string
	TranscodingStatus string
	LastUpdated       time.Time
}

Renditions contains available renditions for a media item

type Result

type Result struct {
	Media  *models.Media      `json:"media"`
	Events []*streaming.Event `json:"events"`
}

Result contains media and associated events that were emitted

type S3Presigner added in v1.6.23

type S3Presigner interface {
	GeneratePresignedURL(ctx context.Context, bucket, key string, expiry time.Duration) (string, error)
}

S3Presigner issues short-lived object reads without making an internal asset part of the unsigned public CDN surface.

type S3Service

type S3Service interface {
	UploadFile(ctx context.Context, bucket, key string, data []byte, contentType string) (string, error)
	DeleteFile(ctx context.Context, bucket, key string) error
}

S3Service defines the interface for S3 operations (for abstraction/mocking)

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service provides media operations

func NewService

func NewService(
	mediaRepo interfaces.MediaRepository,
	accountRepo accountPreferencesRepository,
	publisher streaming.Publisher,
	jobQueue JobQueueService,
	logger *zap.Logger,
	s3Bucket string,
	cdnDomain string,
) *Service

NewService creates a new Media Service with the required dependencies

func (*Service) DeleteMedia added in v1.6.4

func (s *Service) DeleteMedia(ctx context.Context, cmd *DeleteMediaCommand) error

DeleteMedia deletes an owned media record and notifies the owner's stream.

func (*Service) FinalizeUploadGrant added in v1.6.23

func (s *Service) FinalizeUploadGrant(ctx context.Context, ownerID, grantID string) (*models.Media, error)

FinalizeUploadGrant verifies that the stored object's actual bytes match the grant's declared sha256 (and declared size/type bounds) BEFORE any media record exists, consumes the grant exactly once, and only then creates the internal editorial media record through the M0/M1 pipeline. The size cap is enforced from the object's HEAD metadata before any download, so an oversized object is rejected, consumed to FAILED_DIGEST, and deleted without ever entering memory; the digest is then recomputed over a bounded streaming read as defense-in-depth. On any mismatch the grant is consumed to FAILED_DIGEST and the unverified object is deleted; a concurrent finalize loses the single-use consume and fails closed.

func (*Service) GenerateSignedStreamURL

func (s *Service) GenerateSignedStreamURL(ctx context.Context, mediaID string, viewerID string, quality *string) (*StreamSession, error)

GenerateSignedStreamURL generates a signed streaming URL for a media item owned by viewerID.

func (*Service) GetMedia

func (s *Service) GetMedia(ctx context.Context, query *GetMediaQuery) (*models.Media, error)

GetMedia retrieves media with privacy checks

func (*Service) GetMediaRenditions

func (s *Service) GetMediaRenditions(ctx context.Context, mediaID string) (*Renditions, error)

GetMediaRenditions retrieves available renditions for a media item

func (*Service) GetStreamingURL

func (s *Service) GetStreamingURL(ctx context.Context, mediaID string, viewerID string) (*model.MediaStream, error)

GetStreamingURL returns a media streaming URL and metadata for GraphQL. The viewer must own the media; public status/object resolvers should expose already-authorized attachment URLs instead of minting owner-scoped stream URLs.

func (*Service) IssueEditorialAccess added in v1.6.23

func (s *Service) IssueEditorialAccess(ctx context.Context, mediaID string) (*EditorialAccess, error)

IssueEditorialAccess signs a read for one internal object. Callers must first prove that this media ID is bound to a draft the current actor owns or has an active review grant for; this method intentionally grants no list capability.

func (*Service) ListMedia

func (s *Service) ListMedia(ctx context.Context, query *ListMediaQuery) (*ListMediaResult, error)

ListMedia returns paginated media filtered by owner and type

func (*Service) MarkMediaFailed

func (s *Service) MarkMediaFailed(ctx context.Context, mediaID string, errorMsg string) error

MarkMediaFailed marks media as failed and emits events

func (*Service) MarkMediaProcessed

func (s *Service) MarkMediaProcessed(ctx context.Context, mediaID string, variants map[string]models.MediaVariant) error

MarkMediaProcessed marks media as successfully processed and emits events

func (*Service) MintUploadGrant added in v1.6.23

func (s *Service) MintUploadGrant(ctx context.Context, input MintUploadGrantInput) (*models.UploadGrant, string, error)

MintUploadGrant creates a one-time, hash-bound, actor-scoped upload grant and returns the presigned PUT URL bound to its constraints. The object key embeds a media ID minted with the grant so the PUT target and the final media record share one unguessable identity.

func (*Service) PreloadMedia

func (s *Service) PreloadMedia(ctx context.Context, viewerID string, mediaIDs []string) ([]string, error)

PreloadMedia preloads manifests and primes CDN cache for media items owned by viewerID.

func (*Service) PublishMediaDurably added in v1.6.23

func (s *Service) PublishMediaDurably(ctx context.Context, mediaID string) (*PublishedMedia, error)

PublishMediaDurably transitions one internal editorial asset to durable public serving of its exact approved bytes. The publish transition is the single point where durable public serving is minted: before it, internal assets expose no unsigned URL through the application contract.

func (*Service) ReconcileOrphanedPublishedMedia added in v1.6.23

func (s *Service) ReconcileOrphanedPublishedMedia(ctx context.Context) error

ReconcileOrphanedPublishedMedia re-runs the best-effort unpublish for every durable published mint the wired OrphanedPublishedMintSource reports as orphaned (owning draft terminally failed, no live article reference). It is idempotent: UnpublishMediaDurably is a no-op once the record is unpublished and version-guarded against concurrent re-mints, so repeated reconciliation is safe and a live published asset is never touched. Before each unpublish the source re-verifies the candidate's orphan premise at the current state, so a draft that was republished (or an article that appeared) between the enumeration and the unpublish aborts that candidate.

func (*Service) SetCloudFrontService

func (s *Service) SetCloudFrontService(cloudfrontService cloudfrontService)

SetCloudFrontService sets the CloudFront service (optional)

func (*Service) SetDeletionDependencies added in v1.6.4

func (s *Service) SetDeletionDependencies(objectDeleter ObjectDeleter, metadataDeleter MetadataDeleter)

SetDeletionDependencies wires physical-object and processor-metadata cleanup.

func (*Service) SetEditorialKMSKeyID added in v1.6.23

func (s *Service) SetEditorialKMSKeyID(keyID string)

SetEditorialKMSKeyID configures the instance key used to keep internal editorial originals outside the unsigned CDN read surface.

func (*Service) SetManifestService

func (s *Service) SetManifestService(manifestService manifestService)

SetManifestService sets the manifest service (optional)

func (*Service) SetMaxFileSize

func (s *Service) SetMaxFileSize(maxSize int64)

SetMaxFileSize sets the maximum allowed file size

func (*Service) SetOrphanPublishedMintSource added in v1.6.23

func (s *Service) SetOrphanPublishedMintSource(source OrphanedPublishedMintSource)

SetOrphanPublishedMintSource wires the enumeration of orphaned durable published mints used by ReconcileOrphanedPublishedMedia. Leaving it unwired makes reconciliation a no-op; the registry wires it from the CMS side.

func (*Service) SetS3Service added in v1.6.23

func (s *Service) SetS3Service(s3Service S3Service)

SetS3Service wires the object-storage client used for original media bytes.

func (*Service) SetTranscodingService

func (s *Service) SetTranscodingService(transcoder transcoderService)

SetTranscodingService sets the transcoding service (optional)

func (*Service) SetUploadGrantRepository added in v1.6.23

func (s *Service) SetUploadGrantRepository(repo interfaces.UploadGrantRepository)

SetUploadGrantRepository wires the grant storage; upload grant operations fail closed until it is set.

func (*Service) SubmitTranscodeJob

func (s *Service) SubmitTranscodeJob(ctx context.Context, cmd *SubmitTranscodeJobCommand) (*TranscodeJobResult, error)

SubmitTranscodeJob submits a media item for transcoding

func (*Service) UnpublishMediaDurably added in v1.6.23

func (s *Service) UnpublishMediaDurably(ctx context.Context, mediaID string) error

UnpublishMediaDurably best-effort removes durable public serving minted for one internal asset. It clears the record state first under the observed model version (a concurrent re-mint advances the version and is left intact) and only then deletes the deterministic published object, re-reading the record after the clear so a re-mint that lands between the two steps keeps its serving. Assets without published state are a no-op, so repeated rollback is idempotent.

func (*Service) UpdateEditorialLifecycle added in v1.6.23

func (s *Service) UpdateEditorialLifecycle(ctx context.Context, cmd *UpdateEditorialLifecycleCommand) (*models.Media, error)

UpdateEditorialLifecycle applies an explicit editorial lifecycle change to an internal asset. Withdrawn, superseded, and unavailable states are inspectable through the draft preview surface and block publication until re-review.

func (*Service) UpdateMedia

func (s *Service) UpdateMedia(ctx context.Context, cmd *UpdateMediaCommand) (*UpdateResult, error)

UpdateMedia updates media metadata (alt text, focus points) and emits events

func (*Service) UpdateMediaFromTranscodingJob

func (s *Service) UpdateMediaFromTranscodingJob(ctx context.Context, jobID string) error

UpdateMediaFromTranscodingJob updates media record with transcoding job results

func (*Service) UploadGrant added in v1.6.23

func (s *Service) UploadGrant(ctx context.Context, ownerID, grantID string) (*models.UploadGrant, string, error)

UploadGrant returns one grant with its inspectable lifecycle state for the owner, plus a fresh presigned PUT URL while the grant is still minted (so a transient PUT failure can be retried). The URL is best-effort on this query path; the mint response is authoritative.

func (*Service) UploadMedia

func (s *Service) UploadMedia(ctx context.Context, cmd *UploadMediaCommand) (*Result, error)

UploadMedia uploads a new media file, validates it, stores it in S3, creates the record, and queues async processing for thumbnails and analysis

type StreamSession

type StreamSession struct {
	SessionID    string
	MediaID      string
	URL          string
	Quality      string
	Format       string
	ExpiresAt    time.Time
	Bitrate      int
	BufferHealth float64
}

StreamSession contains streaming session information

type SubmitTranscodeJobCommand

type SubmitTranscodeJobCommand struct {
	MediaID        string
	UserID         string
	Username       string
	SourceBucket   string
	SourceKey      string
	ContentType    string
	Duration       int
	Width          int
	Height         int
	QualityLevels  []string // ["480p", "720p", "1080p"]
	GenerateHLS    bool
	GenerateDASH   bool
	ThumbnailCount int
}

SubmitTranscodeJobCommand contains parameters for submitting a transcode job

type TranscodeJobResult

type TranscodeJobResult struct {
	JobID             string
	MediaConvertJobID string
	EstimatedCostUSD  float64
	EstimatedDuration time.Duration
	QualityLevels     []string
	Status            string
}

TranscodeJobResult contains the result of submitting a transcode job

type UpdateEditorialLifecycleCommand added in v1.6.23

type UpdateEditorialLifecycleCommand struct {
	MediaID             string
	UserID              string
	Lifecycle           models.EditorialLifecycle
	SupersededByMediaID string
}

UpdateEditorialLifecycleCommand identifies the asset and the owner requesting an explicit editorial lifecycle change.

type UpdateMediaCommand

type UpdateMediaCommand struct {
	MediaID     string `json:"media_id" validate:"required"`
	UserID      string `json:"user_id" validate:"required"`     // Must be the media owner
	Description string `json:"description" validate:"max=1500"` // Alt text
	Focus       string `json:"focus"`                           // Focus point for cropping (x,y)
}

UpdateMediaCommand contains all data needed to update media metadata

type UpdateResult

type UpdateResult struct {
	Media  *models.Media      `json:"media"`
	Events []*streaming.Event `json:"events"`
}

UpdateResult contains updated media and events

type UploadMediaCommand

type UploadMediaCommand struct {
	UserID        string                  `json:"user_id" validate:"required"`
	FileName      string                  `json:"file_name" validate:"required"`
	ContentType   string                  `json:"content_type" validate:"required"`
	FileData      []byte                  `json:"file_data" validate:"required"`
	Description   string                  `json:"description" validate:"max=1500"` // Alt text
	Focus         string                  `json:"focus"`                           // Focus point for cropping (x,y)
	Sensitive     bool                    `json:"sensitive"`
	SpoilerText   string                  `json:"spoiler_text"`
	MediaCategory models.MediaCategory    `json:"media_category"`
	Editorial     bool                    `json:"editorial"`
	Provenance    *models.MediaProvenance `json:"provenance,omitempty"`
}

UploadMediaCommand contains all data needed to upload a media file

Directories

Path Synopsis
Package transcoding provides CloudFront signed URL generation
Package transcoding provides CloudFront signed URL generation

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL