preset.go
⎇
Raw
1package repository
2
3import (
4 "database/sql"
5 "fmt"
6
7 "vidarchive/internal/models"
8)
9
10type PresetRepository struct {
11 db *sql.DB
12}
13
14func NewPresetRepository(db *sql.DB) *PresetRepository {
15 return &PresetRepository{db: db}
16}
17
18func insertPreset(tx *sql.Tx, p *models.Preset) error {
19 result, err := tx.Exec(
20 `INSERT INTO presets (name, description, is_default, format_mode, format, quality, custom_format, extract_audio, audio_format, embed_subs, sub_langs, embed_thumbnail, embed_metadata, write_info_json, write_comments, comment_sort, max_comments, comment_extractor_args, custom_flags)
21 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
22 p.Name, p.Description, boolToInt(p.IsDefault), p.FormatMode, p.Format, p.Quality, p.CustomFormat,
23 boolToInt(p.ExtractAudio), p.AudioFormat, boolToInt(p.EmbedSubs), p.SubLangs,
24 boolToInt(p.EmbedThumbnail), boolToInt(p.EmbedMetadata), boolToInt(p.WriteInfoJSON),
25 boolToInt(p.WriteComments), p.CommentSort, p.MaxComments, p.CommentExtractorArgs,
26 p.CustomFlags,
27 )
28 if err != nil {
29 return err
30 }
31 id, err := result.LastInsertId()
32 if err != nil {
33 return fmt.Errorf("preset last insert id: %w", err)
34 }
35 p.ID = id
36 return nil
37}
38
39func updatePreset(tx *sql.Tx, p *models.Preset) error {
40 _, err := tx.Exec(
41 `UPDATE presets SET name=?, description=?, is_default=?, format_mode=?, format=?, quality=?, custom_format=?, extract_audio=?, audio_format=?, embed_subs=?, sub_langs=?, embed_thumbnail=?, embed_metadata=?, write_info_json=?, write_comments=?, comment_sort=?, max_comments=?, comment_extractor_args=?, custom_flags=?
42 WHERE id=?`,
43 p.Name, p.Description, boolToInt(p.IsDefault), p.FormatMode, p.Format, p.Quality, p.CustomFormat,
44 boolToInt(p.ExtractAudio), p.AudioFormat, boolToInt(p.EmbedSubs), p.SubLangs,
45 boolToInt(p.EmbedThumbnail), boolToInt(p.EmbedMetadata), boolToInt(p.WriteInfoJSON),
46 boolToInt(p.WriteComments), p.CommentSort, p.MaxComments, p.CommentExtractorArgs,
47 p.CustomFlags, p.ID,
48 )
49 return err
50}
51
52func clearDefault(tx *sql.Tx) error {
53 _, err := tx.Exec(`UPDATE presets SET is_default = 0`)
54 return err
55}
56
57// Save clears the previous default in the same transaction, so a mid-sequence
58// failure cannot leave the library with no default set. Create and Update both
59// route through here, so the exclusive-default invariant can't be bypassed.
60func (r *PresetRepository) Save(p *models.Preset) error {
61 tx, err := r.db.Begin()
62 if err != nil {
63 return err
64 }
65 defer tx.Rollback()
66
67 if p.IsDefault {
68 if err := clearDefault(tx); err != nil {
69 return err
70 }
71 }
72 if p.ID == 0 {
73 err = insertPreset(tx, p)
74 } else {
75 err = updatePreset(tx, p)
76 }
77 if err != nil {
78 return err
79 }
80 return tx.Commit()
81}
82
83func (r *PresetRepository) GetByID(id int64) (*models.Preset, error) {
84 row := r.db.QueryRow(
85 `SELECT id, name, description, is_default, format_mode, format, quality, custom_format, extract_audio, audio_format, embed_subs, sub_langs, embed_thumbnail, embed_metadata, write_info_json, write_comments, comment_sort, max_comments, comment_extractor_args, custom_flags, created_at
86 FROM presets WHERE id = ?`, id,
87 )
88 return scanPreset(row)
89}
90
91func (r *PresetRepository) GetAll() ([]*models.Preset, error) {
92 rows, err := r.db.Query(
93 `SELECT id, name, description, is_default, format_mode, format, quality, custom_format, extract_audio, audio_format, embed_subs, sub_langs, embed_thumbnail, embed_metadata, write_info_json, write_comments, comment_sort, max_comments, comment_extractor_args, custom_flags, created_at
94 FROM presets ORDER BY name`,
95 )
96 if err != nil {
97 return nil, err
98 }
99 defer rows.Close()
100
101 var presets []*models.Preset
102 for rows.Next() {
103 p, err := scanPreset(rows)
104 if err != nil {
105 return nil, err
106 }
107 presets = append(presets, p)
108 }
109 return presets, rows.Err()
110}
111
112func (r *PresetRepository) GetDefault() (*models.Preset, error) {
113 row := r.db.QueryRow(
114 `SELECT id, name, description, is_default, format_mode, format, quality, custom_format, extract_audio, audio_format, embed_subs, sub_langs, embed_thumbnail, embed_metadata, write_info_json, write_comments, comment_sort, max_comments, comment_extractor_args, custom_flags, created_at
115 FROM presets WHERE is_default = 1 LIMIT 1`,
116 )
117 return scanPreset(row)
118}
119
120func (r *PresetRepository) Delete(id int64) error {
121 _, err := r.db.Exec(`DELETE FROM presets WHERE id = ?`, id)
122 return err
123}
124
125func scanPreset(row interface{ Scan(...interface{}) error }) (*models.Preset, error) {
126 var p models.Preset
127 var isDefault, extractAudio, embedSubs, embedThumbnail, embedMetadata, writeInfoJSON, writeComments, maxComments int
128 var description, formatMode, format, quality, customFormat, audioFormat, subLangs, commentSort, commentExtractorArgs, customFlags sql.NullString
129 err := row.Scan(
130 &p.ID, &p.Name, &description, &isDefault, &formatMode, &format, &quality, &customFormat,
131 &extractAudio, &audioFormat, &embedSubs, &subLangs,
132 &embedThumbnail, &embedMetadata, &writeInfoJSON,
133 &writeComments, &commentSort, &maxComments, &commentExtractorArgs,
134 &customFlags, &p.CreatedAt,
135 )
136 if err != nil {
137 return nil, err
138 }
139 p.Description = description.String
140 p.FormatMode = formatMode.String
141 p.Format = format.String
142 p.Quality = quality.String
143 p.CustomFormat = customFormat.String
144 p.AudioFormat = audioFormat.String
145 p.SubLangs = subLangs.String
146 p.CustomFlags = customFlags.String
147 p.CommentSort = commentSort.String
148 p.CommentExtractorArgs = commentExtractorArgs.String
149 p.MaxComments = maxComments
150 p.IsDefault = isDefault == 1
151 p.ExtractAudio = extractAudio == 1
152 p.EmbedSubs = embedSubs == 1
153 p.EmbedThumbnail = embedThumbnail == 1
154 p.EmbedMetadata = embedMetadata == 1
155 p.WriteInfoJSON = writeInfoJSON == 1
156 p.WriteComments = writeComments == 1
157 return &p, nil
158}
159
160func boolToInt(b bool) int {
161 if b {
162 return 1
163 }
164 return 0
165}
166