From 76834600eab8ea5cb9e14d5a992fa2c51eb68167 Mon Sep 17 00:00:00 2001 From: biast12 <53872542+biast12@users.noreply.github.com> Date: Sat, 26 Sep 2026 16:37:06 +0200 Subject: [PATCH 1/2] Handle hidden channels during cache refresh Preserve inaccessible channels in the cache by marking obfuscated metadata, probing unlisted channels, and tracking hidden-channel state in Redis. Update permission checks, ticket operations, admin diagnostics, and recache flows to handle missing View Channel access safely. --- bot/button/handlers/addadmin.go | 8 ++ bot/button/handlers/addsupport.go | 8 ++ .../admindebug/server/modals/panelsettings.go | 46 +++--- .../admindebug/server/modals/permissions.go | 6 +- .../handlers/admindebug/server/recache.go | 3 +- bot/command/impl/admin/adminrecache.go | 3 +- bot/logic/claim.go | 13 ++ bot/logic/open.go | 58 ++++++-- bot/permissionwrapper/permission.go | 19 ++- bot/redis/hiddenchannelcache.go | 42 ++++++ bot/utils/recache.go | 132 ++++++++++++++++++ go.mod | 2 +- restwrapper.go | 2 +- 13 files changed, 304 insertions(+), 38 deletions(-) create mode 100644 bot/redis/hiddenchannelcache.go create mode 100644 bot/utils/recache.go diff --git a/bot/button/handlers/addadmin.go b/bot/button/handlers/addadmin.go index 03cc7524..1d283ee4 100644 --- a/bot/button/handlers/addadmin.go +++ b/bot/button/handlers/addadmin.go @@ -212,6 +212,14 @@ func (h *AddAdminHandler) Execute(ctx *context.ButtonContext) { continue } + // Placeholder overwrites must not be written back + if ch.IsObfuscated() { + ch, err = rest.GetChannel(ctx, ctx.Worker().Token, ctx.Worker().RateLimiter, *ticket.ChannelId) + if err != nil || ch.IsObfuscated() { + continue + } + } + // Apply overwrites to existing channels overwrites := append(ch.PermissionOverwrites, channel.PermissionOverwrite{ Id: id, diff --git a/bot/button/handlers/addsupport.go b/bot/button/handlers/addsupport.go index f891ab47..ab90e3de 100644 --- a/bot/button/handlers/addsupport.go +++ b/bot/button/handlers/addsupport.go @@ -236,6 +236,14 @@ func updateChannelPermissions(ctx cmdregistry.CommandContext, id uint64, mention continue } + // Placeholder overwrites must not be written back + if ch.IsObfuscated() { + ch, err = rest.GetChannel(ctx, ctx.Worker().Token, ctx.Worker().RateLimiter, *ticket.ChannelId) + if err != nil || ch.IsObfuscated() { + continue + } + } + // Apply overwrites to existing channels overwrites := append(ch.PermissionOverwrites, channel.PermissionOverwrite{ Id: id, diff --git a/bot/button/handlers/admindebug/server/modals/panelsettings.go b/bot/button/handlers/admindebug/server/modals/panelsettings.go index a0e90da5..94d00773 100644 --- a/bot/button/handlers/admindebug/server/modals/panelsettings.go +++ b/bot/button/handlers/admindebug/server/modals/panelsettings.go @@ -11,6 +11,7 @@ import ( "github.com/TicketsBot-cloud/database" "github.com/TicketsBot-cloud/gdl/objects/interaction" "github.com/TicketsBot-cloud/gdl/objects/interaction/component" + w "github.com/TicketsBot-cloud/worker" "github.com/TicketsBot-cloud/worker/bot/button/registry" "github.com/TicketsBot-cloud/worker/bot/button/registry/matcher" "github.com/TicketsBot-cloud/worker/bot/command" @@ -77,6 +78,12 @@ func (h *AdminDebugServerPanelSettingsModalHandler) Execute(ctx *context.ModalCo selectedValues := selectData.Values + worker, err := utils.WorkerForGuild(ctx, ctx.Worker(), guildId) + if err != nil { + ctx.HandleError(err) + return + } + // Get all panels for this guild panels, err := dbclient.Client.Panel.GetByGuild(ctx, guildId) if err != nil { @@ -113,7 +120,7 @@ func (h *AdminDebugServerPanelSettingsModalHandler) Execute(ctx *context.ModalCo } // Build settings for this panel - panelSettings := buildPanelSettings(ctx, selectedPanel) + panelSettings := buildPanelSettings(ctx, worker, selectedPanel) results = append(results, panelSettings) } @@ -127,7 +134,21 @@ func (h *AdminDebugServerPanelSettingsModalHandler) Execute(ctx *context.ModalCo })) } -func buildPanelSettings(ctx *context.ModalContext, selectedPanel *database.Panel) string { +func channelLabel(worker *w.Context, channelId uint64, prefix, missing string) string { + ch, err := worker.GetChannel(channelId) + switch { + case utils.IsMissingAccess(err), err == nil && ch.IsObfuscated(): + return fmt.Sprintf("`%d` (no access - bot is missing View Channel)", channelId) + case utils.IsUnknownChannel(err): + return fmt.Sprintf("`%d` (%s)", channelId, missing) + case err != nil: + return fmt.Sprintf("`%d` (could not fetch)", channelId) + default: + return fmt.Sprintf("`%s%s` (%d)", prefix, ch.Name, channelId) + } +} + +func buildPanelSettings(ctx *context.ModalContext, worker *w.Context, selectedPanel *database.Panel) string { var settings []string // Panel header @@ -145,32 +166,17 @@ func buildPanelSettings(ctx *context.ModalContext, selectedPanel *database.Panel // Panel channel if selectedPanel.ChannelId != 0 { - channel, err := ctx.Worker().GetChannel(selectedPanel.ChannelId) - if err == nil { - settings = append(settings, fmt.Sprintf("**Panel Channel:** `#%s` (%d)", channel.Name, selectedPanel.ChannelId)) - } else { - settings = append(settings, fmt.Sprintf("**Panel Channel:** `%d` (channel not found)", selectedPanel.ChannelId)) - } + settings = append(settings, "**Panel Channel:** "+channelLabel(worker, selectedPanel.ChannelId, "#", "channel not found")) } // Target category (for channel mode) if !selectedPanel.UseThreads && selectedPanel.TargetCategory != 0 { - category, err := ctx.Worker().GetChannel(selectedPanel.TargetCategory) - if err == nil { - settings = append(settings, fmt.Sprintf("**Target Category:** `%s` (%d)", category.Name, selectedPanel.TargetCategory)) - } else { - settings = append(settings, fmt.Sprintf("**Target Category:** `%d` (category not found)", selectedPanel.TargetCategory)) - } + settings = append(settings, "**Target Category:** "+channelLabel(worker, selectedPanel.TargetCategory, "", "category not found")) } // Transcript channel if selectedPanel.TranscriptChannelId != nil { - channel, err := ctx.Worker().GetChannel(*selectedPanel.TranscriptChannelId) - if err == nil { - settings = append(settings, fmt.Sprintf("**Transcript Channel:** `#%s` (%d)", channel.Name, *selectedPanel.TranscriptChannelId)) - } else { - settings = append(settings, fmt.Sprintf("**Transcript Channel:** `%d` (channel not found)", *selectedPanel.TranscriptChannelId)) - } + settings = append(settings, "**Transcript Channel:** "+channelLabel(worker, *selectedPanel.TranscriptChannelId, "#", "channel not found")) } // Other settings diff --git a/bot/button/handlers/admindebug/server/modals/permissions.go b/bot/button/handlers/admindebug/server/modals/permissions.go index 9f49ba6a..1cb3305e 100644 --- a/bot/button/handlers/admindebug/server/modals/permissions.go +++ b/bot/button/handlers/admindebug/server/modals/permissions.go @@ -306,10 +306,14 @@ func checkPanelPermissions(worker *w.Context, guildId uint64, botMember member.M func checkChannelPermissions(worker *w.Context, channelId uint64, botMember member.Member, guildId uint64, requiredPermissions []permission.Permission, label string) (string, bool) { channel, err := worker.GetChannel(channelId) - if err != nil { + if err != nil && !utils.IsMissingAccess(err) { return fmt.Sprintf("**%s**\nError: Could not fetch channel", label), false } + if err != nil || channel.IsObfuscated() { + return fmt.Sprintf("**%s** (`%d`)\n**Missing Permissions:**\n- View Channel\n", label, channelId), true + } + // Use permissionwrapper to get missing permissions missingPerms := permissionwrapper.GetMissingPermissionsChannel(worker, guildId, botMember.User.Id, channelId, requiredPermissions...) diff --git a/bot/button/handlers/admindebug/server/recache.go b/bot/button/handlers/admindebug/server/recache.go index 9bf99c4c..96fc3cc3 100644 --- a/bot/button/handlers/admindebug/server/recache.go +++ b/bot/button/handlers/admindebug/server/recache.go @@ -59,7 +59,6 @@ func (h *AdminDebugServerRecacheHandler) Execute(ctx *context.ButtonContext) { // purge cache ctx.Worker().Cache.DeleteGuild(ctx, guildId) - ctx.Worker().Cache.DeleteGuildChannels(ctx, guildId) ctx.Worker().Cache.DeleteGuildRoles(ctx, guildId) worker, err := utils.WorkerForGuild(ctx, ctx.Worker(), guildId) @@ -74,7 +73,7 @@ func (h *AdminDebugServerRecacheHandler) Execute(ctx *context.ButtonContext) { return } - guildChannels, err := worker.GetGuildChannels(guildId) + guildChannels, err := utils.RecacheGuildChannels(ctx, worker, guildId, time.Second*3, true) if err != nil { ctx.HandleError(err) return diff --git a/bot/command/impl/admin/adminrecache.go b/bot/command/impl/admin/adminrecache.go index 267752dd..05812402 100644 --- a/bot/command/impl/admin/adminrecache.go +++ b/bot/command/impl/admin/adminrecache.go @@ -64,7 +64,6 @@ func (AdminRecacheCommand) Execute(ctx registry.CommandContext, guildIdRaw strin // purge cache ctx.Worker().Cache.DeleteGuild(ctx, guildId) - ctx.Worker().Cache.DeleteGuildChannels(ctx, guildId) ctx.Worker().Cache.DeleteGuildRoles(ctx, guildId) // re-cache @@ -80,7 +79,7 @@ func (AdminRecacheCommand) Execute(ctx registry.CommandContext, guildIdRaw strin return } - guildChannels, err := worker.GetGuildChannels(guildId) + guildChannels, err := utils.RecacheGuildChannels(ctx, worker, guildId, time.Second*3, true) if err != nil { ctx.HandleError(err) return diff --git a/bot/logic/claim.go b/bot/logic/claim.go index a687f030..bf29e41f 100644 --- a/bot/logic/claim.go +++ b/bot/logic/claim.go @@ -17,6 +17,7 @@ import ( "github.com/TicketsBot-cloud/worker/bot/command/registry" "github.com/TicketsBot-cloud/worker/bot/customisation" "github.com/TicketsBot-cloud/worker/bot/dbclient" + "github.com/TicketsBot-cloud/worker/bot/permissionwrapper" "github.com/TicketsBot-cloud/worker/bot/utils" "github.com/TicketsBot-cloud/worker/i18n" "golang.org/x/sync/errgroup" @@ -94,6 +95,18 @@ func ApplyClaim(ctx context.Context, cmd registry.CommandContext, ticket databas return err } + // Placeholder overwrites must not be written back + if currentChannel.IsObfuscated() { + currentChannel, err = rest.GetChannel(ctx, cmd.Worker().Token, cmd.Worker().RateLimiter, *ticket.ChannelId) + if err != nil { + return err + } + + if currentChannel.IsObfuscated() { + return permissionwrapper.ErrChannelObfuscated + } + } + // Always update the name to match the new claimed naming scheme shouldUpdateName := true // But skip if the user has manually renamed the channel (doesn't match old unclaimed name) diff --git a/bot/logic/open.go b/bot/logic/open.go index 8e12f400..9489aef5 100644 --- a/bot/logic/open.go +++ b/bot/logic/open.go @@ -34,6 +34,7 @@ import ( "github.com/TicketsBot-cloud/worker/bot/permissionwrapper" "github.com/TicketsBot-cloud/worker/bot/redis" "github.com/TicketsBot-cloud/worker/bot/utils" + "github.com/TicketsBot-cloud/worker/config" "github.com/TicketsBot-cloud/worker/i18n" "go.uber.org/zap" "golang.org/x/sync/errgroup" @@ -165,11 +166,18 @@ func OpenTicket(ctx context.Context, cmd registry.InteractionContext, panel *dat return database.Ticket{}, nil } - // Check if the user can send messages in threads in the parent channel - if !permissionwrapper.HasPermissionsChannel( - cmd.Worker(), cmd.GuildId(), cmd.UserId(), cmd.ChannelId(), - permission.SendMessagesInThreads, - ) { + appPermissions := cmd.InteractionMetadata().AppPermissions + if appPermissions != 0 && !permission.HasPermissionRaw(appPermissions, permission.Administrator) && !permission.HasPermissionRaw(appPermissions, permission.ViewChannel) { + docsUrl := fmt.Sprintf("%s/miscellaneous/permissions-explained", config.Conf.Bot.DocsUrl) + message := cmd.GetMessage(i18n.MessageErrorMissingPermissionsTitle) + ":\n" + message += "* `View Channel`\n" + message += "\n" + cmd.GetMessage(i18n.MessageErrorMissingPermissionsBody, docsUrl) + + cmd.ReplyRaw(customisation.Red, cmd.GetMessage(i18n.Error), message) + return database.Ticket{}, nil + } + + if !canSendMessagesInThreads(cmd) { cmd.Reply(customisation.Red, i18n.Error, i18n.MessageOpenCantMessageInThreads, cmd.ChannelId()) return database.Ticket{}, nil } @@ -745,11 +753,15 @@ func checkChannelLimitAndDetermineParentId( if !utils.ContainsFunc(channels, func(c channel.Channel) bool { return c.Id == categoryId }) { - if err := dbclient.Client.Panel.SetOverflow(ctx, panelId, false, nil); err != nil { - return 0, err + if _, err := worker.GetChannel(categoryId); err != nil { + if utils.IsUnknownChannel(err) { + if err := dbclient.Client.Panel.SetOverflow(ctx, panelId, false, nil); err != nil { + return 0, err + } + } + + return 0, errCategoryChannelLimitReached } - - return 0, errCategoryChannelLimitReached } // Check that the overflow category still has space @@ -770,13 +782,39 @@ func checkChannelLimitAndDetermineParentId( return categoryId, nil } +func canSendMessagesInThreads(cmd registry.InteractionContext) bool { + // Zero when the member had to be looked up outside the interaction + if member, err := cmd.Member(); err == nil && member.Permissions != 0 { + return permission.HasPermissionRaw(member.Permissions, permission.Administrator) || + permission.HasPermissionRaw(member.Permissions, permission.SendMessagesInThreads) + } + + return permissionwrapper.HasPermissionsChannel( + cmd.Worker(), cmd.GuildId(), cmd.UserId(), cmd.ChannelId(), + permission.SendMessagesInThreads, + ) +} + func refreshCachedChannels(ctx context.Context, worker *worker.Context, guildId uint64) error { channels, err := rest.GetGuildChannels(ctx, worker.Token, worker.RateLimiter, guildId) if err != nil { return err } - return worker.Cache.ReplaceChannels(ctx, guildId, channels) + if len(channels) > 0 { + if err := worker.Cache.StoreChannels(ctx, channels); err != nil { + return err + } + } + + // Probing would outlast the 3 second ticket open lock + go func() { + if err := utils.PruneUnlistedChannels(context.Background(), worker, guildId, channels, time.Second*10, false); err != nil { + sentry.Error(err) + } + }() + + return nil } // TODO: Use translation of tickets diff --git a/bot/permissionwrapper/permission.go b/bot/permissionwrapper/permission.go index cf66095e..daff2164 100644 --- a/bot/permissionwrapper/permission.go +++ b/bot/permissionwrapper/permission.go @@ -10,6 +10,8 @@ import ( "github.com/TicketsBot-cloud/worker" ) +var ErrChannelObfuscated = errors.New("channel metadata is obfuscated") + func HasPermissionsChannel(ctx *worker.Context, guildId, userId, channelId uint64, permissions ...permission.Permission) bool { sum, err := getEffectivePermissionsChannel(ctx, guildId, userId, channelId) if err != nil { @@ -60,7 +62,10 @@ func getAllPermissionsChannel(ctx *worker.Context, guildId, userId, channelId ui sum, err := getEffectivePermissionsChannel(ctx, guildId, userId, channelId) if err != nil { - sentry.Error(err) + if !errors.Is(err, ErrChannelObfuscated) { + sentry.Error(err) + } + return permissions } @@ -118,6 +123,10 @@ func GetMissingPermissionsChannel(ctx *worker.Context, guildId, userId, channelI sum, err := getEffectivePermissionsChannel(ctx, guildId, userId, channelId) if err != nil { + if errors.Is(err, ErrChannelObfuscated) { + return []permission.Permission{permission.ViewChannel} + } + sentry.Error(err) return required } @@ -146,6 +155,10 @@ func getEffectivePermissionsChannel(ctx *worker.Context, guildId, userId, channe return 0, err } + if permission.HasPermissionRaw(permissions, permission.Administrator) { + return permissions, nil + } + permissions, err = getChannelBasePermissions(ctx, guildId, channelId, permissions) if err != nil { return 0, err @@ -255,6 +268,10 @@ func getChannelBasePermissions(ctx *worker.Context, guildId, channelId uint64, i return 0, err } + if ch.IsObfuscated() { + return 0, ErrChannelObfuscated + } + for _, overwrite := range ch.PermissionOverwrites { if overwrite.Type == channel.PermissionTypeRole && overwrite.Id == publicRole.Id { initialPermissions &= ^overwrite.Deny diff --git a/bot/redis/hiddenchannelcache.go b/bot/redis/hiddenchannelcache.go new file mode 100644 index 00000000..9b863a4c --- /dev/null +++ b/bot/redis/hiddenchannelcache.go @@ -0,0 +1,42 @@ +package redis + +import ( + "context" + "fmt" + "time" +) + +const hiddenChannelExpiry = time.Hour * 24 + +func hiddenChannelKey(channelId uint64) string { + return fmt.Sprintf("hiddenchannel:%d", channelId) +} + +func SetChannelHidden(ctx context.Context, channelId uint64) error { + return Client.Set(ctx, hiddenChannelKey(channelId), 1, hiddenChannelExpiry).Err() +} + +func GetHiddenChannels(ctx context.Context, channelIds []uint64) (map[uint64]bool, error) { + if len(channelIds) == 0 { + return nil, nil + } + + keys := make([]string, len(channelIds)) + for i, id := range channelIds { + keys[i] = hiddenChannelKey(id) + } + + res, err := Client.MGet(ctx, keys...).Result() + if err != nil { + return nil, err + } + + hidden := make(map[uint64]bool) + for i, value := range res { + if value != nil { + hidden[channelIds[i]] = true + } + } + + return hidden, nil +} diff --git a/bot/utils/recache.go b/bot/utils/recache.go new file mode 100644 index 00000000..1963198c --- /dev/null +++ b/bot/utils/recache.go @@ -0,0 +1,132 @@ +package utils + +import ( + "context" + "errors" + "math/rand" + "net/http" + "time" + + "github.com/TicketsBot-cloud/gdl/objects/channel" + "github.com/TicketsBot-cloud/gdl/rest" + "github.com/TicketsBot-cloud/gdl/rest/request" + w "github.com/TicketsBot-cloud/worker" + "github.com/TicketsBot-cloud/worker/bot/redis" +) + +const maxUnlistedChannelProbes = 100 + +func IsUnknownChannel(err error) bool { + var restError request.RestError + return errors.As(err, &restError) && (restError.StatusCode == http.StatusNotFound || restError.ApiError.Code == 10003) +} + +func IsMissingAccess(err error) bool { + var restError request.RestError + return errors.As(err, &restError) && (restError.StatusCode == http.StatusForbidden || restError.ApiError.Code == 50001) +} + +func RecacheGuildChannels(ctx context.Context, worker *w.Context, guildId uint64, probeBudget time.Duration, reprobeHidden bool) ([]channel.Channel, error) { + channels, err := rest.GetGuildChannels(ctx, worker.Token, worker.RateLimiter, guildId) + if err != nil { + return nil, err + } + + if len(channels) > 0 { + if err := worker.Cache.StoreChannels(ctx, channels); err != nil { + return nil, err + } + } + + if err := PruneUnlistedChannels(ctx, worker, guildId, channels, probeBudget, reprobeHidden); err != nil { + return nil, err + } + + return channels, nil +} + +// Unlisted rows may just be hidden, so only ones confirmed gone are deleted +func PruneUnlistedChannels(ctx context.Context, worker *w.Context, guildId uint64, listed []channel.Channel, probeBudget time.Duration, reprobeHidden bool) error { + cached, err := worker.Cache.GetGuildChannels(ctx, guildId) + if err != nil { + return err + } + + listedIds := make(map[uint64]struct{}, len(listed)) + for _, ch := range listed { + listedIds[ch.Id] = struct{}{} + } + + var unlisted []channel.Channel + for _, ch := range cached { + if _, ok := listedIds[ch.Id]; ok { + continue + } + + if ch.Type == channel.ChannelTypeGuildPublicThread || ch.Type == channel.ChannelTypeGuildPrivateThread || ch.Type == channel.ChannelTypeGuildNewsThread { + if err := worker.Cache.DeleteChannel(ctx, ch.Id); err != nil { + return err + } + + continue + } + + unlisted = append(unlisted, ch) + } + + if !reprobeHidden { + ids := make([]uint64, len(unlisted)) + for i, ch := range unlisted { + ids[i] = ch.Id + } + + hidden, err := redis.GetHiddenChannels(ctx, ids) + if err != nil { + return err + } + + unprobed := unlisted[:0] + for _, ch := range unlisted { + if !hidden[ch.Id] { + unprobed = append(unprobed, ch) + } + } + + unlisted = unprobed + } + + // Shuffled so repeated runs reach rows past the probe limit + rand.Shuffle(len(unlisted), func(i, j int) { + unlisted[i], unlisted[j] = unlisted[j], unlisted[i] + }) + + probeCtx, cancel := context.WithTimeout(ctx, probeBudget) + defer cancel() + + for i, ch := range unlisted { + if i >= maxUnlistedChannelProbes || probeCtx.Err() != nil { + break + } + + _, err := rest.GetChannel(probeCtx, worker.Token, worker.RateLimiter, ch.Id) + switch { + case IsUnknownChannel(err): + if err := worker.Cache.DeleteChannel(ctx, ch.Id); err != nil { + return err + } + case IsMissingAccess(err): + if !ch.IsObfuscated() { + ch.Flags |= channel.ChannelFlagObfuscated + if err := worker.Cache.StoreChannel(ctx, ch); err != nil { + return err + } + } + + if err := redis.SetChannelHidden(ctx, ch.Id); err != nil { + return err + } + } + } + + return nil +} diff --git a/go.mod b/go.mod index 855b27a1..d2053447 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ go 1.26.0 // replace github.com/TicketsBot-cloud/common => ../common -// replace github.com/TicketsBot-cloud/gdl => ../gdl +replace github.com/TicketsBot-cloud/gdl => ../gdl // replace github.com/TicketsBot-cloud/archiverclient => ../archiverclient diff --git a/restwrapper.go b/restwrapper.go index a8118a6d..53e71c6c 100644 --- a/restwrapper.go +++ b/restwrapper.go @@ -330,7 +330,7 @@ func (ctx *Context) GetGuildChannels(guildId uint64) ([]channel.Channel, error) channels, err := rest.GetGuildChannels(context.Background(), ctx.Token, ctx.RateLimiter, guildId) if shouldCache && err == nil { - go ctx.Cache.ReplaceChannels(context.Background(), guildId, channels) + go ctx.Cache.StoreChannels(context.Background(), channels) } return channels, err From a0453f950848dea5c63defc2c6f1a7bbc21311d1 Mon Sep 17 00:00:00 2001 From: biast12 <53872542+biast12@users.noreply.github.com> Date: Sun, 27 Sep 2026 12:30:48 +0200 Subject: [PATCH 2/2] Bump gdl --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index d2053447..50b856c7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ go 1.26.0 // replace github.com/TicketsBot-cloud/common => ../common -replace github.com/TicketsBot-cloud/gdl => ../gdl +// replace github.com/TicketsBot-cloud/gdl => ../gdl // replace github.com/TicketsBot-cloud/archiverclient => ../archiverclient @@ -17,7 +17,7 @@ require ( github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704 github.com/TicketsBot-cloud/common v0.0.0-20260905165836-38e4090764a4 github.com/TicketsBot-cloud/database v0.0.0-20260913165941-c2ecc7191b02 - github.com/TicketsBot-cloud/gdl v0.0.0-20260426095953-999472e6e538 + github.com/TicketsBot-cloud/gdl v0.0.0-20260927072153-8dbf0b284f57 github.com/caarlos0/env/v10 v10.0.0 github.com/elliotchance/orderedmap v1.8.0 github.com/getsentry/sentry-go v0.32.0 diff --git a/go.sum b/go.sum index df93d4ec..dd12f7eb 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,8 @@ github.com/TicketsBot-cloud/common v0.0.0-20260905165836-38e4090764a4 h1:zcPcJ+0 github.com/TicketsBot-cloud/common v0.0.0-20260905165836-38e4090764a4/go.mod h1:yL+VPSYNVK5gxUkA+fbb0WdTjGfWXnr7ScfL0rwk29g= github.com/TicketsBot-cloud/database v0.0.0-20260913165941-c2ecc7191b02 h1:3Z8PpXBUbdYn2srMRg3Nj0MDxnTB53CzIEAOUBIubhM= github.com/TicketsBot-cloud/database v0.0.0-20260913165941-c2ecc7191b02/go.mod h1:0fKn7nPX6KeljYNQtGQiuZ5aJ/TczgXvBhnbz+4GEc8= -github.com/TicketsBot-cloud/gdl v0.0.0-20260426095953-999472e6e538 h1:ewKw1Wv1x/yi8h1IH7EofcYnPUxWZaVTIPFkT97nhn0= -github.com/TicketsBot-cloud/gdl v0.0.0-20260426095953-999472e6e538/go.mod h1:CdwBR2egPtxUXjD2CgC9ZwfuB8dz9HPePM8nuG6dt7Y= +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/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/common v0.0.0-20240613013221-1e27eb8bfe37 h1:NC5fn+uAup0JxLiX85+bjVdyfUUXW3pKZYmp72/29hw=