From b18484e17ae24a9b5270fa7d75f2fe0cee7f018b Mon Sep 17 00:00:00 2001 From: biast12 <53872542+biast12@users.noreply.github.com> Date: Wed, 14 Oct 2026 19:57:39 +0200 Subject: [PATCH] Allow nullable panel colours Make embed, panel, gallery, custom, and support-hours colour fields nullable across schemas and Go models. Update panel embed mapping and custom-colour batch writes to preserve NULL values and return row errors. --- customcolours.go | 30 ++++++++++++++++++------------ embeds.go | 5 +++-- gallery_listings.go | 6 ++++-- gallery_snapshots.go | 2 +- panels.go | 9 +++++---- panelsupporthourssettings.go | 8 +++++--- 6 files changed, 36 insertions(+), 24 deletions(-) diff --git a/customcolours.go b/customcolours.go index ce680ea..6c2945a 100644 --- a/customcolours.go +++ b/customcolours.go @@ -21,12 +21,13 @@ func (c CustomColours) Schema() string { CREATE TABLE IF NOT EXISTS custom_colours( "guild_id" int8 NOT NULL, "colour_id" int2 NOT NULL, - "colour_code" int4 NOT NULL, + "colour_code" int4 NULL, PRIMARY KEY("guild_id", "colour_id") -);` +); +ALTER TABLE custom_colours ALTER COLUMN "colour_code" DROP NOT NULL;` } -func (c *CustomColours) Get(ctx context.Context, guildId uint64, colourId int16) (colourCode int, ok bool, e error) { +func (c *CustomColours) Get(ctx context.Context, guildId uint64, colourId int16) (colourCode *int, ok bool, e error) { query := `SELECT "colour_code" FROM custom_colours WHERE "guild_id" = $1 AND "colour_id" = $2;` if err := c.QueryRow(ctx, query, guildId, colourId).Scan(&colourCode); err == nil { @@ -40,18 +41,19 @@ func (c *CustomColours) Get(ctx context.Context, guildId uint64, colourId int16) return } -func (c *CustomColours) GetAll(ctx context.Context, guildId uint64) (map[int16]int, error) { +func (c *CustomColours) GetAll(ctx context.Context, guildId uint64) (map[int16]*int, error) { query := `SELECT "colour_id", "colour_code" FROM custom_colours WHERE "guild_id" = $1;` rows, err := c.Query(ctx, query, guildId) if err != nil { return nil, err } + defer rows.Close() - colours := make(map[int16]int) + colours := make(map[int16]*int) for rows.Next() { var colourId int16 - var colourCode int + var colourCode *int if err = rows.Scan(&colourId, &colourCode); err != nil { return nil, err @@ -60,10 +62,10 @@ func (c *CustomColours) GetAll(ctx context.Context, guildId uint64) (map[int16]i colours[colourId] = colourCode } - return colours, nil + return colours, rows.Err() } -func (c *CustomColours) Set(ctx context.Context, guildId uint64, colourId int16, colourCode int) (err error) { +func (c *CustomColours) Set(ctx context.Context, guildId uint64, colourId int16, colourCode *int) (err error) { query := ` INSERT INTO custom_colours("guild_id", "colour_id", "colour_code") VALUES($1, $2, $3) ON CONFLICT("guild_id", "colour_id") @@ -74,7 +76,7 @@ DO UPDATE SET "colour_code" = $3;` } // BatchSet colours = map[colour_id]value -func (c *CustomColours) BatchSet(ctx context.Context, guildId uint64, colours map[int16]int) (err error) { +func (c *CustomColours) BatchSet(ctx context.Context, guildId uint64, colours map[int16]*int) (err error) { query := ` INSERT INTO custom_colours("guild_id", "colour_id", "colour_code") VALUES($1, $2, $3) ON CONFLICT("guild_id", "colour_id") @@ -86,8 +88,12 @@ DO UPDATE SET "colour_code" = $3;` } res := c.SendBatch(ctx, batch) - defer res.Close() + for range colours { + if _, err = res.Exec(); err != nil { + res.Close() + return + } + } - _, err = res.Exec() - return + return res.Close() } diff --git a/embeds.go b/embeds.go index c466423..c0552fc 100644 --- a/embeds.go +++ b/embeds.go @@ -13,7 +13,7 @@ type CustomEmbed struct { Title *string `json:"title,omitempty"` Description *string `json:"description,omitempty"` Url *string `json:"url,omitempty"` - Colour uint32 `json:"colour,omitempty"` + Colour *uint32 `json:"colour"` AuthorName *string `json:"author_name,omitempty"` AuthorIconUrl *string `json:"author_icon_url,omitempty"` AuthorUrl *string `json:"author_url,omitempty"` @@ -47,7 +47,7 @@ CREATE TABLE IF NOT EXISTS embeds( "title" VARCHAR(255) NULL, "description" TEXT NULL CONSTRAINT description_length CHECK (length(description) <= 4096), "url" VARCHAR(255) NULL, - "colour" int4 NOT NULL CONSTRAINT colour_range CHECK (colour >= 0 AND colour <= 16777215), + "colour" int4 NULL CONSTRAINT colour_range CHECK (colour >= 0 AND colour <= 16777215), "author_name" VARCHAR(255) NULL, "author_icon_url" VARCHAR(255) NULL, "author_url" VARCHAR(255) NULL, @@ -58,6 +58,7 @@ CREATE TABLE IF NOT EXISTS embeds( "timestamp" TIMESTAMP NULL, PRIMARY KEY("id") ); +ALTER TABLE embeds ALTER COLUMN "colour" DROP NOT NULL; CREATE INDEX IF NOT EXISTS embeds_guild_id ON embeds("guild_id"); ALTER TABLE embeds ALTER COLUMN "title" TYPE VARCHAR(256); diff --git a/gallery_listings.go b/gallery_listings.go index c02bd72..16caf60 100644 --- a/gallery_listings.go +++ b/gallery_listings.go @@ -42,7 +42,7 @@ type GalleryListing struct { // Panel visual design fields - only populated for panel listings Title string `json:"title"` Content string `json:"content"` - Colour int32 `json:"colour"` + Colour *int32 `json:"colour"` ImageUrl *string `json:"image_url"` ThumbnailUrl *string `json:"thumbnail_url"` ButtonStyle *int16 `json:"button_style"` @@ -82,7 +82,7 @@ CREATE TABLE IF NOT EXISTS gallery_listings ( "snapshot_data" JSONB, "title" VARCHAR(255) NOT NULL DEFAULT '', "content" TEXT NOT NULL DEFAULT '', - "colour" INT4 NOT NULL DEFAULT 0, + "colour" INT4 NULL, "image_url" TEXT, "thumbnail_url" TEXT, "button_style" INT2 DEFAULT 1, @@ -92,6 +92,8 @@ CREATE TABLE IF NOT EXISTS gallery_listings ( "created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(), "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW() ); +ALTER TABLE gallery_listings ALTER COLUMN "colour" DROP NOT NULL; +ALTER TABLE gallery_listings ALTER COLUMN "colour" DROP DEFAULT; CREATE INDEX IF NOT EXISTS gallery_listings_status_idx ON gallery_listings("status"); CREATE INDEX IF NOT EXISTS gallery_listings_category_idx ON gallery_listings("category"); CREATE INDEX IF NOT EXISTS gallery_listings_listing_type_idx ON gallery_listings("listing_type"); diff --git a/gallery_snapshots.go b/gallery_snapshots.go index e848802..4b5f717 100644 --- a/gallery_snapshots.go +++ b/gallery_snapshots.go @@ -3,7 +3,7 @@ package database type GalleryPanelSnapshot struct { Title string `json:"title"` Content string `json:"content"` - Colour int32 `json:"colour"` + Colour *int32 `json:"colour"` ImageUrl *string `json:"image_url,omitempty"` ThumbnailUrl *string `json:"thumbnail_url,omitempty"` ButtonStyle *int16 `json:"button_style"` diff --git a/panels.go b/panels.go index c87458a..e6b6117 100644 --- a/panels.go +++ b/panels.go @@ -14,7 +14,7 @@ type Panel struct { GuildId uint64 `json:"guild_id,string"` Title string `json:"title"` Content string `json:"content"` - Colour int32 `json:"colour"` + Colour *int32 `json:"colour"` TargetCategory uint64 `json:"category_id,string"` EmojiName *string `json:"emoji_name"` EmojiId *uint64 `json:"emoji_id,string"` @@ -77,7 +77,7 @@ CREATE TABLE IF NOT EXISTS panels( "guild_id" int8 NOT NULL, "title" varchar(255) NOT NULL, "content" text NOT NULL, - "colour" int4 NOT NULL, + "colour" int4 NULL, "target_category" int8 NOT NULL, "emoji_name" varchar(32) DEFAULT NULL, "emoji_id" int8 DEFAULT NULL, @@ -118,6 +118,7 @@ CREATE TABLE IF NOT EXISTS panels( FOREIGN KEY ("exit_survey_form_id") REFERENCES forms("form_id"), PRIMARY KEY("panel_id") ); +ALTER TABLE panels ALTER COLUMN "colour" DROP NOT NULL; CREATE INDEX IF NOT EXISTS panels_guild_id ON panels("guild_id"); CREATE INDEX IF NOT EXISTS panels_message_id ON panels("message_id"); CREATE INDEX IF NOT EXISTS panels_form_id ON panels("form_id"); @@ -344,7 +345,7 @@ AND panels.panel_id = $2;` if embedId != nil { embed.Id = *embedId embed.GuildId = *embedGuildId - embed.Colour = *embedColour + embed.Colour = embedColour embedPtr = &embed } @@ -712,7 +713,7 @@ ORDER BY panels.panel_id ASC;` if embedId != nil { embed.Id = *embedId embed.GuildId = *embedGuildId - embed.Colour = *embedColour + embed.Colour = embedColour embedPtr = &embed } diff --git a/panelsupporthourssettings.go b/panelsupporthourssettings.go index b18c319..5140eb7 100644 --- a/panelsupporthourssettings.go +++ b/panelsupporthourssettings.go @@ -18,7 +18,7 @@ type PanelSupportHoursSettings struct { OutOfHoursBehaviour OutOfHoursBehaviour `json:"out_of_hours_behaviour"` OutOfHoursTitle string `json:"out_of_hours_title"` OutOfHoursMessage string `json:"out_of_hours_message"` - OutOfHoursColour int `json:"out_of_hours_colour"` + OutOfHoursColour *int `json:"out_of_hours_colour"` } type PanelSupportHoursSettingsTable struct { @@ -36,9 +36,11 @@ CREATE TABLE IF NOT EXISTS panel_support_hours_settings ( "out_of_hours_behaviour" VARCHAR(50) NOT NULL DEFAULT 'block_creation', "out_of_hours_title" VARCHAR(100) NOT NULL DEFAULT 'Support is currently unavailable', "out_of_hours_message" TEXT NOT NULL DEFAULT '', - "out_of_hours_colour" int4 NOT NULL DEFAULT 0, + "out_of_hours_colour" int4 DEFAULT NULL, FOREIGN KEY ("panel_id") REFERENCES panels("panel_id") ON DELETE CASCADE -);` +); +ALTER TABLE panel_support_hours_settings ALTER COLUMN "out_of_hours_colour" DROP NOT NULL; +ALTER TABLE panel_support_hours_settings ALTER COLUMN "out_of_hours_colour" DROP DEFAULT;` } // Get retrieves the support hours settings for a panel. Returns the settings, whether they exist, and any error.