Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions discord/commands/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func InitializeBot() {
service.Discord.AddHandler(OnGuildMemberUpdate)
service.Discord.AddHandler(OnGuildMemberRemove)
service.Discord.AddHandler(OnUserUpdate)
service.Discord.AddHandler(OnThreadUpdate)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reconcile threads after missed gateway events

When this deploy starts with an already archived thread, or the bot is disconnected when a thread auto-archives, no ThreadUpdate is delivered or replayed and this handler is the only path that invokes KeepThreadAlive. The affected thread therefore remains archived permanently; add a startup/Ready sweep and periodic reconciliation of archived, unlocked threads so missed events recover.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow up

service.Discord.Identify.Intents = discordgo.MakeIntent(discordgo.IntentsAll)
err := service.Discord.Open()
if err != nil {
Expand Down Expand Up @@ -166,6 +167,24 @@ func OnUserUpdate(s *discordgo.Session, u *discordgo.UserUpdate) {
service.SyncDiscordUserAvatar(u.ID, member.AvatarURL("256"))
}

// OnThreadUpdate keeps guild threads alive indefinitely. Discord doesn't
// allow disabling thread auto-archival (7-day window at most), so when a
// thread flips to archived we immediately flip it back. Unarchiving emits
// another ThreadUpdate with Archived=false, which falls through the guard
// below — no loop. Locked threads are left alone: locking is an explicit
// moderator "this thread is closed" signal, and force-unarchiving those
// would fight moderation.
func OnThreadUpdate(s *discordgo.Session, t *discordgo.ThreadUpdate) {
if t.GuildID != config.DiscordGuild {
return
}
if t.ThreadMetadata == nil || !t.ThreadMetadata.Archived || t.ThreadMetadata.Locked {
return
}
logger.SugarLogger.Infof("ThreadUpdate: thread %s (%s) was archived, keeping alive", t.ID, t.Name)
service.KeepThreadAlive(t.Channel)
}

func diffRoles(before, after []string) (added, removed []string) {
beforeSet := make(map[string]struct{}, len(before))
for _, r := range before {
Expand Down
24 changes: 24 additions & 0 deletions discord/service/thread_keepalive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package service

import (
"github.com/bwmarrin/discordgo"
"github.com/gaucho-racing/sentinel/discord/pkg/logger"
)

// KeepThreadAlive unarchives a thread that Discord just auto-archived and
// bumps its auto-archive window to the maximum (7 days) so the gateway only
// re-archives it weekly instead of on the channel's default window. The
// unarchive is silent — no message is posted and members aren't notified.
// Requires the bot to have MANAGE_THREADS in the guild.
func KeepThreadAlive(thread *discordgo.Channel) {
archived := false
_, err := Discord.ChannelEdit(thread.ID, &discordgo.ChannelEdit{
Archived: &archived,
AutoArchiveDuration: 10080,
Comment on lines +15 to +17

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid coupling unarchive to a gated archive duration

In guilds without Discord's SEVEN_DAY_THREAD_ARCHIVE feature, 10080 is not an allowed auto-archive duration, so Discord rejects this entire PATCH—including Archived: false—and the thread remains archived. Select a duration supported by the configured guild or retry the unarchive without the gated duration.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think we should be fine as i see the option for 7 days

})
if err != nil {
logger.SugarLogger.Errorf("thread keepalive: failed to unarchive thread %s (%s): %v", thread.ID, thread.Name, err)
return
}
logger.SugarLogger.Infof("thread keepalive: unarchived thread %s (%s)", thread.ID, thread.Name)
}
Loading