feat: implement polls (#1525)
* feat: add poll events * feat: add poll structs * feat(MessageSend): add poll field * feat(InteractionResponseData): add poll field * feat: add endpoints
This commit is contained in:
parent
a31fd8617e
commit
d26ad10ba6
7 changed files with 175 additions and 0 deletions
10
endpoints.go
10
endpoints.go
|
@ -162,6 +162,16 @@ var (
|
||||||
return EndpointMessageReactions(cID, mID, eID) + "/" + uID
|
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 {
|
EndpointApplicationGlobalCommands = func(aID string) string {
|
||||||
return EndpointApplication(aID) + "/commands"
|
return EndpointApplication(aID) + "/commands"
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,8 @@ const (
|
||||||
messageCreateEventType = "MESSAGE_CREATE"
|
messageCreateEventType = "MESSAGE_CREATE"
|
||||||
messageDeleteEventType = "MESSAGE_DELETE"
|
messageDeleteEventType = "MESSAGE_DELETE"
|
||||||
messageDeleteBulkEventType = "MESSAGE_DELETE_BULK"
|
messageDeleteBulkEventType = "MESSAGE_DELETE_BULK"
|
||||||
|
messagePollVoteAddEventType = "MESSAGE_POLL_VOTE_ADD"
|
||||||
|
messagePollVoteRemoveEventType = "MESSAGE_POLL_VOTE_REMOVE"
|
||||||
messageReactionAddEventType = "MESSAGE_REACTION_ADD"
|
messageReactionAddEventType = "MESSAGE_REACTION_ADD"
|
||||||
messageReactionRemoveEventType = "MESSAGE_REACTION_REMOVE"
|
messageReactionRemoveEventType = "MESSAGE_REACTION_REMOVE"
|
||||||
messageReactionRemoveAllEventType = "MESSAGE_REACTION_REMOVE_ALL"
|
messageReactionRemoveAllEventType = "MESSAGE_REACTION_REMOVE_ALL"
|
||||||
|
@ -815,6 +817,46 @@ func (eh messageDeleteBulkEventHandler) Handle(s *Session, i interface{}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// messagePollVoteAddEventHandler is an event handler for MessagePollVoteAdd events.
|
||||||
|
type messagePollVoteAddEventHandler func(*Session, *MessagePollVoteAdd)
|
||||||
|
|
||||||
|
// Type returns the event type for MessagePollVoteAdd events.
|
||||||
|
func (eh messagePollVoteAddEventHandler) Type() string {
|
||||||
|
return messagePollVoteAddEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of MessagePollVoteAdd.
|
||||||
|
func (eh messagePollVoteAddEventHandler) New() interface{} {
|
||||||
|
return &MessagePollVoteAdd{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for MessagePollVoteAdd events.
|
||||||
|
func (eh messagePollVoteAddEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*MessagePollVoteAdd); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// messagePollVoteRemoveEventHandler is an event handler for MessagePollVoteRemove events.
|
||||||
|
type messagePollVoteRemoveEventHandler func(*Session, *MessagePollVoteRemove)
|
||||||
|
|
||||||
|
// Type returns the event type for MessagePollVoteRemove events.
|
||||||
|
func (eh messagePollVoteRemoveEventHandler) Type() string {
|
||||||
|
return messagePollVoteRemoveEventType
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of MessagePollVoteRemove.
|
||||||
|
func (eh messagePollVoteRemoveEventHandler) New() interface{} {
|
||||||
|
return &MessagePollVoteRemove{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle is the handler for MessagePollVoteRemove events.
|
||||||
|
func (eh messagePollVoteRemoveEventHandler) Handle(s *Session, i interface{}) {
|
||||||
|
if t, ok := i.(*MessagePollVoteRemove); ok {
|
||||||
|
eh(s, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// messageReactionAddEventHandler is an event handler for MessageReactionAdd events.
|
// messageReactionAddEventHandler is an event handler for MessageReactionAdd events.
|
||||||
type messageReactionAddEventHandler func(*Session, *MessageReactionAdd)
|
type messageReactionAddEventHandler func(*Session, *MessageReactionAdd)
|
||||||
|
|
||||||
|
@ -1350,6 +1392,10 @@ func handlerForInterface(handler interface{}) EventHandler {
|
||||||
return messageDeleteEventHandler(v)
|
return messageDeleteEventHandler(v)
|
||||||
case func(*Session, *MessageDeleteBulk):
|
case func(*Session, *MessageDeleteBulk):
|
||||||
return messageDeleteBulkEventHandler(v)
|
return messageDeleteBulkEventHandler(v)
|
||||||
|
case func(*Session, *MessagePollVoteAdd):
|
||||||
|
return messagePollVoteAddEventHandler(v)
|
||||||
|
case func(*Session, *MessagePollVoteRemove):
|
||||||
|
return messagePollVoteRemoveEventHandler(v)
|
||||||
case func(*Session, *MessageReactionAdd):
|
case func(*Session, *MessageReactionAdd):
|
||||||
return messageReactionAddEventHandler(v)
|
return messageReactionAddEventHandler(v)
|
||||||
case func(*Session, *MessageReactionRemove):
|
case func(*Session, *MessageReactionRemove):
|
||||||
|
@ -1437,6 +1483,8 @@ func init() {
|
||||||
registerInterfaceProvider(messageCreateEventHandler(nil))
|
registerInterfaceProvider(messageCreateEventHandler(nil))
|
||||||
registerInterfaceProvider(messageDeleteEventHandler(nil))
|
registerInterfaceProvider(messageDeleteEventHandler(nil))
|
||||||
registerInterfaceProvider(messageDeleteBulkEventHandler(nil))
|
registerInterfaceProvider(messageDeleteBulkEventHandler(nil))
|
||||||
|
registerInterfaceProvider(messagePollVoteAddEventHandler(nil))
|
||||||
|
registerInterfaceProvider(messagePollVoteRemoveEventHandler(nil))
|
||||||
registerInterfaceProvider(messageReactionAddEventHandler(nil))
|
registerInterfaceProvider(messageReactionAddEventHandler(nil))
|
||||||
registerInterfaceProvider(messageReactionRemoveEventHandler(nil))
|
registerInterfaceProvider(messageReactionRemoveEventHandler(nil))
|
||||||
registerInterfaceProvider(messageReactionRemoveAllEventHandler(nil))
|
registerInterfaceProvider(messageReactionRemoveAllEventHandler(nil))
|
||||||
|
|
18
events.go
18
events.go
|
@ -407,3 +407,21 @@ type GuildAuditLogEntryCreate struct {
|
||||||
*AuditLogEntry
|
*AuditLogEntry
|
||||||
GuildID string `json:"guild_id"`
|
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"`
|
||||||
|
}
|
||||||
|
|
|
@ -575,6 +575,7 @@ type InteractionResponseData struct {
|
||||||
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
|
AllowedMentions *MessageAllowedMentions `json:"allowed_mentions,omitempty"`
|
||||||
Files []*File `json:"-"`
|
Files []*File `json:"-"`
|
||||||
Attachments *[]*MessageAttachment `json:"attachments,omitempty"`
|
Attachments *[]*MessageAttachment `json:"attachments,omitempty"`
|
||||||
|
Poll *Poll `json:"poll,omitempty"`
|
||||||
|
|
||||||
// NOTE: only MessageFlagsSuppressEmbeds and MessageFlagsEphemeral can be set.
|
// NOTE: only MessageFlagsSuppressEmbeds and MessageFlagsEphemeral can be set.
|
||||||
Flags MessageFlags `json:"flags,omitempty"`
|
Flags MessageFlags `json:"flags,omitempty"`
|
||||||
|
|
|
@ -242,6 +242,7 @@ type MessageSend struct {
|
||||||
Reference *MessageReference `json:"message_reference,omitempty"`
|
Reference *MessageReference `json:"message_reference,omitempty"`
|
||||||
StickerIDs []string `json:"sticker_ids"`
|
StickerIDs []string `json:"sticker_ids"`
|
||||||
Flags MessageFlags `json:"flags,omitempty"`
|
Flags MessageFlags `json:"flags,omitempty"`
|
||||||
|
Poll *Poll `json:"poll,omitempty"`
|
||||||
|
|
||||||
// TODO: Remove this when compatibility is not required.
|
// TODO: Remove this when compatibility is not required.
|
||||||
File *File `json:"-"`
|
File *File `json:"-"`
|
||||||
|
|
46
restapi.go
46
restapi.go
|
@ -3453,3 +3453,49 @@ func (s *Session) UserApplicationRoleConnectionUpdate(appID string, rconn *Appli
|
||||||
err = unmarshal(body, &st)
|
err = unmarshal(body, &st)
|
||||||
return
|
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
structs.go
51
structs.go
|
@ -2334,6 +2334,57 @@ const (
|
||||||
StageInstancePrivacyLevelGuildOnly StageInstancePrivacyLevel = 2
|
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
|
// Constants for the different bit offsets of text channel permissions
|
||||||
const (
|
const (
|
||||||
// Deprecated: PermissionReadMessages has been replaced with PermissionViewChannel for text and voice channels
|
// Deprecated: PermissionReadMessages has been replaced with PermissionViewChannel for text and voice channels
|
||||||
|
|
Loading…
Reference in a new issue