download.go
⎇
Raw
1package repository
2
3import (
4 "database/sql"
5
6 "vidarchive/internal/models"
7)
8
9type DownloadRepository struct {
10 db *sql.DB
11}
12
13func NewDownloadRepository(db *sql.DB) *DownloadRepository {
14 return &DownloadRepository{db: db}
15}
16
17func (r *DownloadRepository) Create(d *models.Download) error {
18 result, err := r.db.Exec(
19 `INSERT INTO downloads (url, status, preset_id, format_override, custom_flags)
20 VALUES (?, ?, ?, ?, ?)`,
21 d.URL, d.Status, d.PresetID, d.FormatOverride, d.CustomFlags,
22 )
23 if err != nil {
24 return err
25 }
26 d.ID, _ = result.LastInsertId()
27 return nil
28}
29
30func (r *DownloadRepository) GetByID(id int64) (*models.Download, error) {
31 row := r.db.QueryRow(
32 `SELECT id, url, status, progress_percent, current_speed, eta, logs, error_message, preset_id, format_override, custom_flags, started_at, completed_at, created_at
33 FROM downloads WHERE id = ?`, id,
34 )
35 return scanDownload(row)
36}
37
38func (r *DownloadRepository) GetAll(status, sortBy string) ([]*models.Download, error) {
39 query := `SELECT id, url, status, progress_percent, current_speed, eta, logs, error_message, preset_id, format_override, custom_flags, started_at, completed_at, created_at
40 FROM downloads WHERE 1=1`
41 var args []interface{}
42
43 if status != "" && status != "all" {
44 query += ` AND status = ?`
45 args = append(args, status)
46 }
47
48 switch sortBy {
49 case "date":
50 query += ` ORDER BY created_at DESC`
51 case "progress":
52 query += ` ORDER BY progress_percent DESC`
53 case "status":
54 query += ` ORDER BY status, created_at DESC`
55 default:
56 query += ` ORDER BY created_at DESC`
57 }
58
59 rows, err := r.db.Query(query, args...)
60 if err != nil {
61 return nil, err
62 }
63 defer rows.Close()
64
65 var downloads []*models.Download
66 for rows.Next() {
67 d, err := scanDownload(rows)
68 if err != nil {
69 return nil, err
70 }
71 downloads = append(downloads, d)
72 }
73 return downloads, rows.Err()
74}
75
76func (r *DownloadRepository) GetQueued(limit int) ([]*models.Download, error) {
77 rows, err := r.db.Query(
78 `SELECT id, url, status, progress_percent, current_speed, eta, logs, error_message, preset_id, format_override, custom_flags, started_at, completed_at, created_at
79 FROM downloads WHERE status = 'queued' ORDER BY created_at ASC LIMIT ?`,
80 limit,
81 )
82 if err != nil {
83 return nil, err
84 }
85 defer rows.Close()
86
87 var downloads []*models.Download
88 for rows.Next() {
89 d, err := scanDownload(rows)
90 if err != nil {
91 return nil, err
92 }
93 downloads = append(downloads, d)
94 }
95 return downloads, rows.Err()
96}
97
98func (r *DownloadRepository) UpdateStatus(id int64, status string) error {
99 _, err := r.db.Exec(`UPDATE downloads SET status = ? WHERE id = ?`, status, id)
100 return err
101}
102
103func (r *DownloadRepository) UpdateProgress(id int64, progress int, speed, eta string) error {
104 _, err := r.db.Exec(
105 `UPDATE downloads SET progress_percent = ?, current_speed = ?, eta = ? WHERE id = ?`,
106 progress, speed, eta, id,
107 )
108 return err
109}
110
111func (r *DownloadRepository) UpdateLogs(id int64, logs string) error {
112 _, err := r.db.Exec(`UPDATE downloads SET logs = ? WHERE id = ?`, logs, id)
113 return err
114}
115
116func (r *DownloadRepository) AppendLogs(id int64, logs string) error {
117 _, err := r.db.Exec(
118 `UPDATE downloads SET logs = COALESCE(logs, '') || ? WHERE id = ?`,
119 logs, id,
120 )
121 return err
122}
123
124func (r *DownloadRepository) MarkStarted(id int64) error {
125 _, err := r.db.Exec(
126 `UPDATE downloads SET status = 'downloading', started_at = CURRENT_TIMESTAMP WHERE id = ?`,
127 id,
128 )
129 return err
130}
131
132func (r *DownloadRepository) MarkCompleted(id int64, status string) error {
133 _, err := r.db.Exec(
134 `UPDATE downloads SET status = ?, completed_at = CURRENT_TIMESTAMP WHERE id = ?`,
135 status, id,
136 )
137 return err
138}
139
140func (r *DownloadRepository) MarkError(id int64, errMsg string) error {
141 _, err := r.db.Exec(
142 `UPDATE downloads SET status = 'error', error_message = ? WHERE id = ?`,
143 errMsg, id,
144 )
145 return err
146}
147
148func (r *DownloadRepository) Delete(id int64) error {
149 _, err := r.db.Exec(`DELETE FROM downloads WHERE id = ?`, id)
150 return err
151}
152
153func scanDownload(row interface{ Scan(...interface{}) error }) (*models.Download, error) {
154 var d models.Download
155 err := row.Scan(
156 &d.ID, &d.URL, &d.Status, &d.ProgressPercent, &d.CurrentSpeed, &d.ETA,
157 &d.Logs, &d.ErrorMessage, &d.PresetID, &d.FormatOverride, &d.CustomFlags,
158 &d.StartedAt, &d.CompletedAt, &d.CreatedAt,
159 )
160 if err != nil {
161 return nil, err
162 }
163 return &d, nil
164}
165