2022-06-14 15:33:34 -04:00
|
|
|
package db
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"sync"
|
2022-06-28 15:26:16 -04:00
|
|
|
|
|
|
|
"gitlab.com/balki/ytui/pubsub"
|
2022-06-14 15:33:34 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
type DownloadStatus string
|
|
|
|
|
|
|
|
var (
|
|
|
|
NotStarted DownloadStatus = "NotStarted"
|
|
|
|
InProgress DownloadStatus = "InProgress"
|
|
|
|
Done DownloadStatus = "Done"
|
|
|
|
Error DownloadStatus = "Error"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Item struct {
|
2022-06-29 17:50:31 -04:00
|
|
|
Id int `json:"id"`
|
|
|
|
Date string `json:"date"`
|
|
|
|
URL string `json:"url"`
|
|
|
|
Title string `json:"title"`
|
|
|
|
Status DownloadStatus `json:"status"`
|
|
|
|
FileName string `json:"file_name"`
|
|
|
|
Pt pubsub.ProgressTracker `json:"-"`
|
|
|
|
TitleChan <-chan struct{} `json:"-"`
|
2022-06-14 15:33:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
type Jdb struct {
|
2022-07-14 14:39:59 -04:00
|
|
|
Foo string `json:"-"`
|
2022-06-14 15:33:34 -04:00
|
|
|
Items []Item `json:"items"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type Db struct {
|
|
|
|
items []Item
|
|
|
|
mutex sync.Mutex
|
|
|
|
lastId int
|
|
|
|
path string
|
2022-06-28 15:26:16 -04:00
|
|
|
index map[string]int
|
2022-06-14 15:33:34 -04:00
|
|
|
}
|
|
|
|
|
2022-06-28 15:26:16 -04:00
|
|
|
func (d *Db) Add(i Item) (int, bool) {
|
2022-06-14 15:33:34 -04:00
|
|
|
d.mutex.Lock()
|
|
|
|
defer d.mutex.Unlock()
|
2022-06-28 15:26:16 -04:00
|
|
|
if id, ok := d.index[i.URL]; ok {
|
|
|
|
return id, false
|
|
|
|
}
|
2022-06-14 15:33:34 -04:00
|
|
|
i.Id = d.lastId
|
|
|
|
d.lastId++
|
|
|
|
d.items = append(d.items, i)
|
|
|
|
d.save()
|
2022-06-28 15:26:16 -04:00
|
|
|
d.index[i.URL] = i.Id
|
|
|
|
return i.Id, true
|
2022-06-14 15:33:34 -04:00
|
|
|
}
|
|
|
|
|
2022-06-30 12:49:15 -04:00
|
|
|
func (d *Db) Transact(id int, persist bool, f func(*Item)) error {
|
2022-06-14 15:33:34 -04:00
|
|
|
d.mutex.Lock()
|
|
|
|
defer d.mutex.Unlock()
|
|
|
|
for i, _ := range d.items {
|
|
|
|
if d.items[i].Id == id {
|
|
|
|
f(&d.items[i])
|
|
|
|
if persist {
|
|
|
|
d.save()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fmt.Errorf("Invalid id: %d", id)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Db) save() error {
|
2022-07-14 14:39:59 -04:00
|
|
|
data, err := json.Marshal(Jdb{"", d.items})
|
2022-06-14 15:33:34 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return os.WriteFile(d.path, data, 0644)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Db) Run(f func(*Jdb)) {
|
|
|
|
d.mutex.Lock()
|
|
|
|
defer d.mutex.Unlock()
|
2022-07-14 14:39:59 -04:00
|
|
|
f(&Jdb{"", d.items})
|
2022-06-14 15:33:34 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Db) Save() error {
|
|
|
|
d.mutex.Lock()
|
|
|
|
defer d.mutex.Unlock()
|
|
|
|
return d.save()
|
|
|
|
}
|
|
|
|
|
|
|
|
func Load(path string) (*Db, error) {
|
|
|
|
data, err := os.ReadFile(path)
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
|
|
return &Db{
|
|
|
|
path: path,
|
|
|
|
lastId: 0,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
var jd Jdb
|
|
|
|
err = json.Unmarshal(data, &jd)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
m := 0
|
2022-06-28 15:26:16 -04:00
|
|
|
indexMap := map[string]int{}
|
2022-06-14 15:33:34 -04:00
|
|
|
for _, item := range jd.Items {
|
|
|
|
if item.Id > m {
|
|
|
|
m = item.Id
|
|
|
|
}
|
2022-06-28 15:26:16 -04:00
|
|
|
indexMap[item.URL] = item.Id
|
2022-06-14 15:33:34 -04:00
|
|
|
}
|
|
|
|
return &Db{
|
|
|
|
items: jd.Items,
|
|
|
|
path: path,
|
|
|
|
lastId: m + 1,
|
2022-06-28 15:26:16 -04:00
|
|
|
index: indexMap,
|
2022-06-14 15:33:34 -04:00
|
|
|
}, nil
|
|
|
|
}
|