diff --git a/README.md b/README.md
index 535b8ef..924ec79 100644
--- a/README.md
+++ b/README.md
@@ -4,14 +4,18 @@ A plugin for [maubot](https://github.com/maubot/maubot) that creates a poll in a
## Usage
'!poll new "Question" "Choice1" "Choice2" "Choice3"' - Creates a new poll with given (at least 1) choices
-'!poll vote choice' - Has user vote for given choice (int). Users can only vote once per poll
-
'!poll results' - Displays the results from the poll
'!poll close' - Ends the poll
+Users vote by adding the matching emoji to the poll (i.e. if the first choice has a :thumbsup: then in order to pick that choice the user has to react with :thumbsup:)
+
+## Version 2.0
+ - Changed voting format to reactions (instead of '!poll vote')
-## Wish List
+## Wish List
- Add user configuration to only allow certain users to create polls
- Add auto-timing ability
- Add ability to run multiple polls at once
+- Make emojis configurable
+- Add placeholder emojis on each poll (to let users just click one)
diff --git a/maubot.yaml b/maubot.yaml
index 361a2ce..27920ef 100644
--- a/maubot.yaml
+++ b/maubot.yaml
@@ -9,7 +9,7 @@ maubot: 0.1.0
id: casavant.tom.poll
# A PEP 440 compliant version string.
-version: 1.0.1
+version: 2.0.0
# The SPDX license identifier for the plugin. https://spdx.org/licenses/
# Optional, assumes all rights reserved if omitted.
diff --git a/poll.py b/poll.py
index 39bd5ee..114dd0c 100644
--- a/poll.py
+++ b/poll.py
@@ -1,12 +1,15 @@
import re
+import random
from typing import List, Tuple
from mautrix.util.config import BaseProxyConfig, ConfigUpdateHelper
+from mautrix.types import (EventType, ReactionEvent)
from maubot import Plugin, MessageEvent
from maubot.handlers import command
QUOTES_REGEX = r"\"?\s*?\"" # Regex to split string between quotes
-
+# [Thumbs Up, Thumbs Down, Grinning, Ghost, Robot, Okay Hand, Clapping Hands, Hundred]
+REACTIONS = ["\U0001F44D", "\U0001F44E", "\U0001F600", "\U0001F47B", "\U0001F916", "\U0001F44C", "\U0001F44F", "\U0001F4AF"]
class Poll:
def __init__(self, question, choices):
@@ -17,9 +20,11 @@ def __init__(self, question, choices):
self.active = True # Begins the poll
self.total = 0
+ self.emojis = random.sample(REACTIONS, len(choices)) # Select a random assortment of emojis
+
def vote(self, choice, user_id):
# Adds a vote to the given choice
- self.votes[choice - 1] += 1
+ self.votes[choice] += 1
# Adds user to list of users who have already voted
self.voters.append(user_id)
self.total += 1
@@ -64,6 +69,7 @@ async def poll(self) -> None:
pass_raw=True,
required=True
)
+
async def handler(self, evt: MessageEvent, poll_setup: str) -> None:
await evt.mark_read()
r = re.compile(QUOTES_REGEX) # Compiles regex for quotes
@@ -78,30 +84,10 @@ async def handler(self, evt: MessageEvent, poll_setup: str) -> None:
self.currentPoll = Poll(question, choices)
# Show users active poll
choice_list = "
".join(
- [f"{i+1}. {choice}" for i, choice in enumerate(choices)]
+ [f"{self.currentPoll.emojis[i]} - {choice}" for i, choice in enumerate(choices)]
)
response = f"{question}
{choice_list}"
-
- await evt.reply(response, allow_html=True)
-
- @poll.subcommand("vote", help="Votes for an option")
- @command.argument(
- "choice", pass_raw=True, required=True
- )
- async def handler(self, evt: MessageEvent, choice: int) -> None:
- await evt.mark_read()
- # Verify the user is able to vote
- if self.currentPoll.hasVoted(evt.sender):
- await evt.reply("You've already voted in this poll")
- elif not self.currentPoll.isActive():
- await evt.reply("I'm sorry this poll has already ended")
- else:
- # Checks if user entered a valid vote
- if self.currentPoll.isAvailable(int(choice)):
- # Makes the vote
- self.currentPoll.vote(int(choice), evt.sender)
- else:
- await evt.reply("You must enter a valid choice")
+ self.currentPoll.event_id = await evt.reply(response, allow_html=True)
@poll.subcommand("results", help="Prints out the current results of the poll")
async def handler(self, evt: MessageEvent) -> None:
@@ -113,3 +99,12 @@ async def handler(self, evt: MessageEvent) -> None:
await evt.mark_read()
self.currentPoll.close_poll()
await evt.reply("This poll is now over. Type !poll results to see the results.")
+
+ @command.passive(regex=r"(?:("+'|'.join(REACTIONS) + r")[\U0001F3FB-\U0001F3FF]?)",
+ field=lambda evt: evt.content.relates_to.key,
+ event_type=EventType.REACTION, msgtypes=None)
+ async def get_react_vote(self, evt: ReactionEvent, _: Tuple[str]) -> None:
+ if (evt.content.relates_to.event_id == self.currentPoll.event_id): # Is this on the correct message?
+ if not self.currentPoll.hasVoted(evt.sender): # has the user already voted?
+ if (evt.content.relates_to.key in self.currentPoll.emojis): # Is this a possible choice?
+ self.currentPoll.vote(self.currentPoll.emojis.index(evt.content.relates_to.key), evt.sender) # Add vote/sender to poll