diff --git a/cache/caches.go b/cache/caches.go index e3f44dd1..32fe5172 100644 --- a/cache/caches.go +++ b/cache/caches.go @@ -747,6 +747,9 @@ type Caches interface { // GuildForumChannel returns a discord.GuildForumChannel from the ChannelCache and a bool indicating if it exists. GuildForumChannel(channelID snowflake.ID) (discord.GuildForumChannel, bool) + + // GuildMediaChannel returns a discord.GuildMediaChannel from the ChannelCache and a bool indicating if it exists. + GuildMediaChannel(channelID snowflake.ID) (discord.GuildMediaChannel, bool) } // New returns a new default Caches instance with the given ConfigOpt(s) applied. @@ -1008,3 +1011,12 @@ func (c *cachesImpl) GuildForumChannel(channelID snowflake.ID) (discord.GuildFor } return discord.GuildForumChannel{}, false } + +func (c *cachesImpl) GuildMediaChannel(channelID snowflake.ID) (discord.GuildMediaChannel, bool) { + if ch, ok := c.Channel(channelID); ok { + if cCh, ok := ch.(discord.GuildMediaChannel); ok { + return cCh, true + } + } + return discord.GuildMediaChannel{}, false +} diff --git a/discord/channel.go b/discord/channel.go index 30f195f0..4b0e9caf 100644 --- a/discord/channel.go +++ b/discord/channel.go @@ -31,6 +31,7 @@ const ( ChannelTypeGuildStageVoice ChannelTypeGuildDirectory ChannelTypeGuildForum + ChannelTypeGuildMedia ) type ChannelFlags int @@ -40,7 +41,8 @@ const ( _ _ ChannelFlagRequireTag - ChannelFlagsNone ChannelFlags = 0 + ChannelFlagHideMediaDownloadOptions ChannelFlags = 1 << 15 + ChannelFlagsNone ChannelFlags = 0 ) // Add allows you to add multiple bits together, producing a new bit @@ -208,6 +210,11 @@ func (u *UnmarshalChannel) UnmarshalJSON(data []byte) error { err = json.Unmarshal(data, &v) channel = v + case ChannelTypeGuildMedia: + var v GuildMediaChannel + err = json.Unmarshal(data, &v) + channel = v + default: err = fmt.Errorf("unknown channel with type %d received", cType.Type) } @@ -1034,12 +1041,12 @@ type GuildForumChannel struct { permissionOverwrites PermissionOverwrites name string parentID *snowflake.ID - LastThreadID *snowflake.ID + LastPostID *snowflake.ID Topic *string NSFW bool RateLimitPerUser int Flags ChannelFlags - AvailableTags []ForumTag + AvailableTags []ChannelTag DefaultReactionEmoji *DefaultReactionEmoji DefaultThreadRateLimitPerUser int DefaultSortOrder *DefaultSortOrder @@ -1058,7 +1065,7 @@ func (c *GuildForumChannel) UnmarshalJSON(data []byte) error { c.permissionOverwrites = v.PermissionOverwrites c.name = v.Name c.parentID = v.ParentID - c.LastThreadID = v.LastThreadID + c.LastPostID = v.LastPostID c.Topic = v.Topic c.NSFW = v.NSFW c.RateLimitPerUser = v.RateLimitPerUser @@ -1080,7 +1087,7 @@ func (c GuildForumChannel) MarshalJSON() ([]byte, error) { PermissionOverwrites: c.permissionOverwrites, Name: c.name, ParentID: c.parentID, - LastThreadID: c.LastThreadID, + LastPostID: c.LastPostID, Topic: c.Topic, NSFW: c.NSFW, RateLimitPerUser: c.RateLimitPerUser, @@ -1136,6 +1143,117 @@ func (c GuildForumChannel) CreatedAt() time.Time { func (GuildForumChannel) channel() {} func (GuildForumChannel) guildChannel() {} +var ( + _ Channel = (*GuildMediaChannel)(nil) + _ GuildChannel = (*GuildMediaChannel)(nil) +) + +type GuildMediaChannel struct { + id snowflake.ID + guildID snowflake.ID + position int + permissionOverwrites PermissionOverwrites + name string + parentID *snowflake.ID + LastPostID *snowflake.ID + Topic *string + NSFW bool + RateLimitPerUser int + Flags ChannelFlags + AvailableTags []ChannelTag + DefaultReactionEmoji *DefaultReactionEmoji + DefaultThreadRateLimitPerUser int + DefaultSortOrder *DefaultSortOrder +} + +func (c *GuildMediaChannel) UnmarshalJSON(data []byte) error { + var v guildMediaChannel + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + c.id = v.ID + c.guildID = v.GuildID + c.position = v.Position + c.permissionOverwrites = v.PermissionOverwrites + c.name = v.Name + c.parentID = v.ParentID + c.LastPostID = v.LastPostID + c.Topic = v.Topic + c.NSFW = v.NSFW + c.RateLimitPerUser = v.RateLimitPerUser + c.Flags = v.Flags + c.AvailableTags = v.AvailableTags + c.DefaultReactionEmoji = v.DefaultReactionEmoji + c.DefaultThreadRateLimitPerUser = v.DefaultThreadRateLimitPerUser + c.DefaultSortOrder = v.DefaultSortOrder + return nil +} + +func (c GuildMediaChannel) MarshalJSON() ([]byte, error) { + return json.Marshal(guildMediaChannel{ + ID: c.id, + Type: c.Type(), + GuildID: c.guildID, + Position: c.position, + PermissionOverwrites: c.permissionOverwrites, + Name: c.name, + ParentID: c.parentID, + LastPostID: c.LastPostID, + Topic: c.Topic, + NSFW: c.NSFW, + RateLimitPerUser: c.RateLimitPerUser, + Flags: c.Flags, + AvailableTags: c.AvailableTags, + DefaultReactionEmoji: c.DefaultReactionEmoji, + DefaultThreadRateLimitPerUser: c.DefaultThreadRateLimitPerUser, + DefaultSortOrder: c.DefaultSortOrder, + }) +} + +func (c GuildMediaChannel) String() string { + return channelString(c) +} + +func (c GuildMediaChannel) Mention() string { + return ChannelMention(c.ID()) +} + +func (GuildMediaChannel) Type() ChannelType { + return ChannelTypeGuildMedia +} + +func (c GuildMediaChannel) ID() snowflake.ID { + return c.id +} + +func (c GuildMediaChannel) Name() string { + return c.name +} + +func (c GuildMediaChannel) GuildID() snowflake.ID { + return c.guildID +} + +func (c GuildMediaChannel) PermissionOverwrites() PermissionOverwrites { + return c.permissionOverwrites +} + +func (c GuildMediaChannel) Position() int { + return c.position +} + +func (c GuildMediaChannel) ParentID() *snowflake.ID { + return c.parentID +} + +func (c GuildMediaChannel) CreatedAt() time.Time { + return c.id.Time() +} + +func (GuildMediaChannel) channel() {} +func (GuildMediaChannel) guildChannel() {} + type FollowedChannel struct { ChannelID snowflake.ID `json:"channel_id"` WebhookID snowflake.ID `json:"webhook_id"` @@ -1167,7 +1285,7 @@ type ThreadMetadata struct { CreateTimestamp time.Time `json:"create_timestamp"` } -type ForumTag struct { +type ChannelTag struct { ID snowflake.ID `json:"id"` Name string `json:"name"` Moderated bool `json:"moderated"` @@ -1236,6 +1354,9 @@ func ApplyGuildIDToChannel(channel GuildChannel, guildID snowflake.ID) GuildChan case GuildForumChannel: c.guildID = guildID return c + case GuildMediaChannel: + c.guildID = guildID + return c default: return channel } diff --git a/discord/channel_create.go b/discord/channel_create.go index edf84eb7..eb5ac7d2 100644 --- a/discord/channel_create.go +++ b/discord/channel_create.go @@ -188,7 +188,7 @@ type GuildForumChannelCreate struct { ParentID snowflake.ID `json:"parent_id,omitempty"` RateLimitPerUser int `json:"rate_limit_per_user"` DefaultReactionEmoji DefaultReactionEmoji `json:"default_reaction_emoji"` - AvailableTags []ForumTag `json:"available_tags"` + AvailableTags []ChannelTag `json:"available_tags"` DefaultSortOrder DefaultSortOrder `json:"default_sort_order"` DefaultForumLayout DefaultForumLayout `json:"default_forum_layout"` } @@ -211,6 +211,36 @@ func (c GuildForumChannelCreate) MarshalJSON() ([]byte, error) { func (GuildForumChannelCreate) channelCreate() {} func (GuildForumChannelCreate) guildChannelCreate() {} +type GuildMediaChannelCreate struct { + Name string `json:"name"` + Topic string `json:"topic,omitempty"` + Position int `json:"position,omitempty"` + PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites,omitempty"` + ParentID snowflake.ID `json:"parent_id,omitempty"` + RateLimitPerUser int `json:"rate_limit_per_user"` + DefaultReactionEmoji DefaultReactionEmoji `json:"default_reaction_emoji"` + AvailableTags []ChannelTag `json:"available_tags"` + DefaultSortOrder DefaultSortOrder `json:"default_sort_order"` +} + +func (c GuildMediaChannelCreate) Type() ChannelType { + return ChannelTypeGuildMedia +} + +func (c GuildMediaChannelCreate) MarshalJSON() ([]byte, error) { + type guildMediaChannelCreate GuildMediaChannelCreate + return json.Marshal(struct { + Type ChannelType `json:"type"` + guildMediaChannelCreate + }{ + Type: c.Type(), + guildMediaChannelCreate: guildMediaChannelCreate(c), + }) +} + +func (GuildMediaChannelCreate) channelCreate() {} +func (GuildMediaChannelCreate) guildChannelCreate() {} + type DMChannelCreate struct { RecipientID snowflake.ID `json:"recipient_id"` } diff --git a/discord/channel_update.go b/discord/channel_update.go index 82bdf470..9ddfe4d2 100644 --- a/discord/channel_update.go +++ b/discord/channel_update.go @@ -104,7 +104,7 @@ type GuildForumChannelUpdate struct { PermissionOverwrites *[]PermissionOverwrite `json:"permission_overwrites,omitempty"` ParentID *snowflake.ID `json:"parent_id,omitempty"` RateLimitPerUser *int `json:"rate_limit_per_user"` - AvailableTags *[]ForumTag `json:"available_tags,omitempty"` + AvailableTags *[]ChannelTag `json:"available_tags,omitempty"` Flags *ChannelFlags `json:"flags,omitempty"` DefaultReactionEmoji *json.Nullable[DefaultReactionEmoji] `json:"default_reaction_emoji,omitempty"` DefaultThreadRateLimitPerUser *int `json:"default_thread_rate_limit_per_user,omitempty"` @@ -115,7 +115,25 @@ type GuildForumChannelUpdate struct { func (GuildForumChannelUpdate) channelUpdate() {} func (GuildForumChannelUpdate) guildChannelUpdate() {} -type GuildForumThreadChannelUpdate struct { +type GuildMediaChannelUpdate struct { + Name *string `json:"name,omitempty"` + Position *int `json:"position,omitempty"` + Topic *string `json:"topic,omitempty"` + NSFW *bool `json:"nsfw,omitempty"` + PermissionOverwrites *[]PermissionOverwrite `json:"permission_overwrites,omitempty"` + ParentID *snowflake.ID `json:"parent_id,omitempty"` + RateLimitPerUser *int `json:"rate_limit_per_user"` + AvailableTags *[]ChannelTag `json:"available_tags,omitempty"` + Flags *ChannelFlags `json:"flags,omitempty"` + DefaultReactionEmoji *json.Nullable[DefaultReactionEmoji] `json:"default_reaction_emoji,omitempty"` + DefaultThreadRateLimitPerUser *int `json:"default_thread_rate_limit_per_user,omitempty"` + DefaultSortOrder *json.Nullable[DefaultSortOrder] `json:"default_sort_order,omitempty"` +} + +func (GuildMediaChannelUpdate) channelUpdate() {} +func (GuildMediaChannelUpdate) guildChannelUpdate() {} + +type GuildPostUpdate struct { Name *string `json:"name,omitempty"` Archived *bool `json:"archived,omitempty"` AutoArchiveDuration *AutoArchiveDuration `json:"auto_archive_duration,omitempty"` @@ -126,8 +144,8 @@ type GuildForumThreadChannelUpdate struct { AppliedTags *[]snowflake.ID `json:"applied_tags,omitempty"` } -func (GuildForumThreadChannelUpdate) channelUpdate() {} -func (GuildForumThreadChannelUpdate) guildChannelUpdate() {} +func (GuildPostUpdate) channelUpdate() {} +func (GuildPostUpdate) guildChannelUpdate() {} type GuildChannelPositionUpdate struct { ID snowflake.ID `json:"id"` diff --git a/discord/channels_raw.go b/discord/channels_raw.go index d2a0667f..33f75e8a 100644 --- a/discord/channels_raw.go +++ b/discord/channels_raw.go @@ -188,14 +188,14 @@ type guildForumChannel struct { NSFW bool `json:"nsfw"` RateLimitPerUser int `json:"rate_limit_per_user"` Flags ChannelFlags `json:"flags"` - AvailableTags []ForumTag `json:"available_tags"` + AvailableTags []ChannelTag `json:"available_tags"` DefaultReactionEmoji *DefaultReactionEmoji `json:"default_reaction_emoji"` DefaultThreadRateLimitPerUser int `json:"default_thread_rate_limit_per_user"` DefaultSortOrder *DefaultSortOrder `json:"default_sort_order"` DefaultForumLayout DefaultForumLayout `json:"default_forum_layout"` // idk discord name your shit correctly - LastThreadID *snowflake.ID `json:"last_message_id"` + LastPostID *snowflake.ID `json:"last_message_id"` } func (t *guildForumChannel) UnmarshalJSON(data []byte) error { @@ -212,6 +212,41 @@ func (t *guildForumChannel) UnmarshalJSON(data []byte) error { return nil } +type guildMediaChannel struct { + ID snowflake.ID `json:"id"` + Type ChannelType `json:"type"` + GuildID snowflake.ID `json:"guild_id"` + Position int `json:"position"` + PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` + Name string `json:"name"` + ParentID *snowflake.ID `json:"parent_id"` + Topic *string `json:"topic"` + NSFW bool `json:"nsfw"` + RateLimitPerUser int `json:"rate_limit_per_user"` + Flags ChannelFlags `json:"flags"` + AvailableTags []ChannelTag `json:"available_tags"` + DefaultReactionEmoji *DefaultReactionEmoji `json:"default_reaction_emoji"` + DefaultThreadRateLimitPerUser int `json:"default_thread_rate_limit_per_user"` + DefaultSortOrder *DefaultSortOrder `json:"default_sort_order"` + + // idk discord name your shit correctly v2 + LastPostID *snowflake.ID `json:"last_message_id"` +} + +func (t *guildMediaChannel) UnmarshalJSON(data []byte) error { + type guildMediaChannelAlias guildMediaChannel + var v struct { + PermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` + guildMediaChannelAlias + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *t = guildMediaChannel(v.guildMediaChannelAlias) + t.PermissionOverwrites = parsePermissionOverwrites(v.PermissionOverwrites) + return nil +} + func parsePermissionOverwrites(overwrites []UnmarshalPermissionOverwrite) []PermissionOverwrite { if len(overwrites) == 0 { return nil diff --git a/discord/thread.go b/discord/thread.go index 88aa7294..1beae101 100644 --- a/discord/thread.go +++ b/discord/thread.go @@ -11,7 +11,7 @@ type ThreadCreateFromMessage struct { RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` } -type ForumThreadCreate struct { +type ThreadChannelPostCreate struct { Name string `json:"name"` AutoArchiveDuration AutoArchiveDuration `json:"auto_archive_duration,omitempty"` RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` @@ -19,7 +19,7 @@ type ForumThreadCreate struct { AppliedTags []snowflake.ID `json:"applied_tags,omitempty"` } -func (c ForumThreadCreate) ToBody() (any, error) { +func (c ThreadChannelPostCreate) ToBody() (any, error) { if len(c.Message.Files) > 0 { c.Message.Attachments = parseAttachments(c.Message.Files) return PayloadWithFiles(c, c.Message.Files...) @@ -27,7 +27,7 @@ func (c ForumThreadCreate) ToBody() (any, error) { return c, nil } -type ForumThread struct { +type ThreadChannelPost struct { GuildThread Message Message `json:"message"` } diff --git a/rest/threads.go b/rest/threads.go index 3bd9e878..57314157 100644 --- a/rest/threads.go +++ b/rest/threads.go @@ -15,9 +15,9 @@ func NewThreads(client Client) Threads { } type Threads interface { - // CreateThreadFromMessage does not work for discord.ChannelTypeGuildForum channels. + // CreateThreadFromMessage does not work for discord.ChannelTypeGuildForum or discord.ChannelTypeGuildMedia channels. CreateThreadFromMessage(channelID snowflake.ID, messageID snowflake.ID, threadCreateFromMessage discord.ThreadCreateFromMessage, opts ...RequestOpt) (thread *discord.GuildThread, err error) - CreateThreadInForum(channelID snowflake.ID, threadCreateInForum discord.ForumThreadCreate, opts ...RequestOpt) (thread *discord.ForumThread, err error) + CreatePostInThreadChannel(channelID snowflake.ID, postCreateInChannel discord.ThreadChannelPostCreate, opts ...RequestOpt) (post *discord.ThreadChannelPost, err error) CreateThread(channelID snowflake.ID, threadCreate discord.ThreadCreate, opts ...RequestOpt) (thread *discord.GuildThread, err error) JoinThread(threadID snowflake.ID, opts ...RequestOpt) error LeaveThread(threadID snowflake.ID, opts ...RequestOpt) error @@ -41,8 +41,8 @@ func (s *threadImpl) CreateThreadFromMessage(channelID snowflake.ID, messageID s return } -func (s *threadImpl) CreateThreadInForum(channelID snowflake.ID, threadCreateInForum discord.ForumThreadCreate, opts ...RequestOpt) (thread *discord.ForumThread, err error) { - body, err := threadCreateInForum.ToBody() +func (s *threadImpl) CreatePostInThreadChannel(channelID snowflake.ID, postCreateInChannel discord.ThreadChannelPostCreate, opts ...RequestOpt) (thread *discord.ThreadChannelPost, err error) { + body, err := postCreateInChannel.ToBody() if err != nil { return }