Source code for fbchat._models._poll
import attr
from .._common import attrs_default
from .. import _exception, _session
from typing import Iterable, Sequence
[docs]@attrs_default
class PollOption:
"""Represents a poll option."""
#: ID of the poll option
id = attr.ib(converter=str, type=str)
#: Text of the poll option
text = attr.ib(type=str)
#: Whether vote when creating or client voted
vote = attr.ib(type=bool)
#: ID of the users who voted for this poll option
voters = attr.ib(type=Sequence[str])
#: Votes count
votes_count = attr.ib(type=int)
@classmethod
def _from_graphql(cls, data):
if data.get("viewer_has_voted") is None:
vote = False
elif isinstance(data["viewer_has_voted"], bool):
vote = data["viewer_has_voted"]
else:
vote = data["viewer_has_voted"] == "true"
return cls(
id=int(data["id"]),
text=data.get("text"),
vote=vote,
voters=(
[m["node"]["id"] for m in data["voters"]["edges"]]
if isinstance(data.get("voters"), dict)
else data["voters"]
),
votes_count=(
data["voters"]["count"]
if isinstance(data.get("voters"), dict)
else data["total_count"]
),
)
[docs]@attrs_default
class Poll:
"""Represents a poll."""
#: ID of the poll
session = attr.ib(type=_session.Session)
#: ID of the poll
id = attr.ib(converter=str, type=str)
#: The poll's question
question = attr.ib(type=str)
#: The poll's top few options. The full list can be fetched with `fetch_options`
options = attr.ib(type=Sequence[PollOption])
#: Options count
options_count = attr.ib(type=int)
@classmethod
def _from_graphql(cls, session, data):
return cls(
session=session,
id=data["id"],
question=data["title"] if data.get("title") else data["text"],
options=[PollOption._from_graphql(m) for m in data["options"]],
options_count=data["total_count"],
)
[docs] def fetch_options(self) -> Sequence[PollOption]:
"""Fetch all `PollOption` objects on the poll.
The result is ordered with options with the most votes first.
Example:
>>> options = poll.fetch_options()
>>> options[0].text
"An option"
"""
data = {"question_id": self.id}
j = self.session._payload_post("/ajax/mercury/get_poll_options", data)
return [PollOption._from_graphql(m) for m in j]
[docs] def set_votes(self, option_ids: Iterable[str], new_options: Iterable[str] = None):
"""Update the user's poll vote.
Args:
option_ids: Option ids to vote for / keep voting for
new_options: New options to add
Example:
>>> options = poll.fetch_options()
>>> # Add option
>>> poll.set_votes([o.id for o in options], new_options=["New option"])
>>> # Remove vote from option
>>> poll.set_votes([o.id for o in options if o.text != "Option 1"])
"""
data = {"question_id": self.id}
for i, option_id in enumerate(option_ids or ()):
data["selected_options[{}]".format(i)] = option_id
for i, option_text in enumerate(new_options or ()):
data["new_options[{}]".format(i)] = option_text
j = self.session._payload_post(
"/messaging/group_polling/update_vote/?dpr=1", data
)
if j.get("status") != "success":
raise _exception.ExternalError(
"Failed updating poll vote: {}".format(j.get("errorTitle")),
j.get("errorMessage"),
)