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
|
||||
}
|
||||
|
||||
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"
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@ const (
|
|||
messageCreateEventType = "MESSAGE_CREATE"
|
||||
messageDeleteEventType = "MESSAGE_DELETE"
|
||||
messageDeleteBulkEventType = "MESSAGE_DELETE_BULK"
|
||||
messagePollVoteAddEventType = "MESSAGE_POLL_VOTE_ADD"
|
||||
messagePollVoteRemoveEventType = "MESSAGE_POLL_VOTE_REMOVE"
|
||||
messageReactionAddEventType = "MESSAGE_REACTION_ADD"
|
||||
messageReactionRemoveEventType = "MESSAGE_REACTION_REMOVE"
|
||||
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.
|
||||
type messageReactionAddEventHandler func(*Session, *MessageReactionAdd)
|
||||
|
||||
|
@ -1350,6 +1392,10 @@ func handlerForInterface(handler interface{}) EventHandler {
|
|||
return messageDeleteEventHandler(v)
|
||||
case func(*Session, *MessageDeleteBulk):
|
||||
return messageDeleteBulkEventHandler(v)
|
||||
case func(*Session, *MessagePollVoteAdd):
|
||||
return messagePollVoteAddEventHandler(v)
|
||||
case func(*Session, *MessagePollVoteRemove):
|
||||
return messagePollVoteRemoveEventHandler(v)
|
||||
case func(*Session, *MessageReactionAdd):
|
||||
return messageReactionAddEventHandler(v)
|
||||
case func(*Session, *MessageReactionRemove):
|
||||
|
@ -1437,6 +1483,8 @@ func init() {
|
|||
registerInterfaceProvider(messageCreateEventHandler(nil))
|
||||
registerInterfaceProvider(messageDeleteEventHandler(nil))
|
||||
registerInterfaceProvider(messageDeleteBulkEventHandler(nil))
|
||||
registerInterfaceProvider(messagePollVoteAddEventHandler(nil))
|
||||
registerInterfaceProvider(messagePollVoteRemoveEventHandler(nil))
|
||||
registerInterfaceProvider(messageReactionAddEventHandler(nil))
|
||||
registerInterfaceProvider(messageReactionRemoveEventHandler(nil))
|
||||
registerInterfaceProvider(messageReactionRemoveAllEventHandler(nil))
|
||||
|
|
18
events.go
18
events.go
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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:"-"`
|
||||
|
|
46
restapi.go
46
restapi.go
|
@ -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
structs.go
51
structs.go
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue