From ce8c7a6363d5d155e01595c4ff1bbe4e65a07118 Mon Sep 17 00:00:00 2001 From: Veda Maharaj <110698921+SoggySaussages@users.noreply.github.com> Date: Wed, 26 Jun 2024 22:22:32 -0700 Subject: [PATCH] cc/threads: fix a few more bugs (#1685) * cc/threads: fix createThread archive duration Signed-off-by: SoggySaussages * cc/threads: allow creation of news threads Signed-off-by: SoggySaussages * discrdgo: ChannelType.IsThread ret true for news Signed-off-by: SoggySaussages * cc/threads: error typo Signed-off-by: SoggySaussages * cc/threads: restrict auto archive dur Previously users could provide any integer between 60 and 10080 as a duration. This caused createThread or editThread to fail given that Discord only permits 60, 1440, 4320, *or* 10080. Now any non permissible value errors. Signed-off-by: SoggySaussages * discordgo: add type for auto archive Signed-off-by: SoggySaussages --------- Signed-off-by: SoggySaussages --- common/templates/context_funcs.go | 25 +++++++++++----- lib/discordgo/restapi.go | 10 +++---- lib/discordgo/structs.go | 49 +++++++++++++++++++------------ lib/dstate/interface.go | 12 ++++---- 4 files changed, 58 insertions(+), 38 deletions(-) diff --git a/common/templates/context_funcs.go b/common/templates/context_funcs.go index e289fa488..5d4423ae1 100644 --- a/common/templates/context_funcs.go +++ b/common/templates/context_funcs.go @@ -1075,9 +1075,12 @@ func (c *Context) tmplCreateThread(channel, msgID, name interface{}, optionals . return nil, errors.New("createThread 'private' must be a boolean") } case 1: - duration := tmplToInt(opt) - if duration < 60 || duration > 10080 { - return nil, errors.New("createThread 'auto_archive_duration' must be and integer between 60 and 10080") + duration := discordgo.AutoArchiveDuration(tmplToInt(opt)) + switch duration { + case discordgo.AutoArchiveDurationOneHour, discordgo.AutoArchiveDurationOneDay, discordgo.AutoArchiveDurationThreeDays, discordgo.AutoArchiveDurationOneWeek: + start.AutoArchiveDuration = duration + default: + return nil, errors.New("createThread 'auto_archive_duration' must be 60, 1440, 4320, or 10080") } case 2: switch opt := opt.(type) { @@ -1093,6 +1096,10 @@ func (c *Context) tmplCreateThread(channel, msgID, name interface{}, optionals . } } + if cstate.Type == discordgo.ChannelTypeGuildNews { + start.Type = discordgo.ChannelTypeGuildNewsThread + } + var ctxThread *discordgo.Channel var err error if mID > 0 { @@ -1344,7 +1351,7 @@ func tagIDFromName(c *dstate.ChannelState, tagName string) int64 { type partialThread struct { RateLimitPerUser *int AppliedTags *[]int64 - AutoArchiveDuration *int + AutoArchiveDuration *discordgo.AutoArchiveDuration Invitable *bool } @@ -1426,11 +1433,13 @@ func processThreadArgs(newThread bool, parent *dstate.ChannelState, values ...in return c, errors.New("`tags` must be of type string or cslice") } case "auto_archive_duration": - duration := tmplToInt(val) - if duration < 60 || duration > 10080 { - return c, errors.New("'auto_archive_duration' must be and integer between 60 and 10080") + duration := discordgo.AutoArchiveDuration(tmplToInt(val)) + switch duration { + case discordgo.AutoArchiveDurationOneHour, discordgo.AutoArchiveDurationOneDay, discordgo.AutoArchiveDurationThreeDays, discordgo.AutoArchiveDurationOneWeek: + c.AutoArchiveDuration = &duration + default: + return nil, errors.New("'auto_archive_duration' must be 60, 1440, 4320, or 10080") } - c.AutoArchiveDuration = &duration case "invitable": val, ok := val.(bool) if ok { diff --git a/lib/discordgo/restapi.go b/lib/discordgo/restapi.go index 429de53d4..6fa58f3cf 100644 --- a/lib/discordgo/restapi.go +++ b/lib/discordgo/restapi.go @@ -2461,7 +2461,7 @@ func (s *Session) MessageThreadStartComplex(channelID, messageID int64, data *Th // messageID : Message to start thread from // name : Name of the thread // archiveDuration : Auto archive duration (in minutes) -func (s *Session) MessageThreadStart(channelID, messageID int64, name string, archiveDuration int) (ch *Channel, err error) { +func (s *Session) MessageThreadStart(channelID, messageID int64, name string, archiveDuration AutoArchiveDuration) (ch *Channel, err error) { return s.MessageThreadStartComplex(channelID, messageID, &ThreadStart{ Name: name, Invitable: false, @@ -2488,7 +2488,7 @@ func (s *Session) ThreadStartComplex(channelID int64, data *ThreadStart) (ch *Ch // channelID : Channel to create thread in // name : Name of the thread // archiveDuration : Auto archive duration (in minutes) -func (s *Session) ThreadStart(channelID int64, name string, typ ChannelType, archiveDuration int) (ch *Channel, err error) { +func (s *Session) ThreadStart(channelID int64, name string, typ ChannelType, archiveDuration AutoArchiveDuration) (ch *Channel, err error) { return s.ThreadStartComplex(channelID, &ThreadStart{ Name: name, Type: typ, @@ -2560,7 +2560,7 @@ func (s *Session) ForumThreadStartComplex(channelID int64, threadData *ThreadSta // name : Name of the thread. // archiveDuration : Auto archive duration. // content : Content of the starting message. -func (s *Session) ForumThreadStart(channelID int64, name string, archiveDuration int, content string) (th *Channel, err error) { +func (s *Session) ForumThreadStart(channelID int64, name string, archiveDuration AutoArchiveDuration, content string) (th *Channel, err error) { return s.ForumThreadStartComplex(channelID, &ThreadStart{ Name: name, AutoArchiveDuration: archiveDuration, @@ -2572,7 +2572,7 @@ func (s *Session) ForumThreadStart(channelID int64, name string, archiveDuration // name : Name of the thread. // archiveDuration : Auto archive duration. // embed : Embed data of the starting message. -func (s *Session) ForumThreadStartEmbed(channelID int64, name string, archiveDuration int, embed *MessageEmbed) (th *Channel, err error) { +func (s *Session) ForumThreadStartEmbed(channelID int64, name string, archiveDuration AutoArchiveDuration, embed *MessageEmbed) (th *Channel, err error) { return s.ForumThreadStartComplex(channelID, &ThreadStart{ Name: name, AutoArchiveDuration: archiveDuration, @@ -2584,7 +2584,7 @@ func (s *Session) ForumThreadStartEmbed(channelID int64, name string, archiveDur // name : Name of the thread. // archiveDuration : Auto archive duration. // embeds : Embeds data of the starting message. -func (s *Session) ForumThreadStartEmbeds(channelID int64, name string, archiveDuration int, embeds []*MessageEmbed) (th *Channel, err error) { +func (s *Session) ForumThreadStartEmbeds(channelID int64, name string, archiveDuration AutoArchiveDuration, embeds []*MessageEmbed) (th *Channel, err error) { return s.ForumThreadStartComplex(channelID, &ThreadStart{ Name: name, AutoArchiveDuration: archiveDuration, diff --git a/lib/discordgo/structs.go b/lib/discordgo/structs.go index 9a9e184fe..b4a6fb095 100644 --- a/lib/discordgo/structs.go +++ b/lib/discordgo/structs.go @@ -155,9 +155,6 @@ type Invite struct { ApproximateMemberCount int `json:"approximate_member_count"` } -// ChannelType is the type of a Channel -type ChannelType int - // ForumSortOrderType represents sort order of a forum channel. type ForumSortOrderType int @@ -180,6 +177,20 @@ const ( ForumLayoutGalleryView ForumLayout = 2 ) +// the thread will stop showing in the channel list after auto_archive_duration minutes of inactivity, can be set to: +// 60, 1440, 4320, 10080 +type AutoArchiveDuration int + +const ( + AutoArchiveDurationOneHour AutoArchiveDuration = 60 + AutoArchiveDurationOneDay AutoArchiveDuration = 1440 + AutoArchiveDurationThreeDays AutoArchiveDuration = 4320 + AutoArchiveDurationOneWeek AutoArchiveDuration = 10080 +) + +// ChannelType is the type of a Channel +type ChannelType int + // Block contains known ChannelType values const ( ChannelTypeGuildText ChannelType = 0 // a text channel within a server @@ -197,7 +208,7 @@ const ( ) func (t ChannelType) IsThread() bool { - return t == ChannelTypeGuildPrivateThread || t == ChannelTypeGuildPublicThread + return t == ChannelTypeGuildPrivateThread || t == ChannelTypeGuildPublicThread || t == ChannelTypeGuildNewsThread } // A Channel holds all data related to an individual Discord channel. @@ -288,7 +299,7 @@ type Channel struct { Archived bool `json:"archived"` // the thread will stop showing in the channel list after auto_archive_duration minutes of inactivity, can be set to: 60, 1440, 4320, 10080 - AutoArchiveDuration int `json:"auto_archive_duration,omitempty"` + AutoArchiveDuration AutoArchiveDuration `json:"auto_archive_duration,omitempty"` // whether the thread is locked; when a thread is locked, only users with MANAGE_THREADS can unarchive it Locked bool `json:"locked"` @@ -338,10 +349,10 @@ type ChannelEdit struct { RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"` // Threads only - Archived *bool `json:"archived,omitempty"` - AutoArchiveDuration int `json:"auto_archive_duration,omitempty"` - Locked *bool `json:"locked,omitempty"` - Invitable *bool `json:"invitable,omitempty"` + Archived *bool `json:"archived,omitempty"` + AutoArchiveDuration AutoArchiveDuration `json:"auto_archive_duration,omitempty"` + Locked *bool `json:"locked,omitempty"` + Invitable *bool `json:"invitable,omitempty"` // NOTE: forum threads only - these are IDs AppliedTags IDSlice `json:"applied_tags,string,omitempty"` @@ -372,11 +383,11 @@ const ( // ThreadStart stores all parameters you can use with MessageThreadStartComplex or ThreadStartComplex type ThreadStart struct { - Name string `json:"name"` - AutoArchiveDuration int `json:"auto_archive_duration,omitempty"` - Type ChannelType `json:"type,omitempty"` - Invitable bool `json:"invitable"` - RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` + Name string `json:"name"` + AutoArchiveDuration AutoArchiveDuration `json:"auto_archive_duration,omitempty"` + Type ChannelType `json:"type,omitempty"` + Invitable bool `json:"invitable"` + RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` // NOTE: forum threads only - these are IDs AppliedTags IDSlice `json:"applied_tags,string,omitempty"` @@ -1595,11 +1606,11 @@ type InteractionApplicationCommandCallbackData struct { } type ThreadMetadata struct { - Archived bool `json:"archived"` // whether the thread is archived - AutoArchiveDuration int `json:"auto_archive_duration"` // duration in minutes to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 - ArchiveTimestamp string `json:"archive_timestamp"` // timestamp when the thread's archive status was last changed, used for calculating recent activity - Locked bool `json:"locked"` // whether the thread is locked; when a thread is locked, only users with MANAGE_THREADS can unarchive it - Invitable bool `json:"invitable"` // Whether non-moderators can add other non-moderators to a thread; only available on private threads + Archived bool `json:"archived"` // whether the thread is archived + AutoArchiveDuration AutoArchiveDuration `json:"auto_archive_duration"` // duration in minutes to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 + ArchiveTimestamp string `json:"archive_timestamp"` // timestamp when the thread's archive status was last changed, used for calculating recent activity + Locked bool `json:"locked"` // whether the thread is locked; when a thread is locked, only users with MANAGE_THREADS can unarchive it + Invitable bool `json:"invitable"` // Whether non-moderators can add other non-moderators to a thread; only available on private threads } // A thread member is used to indicate whether a user has joined a thread or not. diff --git a/lib/dstate/interface.go b/lib/dstate/interface.go index 83352c223..45ca34e6c 100644 --- a/lib/dstate/interface.go +++ b/lib/dstate/interface.go @@ -266,12 +266,12 @@ type ChannelState struct { PermissionOverwrites []discordgo.PermissionOverwrite `json:"permission_overwrites"` - AvailableTags []discordgo.ForumTag `json:"available_tags"` - AppliedTags []int64 `json:"applied_tags"` - Archived bool `json:"archived"` - AutoArchiveDuration int `json:"auto_archive_duration,omitempty"` - Locked bool `json:"locked"` - Invitable bool `json:"invitable"` + AvailableTags []discordgo.ForumTag `json:"available_tags"` + AppliedTags []int64 `json:"applied_tags"` + Archived bool `json:"archived"` + AutoArchiveDuration discordgo.AutoArchiveDuration `json:"auto_archive_duration,omitempty"` + Locked bool `json:"locked"` + Invitable bool `json:"invitable"` DefaultReactionEmoji discordgo.ForumDefaultReaction `json:"default_reaction_emoji"` DefaultThreadRateLimitPerUser int `json:"default_thread_rate_limit_per_user"`