Skip to content

Commit

Permalink
feat: implement polls (#1525)
Browse files Browse the repository at this point in the history
* feat: add poll events

* feat: add poll structs

* feat(MessageSend): add poll field

* feat(InteractionResponseData): add poll field

* feat: add endpoints
  • Loading branch information
FedorLap2006 authored Jun 21, 2024
1 parent a31fd86 commit d26ad10
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 0 deletions.
10 changes: 10 additions & 0 deletions endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,16 @@ var (
return EndpointMessageReactions(cID, mID, eID) + "/" + uID
}

EndpointPoll = func(cID, mID string) string {
return EndpointChannel(cID) + "/polls/" + mID
}
EndpointPollAnswerVoters = func(cID, mID string, aID int) string {
return EndpointPoll(cID, mID) + "/answers/" + strconv.Itoa(aID)
}
EndpointPollExpire = func(cID, mID string) string {
return EndpointPoll(cID, mID) + "/expire"
}

EndpointApplicationGlobalCommands = func(aID string) string {
return EndpointApplication(aID) + "/commands"
}
Expand Down
48 changes: 48 additions & 0 deletions eventhandlers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions events.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,21 @@ type GuildAuditLogEntryCreate struct {
*AuditLogEntry
GuildID string `json:"guild_id"`
}

// MessagePollVoteAdd is the data for a MessagePollVoteAdd event.
type MessagePollVoteAdd struct {
UserID string `json:"user_id"`
ChannelID string `json:"channel_id"`
MessageID string `json:"message_id"`
GuildID string `json:"guild_id,omitempty"`
AnswerID int `json:"answer_id"`
}

// MessagePollVoteRemove is the data for a MessagePollVoteRemove event.
type MessagePollVoteRemove struct {
UserID string `json:"user_id"`
ChannelID string `json:"channel_id"`
MessageID string `json:"message_id"`
GuildID string `json:"guild_id,omitempty"`
AnswerID int `json:"answer_id"`
}
1 change: 1 addition & 0 deletions interactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ type InteractionResponseData struct {
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
Files []*File `json:"-"`
Attachments *[]*MessageAttachment `json:"attachments,omitempty"`
Poll *Poll `json:"poll,omitempty"`

// NOTE: only MessageFlagsSuppressEmbeds and MessageFlagsEphemeral can be set.
Flags MessageFlags `json:"flags,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ type MessageSend struct {
Reference *MessageReference `json:"message_reference,omitempty"`
StickerIDs []string `json:"sticker_ids"`
Flags MessageFlags `json:"flags,omitempty"`
Poll *Poll `json:"poll,omitempty"`

// TODO: Remove this when compatibility is not required.
File *File `json:"-"`
Expand Down
46 changes: 46 additions & 0 deletions restapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -3453,3 +3453,49 @@ func (s *Session) UserApplicationRoleConnectionUpdate(appID string, rconn *Appli
err = unmarshal(body, &st)
return
}

// ----------------------------------------------------------------------
// Functions specific to polls
// ----------------------------------------------------------------------

// PollAnswerVoters returns users who voted for a particular answer in a poll on the specified message.
// channelID : ID of the channel.
// messageID : ID of the message.
// answerID : ID of the answer.
func (s *Session) PollAnswerVoters(channelID, messageID string, answerID int) (voters []*User, err error) {
endpoint := EndpointPollAnswerVoters(channelID, messageID, answerID)

var body []byte
body, err = s.RequestWithBucketID("GET", endpoint, nil, endpoint)
if err != nil {
return
}

var r struct {
Users []*User `json:"users"`
}

err = unmarshal(body, &r)
if err != nil {
return
}

voters = r.Users
return
}

// PollExpire expires poll on the specified message.
// channelID : ID of the channel.
// messageID : ID of the message.
func (s *Session) PollExpire(channelID, messageID string) (msg *Message, err error) {
endpoint := EndpointPollExpire(channelID, messageID)

var body []byte
body, err = s.RequestWithBucketID("POST", endpoint, nil, endpoint)
if err != nil {
return
}

err = unmarshal(body, &msg)
return
}
51 changes: 51 additions & 0 deletions structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2334,6 +2334,57 @@ const (
StageInstancePrivacyLevelGuildOnly StageInstancePrivacyLevel = 2
)

// PollLayoutType represents the layout of a poll.
type PollLayoutType int

// Valid PollLayoutType values.
const (
PollLayoutTypeDefault PollLayoutType = 1
)

// PollMedia contains common data used by question and answers.
type PollMedia struct {
Text string `json:"text,omitempty"`
Emoji *ComponentEmoji `json:"emoji,omitempty"` // TODO: rename the type
}

// PollAnswer represents a single answer in a poll.
type PollAnswer struct {
// NOTE: should not be set on creation.
AnswerID int `json:"answer_id,omitempty"`
Media *PollMedia `json:"poll_media"`
}

// PollAnswerCount stores counted poll votes for a single answer.
type PollAnswerCount struct {
ID int `json:"id"`
Count int `json:"count"`
MeVoted bool `json:"me_voted"`
}

// PollResults contains voting results on a poll.
type PollResults struct {
Finalized bool `json:"is_finalized"`
AnswerCounts []*PollAnswerCount `json:"answer_count"`
}

// Poll contains all poll related data.
type Poll struct {
Question PollMedia `json:"question"`
Answers []PollAnswer `json:"answers"`
AllowMultiselect bool `json:"allow_multiselect"`
LayoutType PollLayoutType `json:"layout_type,omitempty"`

// NOTE: should be set only on creation, when fetching use Expiry.
Duration int `json:"duration,omitempty"`

// NOTE: available only when fetching.

Results *PollResults `json:"results,omitempty"`
// NOTE: as Discord documentation notes, this field might be null even when fetching.
Expiry *time.Time `json:"expiry,omitempty"`
}

// Constants for the different bit offsets of text channel permissions
const (
// Deprecated: PermissionReadMessages has been replaced with PermissionViewChannel for text and voice channels
Expand Down

0 comments on commit d26ad10

Please sign in to comment.