Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add polls #346

Merged
merged 18 commits into from Apr 22, 2024
1 change: 1 addition & 0 deletions discord/message.go
Expand Up @@ -114,6 +114,7 @@ type Message struct {
Position *int `json:"position,omitempty"`
RoleSubscriptionData *RoleSubscriptionData `json:"role_subscription_data,omitempty"`
Resolved *ResolvedData `json:"resolved,omitempty"`
Poll *Poll `json:"poll,omitempty"`
}

func (m *Message) UnmarshalJSON(data []byte) error {
Expand Down
1 change: 1 addition & 0 deletions discord/message_create.go
Expand Up @@ -18,6 +18,7 @@ type MessageCreate struct {
MessageReference *MessageReference `json:"message_reference,omitempty"`
Flags MessageFlags `json:"flags,omitempty"`
EnforceNonce bool `json:"enforce_nonce,omitempty"`
Poll Poll `json:"poll,omitempty"`
}

func (MessageCreate) interactionCallbackData() {}
Expand Down
6 changes: 6 additions & 0 deletions discord/message_create_builder.go
Expand Up @@ -251,6 +251,12 @@ func (b *MessageCreateBuilder) SetSuppressEmbeds(suppressEmbeds bool) *MessageCr
return b
}

// SetPoll sets the Poll of the Message
func (b *MessageCreateBuilder) SetPoll(poll Poll) *MessageCreateBuilder {
b.Poll = poll
return b
}

// Build builds the MessageCreateBuilder to a MessageCreate struct
func (b *MessageCreateBuilder) Build() MessageCreate {
return b.MessageCreate
Expand Down
43 changes: 43 additions & 0 deletions discord/poll.go
@@ -0,0 +1,43 @@
package discord

import (
"time"

"github.com/disgoorg/snowflake/v2"
)

type Poll struct {
Question PollMedia `json:"question"`
Answers []PollAnswer `json:"answers"`
Expiry time.Time `json:"expiry"`
AllowMultiselect bool `json:"allow_multiselect"`
LayoutType PollLayoutType `json:"layout_type"`
Results []PollResults `json:"results"`
sebm253 marked this conversation as resolved.
Show resolved Hide resolved
}

type PollMedia struct {
Text *string `json:"text"`
Emoji *PartialEmoji `json:"emoji"`
}

type PollAnswer struct {
AnswerID *snowflake.ID `json:"answer_id"`
PollMedia PollMedia `json:"poll_media"`
}

type PollResults struct {
IsFinalized bool `json:"is_finalized"`
AnswerCounts []PollAnswerCount `json:"answer_counts"`
}

type PollAnswerCount struct {
ID snowflake.ID `json:"id"`
Count int `json:"count"`
MeVoted bool `json:"me_voted"`
}

type PollLayoutType int

const (
PollLayoutTypeDefault PollLayoutType = iota + 1
)
1 change: 1 addition & 0 deletions discord/webhook_message_create.go
Expand Up @@ -15,6 +15,7 @@ type WebhookMessageCreate struct {
Flags MessageFlags `json:"flags,omitempty"`
ThreadName string `json:"thread_name,omitempty"`
AppliedTags []snowflake.ID `json:"applied_tags,omitempty"`
Poll Poll `json:"poll,omitempty"`
}

// ToBody returns the MessageCreate ready for body
Expand Down
6 changes: 6 additions & 0 deletions discord/webhook_message_create_builder.go
Expand Up @@ -210,6 +210,12 @@ func (b *WebhookMessageCreateBuilder) SetThreadName(threadName string) *WebhookM
return b
}

// SetPoll sets the Poll of the webhook Message
func (b *WebhookMessageCreateBuilder) SetPoll(poll Poll) *WebhookMessageCreateBuilder {
b.Poll = poll
return b
}

// Build builds the WebhookMessageCreateBuilder to a MessageCreate struct
func (b *WebhookMessageCreateBuilder) Build() WebhookMessageCreate {
b.WebhookMessageCreate.Components = b.Components
Expand Down
14 changes: 14 additions & 0 deletions events/listener_adapter.go
Expand Up @@ -147,6 +147,10 @@ type ListenerAdapter struct {
OnMessageUpdate func(event *MessageUpdate)
OnMessageDelete func(event *MessageDelete)

// Message Poll Events
sebm253 marked this conversation as resolved.
Show resolved Hide resolved
OnMessagePollVoteAdd func(event *MessagePollVoteAdd)
OnMessagePollVoteRemove func(event *MessagePollVoteRemove)

// Message Reaction Events
OnMessageReactionAdd func(event *MessageReactionAdd)
OnMessageReactionRemove func(event *MessageReactionRemove)
Expand Down Expand Up @@ -574,6 +578,16 @@ func (l *ListenerAdapter) OnEvent(event bot.Event) {
listener(e)
}

// Message Poll Events
case *MessagePollVoteAdd:
if listener := l.OnMessagePollVoteAdd; listener != nil {
listener(e)
}
case *MessagePollVoteRemove:
if listener := l.OnMessagePollVoteRemove; listener != nil {
listener(e)
}

// Message Reaction Events
case *MessageReactionAdd:
if listener := l.OnMessageReactionAdd; listener != nil {
Expand Down
20 changes: 20 additions & 0 deletions events/message_events.go
Expand Up @@ -43,3 +43,23 @@ type MessageUpdate struct {
type MessageDelete struct {
*GenericMessage
}

// GenericMessagePoll is a generic poll event
type GenericMessagePoll struct {
*GenericEvent
UserID snowflake.ID
ChannelID snowflake.ID
MessageID snowflake.ID
GuildID *snowflake.ID
AnswerID snowflake.ID
}

// MessagePollVoteAdd indicates that a discord.User voted on a discord.Poll
type MessagePollVoteAdd struct {
*GenericMessagePoll
}

// MessagePollVoteRemove indicates that a discord.User removed their vote on a discord.Poll
type MessagePollVoteRemove struct {
*GenericMessagePoll
}
2 changes: 2 additions & 0 deletions gateway/gateway_event_type.go
Expand Up @@ -59,6 +59,8 @@ const (
EventTypeMessageUpdate EventType = "MESSAGE_UPDATE"
EventTypeMessageDelete EventType = "MESSAGE_DELETE"
EventTypeMessageDeleteBulk EventType = "MESSAGE_DELETE_BULK"
EventTypeMessagePollVoteAdd EventType = "MESSAGE_POLL_VOTE_ADD"
EventTypeMessagePollVoteRemove EventType = "MESSAGE_POLL_VOTE_REMOVE"
EventTypeMessageReactionAdd EventType = "MESSAGE_REACTION_ADD"
EventTypeMessageReactionRemove EventType = "MESSAGE_REACTION_REMOVE"
EventTypeMessageReactionRemoveAll EventType = "MESSAGE_REACTION_REMOVE_ALL"
Expand Down
22 changes: 22 additions & 0 deletions gateway/gateway_events.go
Expand Up @@ -507,6 +507,28 @@ type EventMessageDeleteBulk struct {
func (EventMessageDeleteBulk) messageData() {}
func (EventMessageDeleteBulk) eventData() {}

type EventMessagePollVoteAdd struct {
UserID snowflake.ID `json:"user_id"`
ChannelID snowflake.ID `json:"channel_id"`
MessageID snowflake.ID `json:"message_id"`
GuildID *snowflake.ID `json:"guild_id"`
AnswerID snowflake.ID `json:"answer_id"`
}

func (EventMessagePollVoteAdd) messageData() {}
func (EventMessagePollVoteAdd) eventData() {}

type EventMessagePollVoteRemove struct {
UserID snowflake.ID `json:"user_id"`
ChannelID snowflake.ID `json:"channel_id"`
MessageID snowflake.ID `json:"message_id"`
GuildID *snowflake.ID `json:"guild_id"`
AnswerID snowflake.ID `json:"answer_id"`
}

func (EventMessagePollVoteRemove) messageData() {}
func (EventMessagePollVoteRemove) eventData() {}

type EventPresenceUpdate struct {
discord.Presence
}
Expand Down
3 changes: 3 additions & 0 deletions handlers/all_handlers.go
Expand Up @@ -101,6 +101,9 @@ var allEventHandlers = []bot.GatewayEventHandler{
bot.NewGatewayEventHandler(gateway.EventTypeMessageDelete, gatewayHandlerMessageDelete),
bot.NewGatewayEventHandler(gateway.EventTypeMessageDeleteBulk, gatewayHandlerMessageDeleteBulk),

bot.NewGatewayEventHandler(gateway.EventTypeMessagePollVoteAdd, gatewayHandlerMessagePollVoteAdd),
bot.NewGatewayEventHandler(gateway.EventTypeMessagePollVoteRemove, gatewayHandlerMessagePollVoteRemove),

bot.NewGatewayEventHandler(gateway.EventTypeMessageReactionAdd, gatewayHandlerMessageReactionAdd),
bot.NewGatewayEventHandler(gateway.EventTypeMessageReactionRemove, gatewayHandlerMessageReactionRemove),
bot.NewGatewayEventHandler(gateway.EventTypeMessageReactionRemoveAll, gatewayHandlerMessageReactionRemoveAll),
Expand Down
33 changes: 33 additions & 0 deletions handlers/message_poll_handler.go
@@ -0,0 +1,33 @@
package handlers

import (
"github.com/disgoorg/disgo/bot"
"github.com/disgoorg/disgo/events"
"github.com/disgoorg/disgo/gateway"
)

func gatewayHandlerMessagePollVoteAdd(client bot.Client, sequenceNumber int, shardID int, event gateway.EventMessagePollVoteAdd) {
client.EventManager().DispatchEvent(&events.MessagePollVoteAdd{
GenericMessagePoll: &events.GenericMessagePoll{
GenericEvent: events.NewGenericEvent(client, sequenceNumber, shardID),
UserID: event.UserID,
ChannelID: event.ChannelID,
MessageID: event.MessageID,
GuildID: event.GuildID,
AnswerID: event.AnswerID,
},
})
}

func gatewayHandlerMessagePollVoteRemove(client bot.Client, sequenceNumber int, shardID int, event gateway.EventMessagePollVoteRemove) {
client.EventManager().DispatchEvent(&events.MessagePollVoteRemove{
GenericMessagePoll: &events.GenericMessagePoll{
GenericEvent: events.NewGenericEvent(client, sequenceNumber, shardID),
UserID: event.UserID,
ChannelID: event.ChannelID,
MessageID: event.MessageID,
GuildID: event.GuildID,
AnswerID: event.AnswerID,
},
})
}
20 changes: 20 additions & 0 deletions rest/channels.go
Expand Up @@ -47,6 +47,9 @@ type Channels interface {
PinMessage(channelID snowflake.ID, messageID snowflake.ID, opts ...RequestOpt) error
UnpinMessage(channelID snowflake.ID, messageID snowflake.ID, opts ...RequestOpt) error
Follow(channelID snowflake.ID, targetChannelID snowflake.ID, opts ...RequestOpt) (*discord.FollowedChannel, error)

GetPollAnswerVotes(channelID snowflake.ID, messageID snowflake.ID, answerID snowflake.ID, after snowflake.ID, limit int, opts ...RequestOpt) ([]discord.User, error)
ExpirePoll(channelID snowflake.ID, messageID snowflake.ID, opts ...RequestOpt) (*discord.Message, error)
}

type channelImpl struct {
Expand Down Expand Up @@ -222,3 +225,20 @@ func (s *channelImpl) Follow(channelID snowflake.ID, targetChannelID snowflake.I
err = s.client.Do(FollowChannel.Compile(nil, channelID), discord.FollowChannel{ChannelID: targetChannelID}, &followedChannel, opts...)
return
}

func (s *channelImpl) GetPollAnswerVotes(channelID snowflake.ID, messageID snowflake.ID, answerID snowflake.ID, after snowflake.ID, limit int, opts ...RequestOpt) (users []discord.User, err error) {
values := discord.QueryValues{}
if after != 0 {
values["after"] = after
}
if limit != 0 {
values["limit"] = limit
}
err = s.client.Do(GetPollAnswerVotes.Compile(values, channelID, messageID, answerID), nil, &users, opts...)
return
}

func (s *channelImpl) ExpirePoll(channelID snowflake.ID, messageID snowflake.ID, opts ...RequestOpt) (message *discord.Message, err error) {
err = s.client.Do(ExpirePoll.Compile(nil, channelID, messageID), nil, &message, opts...)
return
}
3 changes: 3 additions & 0 deletions rest/rest_endpoints.go
Expand Up @@ -170,6 +170,9 @@ var (

SendTyping = NewEndpoint(http.MethodPost, "/channels/{channel.id}/typing")
FollowChannel = NewEndpoint(http.MethodPost, "/channels/{channel.id}/followers")

GetPollAnswerVotes = NewEndpoint(http.MethodGet, "/channels/{channel.id}/polls/{message.id}/answers/{answer.id}")
ExpirePoll = NewEndpoint(http.MethodPost, "/channels/{channel.id}/poll/{message.id}/expire")
)

// Threads
Expand Down