Files
silo-server/migrations/sql/139_media_requests.sql
T

132 lines
5.7 KiB
SQL

-- +goose Up
-- +goose StatementBegin
CREATE TABLE IF NOT EXISTS public.request_settings (
id boolean PRIMARY KEY DEFAULT true,
requests_enabled boolean NOT NULL DEFAULT false,
global_max_requests integer NOT NULL DEFAULT 5,
global_window_days integer NOT NULL DEFAULT 7,
global_auto_approval_enabled boolean NOT NULL DEFAULT false,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT request_settings_singleton CHECK (id),
CONSTRAINT request_settings_global_max_nonnegative CHECK (global_max_requests >= 0),
CONSTRAINT request_settings_global_window_positive CHECK (global_window_days > 0)
);
INSERT INTO public.request_settings (id)
VALUES (true)
ON CONFLICT (id) DO NOTHING;
CREATE TABLE IF NOT EXISTS public.request_user_limits (
user_id integer PRIMARY KEY REFERENCES public.users(id) ON DELETE CASCADE,
limit_mode text NOT NULL DEFAULT 'inherit',
max_requests integer,
window_days integer,
approval_mode text NOT NULL DEFAULT 'inherit',
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT request_user_limits_limit_mode_check
CHECK (limit_mode IN ('inherit', 'custom', 'unlimited', 'blocked')),
CONSTRAINT request_user_limits_approval_mode_check
CHECK (approval_mode IN ('inherit', 'manual', 'auto', 'blocked')),
CONSTRAINT request_user_limits_max_nonnegative
CHECK (max_requests IS NULL OR max_requests >= 0),
CONSTRAINT request_user_limits_window_positive
CHECK (window_days IS NULL OR window_days > 0)
);
CREATE TABLE IF NOT EXISTS public.request_integrations (
kind text PRIMARY KEY,
enabled boolean NOT NULL DEFAULT false,
base_url text NOT NULL DEFAULT '',
api_key_ref text NOT NULL DEFAULT '',
root_folder text NOT NULL DEFAULT '',
quality_profile_id integer,
tags integer[] NOT NULL DEFAULT '{}',
options jsonb NOT NULL DEFAULT '{}'::jsonb,
last_check_at timestamp with time zone,
last_check_status text NOT NULL DEFAULT '',
last_check_error text NOT NULL DEFAULT '',
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT request_integrations_kind_check CHECK (kind IN ('radarr', 'sonarr'))
);
CREATE TABLE IF NOT EXISTS public.media_requests (
id text PRIMARY KEY,
provider text NOT NULL DEFAULT 'tmdb',
media_type text NOT NULL,
tmdb_id integer NOT NULL,
tvdb_id integer,
imdb_id text NOT NULL DEFAULT '',
title text NOT NULL,
year integer,
overview text NOT NULL DEFAULT '',
poster_path text NOT NULL DEFAULT '',
backdrop_path text NOT NULL DEFAULT '',
status text NOT NULL,
outcome text NOT NULL DEFAULT 'active',
requested_by_user_id integer NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
requested_by_profile_id text NOT NULL DEFAULT '',
integration_kind text NOT NULL DEFAULT '',
external_id text NOT NULL DEFAULT '',
external_status text NOT NULL DEFAULT '',
last_error text NOT NULL DEFAULT '',
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
approved_at timestamp with time zone,
completed_at timestamp with time zone,
CONSTRAINT media_requests_provider_check CHECK (provider IN ('tmdb')),
CONSTRAINT media_requests_media_type_check CHECK (media_type IN ('movie', 'series')),
CONSTRAINT media_requests_status_check
CHECK (status IN ('pending', 'approved', 'queued', 'downloading', 'completed')),
CONSTRAINT media_requests_outcome_check
CHECK (outcome IN ('active', 'declined', 'cancelled', 'failed')),
CONSTRAINT media_requests_tmdb_positive CHECK (tmdb_id > 0)
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_media_requests_active_tmdb
ON public.media_requests (media_type, provider, tmdb_id)
WHERE outcome = 'active' AND status <> 'completed';
CREATE INDEX IF NOT EXISTS idx_media_requests_user_created
ON public.media_requests (requested_by_user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_media_requests_profile_created
ON public.media_requests (requested_by_profile_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_media_requests_status_created
ON public.media_requests (status, created_at DESC)
WHERE outcome = 'active';
CREATE INDEX IF NOT EXISTS idx_media_requests_outcome_created
ON public.media_requests (outcome, created_at DESC);
CREATE TABLE IF NOT EXISTS public.media_request_events (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
request_id text NOT NULL REFERENCES public.media_requests(id) ON DELETE CASCADE,
event_type text NOT NULL,
actor_user_id integer REFERENCES public.users(id) ON DELETE SET NULL,
actor_profile_id text NOT NULL DEFAULT '',
message text NOT NULL DEFAULT '',
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
created_at timestamp with time zone DEFAULT now() NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_media_request_events_request_created
ON public.media_request_events (request_id, created_at DESC);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS public.media_request_events;
DROP INDEX IF EXISTS public.idx_media_requests_outcome_created;
DROP INDEX IF EXISTS public.idx_media_requests_status_created;
DROP INDEX IF EXISTS public.idx_media_requests_profile_created;
DROP INDEX IF EXISTS public.idx_media_requests_user_created;
DROP INDEX IF EXISTS public.idx_media_requests_active_tmdb;
DROP TABLE IF EXISTS public.media_requests;
DROP TABLE IF EXISTS public.request_integrations;
DROP TABLE IF EXISTS public.request_user_limits;
DROP TABLE IF EXISTS public.request_settings;
-- +goose StatementEnd