cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
29
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 7da458848ced66d8eab8b2e86c031c8dc4e0e6fc 316 lines 10 kB view raw
1package models 2 3import ( 4 "encoding/json" 5 "time" 6) 7 8// Model defines the common interface that all domain models must implement 9type Model interface { 10 // GetID returns the primary key identifier 11 GetID() int64 12 // SetID sets the primary key identifier 13 SetID(id int64) 14 // GetTableName returns the database table name for this model 15 GetTableName() string 16 // GetCreatedAt returns when the model was created 17 GetCreatedAt() time.Time 18 // SetCreatedAt sets when the model was created 19 SetCreatedAt(t time.Time) 20 // GetUpdatedAt returns when the model was last updated 21 GetUpdatedAt() time.Time 22 // SetUpdatedAt sets when the model was last updated 23 SetUpdatedAt(t time.Time) 24} 25 26// Task represents a task item with TaskWarrior-inspired fields 27type Task struct { 28 ID int64 `json:"id"` 29 UUID string `json:"uuid"` 30 Description string `json:"description"` 31 // pending, completed, deleted 32 Status string `json:"status"` 33 // A-Z or empty 34 Priority string `json:"priority,omitempty"` 35 Project string `json:"project,omitempty"` 36 Tags []string `json:"tags,omitempty"` 37 Due *time.Time `json:"due,omitempty"` 38 Entry time.Time `json:"entry"` 39 Modified time.Time `json:"modified"` 40 // completion time 41 End *time.Time `json:"end,omitempty"` 42 // when task was started 43 Start *time.Time `json:"start,omitempty"` 44 Annotations []string `json:"annotations,omitempty"` 45} 46 47// Movie represents a movie in the watch queue 48type Movie struct { 49 ID int64 `json:"id"` 50 Title string `json:"title"` 51 Year int `json:"year,omitempty"` 52 // queued, watched, removed 53 Status string `json:"status"` 54 Rating float64 `json:"rating,omitempty"` 55 Notes string `json:"notes,omitempty"` 56 Added time.Time `json:"added"` 57 Watched *time.Time `json:"watched,omitempty"` 58} 59 60// TVShow represents a TV show in the watch queue 61type TVShow struct { 62 ID int64 `json:"id"` 63 Title string `json:"title"` 64 Season int `json:"season,omitempty"` 65 Episode int `json:"episode,omitempty"` 66 // queued, watching, watched, removed 67 Status string `json:"status"` 68 Rating float64 `json:"rating,omitempty"` 69 Notes string `json:"notes,omitempty"` 70 Added time.Time `json:"added"` 71 LastWatched *time.Time `json:"last_watched,omitempty"` 72} 73 74// Book represents a book in the reading list 75type Book struct { 76 ID int64 `json:"id"` 77 Title string `json:"title"` 78 Author string `json:"author,omitempty"` 79 // queued, reading, finished, removed 80 Status string `json:"status"` 81 // percentage 0-100 82 Progress int `json:"progress"` 83 Pages int `json:"pages,omitempty"` 84 Rating float64 `json:"rating,omitempty"` 85 Notes string `json:"notes,omitempty"` 86 Added time.Time `json:"added"` 87 Started *time.Time `json:"started,omitempty"` 88 Finished *time.Time `json:"finished,omitempty"` 89} 90 91// Note represents a markdown note 92type Note struct { 93 ID int64 `json:"id"` 94 Title string `json:"title"` 95 Content string `json:"content"` 96 Tags []string `json:"tags,omitempty"` 97 Archived bool `json:"archived"` 98 Created time.Time `json:"created"` 99 Modified time.Time `json:"modified"` 100 FilePath string `json:"file_path,omitempty"` 101} 102 103// Album represents a music album 104type Album struct { 105 ID int64 `json:"id"` 106 Title string `json:"title"` 107 Artist string `json:"artist"` 108 Genre string `json:"genre,omitempty"` 109 ReleaseYear int `json:"release_year,omitempty"` 110 Tracks []string `json:"tracks,omitempty"` 111 DurationSeconds int `json:"duration_seconds,omitempty"` 112 AlbumArtPath string `json:"album_art_path,omitempty"` 113 Rating int `json:"rating,omitempty"` 114 Created time.Time `json:"created"` 115 Modified time.Time `json:"modified"` 116} 117 118// MarshalTags converts tags slice to JSON string for database storage 119func (t *Task) MarshalTags() (string, error) { 120 if len(t.Tags) == 0 { 121 return "", nil 122 } 123 data, err := json.Marshal(t.Tags) 124 return string(data), err 125} 126 127// UnmarshalTags converts JSON string from database to tags slice 128func (t *Task) UnmarshalTags(data string) error { 129 if data == "" { 130 t.Tags = nil 131 return nil 132 } 133 return json.Unmarshal([]byte(data), &t.Tags) 134} 135 136// MarshalAnnotations converts annotations slice to JSON string for database storage 137func (t *Task) MarshalAnnotations() (string, error) { 138 if len(t.Annotations) == 0 { 139 return "", nil 140 } 141 data, err := json.Marshal(t.Annotations) 142 return string(data), err 143} 144 145// UnmarshalAnnotations converts JSON string from database to annotations slice 146func (t *Task) UnmarshalAnnotations(data string) error { 147 if data == "" { 148 t.Annotations = nil 149 return nil 150 } 151 return json.Unmarshal([]byte(data), &t.Annotations) 152} 153 154// IsCompleted returns true if the task is marked as completed 155func (t *Task) IsCompleted() bool { 156 return t.Status == "completed" 157} 158 159// IsPending returns true if the task is pending 160func (t *Task) IsPending() bool { 161 return t.Status == "pending" 162} 163 164// IsDeleted returns true if the task is deleted 165func (t *Task) IsDeleted() bool { 166 return t.Status == "deleted" 167} 168 169// HasPriority returns true if the task has a priority set 170func (t *Task) HasPriority() bool { 171 return t.Priority != "" 172} 173 174// IsWatched returns true if the movie has been watched 175func (m *Movie) IsWatched() bool { 176 return m.Status == "watched" 177} 178 179// IsQueued returns true if the movie is in the queue 180func (m *Movie) IsQueued() bool { 181 return m.Status == "queued" 182} 183 184// IsWatching returns true if the TV show is currently being watched 185func (tv *TVShow) IsWatching() bool { 186 return tv.Status == "watching" 187} 188 189// IsWatched returns true if the TV show has been watched 190func (tv *TVShow) IsWatched() bool { 191 return tv.Status == "watched" 192} 193 194// IsQueued returns true if the TV show is in the queue 195func (tv *TVShow) IsQueued() bool { 196 return tv.Status == "queued" 197} 198 199// IsReading returns true if the book is currently being read 200func (b *Book) IsReading() bool { 201 return b.Status == "reading" 202} 203 204// IsFinished returns true if the book has been finished 205func (b *Book) IsFinished() bool { 206 return b.Status == "finished" 207} 208 209// IsQueued returns true if the book is in the queue 210func (b *Book) IsQueued() bool { 211 return b.Status == "queued" 212} 213 214// ProgressPercent returns the reading progress as a percentage 215func (b *Book) ProgressPercent() int { 216 return b.Progress 217} 218 219func (t *Task) GetID() int64 { return t.ID } 220func (t *Task) SetID(id int64) { t.ID = id } 221func (t *Task) GetTableName() string { return "tasks" } 222func (t *Task) GetCreatedAt() time.Time { return t.Entry } 223func (t *Task) SetCreatedAt(time time.Time) { t.Entry = time } 224func (t *Task) GetUpdatedAt() time.Time { return t.Modified } 225func (t *Task) SetUpdatedAt(time time.Time) { t.Modified = time } 226 227func (m *Movie) GetID() int64 { return m.ID } 228func (m *Movie) SetID(id int64) { m.ID = id } 229func (m *Movie) GetTableName() string { return "movies" } 230func (m *Movie) GetCreatedAt() time.Time { return m.Added } 231func (m *Movie) SetCreatedAt(time time.Time) { m.Added = time } 232func (m *Movie) GetUpdatedAt() time.Time { return m.Added } 233func (m *Movie) SetUpdatedAt(time time.Time) { m.Added = time } 234 235func (tv *TVShow) GetID() int64 { return tv.ID } 236func (tv *TVShow) SetID(id int64) { tv.ID = id } 237func (tv *TVShow) GetTableName() string { return "tv_shows" } 238func (tv *TVShow) GetCreatedAt() time.Time { return tv.Added } 239func (tv *TVShow) SetCreatedAt(time time.Time) { tv.Added = time } 240func (tv *TVShow) GetUpdatedAt() time.Time { return tv.Added } 241func (tv *TVShow) SetUpdatedAt(time time.Time) { tv.Added = time } 242 243func (b *Book) GetID() int64 { return b.ID } 244func (b *Book) SetID(id int64) { b.ID = id } 245func (b *Book) GetTableName() string { return "books" } 246func (b *Book) GetCreatedAt() time.Time { return b.Added } 247func (b *Book) SetCreatedAt(time time.Time) { b.Added = time } 248func (b *Book) GetUpdatedAt() time.Time { return b.Added } 249func (b *Book) SetUpdatedAt(time time.Time) { b.Added = time } 250 251// MarshalTags converts tags slice to JSON string for database storage 252func (n *Note) MarshalTags() (string, error) { 253 if len(n.Tags) == 0 { 254 return "", nil 255 } 256 data, err := json.Marshal(n.Tags) 257 return string(data), err 258} 259 260// UnmarshalTags converts JSON string from database to tags slice 261func (n *Note) UnmarshalTags(data string) error { 262 if data == "" { 263 n.Tags = nil 264 return nil 265 } 266 return json.Unmarshal([]byte(data), &n.Tags) 267} 268 269// IsArchived returns true if the note is archived 270func (n *Note) IsArchived() bool { 271 return n.Archived 272} 273 274func (n *Note) GetID() int64 { return n.ID } 275func (n *Note) SetID(id int64) { n.ID = id } 276func (n *Note) GetTableName() string { return "notes" } 277func (n *Note) GetCreatedAt() time.Time { return n.Created } 278func (n *Note) SetCreatedAt(time time.Time) { n.Created = time } 279func (n *Note) GetUpdatedAt() time.Time { return n.Modified } 280func (n *Note) SetUpdatedAt(time time.Time) { n.Modified = time } 281 282// MarshalTracks converts tracks slice to JSON string for database storage 283func (a *Album) MarshalTracks() (string, error) { 284 if len(a.Tracks) == 0 { 285 return "", nil 286 } 287 data, err := json.Marshal(a.Tracks) 288 return string(data), err 289} 290 291// UnmarshalTracks converts JSON string from database to tracks slice 292func (a *Album) UnmarshalTracks(data string) error { 293 if data == "" { 294 a.Tracks = nil 295 return nil 296 } 297 return json.Unmarshal([]byte(data), &a.Tracks) 298} 299 300// HasRating returns true if the album has a rating set 301func (a *Album) HasRating() bool { 302 return a.Rating > 0 303} 304 305// IsValidRating returns true if the rating is between 1 and 5 306func (a *Album) IsValidRating() bool { 307 return a.Rating >= 1 && a.Rating <= 5 308} 309 310func (a *Album) GetID() int64 { return a.ID } 311func (a *Album) SetID(id int64) { a.ID = id } 312func (a *Album) GetTableName() string { return "albums" } 313func (a *Album) GetCreatedAt() time.Time { return a.Created } 314func (a *Album) SetCreatedAt(time time.Time) { a.Created = time } 315func (a *Album) GetUpdatedAt() time.Time { return a.Modified } 316func (a *Album) SetUpdatedAt(time time.Time) { a.Modified = time }