Files
silo-server/internal/userdb/subtitle_prefs.go
T

106 lines
3.6 KiB
Go

package userdb
import (
"database/sql"
"fmt"
"github.com/Silo-Server/silo-server/internal/userstore"
)
// SubtitlePreference is an alias for the canonical type in userstore.
type SubtitlePreference = userstore.SubtitlePreference
// SetSubtitlePreference creates or replaces a subtitle preference for a
// given profile and series. Timestamps should be ISO 8601 UTC strings.
func SetSubtitlePreference(db *sql.DB, pref SubtitlePreference) error {
if pref.ShowForcedSubtitles {
pref.HasShowForcedSubtitles = true
}
signatureJSON, err := userstore.MarshalSubtitleTrackSignature(pref.TrackSignature)
if err != nil {
return fmt.Errorf("marshaling subtitle track signature for profile %q series %q: %w",
pref.ProfileID, pref.SeriesID, err)
}
_, err = db.Exec(`
INSERT INTO subtitle_preferences (
profile_id, series_id, subtitle_language, subtitle_track_index,
external_subtitle_path, subtitle_mode, subtitle_track_signature, show_forced_subtitles, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(profile_id, series_id) DO UPDATE SET
subtitle_language = excluded.subtitle_language,
subtitle_track_index = excluded.subtitle_track_index,
external_subtitle_path = excluded.external_subtitle_path,
subtitle_mode = excluded.subtitle_mode,
subtitle_track_signature = excluded.subtitle_track_signature,
show_forced_subtitles = excluded.show_forced_subtitles,
updated_at = excluded.updated_at`,
pref.ProfileID,
pref.SeriesID,
pref.SubtitleLanguage,
pref.SubtitleTrackIndex,
pref.ExternalSubtitlePath,
pref.SubtitleMode,
string(signatureJSON),
libraryPlaybackBoolDBValue(pref.ShowForcedSubtitles, pref.HasShowForcedSubtitles),
pref.UpdatedAt,
)
if err != nil {
return fmt.Errorf("setting subtitle preference for profile %q series %q: %w",
pref.ProfileID, pref.SeriesID, err)
}
return nil
}
// GetSubtitlePreference retrieves the subtitle preference for a profile
// and series. Returns nil (not an error) if no preference exists.
func GetSubtitlePreference(db *sql.DB, profileID, seriesID string) (*SubtitlePreference, error) {
var pref SubtitlePreference
var showForcedSubtitles sql.NullBool
var signatureJSON string
err := db.QueryRow(`
SELECT profile_id, series_id, subtitle_language, subtitle_track_index,
external_subtitle_path, subtitle_mode, subtitle_track_signature, show_forced_subtitles, updated_at
FROM subtitle_preferences
WHERE profile_id = ? AND series_id = ?`,
profileID, seriesID,
).Scan(
&pref.ProfileID,
&pref.SeriesID,
&pref.SubtitleLanguage,
&pref.SubtitleTrackIndex,
&pref.ExternalSubtitlePath,
&pref.SubtitleMode,
&signatureJSON,
&showForcedSubtitles,
&pref.UpdatedAt,
)
if err == sql.ErrNoRows {
return nil, nil
}
if err != nil {
return nil, fmt.Errorf("getting subtitle preference for profile %q series %q: %w",
profileID, seriesID, err)
}
pref.TrackSignature, err = userstore.UnmarshalSubtitleTrackSignature([]byte(signatureJSON))
if err != nil {
return nil, fmt.Errorf("decoding subtitle track signature for profile %q series %q: %w",
profileID, seriesID, err)
}
pref.ShowForcedSubtitles, pref.HasShowForcedSubtitles = boolValue(showForcedSubtitles)
return &pref, nil
}
// DeleteSubtitlePreference removes the subtitle preference for a profile
// and series. It is not an error if the preference does not exist.
func DeleteSubtitlePreference(db *sql.DB, profileID, seriesID string) error {
_, err := db.Exec(
"DELETE FROM subtitle_preferences WHERE profile_id = ? AND series_id = ?",
profileID, seriesID,
)
if err != nil {
return fmt.Errorf("deleting subtitle preference for profile %q series %q: %w",
profileID, seriesID, err)
}
return nil
}