osu! goals: games.osu_goals (maps to pass/FC from the old list) with osu! API v2 metadata (stars NM/DT/HR/HD, BPM, length, AR/OD/CS/HP, combo, objects, tags, community tags, streams from .osu), my best scores and pass/FC via hourly in-app refresh; Goals section on /trackers/games/osu; retired list URL 301s there
All checks were successful
Deploy production / deploy (push) Successful in 1m15s
All checks were successful
Deploy production / deploy (push) Successful in 1m15s
This commit is contained in:
102
drizzle/20261026003557_osu_goals/migration.sql
Normal file
102
drizzle/20261026003557_osu_goals/migration.sql
Normal file
@@ -0,0 +1,102 @@
|
||||
CREATE TABLE "games"."osu_goals" (
|
||||
"id" serial PRIMARY KEY,
|
||||
"name" text NOT NULL,
|
||||
"goal" text,
|
||||
"mods" text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
"notes" text,
|
||||
"sort_order" integer DEFAULT 0 NOT NULL,
|
||||
"list_item_id" integer,
|
||||
"match_status" text DEFAULT 'unmatched' NOT NULL,
|
||||
"match_note" text,
|
||||
"candidates" jsonb DEFAULT '[]' NOT NULL,
|
||||
"beatmapset_id" integer,
|
||||
"beatmap_id" integer,
|
||||
"mode" text,
|
||||
"artist" text,
|
||||
"title" text,
|
||||
"artist_unicode" text,
|
||||
"title_unicode" text,
|
||||
"mapper" text,
|
||||
"mapper_id" integer,
|
||||
"version" text,
|
||||
"diff_mapper_id" integer,
|
||||
"status" text,
|
||||
"ranked_at" timestamp with time zone,
|
||||
"submitted_at" timestamp with time zone,
|
||||
"source" text,
|
||||
"genre" text,
|
||||
"language" text,
|
||||
"tags" text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
"user_tags" text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
"bpm" double precision,
|
||||
"bpm_min" double precision,
|
||||
"bpm_max" double precision,
|
||||
"length_seconds" integer,
|
||||
"drain_seconds" integer,
|
||||
"ar" double precision,
|
||||
"od" double precision,
|
||||
"cs" double precision,
|
||||
"hp" double precision,
|
||||
"max_combo" integer,
|
||||
"circles" integer,
|
||||
"sliders" integer,
|
||||
"spinners" integer,
|
||||
"stars" double precision,
|
||||
"stars_dt" double precision,
|
||||
"stars_hr" double precision,
|
||||
"stars_hd" double precision,
|
||||
"stars_hddt" double precision,
|
||||
"stars_hdhr" double precision,
|
||||
"attributes" jsonb,
|
||||
"longest_stream" integer,
|
||||
"stream_notes" integer,
|
||||
"play_count" integer,
|
||||
"pass_count" integer,
|
||||
"favourite_count" integer,
|
||||
"map_play_count" integer,
|
||||
"cover_url" text,
|
||||
"card_url" text,
|
||||
"list_url" text,
|
||||
"preview_url" text,
|
||||
"focus" text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
"metadata_at" timestamp with time zone,
|
||||
"my_play_count" integer,
|
||||
"best_score_id" bigint,
|
||||
"best_score" bigint,
|
||||
"best_accuracy" double precision,
|
||||
"best_mods" text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
"best_rank" text,
|
||||
"best_pp" double precision,
|
||||
"best_combo" integer,
|
||||
"best_misses" integer,
|
||||
"best_fc" boolean,
|
||||
"best_at" timestamp with time zone,
|
||||
"passed" boolean DEFAULT false NOT NULL,
|
||||
"fc" boolean DEFAULT false NOT NULL,
|
||||
"achieved_at" timestamp with time zone,
|
||||
"scores" jsonb DEFAULT '[]' NOT NULL,
|
||||
"scores_at" timestamp with time zone,
|
||||
"last_error" text,
|
||||
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "osu_goals_goal_check" CHECK ("goal" IS NULL OR "goal" IN ('pass','fc')),
|
||||
CONSTRAINT "osu_goals_match_check" CHECK ("match_status" IN ('matched','ambiguous','unmatched') AND ("match_status" <> 'matched' OR "beatmap_id" IS NOT NULL)),
|
||||
CONSTRAINT "osu_goals_name_check" CHECK (length(btrim("name")) > 0)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE INDEX "osu_goals_beatmap_idx" ON "games"."osu_goals" ("beatmap_id");--> statement-breakpoint
|
||||
-- Hand-written: grants (same pattern as the other app tables) and the updated_at trigger.
|
||||
-- Rows come from the retired list lists.osu_maps (imported once, then refreshed by the app).
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'personal_app') THEN
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON games.osu_goals TO personal_app;
|
||||
GRANT USAGE, SELECT ON SEQUENCE games.osu_goals_id_seq TO personal_app;
|
||||
END IF;
|
||||
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'personal_ro') THEN
|
||||
GRANT SELECT ON games.osu_goals TO personal_ro;
|
||||
END IF;
|
||||
IF to_regprocedure('meta.touch_updated_at()') IS NOT NULL THEN
|
||||
CREATE TRIGGER touch_updated_at BEFORE UPDATE ON games.osu_goals FOR EACH ROW EXECUTE FUNCTION meta.touch_updated_at();
|
||||
END IF;
|
||||
END $$;
|
||||
39883
drizzle/20261026003557_osu_goals/snapshot.json
Normal file
39883
drizzle/20261026003557_osu_goals/snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user