Skip to content

Commit 885e10b

Browse files
committed
feat: polls
1 parent ee63c3d commit 885e10b

File tree

15 files changed

+496
-38
lines changed

15 files changed

+496
-38
lines changed

lib/discordrb.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ module Discordrb
3232
server_message_typing: 1 << 11,
3333
direct_messages: 1 << 12,
3434
direct_message_reactions: 1 << 13,
35-
direct_message_typing: 1 << 14
35+
direct_message_typing: 1 << 14,
36+
server_message_polls: 1 << 24,
37+
direct_message_polls: 1 << 25
3638
}.freeze
3739

3840
# All available intents

lib/discordrb/api/channel.rb

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ def message(token, channel_id, message_id)
7575
# https://discord.com/developers/docs/resources/channel#create-message
7676
# @param attachments [Array<File>, nil] Attachments to use with `attachment://` in embeds. See
7777
# https://discord.com/developers/docs/resources/channel#create-message-using-attachments-within-embeds
78-
def create_message(token, channel_id, message, tts = false, embeds = nil, nonce = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil, flags = nil, enforce_nonce = false)
79-
body = { content: message, tts: tts, embeds: embeds, nonce: nonce, allowed_mentions: allowed_mentions, message_reference: message_reference, components: components&.to_a, flags: flags, enforce_nonce: enforce_nonce }
78+
def create_message(token, channel_id, message, tts = false, embeds = nil, nonce = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil, flags = nil, enforce_nonce = false, poll = nil)
79+
body = { content: message, tts: tts, embeds: embeds, nonce: nonce, allowed_mentions: allowed_mentions, message_reference: message_reference, components: components&.to_a, flags: flags, enforce_nonce: enforce_nonce, poll: poll }
8080
body = if attachments
8181
files = [*0...attachments.size].zip(attachments).to_h
8282
{ **files, payload_json: body.to_json }
@@ -634,4 +634,31 @@ def start_thread_in_forum_or_media_channel(token, channel_id, name, message, att
634634
headers
635635
)
636636
end
637+
638+
# Get a list of users that have voted for a poll answer.
639+
# https://discord.com/developers/docs/resources/poll#get-answer-voters
640+
def get_poll_answer_voters(token, channel_id, message_id, answer_id, limit = 100, after = nil, before = nil)
641+
query = URI.encode_www_form({ limit: limit, after: after, before: before }.compact)
642+
643+
Discordrb::API.request(
644+
:channels_cid_polls_mid_answers_aid,
645+
channel_id,
646+
:get,
647+
"#{Discordrb::API.api_base}/channels/#{channel_id}/polls/#{message_id}/answers/#{answer_id}?#{query}",
648+
Authorization: token
649+
)
650+
end
651+
652+
# End a poll created by the current user.
653+
# https://discord.com/developers/docs/resources/poll#end-poll
654+
def end_poll(token, channel_id, message_id)
655+
Discordrb::API.request(
656+
:channels_cid_polls_mid_expire,
657+
channel_id,
658+
:post,
659+
"#{Discordrb::API.api_base}/channels/#{channel_id}/polls/#{message_id}/expire",
660+
nil,
661+
Authorization: token
662+
)
663+
end
637664
end

lib/discordrb/api/interaction.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ module Discordrb::API::Interaction
66

77
# Respond to an interaction.
88
# https://discord.com/developers/docs/interactions/slash-commands#create-interaction-response
9-
def create_interaction_response(interaction_token, interaction_id, type, content = nil, tts = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil, attachments = nil, choices = nil)
10-
body = { tts: tts, content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, components: components, choices: choices }.compact
9+
def create_interaction_response(interaction_token, interaction_id, type, content = nil, tts = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil, attachments = nil, choices = nil, poll = nil)
10+
body = { tts: tts, content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, components: components, choices: choices, poll: poll }.compact
1111

1212
body = if attachments
1313
files = [*0...attachments.size].zip(attachments).to_h
@@ -51,8 +51,8 @@ def get_original_interaction_response(interaction_token, application_id)
5151

5252
# Edit the original response to an interaction.
5353
# https://discord.com/developers/docs/interactions/slash-commands#edit-original-interaction-response
54-
def edit_original_interaction_response(interaction_token, application_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil, attachments = nil)
55-
Discordrb::API::Webhook.token_edit_message(interaction_token, application_id, '@original', content, embeds, allowed_mentions, components, attachments)
54+
def edit_original_interaction_response(interaction_token, application_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil, attachments = nil, poll = nil)
55+
Discordrb::API::Webhook.token_edit_message(interaction_token, application_id, '@original', content, embeds, allowed_mentions, components, attachments, poll)
5656
end
5757

5858
# Delete the original response to an interaction.

lib/discordrb/api/webhook.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ def token_webhook(webhook_token, webhook_id)
2929

3030
# Execute a webhook via token.
3131
# https://discord.com/developers/docs/resources/webhook#execute-webhook
32-
def token_execute_webhook(webhook_token, webhook_id, wait = false, content = nil, username = nil, avatar_url = nil, tts = nil, file = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil, attachments = nil)
33-
body = { content: content, username: username, avatar_url: avatar_url, tts: tts, embeds: embeds&.map(&:to_hash), allowed_mentions: allowed_mentions, flags: flags, components: components }
32+
def token_execute_webhook(webhook_token, webhook_id, wait = false, content = nil, username = nil, avatar_url = nil, tts = nil, file = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil, attachments = nil, poll = nil)
33+
body = { content: content, username: username, avatar_url: avatar_url, tts: tts, embeds: embeds&.map(&:to_hash), allowed_mentions: allowed_mentions, flags: flags, components: components, poll: poll }
3434

3535
body = if file
3636
{ file: file, payload_json: body.to_json }
@@ -120,8 +120,8 @@ def token_get_message(webhook_token, webhook_id, message_id)
120120

121121
# Edit a webhook message via webhook token
122122
# https://discord.com/developers/docs/resources/webhook#edit-webhook-message
123-
def token_edit_message(webhook_token, webhook_id, message_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil, attachments = nil)
124-
body = { content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components }
123+
def token_edit_message(webhook_token, webhook_id, message_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil, attachments = nil, poll = nil)
124+
body = { content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, poll: poll }
125125

126126
body = if attachments
127127
files = [*0...attachments.size].zip(attachments).to_h

lib/discordrb/bot.rb

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
require 'discordrb/events/invites'
2121
require 'discordrb/events/interactions'
2222
require 'discordrb/events/threads'
23+
require 'discordrb/events/polls'
2324

2425
require 'discordrb/api'
2526
require 'discordrb/api/channel'
@@ -404,16 +405,17 @@ def delete_invite(code)
404405
# @param components [View, Array<Hash>] Interaction components to associate with this message.
405406
# @param flags [Integer] Flags for this message. Currently only SUPPRESS_EMBEDS (1 << 2), SUPPRESS_NOTIFICATIONS (1 << 12), and IS_COMPONENTS_V2 (1 << 15) can be set.
406407
# @param nonce [String, nil] A optional nonce in order to verify that a message was sent. Maximum of twenty-five characters.
407-
# @param enforce_nonce [true, false] whether the nonce should be enforced and used for message de-duplication.
408+
# @param enforce_nonce [true, false] Whether the nonce should be enforced and used for message de-duplication.
409+
# @param poll [Hash, Poll::Builder, Poll, nil] The poll that should be attached to this message.
408410
# @return [Message] The message that was sent.
409-
def send_message(channel, content, tts = false, embeds = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil, flags = 0, nonce = nil, enforce_nonce = false)
411+
def send_message(channel, content, tts = false, embeds = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil, flags = 0, nonce = nil, enforce_nonce = false, poll = nil)
410412
channel = channel.resolve_id
411413
debug("Sending message to #{channel} with content '#{content}'")
412414
allowed_mentions = { parse: [] } if allowed_mentions == false
413415
message_reference = { message_id: message_reference.resolve_id } if message_reference.respond_to?(:resolve_id)
414416
embeds = (embeds.instance_of?(Array) ? embeds.map(&:to_hash) : [embeds&.to_hash]).compact
415417

416-
response = API::Channel.create_message(token, channel, content, tts, embeds, nonce, attachments, allowed_mentions&.to_hash, message_reference, components, flags, enforce_nonce)
418+
response = API::Channel.create_message(token, channel, content, tts, embeds, nonce, attachments, allowed_mentions&.to_hash, message_reference, components, flags, enforce_nonce, poll&.to_h)
417419
Message.new(JSON.parse(response), self)
418420
end
419421

@@ -430,12 +432,13 @@ def send_message(channel, content, tts = false, embeds = nil, attachments = nil,
430432
# @param components [View, Array<Hash>] Interaction components to associate with this message.
431433
# @param flags [Integer] Flags for this message. Currently only SUPPRESS_EMBEDS (1 << 2), SUPPRESS_NOTIFICATIONS (1 << 12), and IS_COMPONENTS_V2 (1 << 15) can be set.
432434
# @param nonce [String, nil] A optional nonce in order to verify that a message was sent. Maximum of twenty-five characters.
433-
# @param enforce_nonce [true, false] whether the nonce should be enforced and used for message de-duplication.
434-
def send_temporary_message(channel, content, timeout, tts = false, embeds = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil, flags = 0, nonce = nil, enforce_nonce = false)
435+
# @param enforce_nonce [true, false] Whether the nonce should be enforced and used for message de-duplication.
436+
# @param poll [Hash, Poll::Builder, Poll, nil] The poll that should be attached to this message.
437+
def send_temporary_message(channel, content, timeout, tts = false, embeds = nil, attachments = nil, allowed_mentions = nil, message_reference = nil, components = nil, flags = 0, nonce = nil, enforce_nonce = false, poll = nil)
435438
Thread.new do
436439
Thread.current[:discordrb_name] = "#{@current_thread}-temp-msg"
437440

438-
message = send_message(channel, content, tts, embeds, attachments, allowed_mentions, message_reference, components, flags, nonce, enforce_nonce)
441+
message = send_message(channel, content, tts, embeds, attachments, allowed_mentions, message_reference, components, flags, nonce, enforce_nonce, poll)
439442
sleep(timeout)
440443
message.delete
441444
end
@@ -1712,6 +1715,14 @@ def handle_dispatch(type, data)
17121715
end
17131716

17141717
event = ThreadMembersUpdateEvent.new(data, self)
1718+
raise_event(event)
1719+
when :MESSAGE_POLL_VOTE_ADD
1720+
event = PollVoteAddEvent.new(data, self)
1721+
1722+
raise_event(event)
1723+
when :MESSAGE_POLL_VOTE_REMOVE
1724+
event = PollVoteRemoveEvent.new(data, self)
1725+
17151726
raise_event(event)
17161727
else
17171728
# another event that we don't support yet

lib/discordrb/container.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,34 @@ def application_command_permissions_update(attributes = {}, &block)
681681
register_event(ApplicationCommandPermissionsUpdateEvent, attributes, block)
682682
end
683683

684+
# This **event** is raised whenever a user votes on a poll.
685+
# @param attributes [Hash] The event's attributes.
686+
# @option attributes [String, Integer, User, Member] :user A user to match against.
687+
# @option attributes [String, Integer, Channel] :channel A channel to match against.
688+
# @option attributes [String, Integer, Server] :server A server to match against.
689+
# @option attributes [String, Integer, Message] :message A message to match against.
690+
# @option attributes [String, Integer, Answer] :answer A poll answer to match against.
691+
# @yield The block is executed when the event is raised.
692+
# @yieldparam event [PollVoteAddEvent] The event that was raised.
693+
# @return [PollVoteAddEventHandler] The event handler that was registered.
694+
def poll_vote_add(attributes = {}, &block)
695+
register_event(PollVoteAddEvent, attributes, block)
696+
end
697+
698+
# This **event** is raised whenever a user removes their vote on a poll.
699+
# @param attributes [Hash] The event's attributes.
700+
# @option attributes [String, Integer, User, Member] :user A user to match against.
701+
# @option attributes [String, Integer, Channel] :channel A channel to match against.
702+
# @option attributes [String, Integer, Server] :server A server to match against.
703+
# @option attributes [String, Integer, Message] :message A message to match against.
704+
# @option attributes [String, Integer, Answer] :answer A poll answer to match against.
705+
# @yield The block is executed when the event is raised.
706+
# @yieldparam event [PollVoteRemoveEvent] The event that was raised.
707+
# @return [PollVoteRemoveEventHandler] The event handler that was registered.
708+
def poll_vote_remove(attributes = {}, &block)
709+
register_event(PollVoteRemoveEvent, attributes, block)
710+
end
711+
684712
# This **event** is raised for every dispatch received over the gateway, whether supported by discordrb or not.
685713
# @param attributes [Hash] The event's attributes.
686714
# @option attributes [String, Symbol, Regexp] :type Matches the event type of the dispatch.

lib/discordrb/data.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,4 @@
4646
require 'discordrb/data/server_preview'
4747
require 'discordrb/data/call'
4848
require 'discordrb/data/snapshot'
49+
require 'discordrb/data/poll'

lib/discordrb/data/channel.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -496,14 +496,16 @@ def send_embed(message = '', embed = nil, attachments = nil, tts = false, allowe
496496
# @param has_components [true, false] Whether this message includes any V2 components. Enabling this disables sending content and embeds.
497497
# @param nonce [nil, String, Integer, false] The 25 character nonce that should be used when sending this message.
498498
# @param enforce_nonce [true, false] Whether the provided nonce should be enforced and used for message de-duplication.
499+
# @param poll [Hash, Poll::Builder, Poll, nil] The poll that should be attached to this message.
499500
# @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the builder overwrite method data.
500501
# @yieldparam view [Webhooks::View] An optional component builder. Arguments passed to the builder overwrite method data.
501502
# @return [Message, nil] The resulting message that was created, or `nil` if the `timeout` parameter was set to a non `nil` value.
502-
def send_message!(content: '', timeout: nil, tts: false, embeds: [], attachments: nil, allowed_mentions: nil, reference: nil, components: nil, flags: 0, has_components: false, nonce: nil, enforce_nonce: false)
503+
def send_message!(content: '', timeout: nil, tts: false, embeds: [], attachments: nil, allowed_mentions: nil, reference: nil, components: nil, flags: 0, has_components: false, nonce: nil, enforce_nonce: false, poll: nil)
503504
builder = Discordrb::Webhooks::Builder.new
504505
view = Discordrb::Webhooks::View.new
505506

506507
builder.tts = tts
508+
builder.poll = poll
507509
builder.content = content
508510
embeds&.each { |embed| builder << embed }
509511
builder.allowed_mentions = allowed_mentions
@@ -515,9 +517,9 @@ def send_message!(content: '', timeout: nil, tts: false, embeds: [], attachments
515517
builder = builder.to_json_hash
516518

517519
if timeout
518-
@bot.send_temporary_message(@id, builder[:content], timeout, builder[:tts], builder[:embeds], attachments, builder[:allowed_mentions], reference, components&.to_a || view.to_a, flags, nonce, enforce_nonce)
520+
@bot.send_temporary_message(@id, builder[:content], timeout, builder[:tts], builder[:embeds], attachments, builder[:allowed_mentions], reference, components&.to_a || view.to_a, flags, nonce, enforce_nonce, builder[:poll])
519521
else
520-
@bot.send_message(@id, builder[:content], builder[:tts], builder[:embeds], attachments, builder[:allowed_mentions], reference, components&.to_a || view.to_a, flags, nonce, enforce_nonce)
522+
@bot.send_message(@id, builder[:content], builder[:tts], builder[:embeds], attachments, builder[:allowed_mentions], reference, components&.to_a || view.to_a, flags, nonce, enforce_nonce, builder[:poll])
521523
end
522524
end
523525

lib/discordrb/data/emoji.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ def inspect
8787
"<Emoji name=#{name} id=#{id} animated=#{animated}>"
8888
end
8989

90+
# Converts this Emoji into a hash that can be sent back to Discord in other endpoints.
91+
# @return [Hash] A hash representation of this emoji.
92+
def to_h
93+
id.nil? ? { name: name } : { id: id }
94+
end
95+
9096
# @!visibility private
9197
def process_roles(roles)
9298
@roles = []

0 commit comments

Comments
 (0)