summaryrefslogtreecommitdiff
path: root/player-server/internal/model/media.go
blob: 39ae4fd5c6805515e39b7dadf7aa49d2e7ce2f81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Package model defines the core domain entities.
package model

import "time"

// MediaType distinguishes between video and audio files.
type MediaType string

const (
	// MediaTypeVideo identifies video files.
	MediaTypeVideo MediaType = "video"
	// MediaTypeAudio identifies audio files.
	MediaTypeAudio MediaType = "audio"
	// MediaTypeImage identifies image files.
	MediaTypeImage MediaType = "image"
)

// Role defines the level of access a user has to a set.
type Role string

const (
	// RoleOwner allows browsing, uploading, deleting and thumbnail updates.
	RoleOwner Role = "owner"
	// RoleViewer allows browsing and playback.
	RoleViewer Role = "viewer"
)

// User represents an application account.
type User struct {
	ID           int64     `json:"id"`
	Username     string    `json:"username"`
	PasswordHash string    `json:"-"`
	IsAdmin      bool      `json:"is_admin"`
	CreatedAt    time.Time `json:"created_at"`
}

// Set represents a top-level media collection (a directory under MEDIA_ROOT).
type Set struct {
	ID                 int64           `json:"id"`
	Name               string          `json:"name"`
	RootPath           string          `json:"root_path"`
	CoverThumbnailPath string          `json:"cover_thumbnail_path"`
	IsPodcast          bool            `json:"is_podcast"`
	Permissions        []SetPermission `json:"permissions"`
	CreatedAt          time.Time       `json:"created_at"`
}

// SetPermission grants a user access to a set.
type SetPermission struct {
	SetID     int64     `json:"set_id"`
	UserID    int64     `json:"user_id"`
	Role      Role      `json:"role"`
	CreatedAt time.Time `json:"created_at"`
}

// Media represents a single media file within a set.
type Media struct {
	ID              int64      `json:"id"`
	SetID           int64      `json:"set_id"`
	RelPath         string     `json:"rel_path"`
	FileName        string     `json:"file_name"`
	AbsPath         string     `json:"abs_path"`
	Type            MediaType  `json:"type"`
	Duration        float64    `json:"duration"`
	Codec           string     `json:"codec"`
	Resolution      string     `json:"resolution"`
	Bitrate         int        `json:"bitrate"`
	FileSizeBytes   int64      `json:"file_size_bytes"`
	Width           int        `json:"width"`
	Height          int        `json:"height"`
	EXIFCamera      string     `json:"exif_camera"`
	EXIFLens        string     `json:"exif_lens"`
	EXIFDate        string     `json:"exif_date"`
	EXIFISO         string     `json:"exif_iso"`
	EXIFFNumber     string     `json:"exif_f_number"`
	EXIFExposure    string     `json:"exif_exposure"`
	EXIFFocalLength string     `json:"exif_focal_length"`
	ThumbnailPath   string     `json:"thumbnail_path"`
	PlayCount       int        `json:"play_count"`
	DeletedAt       *time.Time `json:"deleted_at"`
	CreatedAt       time.Time  `json:"created_at"`
}

// Tag is a label that can be attached to media items.
type Tag struct {
	ID   int64  `json:"id"`
	Name string `json:"name"`
}

// Session is an authenticated browser session.
type Session struct {
	ID        string    `json:"id"`
	UserID    int64     `json:"user_id"`
	ExpiresAt time.Time `json:"expires_at"`
	CreatedAt time.Time `json:"created_at"`
}

// Share is a time-bounded public link to a media item.
type Share struct {
	Token     string    `json:"token"`
	MediaID   int64     `json:"media_id"`
	CreatedBy int64     `json:"created_by"`
	CreatedAt time.Time `json:"created_at"`
	ExpiresAt time.Time `json:"expires_at"`
	MaxUses   *int      `json:"max_uses"`
	UsedCount int       `json:"used_count"`
}

// Note is a per-user, per-media text note.
type Note struct {
	ID        int64     `json:"id"`
	MediaID   int64     `json:"media_id"`
	UserID    int64     `json:"user_id"`
	Content   string    `json:"content"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

// PlaybackProgress stores the last known playback position.
type PlaybackProgress struct {
	UserID          int64     `json:"user_id"`
	MediaID         int64     `json:"media_id"`
	PositionSeconds float64   `json:"position_seconds"`
	Finished        bool      `json:"finished"`
	UpdatedAt       time.Time `json:"updated_at"`
}

// PlaybackAccumulator tracks deltas for the 60-second playback counter rule.
type PlaybackAccumulator struct {
	SessionID          string    `json:"session_id"`
	MediaID            int64     `json:"media_id"`
	LastPosition       float64   `json:"last_position"`
	AccumulatedSeconds float64   `json:"accumulated_seconds"`
	Counted            bool      `json:"counted"`
	UpdatedAt          time.Time `json:"updated_at"`
}

// Favorite records that a user has favorited a media item.
type Favorite struct {
	UserID    int64     `json:"user_id"`
	MediaID   int64     `json:"media_id"`
	CreatedAt time.Time `json:"created_at"`
}

// MediaTag is the join table between media and tags.
type MediaTag struct {
	MediaID int64 `json:"media_id"`
	TagID   int64 `json:"tag_id"`
}

// Metadata holds extracted file properties from ffprobe and os.Stat.
type Metadata struct {
	Duration        float64 `json:"duration"`
	Codec           string  `json:"codec"`
	Resolution      string  `json:"resolution"`
	Bitrate         int     `json:"bitrate"`
	FileSizeBytes   int64   `json:"file_size_bytes"`
	Width           int     `json:"width"`
	Height          int     `json:"height"`
	EXIFCamera      string  `json:"exif_camera"`
	EXIFLens        string  `json:"exif_lens"`
	EXIFDate        string  `json:"exif_date"`
	EXIFISO         string  `json:"exif_iso"`
	EXIFFNumber     string  `json:"exif_f_number"`
	EXIFExposure    string  `json:"exif_exposure"`
	EXIFFocalLength string  `json:"exif_focal_length"`
}