Represents a Discord message poll.
Combines a data struct (received from the gateway), a pipe-friendly builder (for creating polls), and query helpers (for analyzing results).
Building a poll
import EDA.Poll
poll =
new("What's your favorite color?", duration: 48, multiselect: true)
|> add_answer("Red", emoji: "🔴")
|> add_answer("Blue", emoji: "🔵")
|> add_answer("Green", emoji: "🟢")
EDA.API.Message.create(channel_id, poll: poll)Analyzing results
poll = message.poll
EDA.Poll.expired?(poll)
EDA.Poll.finalized?(poll)
EDA.Poll.total_votes(poll)
EDA.Poll.winning_answer(poll)
Summary
Functions
Adds an answer to the poll (max 10 answers).
Returns true if the poll has expired.
Returns true if the poll results are finalized (votes precisely counted).
Parses a poll from a raw Discord API map.
Returns the default layout type (1).
Returns the maximum answer text length (55).
Returns the maximum number of answers (10).
Returns the maximum poll duration in hours (768).
Returns the maximum question length (300).
Returns the minimum poll duration in hours (1).
Creates a new poll with the given question.
Serializes a poll to the Discord API format for message creation.
Returns the total number of votes across all answers.
Returns the answer with the most votes, or nil if there are no results.
Types
@type t() :: %EDA.Poll{ allow_multiselect: boolean(), answers: [EDA.Poll.Answer.t()], duration: integer() | nil, expiry: String.t() | nil, layout_type: integer() | nil, question: String.t(), results: {boolean(), [EDA.Poll.AnswerCount.t()]} | nil }
Functions
Adds an answer to the poll (max 10 answers).
Options
:emoji- AnEDA.Emojistruct or a unicode string (e.g."🔴")
Examples
iex> poll = EDA.Poll.new("Test?") |> EDA.Poll.add_answer("Option A")
iex> length(poll.answers)
1
iex> poll = EDA.Poll.new("Test?") |> EDA.Poll.add_answer("Fire", emoji: "🔥")
iex> hd(poll.answers).emoji
%EDA.Emoji{name: "🔥"}
Returns true if the poll has expired.
Compares the expiry timestamp against DateTime.utc_now/0.
Returns false if expiry is nil.
Examples
iex> EDA.Poll.expired?(%EDA.Poll{expiry: "2020-01-01T00:00:00+00:00"})
true
iex> EDA.Poll.expired?(%EDA.Poll{expiry: nil})
false
Returns true if the poll results are finalized (votes precisely counted).
Examples
iex> EDA.Poll.finalized?(%EDA.Poll{results: {true, []}})
true
iex> EDA.Poll.finalized?(%EDA.Poll{results: {false, []}})
false
iex> EDA.Poll.finalized?(%EDA.Poll{results: nil})
false
Parses a poll from a raw Discord API map.
Examples
iex> raw = %{
...> "question" => %{"text" => "Best language?"},
...> "answers" => [%{"answer_id" => 1, "poll_media" => %{"text" => "Elixir"}}],
...> "expiry" => "2025-01-01T00:00:00+00:00",
...> "allow_multiselect" => false,
...> "layout_type" => 1,
...> "results" => %{
...> "is_finalized" => true,
...> "answer_counts" => [%{"id" => 1, "count" => 10, "me_voted" => false}]
...> }
...> }
iex> poll = EDA.Poll.from_raw(raw)
iex> poll.question
"Best language?"
iex> poll.results
{true, [%EDA.Poll.AnswerCount{id: 1, count: 10, me_voted: false}]}
@spec layout_default() :: integer()
Returns the default layout type (1).
@spec max_answer_length() :: integer()
Returns the maximum answer text length (55).
@spec max_answers() :: integer()
Returns the maximum number of answers (10).
@spec max_duration() :: integer()
Returns the maximum poll duration in hours (768).
@spec max_question_length() :: integer()
Returns the maximum question length (300).
@spec min_duration() :: integer()
Returns the minimum poll duration in hours (1).
Creates a new poll with the given question.
Options
:duration- Duration in hours (1-768, default: 24):multiselect- Allow multiple votes (default: false):layout- Layout type (default: 1)
Examples
iex> poll = EDA.Poll.new("Favorite color?")
iex> poll.question
"Favorite color?"
iex> poll.duration
24
iex> poll = EDA.Poll.new("Pick many", duration: 48, multiselect: true)
iex> poll.duration
48
iex> poll.allow_multiselect
true
Serializes a poll to the Discord API format for message creation.
Examples
iex> poll = %EDA.Poll{question: "Yes?", answers: [%EDA.Poll.Answer{text: "Yes"}], duration: 24, allow_multiselect: false, layout_type: 1}
iex> raw = EDA.Poll.to_raw(poll)
iex> raw["question"]
%{"text" => "Yes?"}
Returns the total number of votes across all answers.
Returns 0 if there are no results.
Examples
iex> counts = [%EDA.Poll.AnswerCount{id: 1, count: 5, me_voted: false}, %EDA.Poll.AnswerCount{id: 2, count: 3, me_voted: true}]
iex> EDA.Poll.total_votes(%EDA.Poll{results: {true, counts}})
8
iex> EDA.Poll.total_votes(%EDA.Poll{results: nil})
0
@spec winning_answer(t()) :: EDA.Poll.Answer.t() | nil
Returns the answer with the most votes, or nil if there are no results.
Matches answer counts back to answers by ID.
Examples
iex> answers = [%EDA.Poll.Answer{answer_id: 1, text: "A"}, %EDA.Poll.Answer{answer_id: 2, text: "B"}]
iex> counts = [%EDA.Poll.AnswerCount{id: 1, count: 3, me_voted: false}, %EDA.Poll.AnswerCount{id: 2, count: 7, me_voted: false}]
iex> EDA.Poll.winning_answer(%EDA.Poll{answers: answers, results: {true, counts}})
%EDA.Poll.Answer{answer_id: 2, text: "B"}
iex> EDA.Poll.winning_answer(%EDA.Poll{results: nil})
nil