# Polls Extension

Lets users create and vote on polls.

Extension name: `pub.versia:polls`

The Polls Extension allows users to create and vote on polls.

This extension requires [`pub.versia:social@1`](/extensions/social), which defines [Notes](/extensions/social#note).

## Definition

### Poll

There is no `question` field: the question goes in the `content` of the Note itself.

- Extension ID: `pub.versia:polls`
- Extends: [Note](/entities/note)

**Fields**

- `options` (`PollOption[]`, required): Array of options for the poll. Each `PollOption` has:

  - `content` (`RichText`, required): Text of the option. Like a Note's `content`, it can contain links and [Custom Emojis](/extensions/custom-emojis).
  - `votes` (`number`, integer, required): Number of votes for this option.

- `multiple_choice` (`boolean`, required): Whether the poll allows multiple votes to be cast for different options.

- `expires_at` (`RFC3339`): RFC 3339 timestamp of when the poll ends and no more votes can be cast. If not present, the poll does not expire.

```jsonc title="Example Note"
{
    "id": "0341e147rp002",
    "type": "pub.versia:social/Note",
    "created_at": "2024-06-19T01:07:44Z",
    "author": "versia.example:033nrcdtky006",
    "category": "microblog",
    "content": "<p>What is your favorite color?</p>",
    // ...
    "extensions": {
        "pub.versia:polls": {
            "options": [
                {
                    "content": "Red",
                    "votes": 9
                },
                {
                    "content": "Blue",
                    "votes": 5
                },
                {
                    "content": "Green",
                    "votes": 0
                }
            ],
            "multiple_choice": false,
            "expires_at": "2024-06-22T01:07:44Z"
        }
    },
    "visibility": "public",
    "is_sensitive": false,
    "mentions": []
}

```

### Vote

A Vote holds every option one user chose in one poll. A user has at most one Vote in each poll.

- Type: `"pub.versia:polls/Vote"`
- Fetch: `GET /.versia/v0.7/entities/pub.versia:polls/Vote/{id}`

**Fields**

- `type` (`string`, required): **MUST** be `pub.versia:polls/Vote`.
- `author` (`Reference`, required): [Reference](/entities#reference) of the user who cast the vote.
- `target` (`Reference`, required): [Reference](/entities#reference) to the note with poll that the user voted on.
- `options` (`number[]`, integer, required): Indexes of the options that the user voted for, in the `options` array of the poll. **MUST** hold at least one index, and **MUST NOT** hold the same index twice.

Inherited from [Entity](/entities):

- [`id`](/entities#entity-id) (`string`, required)
- [`created_at`](/entities#entity-created-at) (`RFC3339`, required)
- [`updated_at`](/entities#entity-updated-at) (`RFC3339`)
- [`extensions`](/entities#entity-extensions) (`Extensions`)

```jsonc title="Example Vote"
{
    "id": "033fsr7ggg004",
    "type": "pub.versia:polls/Vote",
    "created_at": "2021-01-01T00:00:00Z",
    "author": "example.org:033wv9k6n0007",
    "target": "example.com:0337hp246t002",
    "options": [1]
}
```

## Behavior

### Privacy

Individual votes are private. Clients **SHOULD NOT** display who voted, only the number of votes for each option and the total number of votes cast.

A poll's `options` hold numbers of votes, not voters, and a Vote can only be fetched by the instance of the poll's author.

### Voting

The instance of the poll's author **MUST NOT** count a Vote that:

- is for a poll that has closed,
- holds an index that is not in the poll's `options`, or the same index twice,
- holds no index, or more than one on a poll without `multiple_choice`,
- has a different `id` from a Vote that the same user already has in the poll.

Such a Vote **MUST** be [rejected](/validation#rejecting-entities).

A user changes their choices by [sending the Vote again](/entities#changing-an-entity) with the same `id` and new `options`, and withdraws their vote with a [Delete](/entities/delete). After a Delete, the user can vote again with a new Vote. A change or Delete that arrives after the poll has closed leaves the numbers as they are.

A Vote's `target` **MUST NOT** change, and a receiver **MUST** discard a version that changes it. Voting in another poll takes a new Vote.

## Delivery and Access

A sender **MUST** [deliver](/federation#delivery) Votes to the author of the [Note](/extensions/social#note).

Only the instance of the Note's author may [fetch](/federation#access) a Vote.

When a poll's votes change, its Note is [sent again](/entities#changing-an-entity), and **MUST** also be delivered to the users who voted.

## Interaction Types

This extension registers the following [interaction types](/extensions/interaction-controls#interaction-types):

- `pub.versia:polls/vote`, for voting on a Poll attached to a Note.
