132 lines
5.7 KiB
SQL
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
|