hopefully channel working
This commit is contained in:
parent
882f8aea2f
commit
e2dc04c233
29
db/db.go
29
db/db.go
@ -6,6 +6,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"gitlab.com/balki/ytui/pubsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DownloadStatus string
|
type DownloadStatus string
|
||||||
@ -18,14 +20,13 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
Date string `json:"date"`
|
Date string `json:"date"`
|
||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Approved bool `json:"approved"`
|
Status DownloadStatus `json:"status"`
|
||||||
Status DownloadStatus `json:"status"`
|
FileName string `json:"file_name"`
|
||||||
FileName string `json:"file_name"`
|
Pt pubsub.ProgressTracker `json:"-"`
|
||||||
Progress string `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Jdb struct {
|
type Jdb struct {
|
||||||
@ -37,16 +38,21 @@ type Db struct {
|
|||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
lastId int
|
lastId int
|
||||||
path string
|
path string
|
||||||
|
index map[string]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Db) Add(i Item) int {
|
func (d *Db) Add(i Item) (int, bool) {
|
||||||
d.mutex.Lock()
|
d.mutex.Lock()
|
||||||
defer d.mutex.Unlock()
|
defer d.mutex.Unlock()
|
||||||
|
if id, ok := d.index[i.URL]; ok {
|
||||||
|
return id, false
|
||||||
|
}
|
||||||
i.Id = d.lastId
|
i.Id = d.lastId
|
||||||
d.lastId++
|
d.lastId++
|
||||||
d.items = append(d.items, i)
|
d.items = append(d.items, i)
|
||||||
d.save()
|
d.save()
|
||||||
return i.Id
|
d.index[i.URL] = i.Id
|
||||||
|
return i.Id, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Db) Update(id int, persist bool, f func(*Item)) error {
|
func (d *Db) Update(id int, persist bool, f func(*Item)) error {
|
||||||
@ -101,14 +107,17 @@ func Load(path string) (*Db, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
m := 0
|
m := 0
|
||||||
|
indexMap := map[string]int{}
|
||||||
for _, item := range jd.Items {
|
for _, item := range jd.Items {
|
||||||
if item.Id > m {
|
if item.Id > m {
|
||||||
m = item.Id
|
m = item.Id
|
||||||
}
|
}
|
||||||
|
indexMap[item.URL] = item.Id
|
||||||
}
|
}
|
||||||
return &Db{
|
return &Db{
|
||||||
items: jd.Items,
|
items: jd.Items,
|
||||||
path: path,
|
path: path,
|
||||||
lastId: m + 1,
|
lastId: m + 1,
|
||||||
|
index: indexMap,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
111
main.go
111
main.go
@ -16,6 +16,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitlab.com/balki/ytui/db"
|
"gitlab.com/balki/ytui/db"
|
||||||
|
"gitlab.com/balki/ytui/pubsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed templates/index.html
|
//go:embed templates/index.html
|
||||||
@ -24,12 +25,11 @@ var page string
|
|||||||
const port = 8080
|
const port = 8080
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ytdlCmd = []string{"youtube-dl"}
|
ytdlCmd = []string{"youtube-dl"}
|
||||||
videosPath = "./vids"
|
videosPath = "./vids"
|
||||||
videosUrl = "/vids"
|
videosUrl = "/vids"
|
||||||
cachePath = "./cache"
|
cachePath = "./cache"
|
||||||
dbPath = "./db.json"
|
dbPath = "./db.json"
|
||||||
approval bool = false
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var d *db.Db
|
var d *db.Db
|
||||||
@ -41,7 +41,6 @@ func parse() {
|
|||||||
flag.StringVar(&videosUrl, "videosurl", videosUrl, "Prefix of the url, i.e. https://domain.com/<this var>/<video filename>")
|
flag.StringVar(&videosUrl, "videosurl", videosUrl, "Prefix of the url, i.e. https://domain.com/<this var>/<video filename>")
|
||||||
flag.StringVar(&cachePath, "cachepath", cachePath, "Path where temporary download files are saved")
|
flag.StringVar(&cachePath, "cachepath", cachePath, "Path where temporary download files are saved")
|
||||||
flag.StringVar(&dbPath, "dbpath", dbPath, "Path where downloaded info is saved")
|
flag.StringVar(&dbPath, "dbpath", dbPath, "Path where downloaded info is saved")
|
||||||
flag.BoolVar(&approval, "approval", approval, "Is approval required before allowing to watch")
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if ytcmd != ytdlCmd[0] {
|
if ytcmd != ytdlCmd[0] {
|
||||||
ytdlCmd = strings.Fields(ytcmd)
|
ytdlCmd = strings.Fields(ytcmd)
|
||||||
@ -68,12 +67,6 @@ func main() {
|
|||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
defer d.Save()
|
defer d.Save()
|
||||||
seen := map[string]struct{}{}
|
|
||||||
d.Run(func(d *db.Jdb) {
|
|
||||||
for _, i := range d.Items {
|
|
||||||
seen[i.URL] = struct{}{}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
d.Run(func(d *db.Jdb) {
|
d.Run(func(d *db.Jdb) {
|
||||||
@ -89,18 +82,15 @@ func main() {
|
|||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, ok := seen[yturl]; !ok {
|
id, isNew := d.Add(db.Item{
|
||||||
seen[yturl] = struct{}{}
|
Date: time.Now().Format("2006-01-02 15:04"),
|
||||||
id := d.Add(db.Item{
|
URL: yturl,
|
||||||
Date: time.Now().Format("2006-01-02 15:04"),
|
Title: "Loading",
|
||||||
URL: yturl,
|
Status: db.NotStarted,
|
||||||
Title: "Loading",
|
})
|
||||||
Approved: false,
|
if isNew {
|
||||||
Status: db.NotStarted,
|
|
||||||
})
|
|
||||||
go getTitle(id, yturl)
|
go getTitle(id, yturl)
|
||||||
go download(id, yturl)
|
go download(id, yturl)
|
||||||
|
|
||||||
}
|
}
|
||||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||||
})
|
})
|
||||||
@ -123,18 +113,43 @@ func getTitle(id int, yturl string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func download(id int, yturl string) {
|
func download(id int, yturl string) {
|
||||||
|
pt := pubsub.NewProgressTracker()
|
||||||
d.Update(id, true, func(i *db.Item) {
|
d.Update(id, true, func(i *db.Item) {
|
||||||
i.Status = db.InProgress
|
i.Status = db.InProgress
|
||||||
|
i.Pt = pt
|
||||||
})
|
})
|
||||||
|
pc, err := pt.Publish()
|
||||||
|
defer close(pc)
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
|
var status db.DownloadStatus
|
||||||
|
var fname string
|
||||||
|
if fname, err = downloadYt(id, yturl, pc); err != nil {
|
||||||
|
status = db.Error
|
||||||
|
} else {
|
||||||
|
status = db.Done
|
||||||
|
}
|
||||||
|
d.Update(id, true, func(i *db.Item) {
|
||||||
|
i.Status = status
|
||||||
|
i.FileName = fname
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadYt(id int, yturl string, pc chan<- string) (string, error) {
|
||||||
pathTmpl := fmt.Sprintf("%s/video_%d.%%(ext)s", cachePath, id)
|
pathTmpl := fmt.Sprintf("%s/video_%d.%%(ext)s", cachePath, id)
|
||||||
args := append(ytdlCmd, "--newline", "--output", pathTmpl, yturl)
|
args := append(ytdlCmd, "--newline", "--output", pathTmpl, yturl)
|
||||||
cmd := exec.Command(args[0], args[1:]...)
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
rc, err := cmd.StdoutPipe()
|
rc, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
pc <- "Pre starting error"
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
defer rc.Close()
|
||||||
|
pc <- "Starting download"
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
log.Panic(err)
|
pc <- "Start error"
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
br := bufio.NewReader(rc)
|
br := bufio.NewReader(rc)
|
||||||
for {
|
for {
|
||||||
@ -142,33 +157,31 @@ func download(id int, yturl string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
d.Update(id, false, func(i *db.Item) {
|
pc <- string(line)
|
||||||
i.Progress = string(line)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
rc.Close()
|
pc <- "Waiting to complete..."
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
var status db.DownloadStatus
|
|
||||||
var fname string
|
var fname string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
status = db.Error
|
pc <- "Download Error"
|
||||||
} else {
|
return "", fmt.Errorf("Download Error, err: %w", err)
|
||||||
status = db.Done
|
|
||||||
matches, err := fs.Glob(os.DirFS(cachePath), fmt.Sprintf("video_%d.*", id))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if len(matches) != 1 {
|
|
||||||
panic(len(matches))
|
|
||||||
}
|
|
||||||
fname = matches[0]
|
|
||||||
err = os.Rename(path.Join(cachePath, fname), path.Join(videosPath, fname))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
d.Update(id, true, func(i *db.Item) {
|
pc <- "Download Done, renaming"
|
||||||
i.Status = status
|
matches, err := fs.Glob(os.DirFS(cachePath), fmt.Sprintf("video_%d.*", id))
|
||||||
i.FileName = fname
|
if err != nil {
|
||||||
})
|
pc <- "Match Error"
|
||||||
|
return "", fmt.Errorf("Glob match error, err: %w\n", err)
|
||||||
|
}
|
||||||
|
if len(matches) != 1 {
|
||||||
|
pc <- "Multiple Match Error"
|
||||||
|
return "", fmt.Errorf("Got multiple matches, count: %v", len(matches))
|
||||||
|
}
|
||||||
|
fname = matches[0]
|
||||||
|
source := path.Join(cachePath, fname)
|
||||||
|
destination := path.Join(videosPath, fname)
|
||||||
|
if err := os.Rename(source, destination); err != nil {
|
||||||
|
pc <- "Rename error"
|
||||||
|
return "", fmt.Errorf("Rename error, fname: %q, source: %q, destination: %q, err: %w\n", fname, source, destination, err)
|
||||||
|
}
|
||||||
|
return fname, nil
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
<td>
|
<td>
|
||||||
{{ if eq .Status "Done" }}
|
{{ if eq .Status "Done" }}
|
||||||
<a target="_blank" href="{{ vids_prefix }}/{{ .FileName }}">Watch</a>
|
<a target="_blank" href="{{ vids_prefix }}/{{ .FileName }}">Watch</a>
|
||||||
{{ else if eq .Status "InProgress" }}
|
|
||||||
{{ .Progress }}
|
|
||||||
{{ else }}
|
{{ else }}
|
||||||
{{ .Status }}
|
{{ .Status }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
Loading…
Reference in New Issue
Block a user