0.2.71
This commit is contained in:
@@ -15,6 +15,9 @@ import (
|
||||
// MaintenanceKey is the app_settings row backing maintenance mode.
|
||||
const MaintenanceKey = "maintenance"
|
||||
|
||||
// QuietTimeKey is the app_settings row backing the daily server quiet-time window.
|
||||
const QuietTimeKey = "quiet_time"
|
||||
|
||||
// RequestPolicyKey controls which Emby users may send titles to Sonarr/Radarr.
|
||||
const RequestPolicyKey = "request_policy"
|
||||
|
||||
@@ -742,6 +745,101 @@ func (s *Store) SetMaintenance(ctx context.Context, state Maintenance) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// QuietTime is a daily window in the household timezone during which Memby's data plane
|
||||
// and background work stand down. The admin control plane and health checks remain live so
|
||||
// an operator can change a bad schedule without restarting the container.
|
||||
type QuietTime struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
StartTime string `json:"startTime"`
|
||||
EndTime string `json:"endTime"`
|
||||
Message string `json:"message"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
|
||||
const DefaultQuietTimeMessage = "Memby is in quiet time. Try again later."
|
||||
|
||||
func DefaultQuietTime() QuietTime {
|
||||
return QuietTime{StartTime: "23:00", EndTime: "07:00", Message: DefaultQuietTimeMessage}
|
||||
}
|
||||
|
||||
// QuietTimeActive reports whether now falls in the configured local-clock window. A
|
||||
// window crossing midnight includes late evening and the following morning. Equal or
|
||||
// malformed endpoints are treated as inactive; the admin handler refuses both.
|
||||
func QuietTimeActive(policy QuietTime, now time.Time, location *time.Location) bool {
|
||||
if !policy.Enabled {
|
||||
return false
|
||||
}
|
||||
start, startErr := time.Parse("15:04", policy.StartTime)
|
||||
end, endErr := time.Parse("15:04", policy.EndTime)
|
||||
if startErr != nil || endErr != nil || policy.StartTime == policy.EndTime {
|
||||
return false
|
||||
}
|
||||
if location == nil {
|
||||
location = time.UTC
|
||||
}
|
||||
local := now.In(location)
|
||||
minute := local.Hour()*60 + local.Minute()
|
||||
startMinute := start.Hour()*60 + start.Minute()
|
||||
endMinute := end.Hour()*60 + end.Minute()
|
||||
if startMinute < endMinute {
|
||||
return minute >= startMinute && minute < endMinute
|
||||
}
|
||||
return minute >= startMinute || minute < endMinute
|
||||
}
|
||||
|
||||
func normaliseQuietTime(policy QuietTime) QuietTime {
|
||||
defaults := DefaultQuietTime()
|
||||
if parsed, err := time.Parse("15:04", strings.TrimSpace(policy.StartTime)); err == nil {
|
||||
policy.StartTime = parsed.Format("15:04")
|
||||
} else {
|
||||
policy.StartTime = defaults.StartTime
|
||||
}
|
||||
if parsed, err := time.Parse("15:04", strings.TrimSpace(policy.EndTime)); err == nil {
|
||||
policy.EndTime = parsed.Format("15:04")
|
||||
} else {
|
||||
policy.EndTime = defaults.EndTime
|
||||
}
|
||||
policy.Message = strings.TrimSpace(policy.Message)
|
||||
if policy.Message == "" {
|
||||
policy.Message = DefaultQuietTimeMessage
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func (s *Store) QuietTime(ctx context.Context) (QuietTime, error) {
|
||||
var raw []byte
|
||||
err := s.pool.QueryRow(ctx, `SELECT value FROM app_settings WHERE key = $1`, QuietTimeKey).Scan(&raw)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return DefaultQuietTime(), nil
|
||||
}
|
||||
if err != nil {
|
||||
return DefaultQuietTime(), fmt.Errorf("store: read quiet time: %w", err)
|
||||
}
|
||||
var policy QuietTime
|
||||
if err := json.Unmarshal(raw, &policy); err != nil {
|
||||
return DefaultQuietTime(), fmt.Errorf("store: decode quiet time: %w", err)
|
||||
}
|
||||
return normaliseQuietTime(policy), nil
|
||||
}
|
||||
|
||||
func (s *Store) SetQuietTime(ctx context.Context, policy QuietTime) error {
|
||||
policy = normaliseQuietTime(policy)
|
||||
policy.UpdatedAt = time.Now().UTC()
|
||||
raw, err := json.Marshal(policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = s.pool.Exec(ctx, `
|
||||
INSERT INTO app_settings (key, value, updated_at)
|
||||
VALUES ($1, $2::jsonb, now())
|
||||
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now()`,
|
||||
QuietTimeKey, string(raw))
|
||||
if err != nil {
|
||||
return fmt.Errorf("store: write quiet time: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdatePolicyKey is the app_settings row backing the client update policy.
|
||||
const UpdatePolicyKey = "update_policy"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user