Add resumable downloads, download paths, queue controls and history
This commit is contained in:
1 parent
434f6441da
commit
6027cfabb9
43 files changed
+2138
-291
No files matched your search
@@ -0,0 +1,106 @@
|
||||
package jobs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"ddc/internal/fetch"
|
||||
"ddc/internal/files"
|
||||
)
|
||||
|
||||
const (
|
||||
phaseDownloading = "downloading"
|
||||
phasePaused = "paused"
|
||||
phaseFailed = "failed"
|
||||
phaseDone = "done"
|
||||
)
|
||||
|
||||
type jobRecord struct {
|
||||
SourceURL string `json:"sourceUrl"`
|
||||
DisplayURL string `json:"displayUrl"`
|
||||
RequestedName string `json:"requestedName,omitempty"`
|
||||
FileName string `json:"fileName"`
|
||||
AutoExtract bool `json:"autoExtract"`
|
||||
Destination string `json:"destination,omitempty"`
|
||||
Subfolder string `json:"subfolder,omitempty"`
|
||||
Phase string `json:"phase"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Download *fetch.State `json:"download,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
}
|
||||
|
||||
func (job *Job) record() jobRecord {
|
||||
job.mutex.Lock()
|
||||
defer job.mutex.Unlock()
|
||||
record := jobRecord{
|
||||
SourceURL: job.sourceURL,
|
||||
DisplayURL: job.displayURL,
|
||||
RequestedName: job.requestedName,
|
||||
FileName: job.fileName,
|
||||
AutoExtract: job.autoExtract,
|
||||
Phase: phaseFor(job.status, job.downloaded),
|
||||
Message: job.message,
|
||||
Download: job.downloadState,
|
||||
CreatedAt: job.createdAt,
|
||||
}
|
||||
if job.target != nil {
|
||||
record.Destination = job.target.destination
|
||||
record.Subfolder = job.target.subfolder
|
||||
}
|
||||
return record
|
||||
}
|
||||
|
||||
func phaseFor(status Status, downloaded bool) string {
|
||||
switch {
|
||||
case downloaded:
|
||||
return phaseDone
|
||||
case status == StatusPaused:
|
||||
return phasePaused
|
||||
case status == StatusFailed:
|
||||
return phaseFailed
|
||||
default:
|
||||
return phaseDownloading
|
||||
}
|
||||
}
|
||||
|
||||
func (job *Job) saveRecord() {
|
||||
data, err := json.MarshalIndent(job.record(), "", " ")
|
||||
if err != nil {
|
||||
log.Printf("could not encode download %s: %v", job.id, err)
|
||||
return
|
||||
}
|
||||
job.recordMutex.Lock()
|
||||
defer job.recordMutex.Unlock()
|
||||
if err := files.WriteAtomically(filepath.Join(job.directory, files.JobFileName), data); err != nil && !os.IsNotExist(err) {
|
||||
log.Printf("could not save download %s: %v", job.id, err)
|
||||
}
|
||||
}
|
||||
|
||||
func readRecord(directory string) (jobRecord, bool) {
|
||||
data, err := os.ReadFile(filepath.Join(directory, files.JobFileName))
|
||||
if err != nil {
|
||||
return jobRecord{}, false
|
||||
}
|
||||
var record jobRecord
|
||||
if err := json.Unmarshal(data, &record); err != nil {
|
||||
return jobRecord{}, false
|
||||
}
|
||||
return record, true
|
||||
}
|
||||
|
||||
func (job *Job) applyRecord(record jobRecord) {
|
||||
job.sourceURL = record.SourceURL
|
||||
job.displayURL = record.DisplayURL
|
||||
job.requestedName = record.RequestedName
|
||||
job.fileName = record.FileName
|
||||
job.autoExtract = record.AutoExtract
|
||||
if !record.CreatedAt.IsZero() {
|
||||
job.createdAt = record.CreatedAt
|
||||
}
|
||||
if record.Destination != "" {
|
||||
job.target = &moveTarget{destination: record.Destination, subfolder: record.Subfolder}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user