Forum channels (#1246)
* feat: forums Initial implementation of forum channels REST API * fix: linter * feat: cosmetic changes Added periods in the end of all documentation comments * fix(ChannelFlagRequireTag): incorrect value Fix incorrect value of ChannelFlagRequireTag. * refactor(DefaultReaction): rename to ForumDefaultReaction Rename DefaultReaction to ForumDefaultReaction. * fix(Channel): use ForumDefaultReaction Use ForumDefaultReaction instead of DefaultReaction in DefaultReactionEmoji field. * fix: gofmt * feat: cosmetic changes * Change "GUILD_FORUM" to "forum" in comment to ForumTag * Fix spacing for documentation of embeds parameter in ForumThreadStartEmbeds * docs(ForumThreadStartComplex): align parameters Align documentation for parameters of ForumThreadStartComplex.
This commit is contained in:
parent
fea3d77574
commit
e57064892a
2 changed files with 176 additions and 22 deletions
94
restapi.go
94
restapi.go
|
@ -2496,6 +2496,100 @@ func (s *Session) ThreadStart(channelID, name string, typ ChannelType, archiveDu
|
|||
})
|
||||
}
|
||||
|
||||
// ForumThreadStartComplex starts a new thread (creates a post) in a forum channel.
|
||||
// channelID : Channel to create thread in.
|
||||
// threadData : Parameters of the thread.
|
||||
// messageData : Parameters of the starting message.
|
||||
func (s *Session) ForumThreadStartComplex(channelID string, threadData *ThreadStart, messageData *MessageSend) (th *Channel, err error) {
|
||||
endpoint := EndpointChannelThreads(channelID)
|
||||
|
||||
// TODO: Remove this when compatibility is not required.
|
||||
if messageData.Embed != nil {
|
||||
if messageData.Embeds == nil {
|
||||
messageData.Embeds = []*MessageEmbed{messageData.Embed}
|
||||
} else {
|
||||
err = fmt.Errorf("cannot specify both Embed and Embeds")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, embed := range messageData.Embeds {
|
||||
if embed.Type == "" {
|
||||
embed.Type = "rich"
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove this when compatibility is not required.
|
||||
files := messageData.Files
|
||||
if messageData.File != nil {
|
||||
if files == nil {
|
||||
files = []*File{messageData.File}
|
||||
} else {
|
||||
err = fmt.Errorf("cannot specify both File and Files")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
data := struct {
|
||||
*ThreadStart
|
||||
Message *MessageSend `json:"message"`
|
||||
}{ThreadStart: threadData, Message: messageData}
|
||||
|
||||
var response []byte
|
||||
if len(files) > 0 {
|
||||
contentType, body, encodeErr := MultipartBodyWithJSON(data, files)
|
||||
if encodeErr != nil {
|
||||
return th, encodeErr
|
||||
}
|
||||
|
||||
response, err = s.request("POST", endpoint, contentType, body, endpoint, 0)
|
||||
} else {
|
||||
response, err = s.RequestWithBucketID("POST", endpoint, data, endpoint)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = unmarshal(response, &th)
|
||||
return
|
||||
}
|
||||
|
||||
// ForumThreadStart starts a new thread (post) in a forum channel.
|
||||
// channelID : Channel to create thread in.
|
||||
// name : Name of the thread.
|
||||
// archiveDuration : Auto archive duration.
|
||||
// content : Content of the starting message.
|
||||
func (s *Session) ForumThreadStart(channelID, name string, archiveDuration int, content string) (th *Channel, err error) {
|
||||
return s.ForumThreadStartComplex(channelID, &ThreadStart{
|
||||
Name: name,
|
||||
AutoArchiveDuration: archiveDuration,
|
||||
}, &MessageSend{Content: content})
|
||||
}
|
||||
|
||||
// ForumThreadStartEmbed starts a new thread (post) in a forum channel.
|
||||
// channelID : Channel to create thread in.
|
||||
// name : Name of the thread.
|
||||
// archiveDuration : Auto archive duration.
|
||||
// embed : Embed data of the starting message.
|
||||
func (s *Session) ForumThreadStartEmbed(channelID, name string, archiveDuration int, embed *MessageEmbed) (th *Channel, err error) {
|
||||
return s.ForumThreadStartComplex(channelID, &ThreadStart{
|
||||
Name: name,
|
||||
AutoArchiveDuration: archiveDuration,
|
||||
}, &MessageSend{Embeds: []*MessageEmbed{embed}})
|
||||
}
|
||||
|
||||
// ForumThreadStartEmbeds starts a new thread (post) in a forum channel.
|
||||
// channelID : Channel to create thread in.
|
||||
// name : Name of the thread.
|
||||
// archiveDuration : Auto archive duration.
|
||||
// embeds : Embeds data of the starting message.
|
||||
func (s *Session) ForumThreadStartEmbeds(channelID, name string, archiveDuration int, embeds []*MessageEmbed) (th *Channel, err error) {
|
||||
return s.ForumThreadStartComplex(channelID, &ThreadStart{
|
||||
Name: name,
|
||||
AutoArchiveDuration: archiveDuration,
|
||||
}, &MessageSend{Embeds: embeds})
|
||||
}
|
||||
|
||||
// ThreadJoin adds current user to a thread
|
||||
func (s *Session) ThreadJoin(id string) error {
|
||||
endpoint := EndpointThreadMember(id, "@me")
|
||||
|
|
104
structs.go
104
structs.go
|
@ -254,6 +254,20 @@ const (
|
|||
ChannelTypeGuildPublicThread ChannelType = 11
|
||||
ChannelTypeGuildPrivateThread ChannelType = 12
|
||||
ChannelTypeGuildStageVoice ChannelType = 13
|
||||
ChannelTypeGuildForum ChannelType = 15
|
||||
)
|
||||
|
||||
// ChannelFlags represent flags of a channel/thread.
|
||||
type ChannelFlags int
|
||||
|
||||
// Block containing known ChannelFlags values.
|
||||
const (
|
||||
// ChannelFlagPinned indicates whether the thread is pinned in the forum channel.
|
||||
// NOTE: forum threads only.
|
||||
ChannelFlagPinned ChannelFlags = 1 << 1
|
||||
// ChannelFlagRequireTag indicates whether a tag is required to be specified when creating a thread.
|
||||
// NOTE: forum channels only.
|
||||
ChannelFlagRequireTag ChannelFlags = 1 << 4
|
||||
)
|
||||
|
||||
// A Channel holds all data related to an individual Discord channel.
|
||||
|
@ -332,6 +346,18 @@ type Channel struct {
|
|||
|
||||
// All thread members. State channels only.
|
||||
Members []*ThreadMember `json:"-"`
|
||||
|
||||
// Channel flags.
|
||||
Flags ChannelFlags `json:"flags"`
|
||||
|
||||
// The set of tags that can be used in a forum channel.
|
||||
AvailableTags []ForumTag `json:"available_tags"`
|
||||
|
||||
// The IDs of the set of tags that have been applied to a thread in a forum channel.
|
||||
AppliedTags []string `json:"applied_tags"`
|
||||
|
||||
// Emoji to use as the default reaction to a forum post.
|
||||
DefaultReactionEmoji ForumDefaultReaction `json:"default_reaction_emoji"`
|
||||
}
|
||||
|
||||
// Mention returns a string which mentions the channel
|
||||
|
@ -355,6 +381,7 @@ type ChannelEdit struct {
|
|||
PermissionOverwrites []*PermissionOverwrite `json:"permission_overwrites,omitempty"`
|
||||
ParentID string `json:"parent_id,omitempty"`
|
||||
RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"`
|
||||
Flags *ChannelFlags `json:"flags,omitempty"`
|
||||
|
||||
// NOTE: threads only
|
||||
|
||||
|
@ -362,6 +389,14 @@ type ChannelEdit struct {
|
|||
AutoArchiveDuration int `json:"auto_archive_duration,omitempty"`
|
||||
Locked *bool `json:"locked,omitempty"`
|
||||
Invitable *bool `json:"invitable,omitempty"`
|
||||
|
||||
// NOTE: forum channels only
|
||||
|
||||
AvailableTags *[]ForumTag `json:"available_tags,omitempty"`
|
||||
DefaultReactionEmoji *ForumDefaultReaction `json:"default_reaction_emoji,omitempty"`
|
||||
|
||||
// NOTE: forum threads only
|
||||
AppliedTags *[]string `json:"applied_tags,omitempty"`
|
||||
}
|
||||
|
||||
// A ChannelFollow holds data returned after following a news channel
|
||||
|
@ -395,6 +430,9 @@ type ThreadStart struct {
|
|||
Type ChannelType `json:"type,omitempty"`
|
||||
Invitable bool `json:"invitable"`
|
||||
RateLimitPerUser int `json:"rate_limit_per_user,omitempty"`
|
||||
|
||||
// NOTE: forum threads only
|
||||
AppliedTags []string `json:"applied_tags,omitempty"`
|
||||
}
|
||||
|
||||
// ThreadMetadata contains a number of thread-specific channel fields that are not needed by other channel types.
|
||||
|
@ -438,6 +476,24 @@ type AddedThreadMember struct {
|
|||
Presence *Presence `json:"presence"`
|
||||
}
|
||||
|
||||
// ForumDefaultReaction specifies emoji to use as the default reaction to a forum post.
|
||||
// NOTE: Exactly one of EmojiID and EmojiName must be set.
|
||||
type ForumDefaultReaction struct {
|
||||
// The id of a guild's custom emoji.
|
||||
EmojiID string `json:"emoji_id,omitempty"`
|
||||
// The unicode character of the emoji.
|
||||
EmojiName string `json:"emoji_name,omitempty"`
|
||||
}
|
||||
|
||||
// ForumTag represents a tag that is able to be applied to a thread in a forum channel.
|
||||
type ForumTag struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Moderated bool `json:"moderated"`
|
||||
EmojiID string `json:"emoji_id,omitempty"`
|
||||
EmojiName string `json:"emoji_name,omitempty"`
|
||||
}
|
||||
|
||||
// Emoji struct holds data related to Emoji's
|
||||
type Emoji struct {
|
||||
ID string `json:"id"`
|
||||
|
@ -2074,6 +2130,7 @@ const (
|
|||
ErrCodeUnknownGuildWelcomeScreen = 10069
|
||||
ErrCodeUnknownGuildScheduledEvent = 10070
|
||||
ErrCodeUnknownGuildScheduledEventUser = 10071
|
||||
ErrUnknownTag = 10087
|
||||
|
||||
ErrCodeBotsCannotUseEndpoint = 20001
|
||||
ErrCodeOnlyBotsCanUseEndpoint = 20002
|
||||
|
@ -2087,28 +2144,30 @@ const (
|
|||
ErrCodeStageTopicContainsNotAllowedWordsForPublicStages = 20031
|
||||
ErrCodeGuildPremiumSubscriptionLevelTooLow = 20035
|
||||
|
||||
ErrCodeMaximumGuildsReached = 30001
|
||||
ErrCodeMaximumPinsReached = 30003
|
||||
ErrCodeMaximumNumberOfRecipientsReached = 30004
|
||||
ErrCodeMaximumGuildRolesReached = 30005
|
||||
ErrCodeMaximumNumberOfWebhooksReached = 30007
|
||||
ErrCodeMaximumNumberOfEmojisReached = 30008
|
||||
ErrCodeTooManyReactions = 30010
|
||||
ErrCodeMaximumNumberOfGuildChannelsReached = 30013
|
||||
ErrCodeMaximumNumberOfAttachmentsInAMessageReached = 30015
|
||||
ErrCodeMaximumNumberOfInvitesReached = 30016
|
||||
ErrCodeMaximumNumberOfAnimatedEmojisReached = 30018
|
||||
ErrCodeMaximumNumberOfServerMembersReached = 30019
|
||||
ErrCodeMaximumNumberOfGuildDiscoverySubcategoriesReached = 30030
|
||||
ErrCodeGuildAlreadyHasATemplate = 30031
|
||||
ErrCodeMaximumNumberOfThreadParticipantsReached = 30033
|
||||
ErrCodeMaximumNumberOfBansForNonGuildMembersHaveBeenExceeded = 30035
|
||||
ErrCodeMaximumNumberOfBansFetchesHasBeenReached = 30037
|
||||
ErrCodeMaximumNumberOfUncompletedGuildScheduledEventsReached = 30038
|
||||
ErrCodeMaximumNumberOfStickersReached = 30039
|
||||
ErrCodeMaximumNumberOfPruneRequestsHasBeenReached = 30040
|
||||
ErrCodeMaximumNumberOfGuildWidgetSettingsUpdatesHasBeenReached = 30042
|
||||
ErrCodeMaximumNumberOfEditsToMessagesOlderThanOneHourReached = 30046
|
||||
ErrCodeMaximumGuildsReached = 30001
|
||||
ErrCodeMaximumPinsReached = 30003
|
||||
ErrCodeMaximumNumberOfRecipientsReached = 30004
|
||||
ErrCodeMaximumGuildRolesReached = 30005
|
||||
ErrCodeMaximumNumberOfWebhooksReached = 30007
|
||||
ErrCodeMaximumNumberOfEmojisReached = 30008
|
||||
ErrCodeTooManyReactions = 30010
|
||||
ErrCodeMaximumNumberOfGuildChannelsReached = 30013
|
||||
ErrCodeMaximumNumberOfAttachmentsInAMessageReached = 30015
|
||||
ErrCodeMaximumNumberOfInvitesReached = 30016
|
||||
ErrCodeMaximumNumberOfAnimatedEmojisReached = 30018
|
||||
ErrCodeMaximumNumberOfServerMembersReached = 30019
|
||||
ErrCodeMaximumNumberOfGuildDiscoverySubcategoriesReached = 30030
|
||||
ErrCodeGuildAlreadyHasATemplate = 30031
|
||||
ErrCodeMaximumNumberOfThreadParticipantsReached = 30033
|
||||
ErrCodeMaximumNumberOfBansForNonGuildMembersHaveBeenExceeded = 30035
|
||||
ErrCodeMaximumNumberOfBansFetchesHasBeenReached = 30037
|
||||
ErrCodeMaximumNumberOfUncompletedGuildScheduledEventsReached = 30038
|
||||
ErrCodeMaximumNumberOfStickersReached = 30039
|
||||
ErrCodeMaximumNumberOfPruneRequestsHasBeenReached = 30040
|
||||
ErrCodeMaximumNumberOfGuildWidgetSettingsUpdatesHasBeenReached = 30042
|
||||
ErrCodeMaximumNumberOfEditsToMessagesOlderThanOneHourReached = 30046
|
||||
ErrCodeMaximumNumberOfPinnedThreadsInForumChannelHasBeenReached = 30047
|
||||
ErrCodeMaximumNumberOfTagsInForumChannelHasBeenReached = 30048
|
||||
|
||||
ErrCodeUnauthorized = 40001
|
||||
ErrCodeActionRequiredVerifiedAccount = 40002
|
||||
|
@ -2121,6 +2180,7 @@ const (
|
|||
ErrCodeMessageAlreadyCrossposted = 40033
|
||||
ErrCodeAnApplicationWithThatNameAlreadyExists = 40041
|
||||
ErrCodeInteractionHasAlreadyBeenAcknowledged = 40060
|
||||
ErrCodeTagNamesMustBeUnique = 40061
|
||||
|
||||
ErrCodeMissingAccess = 50001
|
||||
ErrCodeInvalidAccountType = 50002
|
||||
|
|
Loading…
Reference in a new issue