This commit is contained in:
parent
4b42e4f998
commit
ae765fdf64
224
downloader.go
224
downloader.go
@ -16,7 +16,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DownloadAllVideos(db *mysqlite.Db) error {
|
func DownloadAllVideos(db *mysqlite.Db) (rerr error) {
|
||||||
// Ensure no partial videos exist
|
// Ensure no partial videos exist
|
||||||
tempDir := os.Getenv("VIVAPLUS_DOWNLOAD")
|
tempDir := os.Getenv("VIVAPLUS_DOWNLOAD")
|
||||||
if tempDir == "" {
|
if tempDir == "" {
|
||||||
@ -43,116 +43,120 @@ func DownloadAllVideos(db *mysqlite.Db) error {
|
|||||||
|
|
||||||
log.Printf("Starting downloads...")
|
log.Printf("Starting downloads...")
|
||||||
for {
|
for {
|
||||||
// Fetch the next record from the database
|
err = downloadVideo(db, downloadDir, tempDir)
|
||||||
var id, episode int
|
|
||||||
var href, cast, title, description, uploadDateStr, thumbnailUrl string
|
|
||||||
err = db.Query("select id, url, `cast`, title, description, upload_date, thumbnail, episode from videos where state = 'pending' and episode is not null order by year, episode limit 1").
|
|
||||||
ScanSingle(&id, &href, &cast, &title, &description, &uploadDateStr, &thumbnailUrl, &episode)
|
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
|
||||||
log.Printf("No videos found for downloading")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error fetching record: %w", err)
|
return err
|
||||||
}
|
}
|
||||||
uploadDate, err := time.Parse(time.DateOnly, uploadDateStr)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error parsing upload date '%s': %w", uploadDateStr, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Download the actual video
|
|
||||||
baseFileName := fmt.Sprintf("/S%dE%03d", uploadDate.Year(), episode)
|
|
||||||
log.Printf("Downloading %s", href)
|
|
||||||
cmd := exec.Command("yt-dlp", cast, "-o", filepath.Join(tempDir, baseFileName+".%(ext)s"))
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error downloading video: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move it into the destination directory
|
|
||||||
destinationDir := filepath.Join(downloadDir, fmt.Sprintf("Season %d", uploadDate.Year()))
|
|
||||||
err = os.MkdirAll(destinationDir, 0750)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error creating target directory: %w", err)
|
|
||||||
}
|
|
||||||
files, err := os.ReadDir(tempDir)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error retrieving downloaded files: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
srcPath := filepath.Join(tempDir, file.Name())
|
|
||||||
destPath := filepath.Join(destinationDir, file.Name())
|
|
||||||
log.Printf("Moving %s to %s", srcPath, destPath)
|
|
||||||
err = os.Rename(srcPath, destPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error moving file: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write XML sidecar
|
|
||||||
nfo := NFO{}
|
|
||||||
nfo.Plot = description
|
|
||||||
nfo.Title = title
|
|
||||||
nfo.Year = uploadDate.Year()
|
|
||||||
nfo.Aired = uploadDate.Format(time.DateOnly)
|
|
||||||
nfoData, err := xml.MarshalIndent(nfo, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error marshalling NFO data: %w", err)
|
|
||||||
}
|
|
||||||
nfoString := xml.Header + string(nfoData)
|
|
||||||
nfoFile, err := os.Create(filepath.Join(destinationDir, baseFileName+".nfo"))
|
|
||||||
defer nfoFile.Close()
|
|
||||||
_, err = nfoFile.WriteString(nfoString)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error writing NFO file: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write thumbnail
|
|
||||||
parsedThumbnailUrl, err := url.Parse(thumbnailUrl)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error parsing thumbnail url: %w", err)
|
|
||||||
}
|
|
||||||
thumbnailExt := filepath.Ext(parsedThumbnailUrl.Path)
|
|
||||||
thumbnailFile, err := os.Create(filepath.Join(destinationDir, baseFileName+"-thumb"+thumbnailExt))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error creating thumbnail: %w", err)
|
|
||||||
}
|
|
||||||
defer thumbnailFile.Close()
|
|
||||||
thumbnailResp, err := http.Get(thumbnailUrl)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error fetching thumbnail: %w", err)
|
|
||||||
}
|
|
||||||
defer thumbnailResp.Body.Close()
|
|
||||||
_, err = io.Copy(thumbnailFile, thumbnailResp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error writing thumbnail: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the database state to done
|
|
||||||
tx, err := db.Begin()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error starting transaction: %w", err)
|
|
||||||
}
|
|
||||||
defer tx.Rollback()
|
|
||||||
result, err := tx.Exec("update videos set state = 'done' where id = ?", id)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error updating database: %w", err)
|
|
||||||
}
|
|
||||||
count, err := result.RowsAffected()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error getting number of rows affected: %d", err)
|
|
||||||
}
|
|
||||||
if count != 1 {
|
|
||||||
return fmt.Errorf("unexpected number of rows changed (expected exactly 1): %d", count)
|
|
||||||
}
|
|
||||||
err = tx.Commit()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error commiting transaction: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Finished downloading file")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func downloadVideo(db *mysqlite.Db, downloadDir string, tempDir string) (rerr error) {
|
||||||
|
// Fetch the next record from the database
|
||||||
|
var id, episode int
|
||||||
|
var href, cast, title, description, uploadDateStr, thumbnailUrl string
|
||||||
|
err := db.Query("select id, url, `cast`, title, description, upload_date, thumbnail, episode from videos where state = 'pending' and episode is not null order by year, episode limit 1").
|
||||||
|
ScanSingle(&id, &href, &cast, &title, &description, &uploadDateStr, &thumbnailUrl, &episode)
|
||||||
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
log.Printf("No videos found for downloading")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error fetching record: %w", err)
|
||||||
|
}
|
||||||
|
uploadDate, err := time.Parse(time.DateOnly, uploadDateStr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error parsing upload date '%s': %w", uploadDateStr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download the actual video
|
||||||
|
baseFileName := fmt.Sprintf("/S%dE%03d", uploadDate.Year(), episode)
|
||||||
|
log.Printf("Downloading %s", href)
|
||||||
|
cmd := exec.Command("yt-dlp", cast, "-o", filepath.Join(tempDir, baseFileName+".%(ext)s"))
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error downloading video: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move it into the destination directory
|
||||||
|
destinationDir := filepath.Join(downloadDir, fmt.Sprintf("Season %d", uploadDate.Year()))
|
||||||
|
err = os.MkdirAll(destinationDir, 0750)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating target directory: %w", err)
|
||||||
|
}
|
||||||
|
files, err := os.ReadDir(tempDir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error retrieving downloaded files: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
srcPath := filepath.Join(tempDir, file.Name())
|
||||||
|
destPath := filepath.Join(destinationDir, file.Name())
|
||||||
|
log.Printf("Moving %s to %s", srcPath, destPath)
|
||||||
|
err = os.Rename(srcPath, destPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error moving file: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write XML sidecar
|
||||||
|
nfo := NFO{}
|
||||||
|
nfo.Plot = description
|
||||||
|
nfo.Title = title
|
||||||
|
nfo.Year = uploadDate.Year()
|
||||||
|
nfo.Aired = uploadDate.Format(time.DateOnly)
|
||||||
|
nfoData, err := xml.MarshalIndent(nfo, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error marshalling NFO data: %w", err)
|
||||||
|
}
|
||||||
|
nfoString := xml.Header + string(nfoData)
|
||||||
|
nfoFile, err := os.Create(filepath.Join(destinationDir, baseFileName+".nfo"))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating NFO file: %w", err)
|
||||||
|
}
|
||||||
|
defer forwardError(nfoFile.Close(), &rerr)
|
||||||
|
_, err = nfoFile.WriteString(nfoString)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error writing NFO file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write thumbnail
|
||||||
|
parsedThumbnailUrl, err := url.Parse(thumbnailUrl)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error parsing thumbnail url: %w", err)
|
||||||
|
}
|
||||||
|
thumbnailExt := filepath.Ext(parsedThumbnailUrl.Path)
|
||||||
|
thumbnailFile, err := os.Create(filepath.Join(destinationDir, baseFileName+"-thumb"+thumbnailExt))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating thumbnail: %w", err)
|
||||||
|
}
|
||||||
|
defer forwardError(thumbnailFile.Close(), &rerr)
|
||||||
|
thumbnailResp, err := http.Get(thumbnailUrl)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error fetching thumbnail: %w", err)
|
||||||
|
}
|
||||||
|
defer forwardError(thumbnailResp.Body.Close(), &rerr)
|
||||||
|
_, err = io.Copy(thumbnailFile, thumbnailResp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error writing thumbnail: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the database state to done
|
||||||
|
tx, err := db.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error starting transaction: %w", err)
|
||||||
|
}
|
||||||
|
defer forwardError(tx.Rollback(), &rerr)
|
||||||
|
err = tx.Query("update videos set state = 'done' where id = ?").Bind(id).Exec()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error updating database: %w", err)
|
||||||
|
}
|
||||||
|
err = tx.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error commiting transaction: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Finished downloading file")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user