diff --git a/backend/app/http/endpoints/api/admin/gallery/list.go b/backend/app/http/endpoints/api/admin/gallery/list.go index 9f1b4bec..dd71a9ad 100644 --- a/backend/app/http/endpoints/api/admin/gallery/list.go +++ b/backend/app/http/endpoints/api/admin/gallery/list.go @@ -39,7 +39,7 @@ type adminListingResponse struct { SnapshotData stdjson.RawMessage `json:"snapshot_data,omitempty"` 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"` diff --git a/backend/app/http/endpoints/api/gallery/galleryimport.go b/backend/app/http/endpoints/api/gallery/galleryimport.go index 138adf65..9231f02b 100644 --- a/backend/app/http/endpoints/api/gallery/galleryimport.go +++ b/backend/app/http/endpoints/api/gallery/galleryimport.go @@ -185,7 +185,7 @@ func ImportHandler(ctx *gin.Context) { e := embed.NewEmbed(). SetTitle(panel.Title). SetDescription(panel.Content). - SetColor(int(panel.Colour)) + SetColorPtr(utils.ConvertPtr[int](panel.Colour)) if panel.ImageUrl != nil { e.SetImage(*panel.ImageUrl) diff --git a/backend/app/http/endpoints/api/gallery/submit_form.go b/backend/app/http/endpoints/api/gallery/submit_form.go index d54a257f..41473ef5 100644 --- a/backend/app/http/endpoints/api/gallery/submit_form.go +++ b/backend/app/http/endpoints/api/gallery/submit_form.go @@ -171,7 +171,7 @@ func SubmitFormHandler(ctx *gin.Context) { // Panel fields left at zero values for non-panel listings Title: "", Content: "", - Colour: 0, + Colour: nil, ButtonLabel: "", } diff --git a/backend/app/http/endpoints/api/gallery/submit_tag.go b/backend/app/http/endpoints/api/gallery/submit_tag.go index 5ba3d519..35120dda 100644 --- a/backend/app/http/endpoints/api/gallery/submit_tag.go +++ b/backend/app/http/endpoints/api/gallery/submit_tag.go @@ -116,7 +116,7 @@ func SubmitTagHandler(ctx *gin.Context) { // Panel fields left at zero values for non-panel listings Title: "", Content: "", - Colour: 0, + Colour: nil, ButtonLabel: "", } diff --git a/backend/app/http/endpoints/api/gallery/types.go b/backend/app/http/endpoints/api/gallery/types.go index 519a2d3d..9eeb4815 100644 --- a/backend/app/http/endpoints/api/gallery/types.go +++ b/backend/app/http/endpoints/api/gallery/types.go @@ -70,7 +70,7 @@ type galleryListingPublicResponse struct { SnapshotData stdjson.RawMessage `json:"snapshot_data,omitempty"` 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"` @@ -99,7 +99,7 @@ type galleryListingResponse struct { SnapshotData stdjson.RawMessage `json:"snapshot_data,omitempty"` 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/backend/app/http/endpoints/api/panel/multipanelget.go b/backend/app/http/endpoints/api/panel/multipanelget.go index ff784c5e..f791ce34 100644 --- a/backend/app/http/endpoints/api/panel/multipanelget.go +++ b/backend/app/http/endpoints/api/panel/multipanelget.go @@ -59,7 +59,7 @@ func MultiPanelGet(ctx *gin.Context) { if multiPanel.Embed != nil && multiPanel.Embed.CustomEmbed != nil { transformedEmbed = types.NewCustomEmbed(multiPanel.Embed.CustomEmbed, multiPanel.Embed.Fields) } else { - transformedEmbed = &types.CustomEmbed{Colour: 0x5865f2} + transformedEmbed = &types.CustomEmbed{Colour: utils.Ptr(types.Colour(0x5865f2))} } panels, err := dbclient.Client.MultiPanelTargets.GetPanels(ctx, multiPanelId) diff --git a/backend/app/http/endpoints/api/panel/multipanelmessagedata.go b/backend/app/http/endpoints/api/panel/multipanelmessagedata.go index cb1c5288..69938c00 100644 --- a/backend/app/http/endpoints/api/panel/multipanelmessagedata.go +++ b/backend/app/http/endpoints/api/panel/multipanelmessagedata.go @@ -43,7 +43,8 @@ func multiPanelDiscordSubPanelError(action, detail string) string { } func multiPanelIntoMessageData(panel database.MultiPanel, footer footerPolicy) multiPanelMessageData { - custom := &types.CustomEmbed{Colour: 0x5865f2} + blurple := types.Colour(0x5865f2) + custom := &types.CustomEmbed{Colour: &blurple} if panel.Embed != nil && panel.Embed.CustomEmbed != nil { custom = types.NewCustomEmbed(panel.Embed.CustomEmbed, panel.Embed.Fields) } diff --git a/backend/app/http/endpoints/api/panel/panelcreate.go b/backend/app/http/endpoints/api/panel/panelcreate.go index abbd40d6..f7ec22a8 100644 --- a/backend/app/http/endpoints/api/panel/panelcreate.go +++ b/backend/app/http/endpoints/api/panel/panelcreate.go @@ -40,7 +40,7 @@ type panelBody struct { MessageId uint64 `json:"message_id,string"` Title string `json:"title"` Content string `json:"content"` - Colour uint32 `json:"colour"` + Colour *uint32 `json:"colour" validate:"omitempty,max=16777215"` CategoryId uint64 `json:"category_id,string"` Emoji types.Emoji `json:"emote"` WelcomeMessage *types.CustomEmbed `json:"welcome_message" validate:"omitempty"` @@ -86,7 +86,7 @@ func (p *panelBody) IntoPanelMessageData(customId string, showBranding bool) pan Title: p.Title, Content: p.Content, CustomId: customId, - Colour: int(p.Colour), + Colour: utils.ConvertPtr[int](p.Colour), ImageUrl: p.ImageUrl, ThumbnailUrl: p.ThumbnailUrl, Emoji: p.getEmoji(), @@ -290,7 +290,7 @@ func CreatePanel(c *gin.Context) { GuildId: guildId, Title: data.Title, Content: data.Content, - Colour: int32(data.Colour), + Colour: utils.ConvertPtr[int32](data.Colour), TargetCategory: data.CategoryId, EmojiId: emojiId, EmojiName: emojiName, diff --git a/backend/app/http/endpoints/api/panel/panellist.go b/backend/app/http/endpoints/api/panel/panellist.go index 20d43996..4aeadfb5 100644 --- a/backend/app/http/endpoints/api/panel/panellist.go +++ b/backend/app/http/endpoints/api/panel/panellist.go @@ -18,7 +18,7 @@ func ListPanels(c *gin.Context) { PanelId int `json:"panel_id"` ChannelId uint64 `json:"channel_id,string"` Title string `json:"title"` - Colour int32 `json:"colour"` + Colour *int32 `json:"colour"` ButtonLabel string `json:"button_label"` ButtonStyle int `json:"button_style,string"` EmojiName *string `json:"emoji_name,omitempty"` diff --git a/backend/app/http/endpoints/api/panel/panelmessagedata.go b/backend/app/http/endpoints/api/panel/panelmessagedata.go index 16c4829d..e20e0604 100644 --- a/backend/app/http/endpoints/api/panel/panelmessagedata.go +++ b/backend/app/http/endpoints/api/panel/panelmessagedata.go @@ -12,13 +12,14 @@ import ( "github.com/ticketsbot-cloud/dashboard/backend/app" "github.com/ticketsbot-cloud/dashboard/backend/botcontext" "github.com/ticketsbot-cloud/dashboard/backend/config" + "github.com/ticketsbot-cloud/dashboard/backend/utils" ) type panelMessageData struct { ChannelId uint64 Title, Content, CustomId string - Colour int + Colour *int ImageUrl, ThumbnailUrl *string Emoji *emoji.Emoji ButtonStyle component.ButtonStyle @@ -47,7 +48,7 @@ func panelIntoMessageData(panel database.Panel, showBranding bool) panelMessageD Title: panel.Title, Content: panel.Content, CustomId: panel.CustomId, - Colour: int(panel.Colour), + Colour: utils.ConvertPtr[int](panel.Colour), ImageUrl: panel.ImageUrl, ThumbnailUrl: panel.ThumbnailUrl, Emoji: emote, @@ -62,7 +63,7 @@ func (p *panelMessageData) send(c *botcontext.BotContext) (uint64, error) { e := embed.NewEmbed(). SetTitle(p.Title). SetDescription(p.Content). - SetColor(p.Colour) + SetColorPtr(p.Colour) if p.ImageUrl != nil { e.SetImage(*p.ImageUrl) @@ -105,7 +106,7 @@ func (p *panelMessageData) edit(c *botcontext.BotContext, messageId uint64) erro e := embed.NewEmbed(). SetTitle(p.Title). SetDescription(p.Content). - SetColor(p.Colour) + SetColorPtr(p.Colour) if p.ImageUrl != nil { e.SetImage(*p.ImageUrl) diff --git a/backend/app/http/endpoints/api/panel/panelupdate.go b/backend/app/http/endpoints/api/panel/panelupdate.go index 97007d2f..4c768cce 100644 --- a/backend/app/http/endpoints/api/panel/panelupdate.go +++ b/backend/app/http/endpoints/api/panel/panelupdate.go @@ -279,7 +279,7 @@ func UpdatePanel(c *gin.Context) { GuildId: guildId, Title: data.Title, Content: data.Content, - Colour: int32(data.Colour), + Colour: utils.ConvertPtr[int32](data.Colour), TargetCategory: data.CategoryId, EmojiName: emojiName, EmojiId: emojiId, diff --git a/backend/app/http/endpoints/api/panel/supporthours.go b/backend/app/http/endpoints/api/panel/supporthours.go index a7ffab74..7b485df6 100644 --- a/backend/app/http/endpoints/api/panel/supporthours.go +++ b/backend/app/http/endpoints/api/panel/supporthours.go @@ -25,7 +25,7 @@ type supportHoursResponse struct { OutOfHoursBehaviour string `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"` } // supportHoursAuditData is used for audit log old/new data to include both hours and settings @@ -98,14 +98,10 @@ func GetSupportHours(c *gin.Context) { outOfHoursBehaviour := string(database.OutOfHoursBehaviourBlockCreation) var outOfHoursTitle string var outOfHoursMessage string - outOfHoursColour := 0xFC3F35 if settingsExist { outOfHoursBehaviour = string(settings.OutOfHoursBehaviour) outOfHoursTitle = settings.OutOfHoursTitle outOfHoursMessage = settings.OutOfHoursMessage - if settings.OutOfHoursColour != 0 { - outOfHoursColour = settings.OutOfHoursColour - } } response := supportHoursResponse{ @@ -114,12 +110,20 @@ func GetSupportHours(c *gin.Context) { OutOfHoursBehaviour: outOfHoursBehaviour, OutOfHoursTitle: outOfHoursTitle, OutOfHoursMessage: outOfHoursMessage, - OutOfHoursColour: outOfHoursColour, + OutOfHoursColour: outOfHoursColourResponse(settings, settingsExist), } c.JSON(http.StatusOK, response) } +func outOfHoursColourResponse(settings database.PanelSupportHoursSettings, settingsExist bool) *int { + if !settingsExist { + return utils.Ptr(0xFC3F35) + } + + return settings.OutOfHoursColour +} + // supportHoursPayload represents individual hour configuration in requests type supportHoursPayload struct { DayOfWeek int `json:"day_of_week"` @@ -135,7 +139,11 @@ type supportHoursRequestBody struct { OutOfHoursBehaviour string `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"` +} + +func isValidOutOfHoursColour(colour *int) bool { + return colour == nil || (*colour >= 0 && *colour <= 0xFFFFFF) } func SetSupportHours(c *gin.Context) { @@ -223,6 +231,11 @@ func SetSupportHours(c *gin.Context) { return } + if !isValidOutOfHoursColour(requestBody.OutOfHoursColour) { + c.JSON(http.StatusBadRequest, utils.ErrorStr("Invalid out of hours colour")) + return + } + // Fetch existing data for audit log oldHours, err := dbclient.Client.PanelSupportHours.GetByPanelId(c, panelId) if err != nil { @@ -319,7 +332,7 @@ func SetSupportHours(c *gin.Context) { if string(oldSettings.OutOfHoursBehaviour) != behaviour || oldSettings.OutOfHoursTitle != outOfHoursTitle || oldSettings.OutOfHoursMessage != outOfHoursMessage || - oldSettings.OutOfHoursColour != requestBody.OutOfHoursColour { + !utils.PtrEqual(oldSettings.OutOfHoursColour, requestBody.OutOfHoursColour) { hasChanges = true } diff --git a/backend/app/http/endpoints/api/settings/settings.go b/backend/app/http/endpoints/api/settings/settings.go index 9f779b81..92759d6a 100644 --- a/backend/app/http/endpoints/api/settings/settings.go +++ b/backend/app/http/endpoints/api/settings/settings.go @@ -20,7 +20,7 @@ type ( Language *string `json:"language"` } - ColourMap map[customisation.Colour]utils.HexColour + ColourMap map[customisation.Colour]*utils.HexColour ) func loadSettings(ctx context.Context, guildId uint64) (Settings, error) { @@ -101,20 +101,24 @@ func getColourMap(guildId uint64) (ColourMap, error) { return nil, err } + return newColourMap(raw), nil +} + +func newColourMap(raw map[int16]*int) ColourMap { colours := make(ColourMap) for id, hex := range raw { if !utils.Exists(activeColours, customisation.Colour(id)) { continue } - colours[customisation.Colour(id)] = utils.HexColour(hex) + colours[customisation.Colour(id)] = utils.ConvertPtr[utils.HexColour](hex) } for _, id := range activeColours { if _, ok := colours[id]; !ok { - colours[id] = utils.HexColour(customisation.DefaultColours[id]) + colours[id] = utils.Ptr(utils.HexColour(customisation.DefaultColours[id])) } } - return colours, nil + return colours } diff --git a/backend/app/http/endpoints/api/settings/updatesettings.go b/backend/app/http/endpoints/api/settings/updatesettings.go index ed13cce8..bd986a0f 100644 --- a/backend/app/http/endpoints/api/settings/updatesettings.go +++ b/backend/app/http/endpoints/api/settings/updatesettings.go @@ -127,7 +127,7 @@ func (s *Settings) Validate(ctx context.Context, guildId uint64, premiumTier pre for _, colourCode := range activeColours { if _, ok := s.Colours[colourCode]; !ok { - s.Colours[colourCode] = utils.HexColour(customisation.DefaultColours[colourCode]) + s.Colours[colourCode] = utils.Ptr(utils.HexColour(customisation.DefaultColours[colourCode])) } } @@ -171,9 +171,9 @@ func (s *Settings) updateLanguage(guildId uint64) error { func (s *Settings) updateColours(guildId uint64) error { // Convert ColourMap to primitives - converted := make(map[int16]int) + converted := make(map[int16]*int) for colour, hex := range s.Colours { - converted[int16(colour)] = int(hex) + converted[int16(colour)] = utils.ConvertPtr[int](hex) } return dbclient.Client.CustomColours.BatchSet(context.Background(), guildId, converted) diff --git a/backend/app/http/endpoints/api/ticket/closerequest.go b/backend/app/http/endpoints/api/ticket/closerequest.go index 4d569eb1..52b03305 100644 --- a/backend/app/http/endpoints/api/ticket/closerequest.go +++ b/backend/app/http/endpoints/api/ticket/closerequest.go @@ -162,7 +162,7 @@ func buildCloseRequestMessage(locale *i18n.Locale, requesterId uint64, reason *s msgEmbed := &embed.Embed{ Title: i18n.GetMessage(locale, i18n.TitleCloseRequest), Description: description, - Color: 0x2ECC71, + Color: utils.Ptr(0x2ECC71), } components := []component.Component{ diff --git a/backend/go.mod b/backend/go.mod index 55af17fb..782e8277 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -6,78 +6,81 @@ go 1.26.0 // replace github.com/TicketsBot-cloud/common => ../../common -// replace github.com/TicketsBot-cloud/worker => ../../worker +replace github.com/TicketsBot-cloud/worker => ../../worker // replace github.com/TicketsBot-cloud/gdl => ../../gdl replace github.com/go-playground/validator/v10 => github.com/go-playground/validator/v10 v10.14.0 require ( - github.com/BurntSushi/toml v1.2.1 - github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704 - github.com/TicketsBot-cloud/common v0.0.0-20260927072029-424264fc4be2 - github.com/TicketsBot-cloud/database v0.0.0-20261002063446-01dca52a987e - github.com/TicketsBot-cloud/gdl v0.0.0-20260927072153-8dbf0b284f57 - github.com/TicketsBot-cloud/logarchiver v0.0.0-20251018211319-7a7df5cacbdc - github.com/TicketsBot-cloud/worker v0.0.0-20260827073646-455b39e53841 - github.com/apex/log v1.1.2 - github.com/caarlos0/env/v11 v11.2.2 - github.com/getsentry/sentry-go v0.33.0 - github.com/getsentry/sentry-go/gin v0.33.0 - github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607 - github.com/gin-gonic/gin v1.10.1 - github.com/go-playground/validator/v10 v10.20.0 + github.com/BurntSushi/toml v1.6.0 + github.com/TicketsBot-cloud/archiverclient v0.0.0-20260912070140-b0cd1b003b87 + github.com/TicketsBot-cloud/common v0.0.0-20261022190115-887ce60dce1b + github.com/TicketsBot-cloud/database v0.0.0-20261022191045-27b0736fc5a3 + github.com/TicketsBot-cloud/gdl v0.0.0-20261022191043-9caa827c743a + github.com/TicketsBot-cloud/logarchiver v0.0.0-20260929182354-92f0b13a1e1f + github.com/TicketsBot-cloud/worker v0.0.0-20261022190051-090307fd295d + github.com/apex/log v1.9.0 + github.com/caarlos0/env/v11 v11.4.1 + github.com/getsentry/sentry-go v0.50.0 + github.com/getsentry/sentry-go/gin v0.50.0 + github.com/gin-gonic/contrib v0.0.0-20260101091603-d12f07a9136b + github.com/gin-gonic/gin v1.12.0 + github.com/go-playground/validator/v10 v10.30.5 github.com/go-redis/redis v6.15.9+incompatible github.com/go-redis/redis/v8 v8.11.5 - github.com/go-redis/redis_rate/v9 v9.1.1 + github.com/go-redis/redis_rate/v9 v9.1.2 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/uuid v1.6.0 - github.com/gorilla/websocket v1.5.0 + github.com/gorilla/websocket v1.5.3 github.com/jackc/pgconn v1.14.3 github.com/jackc/pgtype v1.14.4 github.com/jackc/pgx/v4 v4.18.3 github.com/joho/godotenv v1.5.1 github.com/mailgun/mailgun-go/v4 v4.23.0 - github.com/penglongli/gin-metrics v0.1.10 + github.com/penglongli/gin-metrics v0.1.13 github.com/pkg/errors v0.9.1 - github.com/polarsource/polar-go v0.15.0 - github.com/prometheus/client_golang v1.22.0 + github.com/polarsource/polar-go v0.16.0 + github.com/prometheus/client_golang v1.25.0 github.com/sirupsen/logrus v1.10.2 github.com/stretchr/testify v1.12.1 - github.com/weppos/publicsuffix-go v0.20.0 + github.com/weppos/publicsuffix-go v0.50.3 go.uber.org/zap v1.28.0 - golang.org/x/sync v0.23.0 + golang.org/x/sync v0.24.0 ) require ( github.com/TicketsBot/common v0.0.0-20241117150316-ff54c97b45c1 // indirect github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.2.0 // indirect - github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect + github.com/bits-and-blooms/bitset v1.26.0 // indirect + github.com/boj/redistore v1.4.2 // indirect github.com/boltdb/bolt v1.3.1 // indirect - github.com/bytedance/sonic v1.13.2 // indirect - github.com/bytedance/sonic/loader v0.2.4 // indirect + github.com/bytedance/gopkg v0.1.4 // indirect + github.com/bytedance/sonic v1.15.4 // indirect + github.com/bytedance/sonic/loader v0.5.3 // indirect github.com/caarlos0/env v3.5.0+incompatible // indirect github.com/caarlos0/env/v10 v10.0.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/cloudwego/base64x v0.1.5 // indirect + github.com/clipperhouse/uax29/v2 v2.7.0 // indirect + github.com/cloudwego/base64x v0.1.7 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect - github.com/dustin/go-humanize v1.0.1 // indirect + github.com/dustin/go-humanize v1.1.0 // indirect github.com/elliotchance/orderedmap v1.8.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.9 // indirect - github.com/gin-contrib/sse v1.1.0 // indirect - github.com/go-chi/chi/v5 v5.2.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.16 // indirect + github.com/gin-contrib/sse v1.1.2 // indirect + github.com/go-chi/chi/v5 v5.5.0 // indirect github.com/go-ini/ini v1.67.0 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-redsync/redsync/v4 v4.13.0 // indirect - github.com/goccy/go-json v0.10.5 // indirect + github.com/go-playground/locales v0.14.2 // indirect + github.com/go-playground/universal-translator v0.18.2 // indirect + github.com/go-redsync/redsync/v4 v4.18.0 // indirect + github.com/goccy/go-json v0.11.2 // indirect + github.com/goccy/go-yaml v1.19.2 // indirect github.com/gomodule/redigo v2.0.0+incompatible // indirect - github.com/gorilla/context v1.1.1 // indirect - github.com/gorilla/securecookie v1.1.1 // indirect - github.com/gorilla/sessions v1.2.1 // indirect - github.com/growthbook/growthbook-golang v0.2.9 // indirect + github.com/gorilla/context v1.1.2 // indirect + github.com/gorilla/securecookie v1.1.2 // indirect + github.com/gorilla/sessions v1.4.0 // indirect + github.com/growthbook/growthbook-golang v0.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect @@ -86,52 +89,58 @@ require ( github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx v3.6.2+incompatible // indirect - github.com/jackc/pgx/v5 v5.7.6 // indirect + github.com/jackc/pgx/v5 v5.11.0 // indirect github.com/jackc/puddle v1.3.0 // indirect - github.com/jackc/puddle/v2 v2.2.2 // indirect - github.com/jedib0t/go-pretty/v6 v6.6.7 // indirect + github.com/jackc/puddle/v2 v2.2.3 // indirect + github.com/jedib0t/go-pretty/v6 v6.8.3 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/juju/ratelimit v1.0.2 // indirect - github.com/klauspost/compress v1.18.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/mailgun/errors v0.4.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/klauspost/compress v1.20.3 // indirect + github.com/klauspost/cpuid/v2 v2.4.1 // indirect + github.com/klauspost/crc32 v1.3.0 // indirect + github.com/leodido/go-urn v1.5.0 // indirect + github.com/mailgun/errors v0.6.0 // indirect + github.com/mattn/go-isatty v0.0.24 // indirect + github.com/mattn/go-runewidth v0.0.31 // indirect github.com/minio/crc64nvme v1.1.1 // indirect github.com/minio/md5-simd v1.1.2 // indirect - github.com/minio/minio-go/v7 v7.0.95 // indirect + github.com/minio/minio-go/v7 v7.4.1 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/philhofer/fwd v1.2.0 // indirect - github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.63.0 // indirect - github.com/prometheus/procfs v0.16.1 // indirect + github.com/pasztorpisti/qs v0.0.0-20261010143646-f74307759693 // indirect + github.com/pelletier/go-toml/v2 v2.4.3 // indirect + github.com/philhofer/fwd v1.2.1 // indirect + github.com/prometheus/client_model v0.6.3 // indirect + github.com/prometheus/common v0.72.1 // indirect + github.com/prometheus/procfs v0.22.0 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.64.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/rs/xid v1.6.0 // indirect - github.com/schollz/progressbar/v3 v3.18.0 // indirect - github.com/spyzhov/ajson v0.8.0 // indirect + github.com/schollz/progressbar/v3 v3.19.1 // indirect + github.com/spyzhov/ajson v0.9.6 // indirect github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9 // indirect - github.com/tinylib/msgp v1.4.0 // indirect - github.com/tmaxmax/go-sse v0.10.0 // indirect + github.com/tinylib/msgp v1.6.5 // indirect + github.com/tmaxmax/go-sse v0.11.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.12 // indirect - go.uber.org/atomic v1.11.0 // indirect + github.com/ugorji/go/codec v1.3.2 // indirect + github.com/zeebo/xxh3 v1.1.0 // indirect + go.mongodb.org/mongo-driver/v2 v2.9.2 // indirect + go.uber.org/atomic v1.12.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect - golang.org/x/arch v0.17.0 // indirect - golang.org/x/crypto v0.57.0 // indirect - golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa // indirect - golang.org/x/net v0.58.0 // indirect - golang.org/x/sys v0.48.0 // indirect - golang.org/x/term v0.46.0 // indirect - golang.org/x/text v0.42.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + golang.org/x/arch v0.32.0 // indirect + golang.org/x/crypto v0.58.0 // indirect + golang.org/x/exp v0.0.0-20261014143641-f0251eb4aa3e // indirect + golang.org/x/net v0.61.0 // indirect + golang.org/x/sys v0.49.0 // indirect + golang.org/x/term v0.47.0 // indirect + golang.org/x/text v0.43.0 // indirect + google.golang.org/protobuf v1.36.12 // indirect gopkg.in/alexcesaro/statsd.v2 v2.0.0 // indirect + gopkg.in/ini.v1 v1.67.3 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect nhooyr.io/websocket v1.8.17 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 154db232..b4d8ed1c 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -34,21 +34,25 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= +github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/ReneKroon/ttlcache v1.6.0/go.mod h1:DG6nbhXKUQhrExfwwLuZUdH7UnRDDRA1IW+nBuCssvs= github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704 h1:liLfvCrzoJ89DXFHzsd1iK3cyP8s4i0CnZPRFEj53zg= github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704/go.mod h1:Mux1bEPpOHwRw1wo6Fa6qJLJH9Erk9qv1yAIfLi1Wmw= -github.com/TicketsBot-cloud/common v0.0.0-20260927072029-424264fc4be2 h1:qeebeGGdrsDXrngOVrKMDt9G3JUTJwT/IEPTB61d46s= -github.com/TicketsBot-cloud/common v0.0.0-20260927072029-424264fc4be2/go.mod h1:yL+VPSYNVK5gxUkA+fbb0WdTjGfWXnr7ScfL0rwk29g= -github.com/TicketsBot-cloud/database v0.0.0-20261002063446-01dca52a987e h1:kZS42Mp+6wBhApK7zA6F1SX8ZYYG18cVRHB2ZDTvx94= -github.com/TicketsBot-cloud/database v0.0.0-20261002063446-01dca52a987e/go.mod h1:0fKn7nPX6KeljYNQtGQiuZ5aJ/TczgXvBhnbz+4GEc8= -github.com/TicketsBot-cloud/gdl v0.0.0-20260927072153-8dbf0b284f57 h1:cFlQplQOlJCb+JQfxny+MJTg4dMKyEAvzB50MrWRa1E= -github.com/TicketsBot-cloud/gdl v0.0.0-20260927072153-8dbf0b284f57/go.mod h1:CdwBR2egPtxUXjD2CgC9ZwfuB8dz9HPePM8nuG6dt7Y= +github.com/TicketsBot-cloud/archiverclient v0.0.0-20260912070140-b0cd1b003b87 h1:EXh3e+nFSb58yuGtqIHmnKxNMId2GTlU0YvK6eVz3mU= +github.com/TicketsBot-cloud/archiverclient v0.0.0-20260912070140-b0cd1b003b87/go.mod h1:lqTqK/5vpGTn4rVA+Ag685MD4ejEwXe2RiWECT2KRSE= +github.com/TicketsBot-cloud/common v0.0.0-20261022190115-887ce60dce1b h1:NpnVYVEX8Ca/ngmJgEmUj3jFI5agGjqoISiZ1L5xzMg= +github.com/TicketsBot-cloud/common v0.0.0-20261022190115-887ce60dce1b/go.mod h1:yL+VPSYNVK5gxUkA+fbb0WdTjGfWXnr7ScfL0rwk29g= +github.com/TicketsBot-cloud/database v0.0.0-20261022191045-27b0736fc5a3 h1:rTdFBsz3cSOrE4RR+1Q55MNWYdsp3DvzctuQTC9aDL8= +github.com/TicketsBot-cloud/database v0.0.0-20261022191045-27b0736fc5a3/go.mod h1:0fKn7nPX6KeljYNQtGQiuZ5aJ/TczgXvBhnbz+4GEc8= +github.com/TicketsBot-cloud/gdl v0.0.0-20261022191043-9caa827c743a h1:e5tzjv+rKBV87epE/Tv3/yADr4dCG5SoBrpqv28x6nE= +github.com/TicketsBot-cloud/gdl v0.0.0-20261022191043-9caa827c743a/go.mod h1:CdwBR2egPtxUXjD2CgC9ZwfuB8dz9HPePM8nuG6dt7Y= github.com/TicketsBot-cloud/logarchiver v0.0.0-20251018211319-7a7df5cacbdc h1:qTLNpCvIqM7UwZ6MdWQ9EztcDsIJfHh+VJdG+ULLEaA= github.com/TicketsBot-cloud/logarchiver v0.0.0-20251018211319-7a7df5cacbdc/go.mod h1:pZqkzPNNTqnwKZvCT8kCaTHxrG7HJbxZV83S0p7mmzM= -github.com/TicketsBot-cloud/worker v0.0.0-20260827073646-455b39e53841 h1:TBabCBrj8XiiDey2iqicOA6HfDIyqZ63akGhImheoxs= -github.com/TicketsBot-cloud/worker v0.0.0-20260827073646-455b39e53841/go.mod h1:M0sHFxthu1YLTVAyAVhOtmA7ATP8lXmOLg2wzX/4jts= +github.com/TicketsBot-cloud/logarchiver v0.0.0-20260929182354-92f0b13a1e1f h1:bEiXr28yBmqeE17617N5apA+oBd7GMDZyqCw40Il1rc= +github.com/TicketsBot-cloud/logarchiver v0.0.0-20260929182354-92f0b13a1e1f/go.mod h1:1pv+CJbf7yr1cBJVDILqLgE7iJJsoRC4zK3381a/8mM= github.com/TicketsBot/common v0.0.0-20241117150316-ff54c97b45c1 h1:FqC1KGOsmB+ikvbmDkyNQU6bGUWyfYq8Ip9r4KxTveY= github.com/TicketsBot/common v0.0.0-20241117150316-ff54c97b45c1/go.mod h1:N7zwetwx8B3RK/ZajWwMroJSyv2ZJ+bIOZWv/z8DhaM= github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261 h1:NHD5GB6cjlkpZFjC76Yli2S63/J2nhr8MuE6KlYJpQM= @@ -60,7 +64,10 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/apex/log v1.1.2 h1:bnDuVoi+o98wOdVqfEzNDlY0tcmBia7r4YkjS9EqGYk= github.com/apex/log v1.1.2/go.mod h1:SyfRweFO+TlkIJ3DVizTSeI1xk7jOIIqOnUPZQTTsww= +github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0= +github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA= github.com/apex/logs v0.0.3/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= +github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -71,21 +78,33 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.26.0 h1:WPvcPZbP1yuKofmjs2SYIFO1EjzIGhCP9ducElLsh5Q= +github.com/bits-and-blooms/bitset v1.26.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff h1:RmdPFa+slIr4SCBg4st/l/vZWVe9QJKMXGO60Bxbe04= github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P97fT2CiHkbFQwkK3mjsFAP6zCYV2aXtjw= +github.com/boj/redistore v1.4.2 h1:44FVJnBTdzDV9VpaByCOaQs0ND8hzABD2xBHcAIbX9s= +github.com/boj/redistore v1.4.2/go.mod h1:jjh65GXAH+5lj29pPRnQHdRNOt/lmP0LOaK+fiG2Fu8= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM= +github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4= github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ= github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= +github.com/bytedance/sonic v1.15.4 h1:FgtV/4aBHpla9AxuMpuuzVUpa/Cf3izufkxNmnEzdI8= +github.com/bytedance/sonic v1.15.4/go.mod h1:8e51yTPdY8M6t+vvGL1c2Y1xL9i+frEeIAQAEl75NUc= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY= github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= +github.com/bytedance/sonic/loader v0.5.3 h1:ziVGAbXQtLoaot/M6YQxntGkekxz6B/DyuJVwnTbMAA= +github.com/bytedance/sonic/loader v0.5.3/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= github.com/caarlos0/env v3.5.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y= github.com/caarlos0/env/v10 v10.0.0 h1:yIHUBZGsyqCnpTkbjk8asUlx6RFhhEs+h7TOBdgdzXA= github.com/caarlos0/env/v10 v10.0.0/go.mod h1:ZfulV76NvVPw3tm591U4SwL3Xx9ldzBP9aGxzeN7G18= github.com/caarlos0/env/v11 v11.2.2 h1:95fApNrUyueipoZN/EhA8mMxiNxrBwDa+oAZrMWl3Kg= github.com/caarlos0/env/v11 v11.2.2/go.mod h1:JBfcdeQiBoI3Zh1QRAWfe+tpiNTmDtcCj/hHHHMx0vc= +github.com/caarlos0/env/v11 v11.4.1 h1:fYwH0sWEsBSMPG7t4e/PEfTFzrWrpjyygXyUnWiSwEw= +github.com/caarlos0/env/v11 v11.4.1/go.mod h1:qupehSf/Y0TUTsxKywqRt/vJjN5nz6vauiYEUUr8P4U= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -97,8 +116,12 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= +github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/base64x v0.1.7 h1:NppS+Fgzg5ovhn4NkUXaDT3x9jldgH5ToMCqzBSi2zI= +github.com/cloudwego/base64x v0.1.7/go.mod h1:Cu1PV9zfrSf7ET2tIbWbbEy7jO7HHJ13q4X2SQ8aWYg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= @@ -109,10 +132,13 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/dustin/go-humanize v1.1.0 h1:dbKTrvD0klcbBV/h4AWJdMuZogJACoMlvWIWZ5b2xWg= +github.com/dustin/go-humanize v1.1.0/go.mod h1:hc1CvRkJMsgxqjmjMQF3QNRAZBwY8AXBAzKYoSX9sFI= github.com/elliotchance/orderedmap v1.8.0 h1:TrOREecvh3JbS+NCgwposXG5ZTFHtEsQiCGOhPElnMw= github.com/elliotchance/orderedmap v1.8.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -127,20 +153,34 @@ github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8 github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok= +github.com/gabriel-vasile/mimetype v1.4.16 h1:5izNFuvA37st1dDRAcA7TtmngBmRgiIPDmTtiEvjx1E= +github.com/gabriel-vasile/mimetype v1.4.16/go.mod h1:3oFFwxX8kTklZwzIl2aQEDZT0lKY8xH92ST88bAwba4= github.com/getsentry/sentry-go v0.33.0 h1:YWyDii0KGVov3xOaamOnF0mjOrqSjBqwv48UEzn7QFg= github.com/getsentry/sentry-go v0.33.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= +github.com/getsentry/sentry-go v0.50.0 h1:gkO59rn/i0RCAXUUTflC5QVbTQGPXbaFabs2olVzc9g= +github.com/getsentry/sentry-go v0.50.0/go.mod h1:+xsDuN+SoRN/xfs1hdq78wnrE3omIZf+FCuh9FOW1C8= github.com/getsentry/sentry-go/gin v0.33.0 h1:8oH2ydD/EeKlDMoENhCtq3rJ7EcQtjfdzrMM1Ku2J3I= github.com/getsentry/sentry-go/gin v0.33.0/go.mod h1:uwqds9mMjBCn/+WcgtX0z+mBq487macTzDxNljM+/g8= +github.com/getsentry/sentry-go/gin v0.50.0 h1:HqbA/kyum1IGH3rxvZzkg8VSOK13U42w+Lb1DGLflOE= +github.com/getsentry/sentry-go/gin v0.50.0/go.mod h1:KcoYQKSq4o6Mi7Jr3ldOUgPNTsopcklG1KaE7tCoHzI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-contrib/sse v1.1.2 h1:MU2fgl1RrdYTMcgJLtz2kJF+vPg3xrqaaKfUUU18tCo= +github.com/gin-contrib/sse v1.1.2/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s= github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607 h1:MrIm8EEPue08JS4eh+b08IOG+wd0WRWEHWnewNfWFX0= github.com/gin-gonic/contrib v0.0.0-20191209060500-d6e26eeaa607/go.mod h1:iqneQ2Df3omzIVTkIfn7c1acsVnMGiSLn4XF5Blh3Yg= +github.com/gin-gonic/contrib v0.0.0-20260101091603-d12f07a9136b h1:bB9iNoDhFROcjyVhpplzXcrZjQDlPMRW48cQa+IoFtU= +github.com/gin-gonic/contrib v0.0.0-20260101091603-d12f07a9136b/go.mod h1:iqneQ2Df3omzIVTkIfn7c1acsVnMGiSLn4XF5Blh3Yg= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= +github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= +github.com/go-chi/chi/v5 v5.5.0 h1:xdKQ1dJmVJsmgahrXSKhUx8NyVPzpwdlyrrQFpMPJgg= +github.com/go-chi/chi/v5 v5.5.0/go.mod h1:d1IG7GtKPSjPyBP365PH8sAGVHk3qfB/IhjFNRH1wWM= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -158,8 +198,12 @@ github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lY github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/locales v0.14.2 h1:d8UmcrM6Nip0hfGZKLGpAvZH37XB4TS0xzK9B56YNCY= +github.com/go-playground/locales v0.14.2/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/universal-translator v0.18.2 h1:LCsMLC9RzmbUMNUPVYD15dmcjwYAJhmX8mPZRW4rAVU= +github.com/go-playground/universal-translator v0.18.2/go.mod h1:67VZIMp5lQpDWlnStOct22q1bkdJGJqHghbOtmkawxk= github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= @@ -171,11 +215,19 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-redis/redis_rate/v9 v9.1.1 h1:7SIrbnhQ7zsTNEgIvprFhJf7/+l3wSpZc2iRVwUmaq8= github.com/go-redis/redis_rate/v9 v9.1.1/go.mod h1:jjU9YxOSZ3cz0yj1QJVAJiy5ueKmL9o4AySJHcKyTSE= +github.com/go-redis/redis_rate/v9 v9.1.2 h1:H0l5VzoAtOE6ydd38j8MCq3ABlGLnvvbA1xDSVVCHgQ= +github.com/go-redis/redis_rate/v9 v9.1.2/go.mod h1:oam2de2apSgRG8aJzwJddXbNu91Iyz1m8IKJE2vpvlQ= github.com/go-redsync/redsync/v4 v4.13.0 h1:49X6GJfnbLGaIpBBREM/zA4uIMDXKAh1NDkvQ1EkZKA= github.com/go-redsync/redsync/v4 v4.13.0/go.mod h1:HMW4Q224GZQz6x1Xc7040Yfgacukdzu7ifTDAKiyErQ= +github.com/go-redsync/redsync/v4 v4.18.0 h1:DDM09PEhmNTf/vziolf2x6391y1hHxF5vQ4ytHl9xQc= +github.com/go-redsync/redsync/v4 v4.18.0/go.mod h1:yuoqcQ55FS1VypSeVTMqFsJqTdWpEH5eA4MQGKJ9c4M= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-json v0.11.2 h1:jdZv93Tt4ioR8yW1CoNsvSxrcZlCXAUU1aZXN7gpXUA= +github.com/goccy/go-json v0.11.2/go.mod h1:3NdmfEkZlB7YI5UFw/qdFKq8XN1aiWR0YyRPWZNQltY= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -244,15 +296,25 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= +github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= +github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/growthbook/growthbook-golang v0.2.9 h1:J/HGjxhHFgGtpEu/VJmGnxbTJjAeYZtb2qsLClrtdjo= github.com/growthbook/growthbook-golang v0.2.9/go.mod h1:mY8oBSateRALL7hMwr8UaPmsdm+10ffmgWIT1N5iQZE= +github.com/growthbook/growthbook-golang v0.6.0 h1:6PWRRr59lBme4gMOHCHoaqWrttb4nf8CiEHEwz2kPow= +github.com/growthbook/growthbook-golang v0.6.0/go.mod h1:mY8oBSateRALL7hMwr8UaPmsdm+10ffmgWIT1N5iQZE= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -262,6 +324,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= @@ -282,6 +345,7 @@ github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5W github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= @@ -313,6 +377,8 @@ github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA= github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk= github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M= +github.com/jackc/pgx/v5 v5.11.0 h1:IzBBtyK9AHqf98cctWFifYSci2hgQR/cd56wB4p+ogg= +github.com/jackc/pgx/v5 v5.11.0/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -320,8 +386,12 @@ github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/puddle/v2 v2.2.3 h1:f8HoREISb3l5eO9coPgK7U3hKLhWGokOFVcThl5jrao= +github.com/jackc/puddle/v2 v2.2.3/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo= github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= +github.com/jedib0t/go-pretty/v6 v6.8.3 h1:yVSk5aemoYHCvcrtqyXklwqcgHQIQzmy/oUzFlmffSQ= +github.com/jedib0t/go-pretty/v6 v6.8.3/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= @@ -342,16 +412,23 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.20.3 h1:zWNoFqq/lSuYQRim3dUXlXeA0IqwuZGicdG5ZTfY5j4= +github.com/klauspost/compress v1.20.3/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= +github.com/klauspost/cpuid/v2 v2.4.1 h1:I9KxadAkvo+QjtcEE2f2tyfEvmIla/T0m+14PrZNl0U= +github.com/klauspost/cpuid/v2 v2.4.1/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU= +github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM= +github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -364,6 +441,8 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0= +github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -371,6 +450,8 @@ github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mailgun/errors v0.4.0 h1:6LFBvod6VIW83CMIOT9sYNp28TCX0NejFPP4dSX++i8= github.com/mailgun/errors v0.4.0/go.mod h1:xGBaaKdEdQT0/FhwvoXv4oBaqqmVZz9P1XEnvD/onc0= +github.com/mailgun/errors v0.6.0 h1:IWmzIGwXCSN/Q60JT/lXvam3xRAgTUJSX88KwKJ7hss= +github.com/mailgun/errors v0.6.0/go.mod h1:+2nrgY77E0vDkG4ErehpcpbSkMLkseJzKbrva89WeSs= github.com/mailgun/mailgun-go/v4 v4.23.0 h1:jPEMJzzin2s7lvehcfv/0UkyBu18GvcURPr2+xtZRbk= github.com/mailgun/mailgun-go/v4 v4.23.0/go.mod h1:imTtizoFtpfZqPqGP8vltVBB6q9yWcv6llBhfFeElZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= @@ -382,8 +463,12 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI= +github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.31 h1:1oCV4ReTlosDBc6rYRw5cL8S/4y8iv5oRl4SJ5IBgwo= +github.com/mattn/go-runewidth v0.0.31/go.mod h1:3qAiGCV4Koz/yuveO58qUefmUTRm8r0IGEXZ9jeHp/8= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI= @@ -392,6 +477,8 @@ github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.95 h1:ywOUPg+PebTMTzn9VDsoFJy32ZuARN9zhB+K3IYEvYU= github.com/minio/minio-go/v7 v7.0.95/go.mod h1:wOOX3uxS334vImCNRVyIDdXX9OsXDm89ToynKgqUKlo= +github.com/minio/minio-go/v7 v7.4.1 h1:PtU/zIOfQRWZ+QydXAZysc+xZYHdG+BBR4Z6TUvy73w= +github.com/minio/minio-go/v7 v7.4.1/go.mod h1:nQnQi7zTfXR4lREtYXZQWqo5aw0Rqv+ZqCGrTORygRk= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -421,12 +508,22 @@ github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c h1:Gcce/r5tSQeprxswXXOwQ/RBU1bjQWVd9dB7QKoPXBE= github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c/go.mod h1:1iCZ0433JJMecYqCa+TdWA9Pax8MGl4ByuNDZ7eSnQY= +github.com/pasztorpisti/qs v0.0.0-20261010143646-f74307759693 h1:6J6THZn5x1c4OFIdeOm2JSTmA7m2ELB2Cn6UVf/yv8M= +github.com/pasztorpisti/qs v0.0.0-20261010143646-f74307759693/go.mod h1:1iCZ0433JJMecYqCa+TdWA9Pax8MGl4ByuNDZ7eSnQY= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pelletier/go-toml/v2 v2.4.3 h1:GTRvJQutkOSftxIFD5xw9aepkYNuPWmVJpffdDPYVpY= +github.com/pelletier/go-toml/v2 v2.4.3/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/penglongli/gin-metrics v0.1.10 h1:mNNWCM3swMOVHwzrHeXsE4C/myu8P/HIFohtyMi9rN8= github.com/penglongli/gin-metrics v0.1.10/go.mod h1:wxGsGUwpVGv3hmYSxQn2GZgRL3YuCgiRFq2d0X6+EOU= +github.com/penglongli/gin-metrics v0.1.13 h1:a1wyrXcbUVxL5w4c2TSv+9kyQA9qM1o23h0V6SdSHgQ= +github.com/penglongli/gin-metrics v0.1.13/go.mod h1:VEmSyx/9TwUG50IsPCgjMKOUuGO74V2lmkLZ6x1Dlko= github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= +github.com/philhofer/fwd v1.2.1 h1:UtpS73q8bFgy/yH3gCq8LSNvj5gv/FowNOiWZa7uKwQ= +github.com/philhofer/fwd v1.2.1/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -436,6 +533,8 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polarsource/polar-go v0.15.0 h1:3Rwe6pq/ZAjkZbGgR6Xb339Gw7vZubln1oYk6kuvtIw= github.com/polarsource/polar-go v0.15.0/go.mod h1:FB11Q4m2n3wIk6l/POOkz0MVOUx1o0Yt4Y97MnQfe0c= +github.com/polarsource/polar-go v0.16.0 h1:0YB4+DB0vsuvdxNVOvJpju5yKkMCHt6vmBRp9W2sKeo= +github.com/polarsource/polar-go v0.16.0/go.mod h1:FB11Q4m2n3wIk6l/POOkz0MVOUx1o0Yt4Y97MnQfe0c= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -443,18 +542,24 @@ github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_golang v1.25.0 h1:cDtW1TcFsMi1RJc8khwCKB4VhzwV04aKqbYtNOXuiK0= +github.com/prometheus/client_golang v1.25.0/go.mod h1:j2X/4/kaQHLPnmyEU8zjmkndo1T317VpCIQEml8LTKk= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/client_model v0.6.3 h1:O0jaTVAYNxTHYInEPFJt5I3+sN8zqBtVMPTB1qyxiEo= +github.com/prometheus/client_model v0.6.3/go.mod h1:gpN5P9S7Rr6Yr92PiQ+Ixvhf6JZEkF1dnxsYL2aPBEM= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= +github.com/prometheus/common v0.72.1 h1:ZAiQed/nk8IIcsdzb2TlJu23NEUDyDLQ9TXTN2WRK6Y= +github.com/prometheus/common v0.72.1/go.mod h1:1IoBY4IRaJnhs2ESjNzjilP1cJ/P8pimGoomq7zRXrA= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -462,10 +567,18 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prometheus/procfs v0.22.0 h1:6q9+/JL9IKAPbCmBrv9n5O5Ty3NKnciV5X7YGw0oics= +github.com/prometheus/procfs v0.22.0/go.mod h1:CvmFr/GVhIjIvWJZW3tgkODBQMRIf0EyWMQLHCHab58= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.64.1 h1:BCNTP+6x6++OPKrGST2FR3f1tycx8O3QOA3QQv09g70= +github.com/quic-go/quic-go v0.64.1/go.mod h1:RAro2j2yN9a9EiPACLHT9IB2NXCvGQmmo/alT0yYI0w= github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8= github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.22.0 h1:laDvpYXTJtZLloinw1fA5Kqd6HAEH2XKxOkG/PDq2F0= github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo= github.com/redis/rueidis v1.0.19/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo= +github.com/redis/rueidis v1.0.77 h1:ZR41bgJcm7oRFb3aSDPrRhC0eonDSrPzjvvZvHIlNjM= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -473,6 +586,7 @@ github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= @@ -481,6 +595,8 @@ github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThC github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/schollz/progressbar/v3 v3.18.0 h1:uXdoHABRFmNIjUfte/Ex7WtuyVslrw2wVPQmCN62HpA= github.com/schollz/progressbar/v3 v3.18.0/go.mod h1:IsO3lpbaGuzh8zIMzgY3+J8l4C8GjO0Y9S69eFvNsec= +github.com/schollz/progressbar/v3 v3.19.1 h1:iv8BgwOvdML/S3p84uBpy/IMigv4U9594vPZYa2EdrU= +github.com/schollz/progressbar/v3 v3.19.1/go.mod h1:LFL7jqimKxfhero4K1eCkUr/6R39AgQeiPCJtlTWIW8= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -497,11 +613,14 @@ github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= github.com/spyzhov/ajson v0.8.0 h1:sFXyMbi4Y/BKjrsfkUZHSjA2JM1184enheSjjoT/zCc= github.com/spyzhov/ajson v0.8.0/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA= +github.com/spyzhov/ajson v0.9.6 h1:iJRDaLa+GjhCDAt1yFtU/LKMtLtsNVKkxqlpvrHHlpQ= +github.com/spyzhov/ajson v0.9.6/go.mod h1:a6oSw0MMb7Z5aD2tPoPO+jq11ETKgXUr2XktHdT8Wt8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -512,6 +631,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= github.com/stretchr/testify v1.12.1/go.mod h1:MDEgiDPPsNp5cuIrHPPCyornHKgEVbtFUmoNlxoYthg= github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= @@ -520,27 +642,41 @@ github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9 h1:i2aD44Moa5N5pt github.com/tatsuworks/czlib v0.0.0-20190916144400-8a51758ea0d9/go.mod h1:6HrfShlf4bKeQEFdWn4JP/yet/mHW2RhxOQf0e3HWA0= github.com/tinylib/msgp v1.4.0 h1:SYOeDRiydzOw9kSiwdYp9UcBgPFtLU2WDHaJXyHruf8= github.com/tinylib/msgp v1.4.0/go.mod h1:cvjFkb4RiC8qSBOPMGPSzSAx47nAsfhLVTCZZNuHv5o= +github.com/tinylib/msgp v1.6.5 h1:iAH6XTP7BpzErjBZlujJQXxA+GmRi2YWs6M4KdLtNbE= +github.com/tinylib/msgp v1.6.5/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= +github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= +github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj52Uc= github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= github.com/tmaxmax/go-sse v0.10.0 h1:j9F93WB4Hxt8wUf6oGffMm4dutALvUPoDDxfuDQOSqA= github.com/tmaxmax/go-sse v0.10.0/go.mod h1:u/2kZQR1tyngo1lKaNCj1mJmhXGZWS1Zs5yiSOD+Eg8= +github.com/tmaxmax/go-sse v0.11.0 h1:nogmJM6rJUoOLoAwEKeQe5XlVpt9l7N82SS1jI7lWFg= +github.com/tmaxmax/go-sse v0.11.0/go.mod h1:u/2kZQR1tyngo1lKaNCj1mJmhXGZWS1Zs5yiSOD+Eg8= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ugorji/go/codec v1.3.2 h1:zkEASHHyEClGeURfgNT9PJZVfAbs9oEX9QXggwWNJbc= +github.com/ugorji/go/codec v1.3.2/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= github.com/weppos/publicsuffix-go v0.12.0/go.mod h1:z3LCPQ38eedDQSwmsSRW4Y7t2L8Ln16JPQ02lHAdn5k= github.com/weppos/publicsuffix-go v0.20.0 h1:59ypvSUbW3Dunc6zVm+v+MmXf2Q6cGiNDkxgRIzEnaA= github.com/weppos/publicsuffix-go v0.20.0/go.mod h1:5ZC/Uv3fIEUE0eP6o9+Yg4+5+W8V0/BieMi05feGXVA= +github.com/weppos/publicsuffix-go v0.50.3 h1:eT5dcjHQcVDNc0igpFEsGHKIip30feuB2zuuI9eJxiE= +github.com/weppos/publicsuffix-go v0.50.3/go.mod h1:/rOa781xBykZhHK/I3QeHo92qdDKVmKZKF7s8qAEM/4= github.com/weppos/publicsuffix-go/publicsuffix/generator v0.0.0-20220704091424-e0182326a282/go.mod h1:GHfoeIdZLdZmLjMlzBftbTDntahTttUMWjxZwQJhULE= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= +github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.mongodb.org/mongo-driver/v2 v2.9.2 h1:OCAdjI37pC/SVxucz/9CM8zD4jCdegtsY5QcKzYFCgE= +go.mongodb.org/mongo-driver/v2 v2.9.2/go.mod h1:SHKN0IWkKmEVGHLjXnni6s4wPKX4v86FTgOeJJFuXcA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -553,6 +689,8 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/atomic v1.12.0 h1:BvcXdFKuviU4fTL/f+SxdQ5qJX/Jix8pAkgdUcb3XOE= +go.uber.org/atomic v1.12.0/go.mod h1:I6c4cg+6HCxRjfjSsYtApoFILnpc0CGUdGkXVqbYVNk= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= @@ -571,6 +709,8 @@ go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU= golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= +golang.org/x/arch v0.32.0 h1:NjGf8/xGf5JgAJ4dw4NtME5R1L7xatagqAg95T3LgII= +golang.org/x/arch v0.32.0/go.mod h1:KcJSod3cqT2dKcjBxqTyGfbumNikqU9p5tHJinPJnuY= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -587,8 +727,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= -golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= -golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= +golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54= +golang.org/x/crypto v0.58.0/go.mod h1:Xh+kl5A+M0gMiWDytH2Hhr5Z7WbNCpv/eB/EFgfSk+w= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -601,6 +741,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa h1:QSyA8ishJCyT21kER9KwNt0b7BM3iRK4x9QXhjN5Fdk= golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa/go.mod h1:zeBbvyFKDaLwa7CH/zI8KXt7gTl14SF7sO08Pl5jBCM= +golang.org/x/exp v0.0.0-20261014143641-f0251eb4aa3e h1:HgI6W1OolKK6tcV74is+rl9SMT0njsHlp0TbQiGXI/A= +golang.org/x/exp v0.0.0-20261014143641-f0251eb4aa3e/go.mod h1:DBoxwWhjaW8DJJw/YeM4zpeOKMC1FMXSblsYy+1mFSw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -662,8 +804,10 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= -golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= +golang.org/x/net v0.60.0 h1:79p50tfZlm0J9YfoDsSi639qSXNGVwEzOPLCxM2FsYU= +golang.org/x/net v0.60.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= +golang.org/x/net v0.61.0 h1:RR+6j/BTBCrggOLugxa+66R8FvoN6MHlzDlZIbN9YFw= +golang.org/x/net v0.61.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -681,8 +825,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.23.0 h1:KameEIfc1IkluZyXWLn39Wd4tURc6GbCiISGiZm2bQk= -golang.org/x/sync v0.23.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= +golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA= +golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -737,8 +881,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= -golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= +golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= +golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -746,8 +890,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE= -golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc= +golang.org/x/term v0.47.0 h1:cpyOwQkr2Nzxe2p6KnrTG7Ei2wtzjsuSjhpXXepZ/BM= +golang.org/x/term v0.47.0/go.mod h1:efAfAuG6RKABvg1ArGebRkvX6LXul14SM67o2e4mUCY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -761,8 +905,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= -golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= +golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc= +golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -896,6 +1040,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= +google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/statsd.v2 v2.0.0 h1:FXkZSCZIH17vLCO5sO2UucTHsH9pc+17F6pl3JVCwMc= gopkg.in/alexcesaro/statsd.v2 v2.0.0/go.mod h1:i0ubccKGzBVNBpdGV5MocxyA/XlLUJzA7SLonnE4drU= @@ -907,6 +1053,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/ini.v1 v1.67.3 h1:iM9Lhz5MRSGhHVGGwCuzG9KO8PoirCXj/m/qTmOJJQw= +gopkg.in/ini.v1 v1.67.3/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -918,6 +1066,7 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/backend/utils/types/customembed.go b/backend/utils/types/customembed.go index 8b8d3b62..def893a1 100644 --- a/backend/utils/types/customembed.go +++ b/backend/utils/types/customembed.go @@ -27,7 +27,7 @@ type CustomEmbed struct { Title *string `json:"title" validate:"omitempty,min=1,max=256"` Description *string `json:"description" validate:"omitempty,min=1,max=4096"` Url *string `json:"url" validate:"omitempty,max=255"` - Colour Colour `json:"colour" validate:"gte=0,lte=16777215"` + Colour *Colour `json:"colour" validate:"omitempty,lte=16777215"` Author Author `json:"author"` ImageUrl *string `json:"image_url" validate:"omitempty,max=255"` ThumbnailUrl *string `json:"thumbnail_url" validate:"omitempty,max=255"` @@ -105,7 +105,7 @@ func NewCustomEmbed(c *database.CustomEmbed, fields []database.EmbedField) *Cust Title: c.Title, Description: c.Description, Url: c.Url, - Colour: Colour(c.Colour), + Colour: utils.ConvertPtr[Colour](c.Colour), Author: Author{ Name: c.AuthorName, IconUrl: c.AuthorIconUrl, @@ -136,7 +136,7 @@ func (c *CustomEmbed) IntoDatabaseStruct() (*database.CustomEmbed, []database.Em Title: c.Title, Description: c.Description, Url: c.Url, - Colour: uint32(c.Colour), + Colour: utils.ConvertPtr[uint32](c.Colour), AuthorName: c.Author.Name, AuthorIconUrl: c.Author.IconUrl, AuthorUrl: c.Author.Url, @@ -154,7 +154,7 @@ func (c *CustomEmbed) IntoDiscordEmbed() *embed.Embed { Description: utils.ValueOrZero(c.Description), Url: resolveAvatarPlaceholder(utils.ValueOrZero(c.Url)), Timestamp: TimeOrNil(c.Timestamp), - Color: int(c.Colour), + Color: utils.ConvertPtr[int](c.Colour), } if c.Footer.Text != nil { diff --git a/backend/utils/utils.go b/backend/utils/utils.go index 10ac66f8..0ea0bad9 100644 --- a/backend/utils/utils.go +++ b/backend/utils/utils.go @@ -12,6 +12,26 @@ func ValueOrZero[T any](v *T) T { } } +type integer interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 +} + +func ConvertPtr[U, T integer](v *T) *U { + if v == nil { + return nil + } + + return Ptr(U(*v)) +} + +func PtrEqual[T comparable](a, b *T) bool { + if a == nil || b == nil { + return a == b + } + + return *a == *b +} + func SetNilIfZero[T comparable](value **T) { if value != nil && *value != nil && **value == *new(T) { *value = nil diff --git a/frontend/src/components/ColourSelect.tsx b/frontend/src/components/ColourSelect.tsx index b104ad96..da1f7774 100644 --- a/frontend/src/components/ColourSelect.tsx +++ b/frontend/src/components/ColourSelect.tsx @@ -1,57 +1,127 @@ -import React, { useEffect, useId, useRef } from "react"; - -interface ColourSelectProps { - value: string; - onChange: (value: string) => void; +import React, { useEffect, useId, useRef, useState } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faBan } from "@fortawesome/free-solid-svg-icons"; +import { IDLE_INPUT_CLASS } from "@/lib/field-validity"; +interface ColourSelectBaseProps { disabled?: boolean; className?: string; label?: string; // Optional label } -const ColourSelect: React.FC = ({ - value, - onChange, - disabled = false, - className = "", - label, -}) => { +interface SolidColourSelectProps extends ColourSelectBaseProps { + nullable?: false; + clearable?: never; + fallbackColour?: never; + value: string; + onChange: (value: string) => void; +} + +interface NullableColourSelectProps extends ColourSelectBaseProps { + nullable: true; + value: string | null; + onChange: (value: string | null) => void; + clearable?: boolean; + fallbackColour?: string; +} + +type ColourSelectProps = SolidColourSelectProps | NullableColourSelectProps; + +const ColourSelect: React.FC = (props) => { + const { value, disabled = false, className = "", label } = props; + const clearable = props.nullable && props.clearable; + const fallbackColour = (props.nullable && props.fallbackColour) || "#5865f2"; const inputRef = useRef(null); const debounceRef = useRef | null>(null); const inputId = useId(); + const labelId = useId(); + const noneId = useId(); + // Seeded once: tracking value would reset an untouched input to the fallback on clear. + const [initialColour] = useState(value ?? fallbackColour); // Sync external value changes into the uncontrolled input useEffect(() => { - if (inputRef.current && inputRef.current.value !== value) { + if (value !== null && inputRef.current && inputRef.current.value !== value) { inputRef.current.value = value; } }, [value]); + useEffect(() => { + return () => { + if (debounceRef.current) clearTimeout(debounceRef.current); + }; + }, []); + const handleChange = (e: React.ChangeEvent) => { if (debounceRef.current) clearTimeout(debounceRef.current); - debounceRef.current = setTimeout(() => onChange(e.target.value), 100); + debounceRef.current = setTimeout(() => props.onChange(e.target.value), 100); + }; + + // Picking the input's current colour fires no change event, so commit on click. + const handleClick = (e: React.MouseEvent) => { + if (clearable && value === null) props.onChange(e.currentTarget.value); }; + const clear = (e: React.MouseEvent) => { + if (!props.nullable) return; + const hadFocus = document.activeElement === e.currentTarget; + if (debounceRef.current) clearTimeout(debounceRef.current); + props.onChange(null); + // Focusing the input after a tap opens its picker on iOS. + if (hadFocus) inputRef.current?.focus(); + }; + + const isNone = value === null; + const clearLabel = label + ? `Clear ${label}${/colour/i.test(label) ? "" : " colour"}` + : "Clear colour"; + return (
{label && ( -
); diff --git a/frontend/src/components/EmbedPreview.tsx b/frontend/src/components/EmbedPreview.tsx index 983871de..2cbe0ebf 100644 --- a/frontend/src/components/EmbedPreview.tsx +++ b/frontend/src/components/EmbedPreview.tsx @@ -3,6 +3,7 @@ import { isSafeUrl } from "@/lib/url"; import { formatEmbedTimestampForDisplay } from "@/lib/embed-timestamp"; import DiscordText from "@/components/discord/DiscordText"; import { previewAvatarUrl } from "@/lib/embed-avatar"; +import { embedBorderColour } from "@/lib/colour"; interface EmbedField { name: string; @@ -14,7 +15,7 @@ interface EmbedPreviewData { title?: string; description?: string; url?: string; - colour: number; + colour?: number | null; author?: { name?: string; icon_url?: string; url?: string }; image_url?: string; thumbnail_url?: string; @@ -29,7 +30,7 @@ interface EmbedPreviewProps { } const EmbedPreview: FC = ({ embed, raw = false }) => { - const borderColor = `#${(embed.colour || 0x5865f2).toString(16).padStart(6, "0")}`; + const borderColor = embedBorderColour(embed.colour); const footerTimestamp = formatEmbedTimestampForDisplay(embed.timestamp); const thumbnailUrl = previewAvatarUrl(embed.thumbnail_url); const imageUrl = previewAvatarUrl(embed.image_url); diff --git a/frontend/src/components/GalleryCard.tsx b/frontend/src/components/GalleryCard.tsx index 7ce0df9c..28e68fdf 100644 --- a/frontend/src/components/GalleryCard.tsx +++ b/frontend/src/components/GalleryCard.tsx @@ -6,6 +6,7 @@ import { faDownload, faStar } from "@fortawesome/free-solid-svg-icons"; import { Link } from "react-router"; import { GALLERY_TYPE_BADGES } from "@/components/gallery/GalleryListingPreview"; import { userAvatarUrl } from "@/lib/discord-cdn"; +import { embedColourHex } from "@/lib/colour"; interface GalleryCardProps { listing: GalleryListing; @@ -18,21 +19,19 @@ interface GalleryCardProps { const BODY_CLASS = "group flex flex-col flex-1 p-4 text-left transition-colors hover:bg-gray-700/50 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-inset"; -function getColourHex(listing: GalleryListing): string { +function getColourHex(listing: GalleryListing): string | undefined { const type = listing.listing_type || "panel"; if (type === "tag") { const snapshot = listing.snapshot_data as GalleryTagSnapshot | undefined; - const embedColour = snapshot?.embed?.colour; - const colour = embedColour ?? 0x14b8a6; - return "#" + colour.toString(16).padStart(6, "0"); + return embedColourHex(snapshot?.embed?.colour) ?? "#14b8a6"; } if (type === "form") { return "#" + (0xf97316).toString(16).padStart(6, "0"); } - return "#" + listing.colour.toString(16).padStart(6, "0"); + return embedColourHex(listing.colour) ?? undefined; } function getContentPreview(listing: GalleryListing): string { diff --git a/frontend/src/components/PanelPreview.tsx b/frontend/src/components/PanelPreview.tsx index a030b02a..1a753e02 100644 --- a/frontend/src/components/PanelPreview.tsx +++ b/frontend/src/components/PanelPreview.tsx @@ -7,6 +7,7 @@ import { BRANDING_FOOTER_ICON, BRANDING_FOOTER_TEXT } from "@/lib/constants"; import { formatEmbedTimestampForDisplay } from "@/lib/embed-timestamp"; import { isSafeUrl } from "@/lib/url"; import { previewAvatarUrl } from "@/lib/embed-avatar"; +import { embedBorderColour } from "@/lib/colour"; function resolveEmoteName(emote: Panel["emote"] | undefined): string { if (typeof emote === "string") return emote; @@ -38,7 +39,7 @@ const PanelPreview: FC = ({ type, data, brandingFooter }) =>
@@ -103,7 +104,7 @@ const PanelPreview: FC = ({ type, data, brandingFooter }) => const resolveTicketAvatar = (url: string | null | undefined) => isMultiPanelRequest ? url : previewAvatarUrl(url); - const borderColor = embedData?.colour || "#5865f2"; + const borderColor = embedData ? embedBorderColour(embedData.colour) : "#5865f2"; const footerText = embedData?.footer ? typeof embedData.footer === "string" diff --git a/frontend/src/components/SupportHoursForm.tsx b/frontend/src/components/SupportHoursForm.tsx index 4963284c..abfc7dca 100644 --- a/frontend/src/components/SupportHoursForm.tsx +++ b/frontend/src/components/SupportHoursForm.tsx @@ -4,6 +4,7 @@ import type { SupportHoursData } from "@/types"; import Button from "@/components/Button"; import Select from "@/components/Select"; import ColourSelect from "@/components/ColourSelect"; +import { embedColourHex, embedColourInt } from "@/lib/colour"; import TextInput from "@/components/TextInput"; import Textarea from "@/components/Textarea"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; @@ -23,14 +24,6 @@ function formatTime(timeString: string): string { return "09:00"; } -function colourIntToHex(colour: number): string { - return `#${colour.toString(16).padStart(6, "0")}`; -} - -function hexToColourInt(hex: string): number { - return parseInt(hex.replace("#", ""), 16); -} - interface HoursState { day_of_week: number; enabled: boolean; @@ -58,7 +51,7 @@ const SupportHoursForm: FC = ({ value, onChange }) => { >("block_creation"); const [outOfHoursTitle, setOutOfHoursTitle] = useState(""); const [outOfHoursMessage, setOutOfHoursMessage] = useState(""); - const [outOfHoursColour, setOutOfHoursColour] = useState("#FC3F35"); + const [outOfHoursColour, setOutOfHoursColour] = useState("#FC3F35"); const [currentTimeDisplay, setCurrentTimeDisplay] = useState(""); // Load initial data from value prop @@ -68,7 +61,8 @@ const SupportHoursForm: FC = ({ value, onChange }) => { if (value.out_of_hours_behaviour) setOutOfHoursBehaviour(value.out_of_hours_behaviour); if (value.out_of_hours_title) setOutOfHoursTitle(value.out_of_hours_title); if (value.out_of_hours_message) setOutOfHoursMessage(value.out_of_hours_message); - if (value.out_of_hours_colour) setOutOfHoursColour(colourIntToHex(value.out_of_hours_colour)); + if (value.out_of_hours_colour !== undefined) + setOutOfHoursColour(embedColourHex(value.out_of_hours_colour)); if (value.hours && value.hours.length > 0) { setHours((prev) => { @@ -128,7 +122,7 @@ const SupportHoursForm: FC = ({ value, onChange }) => { newBehaviour: "block_creation" | "allow_with_warning", newTitle: string, newMessage: string, - newColour: string, + newColour: string | null, ) => { const enabledHours = newHours.filter((h) => h.enabled); if (enabledHours.length === 0) { @@ -146,7 +140,7 @@ const SupportHoursForm: FC = ({ value, onChange }) => { out_of_hours_behaviour: newBehaviour, out_of_hours_title: newTitle, out_of_hours_message: newMessage, - out_of_hours_colour: hexToColourInt(newColour), + out_of_hours_colour: embedColourInt(newColour), }); }, [onChange], @@ -226,7 +220,7 @@ const SupportHoursForm: FC = ({ value, onChange }) => { emitChange(hours, timezone, outOfHoursBehaviour, outOfHoursTitle, clamped, outOfHoursColour); }; - const handleColourChange = (val: string) => { + const handleColourChange = (val: string | null) => { setOutOfHoursColour(val); emitChange(hours, timezone, outOfHoursBehaviour, outOfHoursTitle, outOfHoursMessage, val); }; @@ -405,8 +399,11 @@ const SupportHoursForm: FC = ({ value, onChange }) => {

diff --git a/frontend/src/components/discord/DiscordEmbed.tsx b/frontend/src/components/discord/DiscordEmbed.tsx index 86979495..ff70c967 100644 --- a/frontend/src/components/discord/DiscordEmbed.tsx +++ b/frontend/src/components/discord/DiscordEmbed.tsx @@ -19,7 +19,8 @@ const DiscordEmbedComponent: FC = ({ embed, entities, classNa
{embed.author && ( diff --git a/frontend/src/components/discord/container/Container.tsx b/frontend/src/components/discord/container/Container.tsx index 49d371ae..bc1cf977 100644 --- a/frontend/src/components/discord/container/Container.tsx +++ b/frontend/src/components/discord/container/Container.tsx @@ -1,4 +1,5 @@ import type { GuildChannel, GuildRole, User } from "@/types"; +import { intToColour } from "@/lib/colour"; import DiscordContent from "../DiscordContent"; import ActionRow from "./ActionRow"; import Button from "./Button"; @@ -13,7 +14,7 @@ interface ContainerProps { }; component?: { spoiler?: boolean; - accent_color?: string; + accent_color?: number | null; type?: number; emoji?: { name: string }; label?: string; @@ -62,7 +63,8 @@ interface ContainerProps { } export default function Container({ component = {}, entities }: ContainerProps) { - const borderColor = component.accent_color || "transparent"; + const borderColor = + component.accent_color != null ? intToColour(component.accent_color) : "transparent"; const spoilerClass = component.spoiler ? "blur hover:blur-none" : ""; return ( diff --git a/frontend/src/components/gallery/GalleryListingPreview.tsx b/frontend/src/components/gallery/GalleryListingPreview.tsx index 4b5493c5..06850ab4 100644 --- a/frontend/src/components/gallery/GalleryListingPreview.tsx +++ b/frontend/src/components/gallery/GalleryListingPreview.tsx @@ -3,6 +3,7 @@ import DiscordText from "@/components/discord/DiscordText"; import { parseDiscordMarkdown } from "@/lib/discord-markdown"; import EmbedPreview from "@/components/EmbedPreview"; import DiscordButton from "@/components/discord/container/Button"; +import { embedColourInt } from "@/lib/colour"; import type { GalleryListing, GalleryTagSnapshot, @@ -135,7 +136,7 @@ const PanelListingPreview: FC<{ listing: GalleryListing; raw: boolean }> = ({ li raw={raw} embed={{ ...welcomeMessage, - colour: parseInt(welcomeMessage.colour, 10) || listing.colour, + colour: embedColourInt(welcomeMessage.colour), }} /> @@ -164,12 +165,7 @@ const TagListingPreview: FC<{ listing: GalleryListing; raw: boolean }> = ({ list className="text-gray-300 text-sm mb-4 bg-gray-900 rounded p-3" /> )} - {snapshot.embed && ( - - )} + {snapshot.embed && } ); }; diff --git a/frontend/src/components/modals/TagEditorModal.tsx b/frontend/src/components/modals/TagEditorModal.tsx index 9ccc0d11..6bc1e464 100644 --- a/frontend/src/components/modals/TagEditorModal.tsx +++ b/frontend/src/components/modals/TagEditorModal.tsx @@ -14,6 +14,7 @@ import DateTimePicker from "@/components/DateTimePicker"; import { useKBArticles } from "@/hooks/queries/useKB"; import { parseEmbedTimestamp, serializeEmbedTimestamp } from "@/lib/embed-timestamp"; import { embedUrlError } from "@/lib/embed-url"; +import { embedColourHex, embedColourInt } from "@/lib/colour"; import type { Tag, TagEmbed } from "@/types"; import { EMBED_LIMITS } from "@/constants/embedLimits"; import { BRANDING_FOOTER_TEXT } from "@/lib/constants"; @@ -79,12 +80,7 @@ const TagEditorModal: FC = ({ ? { ...defaultEmbed, ...tag.embed, - colour: (() => { - const c = tag.embed.colour; - if (typeof c === "number") return c; - const parsed = parseInt(String(c ?? "").replace(/^#/, ""), 16); - return isNaN(parsed) ? defaultEmbed.colour : parsed; - })(), + colour: embedColourInt(tag.embed.colour), author: { ...defaultEmbed.author, ...tag.embed.author }, footer: { ...defaultEmbed.footer, ...tag.embed.footer }, fields: tag.embed.fields?.length ? [...tag.embed.fields] : [], @@ -103,12 +99,7 @@ const TagEditorModal: FC = ({ ? { ...defaultEmbed, ...tag.embed, - colour: (() => { - const c = tag.embed.colour; - if (typeof c === "number") return c; - const parsed = parseInt(String(c ?? "").replace(/^#/, ""), 16); - return isNaN(parsed) ? defaultEmbed.colour : parsed; - })(), + colour: embedColourInt(tag.embed.colour), author: { ...defaultEmbed.author, ...tag.embed.author }, footer: { ...defaultEmbed.footer, ...tag.embed.footer }, fields: tag.embed.fields?.length ? [...tag.embed.fields] : [], @@ -283,12 +274,14 @@ const TagEditorModal: FC = ({ showCount /> setEmbed((prev) => ({ ...prev, - colour: parseInt(v.replace("#", ""), 16), + colour: embedColourInt(v), })) } /> diff --git a/frontend/src/lib/colour.ts b/frontend/src/lib/colour.ts index bf9bb567..09ece227 100644 --- a/frontend/src/lib/colour.ts +++ b/frontend/src/lib/colour.ts @@ -14,3 +14,21 @@ export function roleColour(colour: number): string { export function normaliseColour(colour: string): string { return colour.startsWith("#") ? colour : `#${colour}`; } + +export const DISCORD_DEFAULT_EMBED_BORDER = "#1e1f22"; + +export function embedColourHex(colour: number | string | null | undefined): string | null { + if (colour == null || colour === "") return null; + const hex = + typeof colour === "number" ? intToColour(colour) : normaliseColour(colour).toLowerCase(); + return /^#[0-9a-f]{6}$/.test(hex) ? hex : null; +} + +export function embedColourInt(colour: number | string | null | undefined): number | null { + const hex = embedColourHex(colour); + return hex === null ? null : colourToInt(hex); +} + +export function embedBorderColour(colour: number | string | null | undefined): string { + return embedColourHex(colour) ?? DISCORD_DEFAULT_EMBED_BORDER; +} diff --git a/frontend/src/pages/manage/GuildSettings.tsx b/frontend/src/pages/manage/GuildSettings.tsx index f927847d..a9770cdc 100644 --- a/frontend/src/pages/manage/GuildSettings.tsx +++ b/frontend/src/pages/manage/GuildSettings.tsx @@ -21,7 +21,7 @@ import type { GuildSettings } from "@/types"; import PermissionWarningBanner from "@/components/PermissionWarningBanner"; import PanelSwitchBehaviourInfoModal from "@/components/modals/PanelSwitchBehaviourInfoModal"; import { PANEL_SWITCH_OPTIONS } from "@/constants/panelSwitchBehaviour"; -import { intToColour } from "@/lib/colour"; +import { embedColourHex } from "@/lib/colour"; const PanelSwitchSelect: FC<{ value: number; onChange: (v: number) => void }> = ({ value, @@ -220,7 +220,7 @@ const GuildSettings: FC = () => { ...panels.map((p) => ({ key: p.panel_id.toString(), label: p.title, - color: intToColour(p.colour), + color: embedColourHex(p.colour) ?? undefined, })), ]} /> @@ -259,13 +259,21 @@ const GuildSettings: FC = () => { >
updateField("colours", { ...form.colours, "0": v })} label="Success" /> updateField("colours", { ...form.colours, "1": v })} label="Failure" /> diff --git a/frontend/src/pages/manage/kb/create.tsx b/frontend/src/pages/manage/kb/create.tsx index fe4c6432..99428836 100644 --- a/frontend/src/pages/manage/kb/create.tsx +++ b/frontend/src/pages/manage/kb/create.tsx @@ -23,6 +23,7 @@ import type { TagEmbed } from "@/types"; import { EMBED_LIMITS } from "@/constants/embedLimits"; import { BRANDING_FOOTER_TEXT } from "@/lib/constants"; import { embedUrlError } from "@/lib/embed-url"; +import { embedColourHex, embedColourInt } from "@/lib/colour"; import EmbedCharacterTotal from "@/components/EmbedCharacterTotal"; const defaultEmbed: TagEmbed = { @@ -261,12 +262,14 @@ const CreateKBArticlePage: FC = () => { showCount /> setEmbed((prev) => ({ ...prev, - colour: parseInt(v.replace("#", ""), 16), + colour: embedColourInt(v), })) } /> diff --git a/frontend/src/pages/manage/kb/edit.tsx b/frontend/src/pages/manage/kb/edit.tsx index 68084df9..072fa573 100644 --- a/frontend/src/pages/manage/kb/edit.tsx +++ b/frontend/src/pages/manage/kb/edit.tsx @@ -24,6 +24,7 @@ import type { TagEmbed } from "@/types"; import { EMBED_LIMITS } from "@/constants/embedLimits"; import { BRANDING_FOOTER_TEXT } from "@/lib/constants"; import { embedUrlError } from "@/lib/embed-url"; +import { embedColourHex, embedColourInt } from "@/lib/colour"; import EmbedCharacterTotal from "@/components/EmbedCharacterTotal"; const defaultEmbed: TagEmbed = { @@ -73,16 +74,10 @@ const EditKBArticlePage: FC = () => { if (article.embed) { setUseEmbed(true); - const embedColour = (() => { - const c = article.embed.colour; - if (typeof c === "number") return c; - const parsed = parseInt(String(c ?? "").replace(/^#/, ""), 16); - return isNaN(parsed) ? defaultEmbed.colour : parsed; - })(); setEmbed({ ...defaultEmbed, ...article.embed, - colour: embedColour, + colour: embedColourInt(article.embed.colour), author: { ...defaultEmbed.author, ...article.embed.author }, footer: { ...defaultEmbed.footer, ...article.embed.footer }, fields: article.embed.fields?.length ? [...article.embed.fields] : [], @@ -330,12 +325,14 @@ const EditKBArticlePage: FC = () => { showCount /> setEmbed((prev) => ({ ...prev, - colour: parseInt(v.replace("#", ""), 16), + colour: embedColourInt(v), })) } /> diff --git a/frontend/src/pages/manage/multipanels/create.tsx b/frontend/src/pages/manage/multipanels/create.tsx index 4b1602af..2cae5e85 100644 --- a/frontend/src/pages/manage/multipanels/create.tsx +++ b/frontend/src/pages/manage/multipanels/create.tsx @@ -22,7 +22,7 @@ import MultiSelect from "@/components/MultiSelect"; import Select from "@/components/Select"; import TextInput from "@/components/TextInput"; import ColourSelect from "@/components/ColourSelect"; -import { intToColour } from "@/lib/colour"; +import { embedColourHex } from "@/lib/colour"; import Textarea from "@/components/Textarea"; import PanelPreview from "@/components/PanelPreview"; import DateTimePicker from "@/components/DateTimePicker"; @@ -245,7 +245,7 @@ const MultiPanelsPage: FC = () => { options={panels?.map((panel) => ({ label: panel.title, key: panel.panel_id.toString(), - color: intToColour(panel.colour), + color: embedColourHex(panel.colour) ?? undefined, }))} onChange={(e) => setMultiPanel((prev) => { @@ -373,8 +373,10 @@ const MultiPanelsPage: FC = () => { showCount /> setMultiPanel((prev) => prev ? { ...prev, embed: { ...prev.embed, colour: e } } : prev, diff --git a/frontend/src/pages/manage/multipanels/edit.tsx b/frontend/src/pages/manage/multipanels/edit.tsx index b2dcf804..2dde4e46 100644 --- a/frontend/src/pages/manage/multipanels/edit.tsx +++ b/frontend/src/pages/manage/multipanels/edit.tsx @@ -22,7 +22,7 @@ import MultiSelect from "@/components/MultiSelect"; import Select from "@/components/Select"; import TextInput from "@/components/TextInput"; import ColourSelect from "@/components/ColourSelect"; -import { intToColour } from "@/lib/colour"; +import { embedColourHex } from "@/lib/colour"; import Textarea from "@/components/Textarea"; import PanelPreview from "@/components/PanelPreview"; import DateTimePicker from "@/components/DateTimePicker"; @@ -246,7 +246,7 @@ const MultiPanelsPage: FC = () => { options={panels?.map((panel) => ({ label: panel.title, key: panel.panel_id.toString(), - color: intToColour(panel.colour), + color: embedColourHex(panel.colour) ?? undefined, }))} onChange={(e) => setMultiPanel((prev) => { @@ -374,8 +374,10 @@ const MultiPanelsPage: FC = () => { showCount /> setMultiPanel((prev) => prev ? { ...prev, embed: { ...prev.embed, colour: e } } : prev, diff --git a/frontend/src/pages/manage/panels/create.tsx b/frontend/src/pages/manage/panels/create.tsx index 9214d77c..b112d0e8 100644 --- a/frontend/src/pages/manage/panels/create.tsx +++ b/frontend/src/pages/manage/panels/create.tsx @@ -23,7 +23,7 @@ import TextInput from "@/components/TextInput"; import NumberInput from "@/components/NumberInput"; import ColourSelect from "@/components/ColourSelect"; import { BUTTON_STYLE_OPTIONS } from "@/constants/buttonStyles"; -import { roleColour } from "@/lib/colour"; +import { embedColourHex, embedColourInt, roleColour } from "@/lib/colour"; import Textarea from "@/components/Textarea"; import EmojiPicker from "@/components/EmojiPicker"; import PanelPreview from "@/components/PanelPreview"; @@ -320,12 +320,12 @@ const PanelsPage: FC = () => { showCount /> - setPanel((prev) => - prev ? { ...prev, colour: parseInt(e.replace("#", ""), 16) } : prev, - ) + setPanel((prev) => (prev ? { ...prev, colour: embedColourInt(e) } : prev)) } />
@@ -647,8 +647,12 @@ const PanelsPage: FC = () => { showCount /> setPanel((prev) => prev diff --git a/frontend/src/pages/manage/panels/edit.tsx b/frontend/src/pages/manage/panels/edit.tsx index 80f2252f..dd110235 100644 --- a/frontend/src/pages/manage/panels/edit.tsx +++ b/frontend/src/pages/manage/panels/edit.tsx @@ -24,7 +24,7 @@ import TextInput from "@/components/TextInput"; import NumberInput from "@/components/NumberInput"; import ColourSelect from "@/components/ColourSelect"; import { BUTTON_STYLE_OPTIONS } from "@/constants/buttonStyles"; -import { roleColour } from "@/lib/colour"; +import { embedColourHex, embedColourInt, roleColour } from "@/lib/colour"; import Textarea from "@/components/Textarea"; import EmojiPicker from "@/components/EmojiPicker"; import PanelPreview from "@/components/PanelPreview"; @@ -240,12 +240,12 @@ const EditPanelsPage: FC = () => { showCount /> - setPanel((prev) => - prev ? { ...prev, colour: parseInt(e.replace("#", ""), 16) } : prev, - ) + setPanel((prev) => (prev ? { ...prev, colour: embedColourInt(e) } : prev)) } />
@@ -561,8 +561,12 @@ const EditPanelsPage: FC = () => { showCount /> setPanel((prev) => prev diff --git a/frontend/src/pages/manage/setup/components/PanelsStep.tsx b/frontend/src/pages/manage/setup/components/PanelsStep.tsx index 8f0315d5..adcd0c9a 100644 --- a/frontend/src/pages/manage/setup/components/PanelsStep.tsx +++ b/frontend/src/pages/manage/setup/components/PanelsStep.tsx @@ -11,6 +11,7 @@ import CardGridSkeleton from "@/components/skeletons/CardGridSkeleton"; import Tabs from "@/components/Tabs"; import type { GalleryListing } from "@/types"; import { EMBED_LIMITS } from "@/constants/embedLimits"; +import { embedColourInt, intToColour } from "@/lib/colour"; interface PanelsStepProps { guildId: string; @@ -25,20 +26,6 @@ type TabId = "import" | "scratch"; /** Blurple (#5865F2) as a decimal integer. */ const DEFAULT_COLOUR = 5793266; -/** - * Converts a decimal colour integer to a CSS hex string (e.g. 5793266 -> "#5865F2"). - */ -function colourToHex(colour: number): string { - return "#" + colour.toString(16).padStart(6, "0"); -} - -/** - * Converts a CSS hex string to a decimal integer (e.g. "#5865F2" -> 5793266). - */ -function hexToColour(hex: string): number { - return parseInt(hex.replace("#", ""), 16) || DEFAULT_COLOUR; -} - const PanelsStep: FC = ({ guildId, channels, @@ -59,7 +46,7 @@ const PanelsStep: FC = ({ // ─── Create-from-scratch state ─────────────────────────────────────────────── const [title, setTitle] = useState("Open a Ticket"); const [content, setContent] = useState("Click the button below to open a support ticket."); - const [colour, setColour] = useState(colourToHex(DEFAULT_COLOUR)); + const [colour, setColour] = useState(intToColour(DEFAULT_COLOUR)); const [channel, setChannel] = useState(null); const [category, setCategory] = useState(null); const [teamId, setTeamId] = useState("default"); @@ -156,7 +143,7 @@ const PanelsStep: FC = ({ await apiClient.panels.create(guildId, { title: title.trim(), content, - colour: hexToColour(colour), + colour: embedColourInt(colour), channel_id: channel, category_id: category, default_team: teamId === "default", @@ -260,7 +247,7 @@ const PanelsStep: FC = ({ placeholder="Open a Ticket" maxLength={80} /> - +