diff --git a/docs/interactions/Receiving_and_Responding.md b/docs/interactions/Receiving_and_Responding.md index ad6004c308..390f1874c1 100644 --- a/docs/interactions/Receiving_and_Responding.md +++ b/docs/interactions/Receiving_and_Responding.md @@ -241,6 +241,7 @@ Not all message fields are currently supported. | flags? | integer | [message flags](#DOCS_RESOURCES_CHANNEL/message-object-message-flags) combined as a [bitfield](https://en.wikipedia.org/wiki/Bit_field) (only `SUPPRESS_EMBEDS`, `EPHEMERAL`, and `SUPPRESS_NOTIFICATIONS` can be set) | | components? | array of [components](#DOCS_INTERACTIONS_MESSAGE_COMPONENTS/) | message components | | attachments? \* | array of partial [attachment](#DOCS_RESOURCES_CHANNEL/attachment-object) objects | attachment objects with filename and description | +| poll? | [poll](#DOCS_RESOURCES_POLL/poll-object) object | A poll! | \* See [Uploading Files](#DOCS_REFERENCE/uploading-files) for details. diff --git a/docs/resources/Channel.md b/docs/resources/Channel.md index 24f92ad6d7..9654be164a 100644 --- a/docs/resources/Channel.md +++ b/docs/resources/Channel.md @@ -264,7 +264,7 @@ Represents a message sent in a channel within Discord. > Fields specific to the `MESSAGE_CREATE` and `MESSAGE_UPDATE` events are listed in the [Gateway documentation](#DOCS_TOPICS_GATEWAY_EVENTS/message-create). > warn -> `content`, `embeds`, `attachments`, and `components` require the [`MESSAGE_CONTENT` intent](#DOCS_TOPICS_GATEWAY/message-content-intent) to receive non-empty values. +> `content`, `embeds`, `attachments`, `components`, and `poll` require the [`MESSAGE_CONTENT` intent](#DOCS_TOPICS_GATEWAY/message-content-intent) to receive non-empty values. | Field | Type | Description | |-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -301,6 +301,7 @@ Represents a message sent in a channel within Discord. | position? | integer | A generally increasing integer (there may be gaps or duplicates) that represents the approximate position of the message in a thread, it can be used to estimate the relative position of the message in a thread in company with `total_message_sent` on parent thread | | role_subscription_data? | [role subscription data](#DOCS_RESOURCES_CHANNEL/role-subscription-data-object) object | data of the role subscription purchase or renewal that prompted this ROLE_SUBSCRIPTION_PURCHASE message | | resolved? | [resolved](#DOCS_INTERACTIONS_RECEIVING_AND_RESPONDING/interaction-object-resolved-data-structure) data | data for users, members, channels, and roles in the message's [auto-populated select menus](#DOCS_INTERACTIONS_MESSAGE_COMPONENTS/select-menus) | +| poll? | [poll](#DOCS_RESOURCES_POLL/poll-object) object | A poll! | \* The author object follows the structure of the user object, but is only a valid user in the case where the message is generated by a user or bot user. If the message is generated by a webhook, the author object corresponds to the webhook's id, username, and avatar. You can tell if a message is generated by a webhook by checking for the `webhook_id` on the message object. @@ -1068,7 +1069,7 @@ Files must be attached using a `multipart/form-data` body as described in [Uploa ###### JSON/Form Params > info -> When creating a message, apps must provide a value for **at least one of** `content`, `embeds`, `sticker_ids`, `components`, or `files[n]`. +> When creating a message, apps must provide a value for **at least one of** `content`, `embeds`, `sticker_ids`, `components`, `files[n]`, or `poll`. | Field | Type | Description | |--------------------|---------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -1085,8 +1086,9 @@ Files must be attached using a `multipart/form-data` body as described in [Uploa | attachments? | array of partial [attachment](#DOCS_RESOURCES_CHANNEL/attachment-object) objects | Attachment objects with filename and description. See [Uploading Files](#DOCS_REFERENCE/uploading-files | | flags? | integer | [Message flags](#DOCS_RESOURCES_CHANNEL/message-object-message-flags) combined as a [bitfield](https://en.wikipedia.org/wiki/Bit_field) (only `SUPPRESS_EMBEDS` and `SUPPRESS_NOTIFICATIONS` can be set) | | enforce_nonce? | boolean | If true and nonce is present, it will be checked for uniqueness in the past few minutes. If another message was created by the same author with the same nonce, that message will be returned and no new message will be created. | +| poll? | [poll](#DOCS_RESOURCES_POLL/poll-object) object | A poll! | -\* At least one of `content`, `embeds`, `sticker_ids`, `components`, or `files[n]` is required. +\* At least one of `content`, `embeds`, `sticker_ids`, `components`, `files[n]`, or `poll` is required. ###### Example Request Body (application/json) @@ -1478,6 +1480,7 @@ Returns archived threads in the channel that are of [type](#DOCS_RESOURCES_CHANN |---------|-----------|----------------------------------------------| | before? | snowflake | returns threads before this id | | limit? | integer | optional maximum number of threads to return | +`text` should always be non-null right now for both questions and answers, but please do not depend on that in the future. ###### Response Body diff --git a/docs/resources/Poll.md b/docs/resources/Poll.md new file mode 100644 index 0000000000..05e9e3b411 --- /dev/null +++ b/docs/resources/Poll.md @@ -0,0 +1,122 @@ +# Poll Resource + +A poll is... well... a poll! It holds information about a poll! + +![If you get it you get it](example-poll.png) + +### Poll Object + +The poll object has a lot of levels and nested structures. It was also designed +to support future extensibility, so some fields may appear to be more complex than +necessary. + +The request and response models are closely aligned. So for the sake of brevity +we will have common structure declarations instead of duplicating request and response structures. + +Fields marked by an \* are only sent as part of responses from Discord's API/Gateway. + +###### Poll Object Structure + +| Field | Type | Description | +|-------------------|-----------------------------------------------------------------------------------------------------|-----------------------------------------------------------------| +| question | [Poll Media Object](#DOCS_RESOURCES_POLL/poll-media-object-poll-media-object-structure) | The question of the poll. Only `text` is supported. | +| answers | List of [Poll Answer Objects](#DOCS_RESOURCES_POLL/poll-answer-object-poll-answer-object-structure) | Each of the answers available in the poll. | +| expiry | IS08601 timestamp | The time when the poll ends. | +| allow_multiselect | boolean | Whether a user can select multiple answers | +| layout_type | integer | The [layout type](#DOCS_RESOURCES_POLL/layout-type) of the poll | +| results\* | [Poll Results Object](#DOCS_RESOURCES_POLL/poll-results-object-poll-results-object-structure) | The results of the poll | + +### Layout Type + +We might have different layouts for polls in the future. +For now though, this number will be 1. + +| Type | ID | Description | +|---------|----|--------------------------------| +| DEFAULT | 1 | The, uhm, default layout type. | + +### Poll Media Object + +The poll media object is a common object that backs both the question and answers. +The intention is that it allows us to extensibly add new ways to display things in the future. +For now, `question` only supports `text`, while answers can have an optional `emoji`. + +###### Poll Media Object Structure + +| Field | Type | Description | +|--------|-----------------------------------------------------|------------------------| +| text? | string | The text of the field | +| emoji? | partial [emoji](#DOCS_RESOURCES_EMOJI/emoji-object) | The emoji of the field | + +`text` should always be non-null for both questions and answers, but please do not depend on that in the future. + +When creating a poll answer with an emoji, one only needs to send either the `id` (custom emoji) or `name` (default emoji) as the only field. + +### Poll Answer Object + +The `answer_id` is a number that labels each answer. +As an implementation detail, it currently starts at 1 for the first answer and goes up sequentially. +We recommend against depending on this sequence. + +###### Poll Answer Object Structure + +| Field | Type | Description | +|-------------|-----------------------------------------------------------------------------------------|------------------------| +| answer_id\* | integer | The ID of the answer | +| poll_media | [Poll Media Object](#DOCS_RESOURCES_POLL/poll-media-object-poll-media-object-structure) | The data of the answer | + +### Poll Results Object + +In a nutshell, this contains the number of votes for each answer. + +Due to the intricacies of counting at scale, while a poll is in progress the results may not be perfectly accurate. +They usually are accurate, and shouldn't deviate significantly -- it's just difficult to make guarantees. + +To compensate for this, after a poll is finished there is a background job which performs a final, accurate tally of votes. +This tally has concluded once `is_finalized` is `true`. + +If `answer_counts` does not contain an entry for a particular answer, then there are no votes for that answer. + +###### Poll Results Object Structure + +| Field | Type | Description | +|---------------|-----------------------------------------------------------------------------------------------------------------|-----------------------------------------------| +| is_finalized | boolean | Whether the votes have been precisely counted | +| answer_counts | List of [Poll Answer Count Object](#DOCS_RESOURCES_POLL/poll-results-object-poll-answer-count-object-structure) | The counts for each answer | + +###### Poll Answer Count Object Structure + +| Field | Type | Description | +|----------|---------|------------------------------------------------| +| id | integer | The `answer_id` | +| count | integer | The number of votes for this answer | +| me_voted | boolean | Whether the current user voted for this answer | + +# Poll Endpoints + +For creating a poll, see [Create Message](#DOCS_RESOURCES_CHANNEL/create-message). After creation, the poll message cannot be editted. + +Apps are not allowed to vote on polls. No rights! :) + +## Get Answer Voters % GET /channels/{channel.id#DOCS_RESOURCES_CHANNEL/channel-object}/polls/{message.id#DOCS_RESOURCES_CHANNEL/message-object}/answers/{answer_id#DOCS_RESOURCES_POLL/poll-answer-object} + +Get a list of users that voted for this specific answer. + +###### Query String Params + +| Field | Type | Description | Default | +|--------|-----------|---------------------------------------|---------| +| after? | snowflake | Get users after this user ID | absent | +| limit? | integer | Max number of users to return (1-100) | 25 | + +###### Response Body + +| Field | Type | Description | +|-------|---------------------------------------------------|----------------------------------| +| users | array of [user](#DOCS_RESOURCES_USER/user-object) | Users who created to this answer | + +## Expire Poll % POST /channels/{channel.id#DOCS_RESOURCES_CHANNEL/channel-object}/poll/{message.id#DOCS_RESOURCES_CHANNEL/message-object}/expire + +Immediately expires (i.e. ends) the poll. + +Returns a [message](#DOCS_RESOURCES_CHANNEL/message-object) object. Fires a [Message Update](#DOCS_TOPICS_GATEWAY_EVENTS/message-update) Gateway event. diff --git a/docs/resources/Webhook.md b/docs/resources/Webhook.md index 490db8236a..b373dc3372 100644 --- a/docs/resources/Webhook.md +++ b/docs/resources/Webhook.md @@ -188,21 +188,22 @@ Refer to [Uploading Files](#DOCS_REFERENCE/uploading-files) for details on attac ###### JSON/Form Params -| Field | Type | Description | Required | -|-------------------|--------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------| -| content | string | the message contents (up to 2000 characters) | one of content, file, embeds | -| username | string | override the default username of the webhook | false | -| avatar_url | string | override the default avatar of the webhook | false | -| tts | boolean | true if this is a TTS message | false | -| embeds | array of up to 10 [embed](#DOCS_RESOURCES_CHANNEL/embed-object) objects | embedded `rich` content | one of content, file, embeds | -| allowed_mentions | [allowed mention object](#DOCS_RESOURCES_CHANNEL/allowed-mentions-object) | allowed mentions for the message | false | -| components \* | array of [message component](#DOCS_INTERACTIONS_MESSAGE_COMPONENTS/component-object) | the components to include with the message | false | -| files[n] \*\* | file contents | the contents of the file being sent | one of content, file, embeds | -| payload_json \*\* | string | JSON encoded body of non-file params | `multipart/form-data` only | -| attachments \*\* | array of partial [attachment](#DOCS_RESOURCES_CHANNEL/attachment-object) objects | attachment objects with filename and description | false | -| flags | integer | [message flags](#DOCS_RESOURCES_CHANNEL/message-object-message-flags) combined as a [bitfield](https://en.wikipedia.org/wiki/Bit_field) (only `SUPPRESS_EMBEDS` and `SUPPRESS_NOTIFICATIONS` can be set can be set) | false | -| thread_name | string | name of thread to create (requires the webhook channel to be a forum or media channel) | false | -| applied_tags | array of snowflakes | array of tag ids to apply to the thread (requires the webhook channel to be a forum or media channel) | false | +| Field | Type | Description | Required | +|-------------------|--------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------| +| content | string | the message contents (up to 2000 characters) | one of content, file, embeds, poll | +| username | string | override the default username of the webhook | false | +| avatar_url | string | override the default avatar of the webhook | false | +| tts | boolean | true if this is a TTS message | false | +| embeds | array of up to 10 [embed](#DOCS_RESOURCES_CHANNEL/embed-object) objects | embedded `rich` content | one of content, file, embeds, poll | +| allowed_mentions | [allowed mention object](#DOCS_RESOURCES_CHANNEL/allowed-mentions-object) | allowed mentions for the message | false | +| components \* | array of [message component](#DOCS_INTERACTIONS_MESSAGE_COMPONENTS/component-object) | the components to include with the message | false | +| files[n] \*\* | file contents | the contents of the file being sent | one of content, file, embeds, poll | +| payload_json \*\* | string | JSON encoded body of non-file params | `multipart/form-data` only | +| attachments \*\* | array of partial [attachment](#DOCS_RESOURCES_CHANNEL/attachment-object) objects | attachment objects with filename and description | false | +| flags | integer | [message flags](#DOCS_RESOURCES_CHANNEL/message-object-message-flags) combined as a [bitfield](https://en.wikipedia.org/wiki/Bit_field) (only `SUPPRESS_EMBEDS` and `SUPPRESS_NOTIFICATIONS` can be set can be set) | false | +| thread_name | string | name of thread to create (requires the webhook channel to be a forum or media channel) | false | +| applied_tags | array of snowflakes | array of tag ids to apply to the thread (requires the webhook channel to be a forum or media channel) | false | +| poll | [poll](#DOCS_RESOURCES_POLL/poll-object) object | A poll! | one of content, file, embeds, poll | \* Requires an application-owned webhook. diff --git a/docs/topics/Gateway_Events.md b/docs/topics/Gateway_Events.md index d508d7226c..2c7cfa8020 100644 --- a/docs/topics/Gateway_Events.md +++ b/docs/topics/Gateway_Events.md @@ -339,6 +339,8 @@ Receive events are Gateway events encapsulated in an [event payload](#DOCS_TOPIC | [Voice State Update](#DOCS_TOPICS_GATEWAY_EVENTS/voice-state-update) | Someone joined, left, or moved a voice channel | | [Voice Server Update](#DOCS_TOPICS_GATEWAY_EVENTS/voice-server-update) | Guild's voice server was updated | | [Webhooks Update](#DOCS_TOPICS_GATEWAY_EVENTS/webhooks-update) | Guild channel webhook was created, update, or deleted | +| [Message Poll Vote Add](#DOCS_TOPICS_GATEWAY_EVENTS/message-poll-vote-add) | User voted on a poll | +| [Message Poll Vote Remove](#DOCS_TOPICS_GATEWAY_EVENTS/message-poll-vote-remove) | User remove a vote on a poll | #### Hello @@ -1243,4 +1245,32 @@ Sent when a [Stage instance](#DOCS_RESOURCES_STAGE_INSTANCE) has been updated. I Sent when a [Stage instance](#DOCS_RESOURCES_STAGE_INSTANCE) has been deleted (i.e. the Stage has been closed). Inner payload is a [Stage instance](#DOCS_RESOURCES_STAGE_INSTANCE/stage-instance-object) +### Polls +#### Message Poll Vote Add + +Sent when a user votes on a poll. If the poll allows multiple selection, one event will be sent per answer. + +###### Message Poll Vote Add Fields + +| Field | Type | Description | +|------------|-----------|-------------------| +| user_id | snowflake | ID of the user | +| channel_id | snowflake | ID of the channel | +| message_id | snowflake | ID of the message | +| guild_id? | snowflake | ID of the guild | +| answer_id | integer | ID of the answer | + +#### Message Poll Vote Remove + +Sent when a user removes their vote on a poll. If the poll allows for multiple selections, one event will be sent per answer. + +###### Message Poll Vote Remove Fields + +| Field | Type | Description | +|------------|-----------|-------------------| +| user_id | snowflake | ID of the user | +| channel_id | snowflake | ID of the channel | +| message_id | snowflake | ID of the message | +| guild_id? | snowflake | ID of the guild | +| answer_id | integer | ID of the answer | diff --git a/docs/topics/Opcodes_and_Status_Codes.md b/docs/topics/Opcodes_and_Status_Codes.md index 2ce984862c..9173bb0d92 100644 --- a/docs/topics/Opcodes_and_Status_Codes.md +++ b/docs/topics/Opcodes_and_Status_Codes.md @@ -311,6 +311,13 @@ Along with the HTTP error code, our API can also return more detailed error code | 240000 | Message blocked by harmful links filter | | 350000 | Cannot enable onboarding, requirements are not met | | 350001 | Cannot update onboarding while below requirements | +| 520000 | Poll voting blocked | +| 520001 | Poll expired | +| 520002 | Invalid channel type for poll creation | +| 520003 | Cannot edit a poll message | +| 520004 | Cannot use an emoji included with the poll | +| 520006 | Cannot expire a non-poll message | +| 520007 | Poll is already expired | ###### Example JSON Error Response diff --git a/images/example-poll.png b/images/example-poll.png new file mode 100644 index 0000000000..2c934fae52 Binary files /dev/null and b/images/example-poll.png differ