feat: add redis cache to store polls state
This commit is contained in:
68
cogs/fun.py
68
cogs/fun.py
@@ -1,21 +1,17 @@
|
||||
from os import name
|
||||
import random
|
||||
import discord
|
||||
from discord.ext.commands.core import command
|
||||
import requests
|
||||
import json
|
||||
import requests
|
||||
from data import poll_cache
|
||||
from model import Poll
|
||||
from data import polls
|
||||
from datetime import date
|
||||
from discord.ext import commands
|
||||
from discord.raw_models import RawReactionActionEvent
|
||||
|
||||
class Fun(commands.Cog):
|
||||
"""Commands that are good for the soul!"""
|
||||
|
||||
OPTION_EMOJIS = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣"]
|
||||
FULL_CHAR = "█"
|
||||
BAR_LENGTH = 20
|
||||
|
||||
@commands.command()
|
||||
async def flip(self, ctx) -> None:
|
||||
"""Flips a coin and return either heads or tails."""
|
||||
@@ -65,27 +61,25 @@ class Fun(commands.Cog):
|
||||
await ctx.send("**Please provide the parameters for the poll. ex.** `!poll \"My question?\" option1 option2`")
|
||||
return
|
||||
|
||||
# parse the parameters
|
||||
question = params[0]
|
||||
options = params[1:]
|
||||
|
||||
# create embed response
|
||||
poll_embed = discord.Embed(title=question, description="\u200b", color=0x3DCCDD)
|
||||
for i in range(len(options)):
|
||||
poll_embed.add_field(value="\u200b", name=f"{self.OPTION_EMOJIS[i]} {options[i]}", inline=False)
|
||||
poll_embed.add_field(value="\u200b", name=f"{Poll.OPTION_EMOJIS[i]} {options[i]}", inline=False)
|
||||
poll_embed.set_footer(text=f"Poll created on • {date.today().strftime('%m/%d/%y')}")
|
||||
|
||||
message = await ctx.send(embed=poll_embed)
|
||||
|
||||
# add poll to cache
|
||||
poll_cache[message.id] = {}
|
||||
for i in range(len(options)):
|
||||
poll_cache[message.id][f"{self.OPTION_EMOJIS[i]}"] = []
|
||||
poll_cache[message.id]["question"] = question
|
||||
poll_cache[message.id]["options"] = ",".join(options)
|
||||
poll = Poll(message.id, question, options)
|
||||
polls[message.id] = json.dumps(poll.__dict__)
|
||||
|
||||
# add option emojis to poll
|
||||
# add option emoji reactions to poll
|
||||
for i in range(len(options)):
|
||||
await message.add_reaction(self.OPTION_EMOJIS[i])
|
||||
await message.add_reaction(Poll.OPTION_EMOJIS[i])
|
||||
|
||||
@poll.command(usage="<message_id>", name="results")
|
||||
async def poll_results(self, ctx, message_id: int = None) -> None:
|
||||
@@ -95,27 +89,39 @@ class Fun(commands.Cog):
|
||||
await ctx.send("**Please provide the message id of a poll. ex.** `!poll results 870733802190807050")
|
||||
return
|
||||
|
||||
if message_id not in poll_cache:
|
||||
if message_id not in polls:
|
||||
await ctx.send("**Could not find poll with that message id.**")
|
||||
return
|
||||
|
||||
poll = poll_cache[message_id]
|
||||
question = poll["question"]
|
||||
options = poll["options"].split(",")
|
||||
|
||||
total_votes = sum([0 if item[0] == "question" or item[0] == "options" else len(item[1]) for item in poll.items()])
|
||||
option_percentages = []
|
||||
for i in range(len(options)):
|
||||
option_votes = len(poll[self.OPTION_EMOJIS[i]])
|
||||
option_percentages.append(0 if total_votes == 0 else option_votes / total_votes)
|
||||
poll = Poll.create_from(json.loads(polls[message_id]))
|
||||
|
||||
# construct embed response
|
||||
results_embed = discord.Embed(title=question, description="🥁", color=0x3DCCDD)
|
||||
for i in range(len(options)):
|
||||
str_bar = "".join([self.FULL_CHAR for _ in range(int(self.BAR_LENGTH * option_percentages[i]))])
|
||||
str_percent = f"{option_percentages[i] * 100:.2f}%"
|
||||
str_votes = f"({int(option_percentages[i] * total_votes)} votes)"
|
||||
results_embed.add_field(name=f"{self.OPTION_EMOJIS[i]} {options[i]}", value=f"{str_bar} {str_percent} {str_votes}", inline=False)
|
||||
results_embed = discord.Embed(title=poll.question, description="🥁", color=0x3DCCDD)
|
||||
for option in poll.options:
|
||||
str_bar = "".join([Poll.BAR_CHAR for _ in range(int(Poll.BAR_LENGTH * poll.get_vote_percentage(option)))])
|
||||
str_percent = f"{poll.get_vote_percentage(option) * 100:.2f}%"
|
||||
str_votes = f"({poll.get_vote_count(option)} votes)"
|
||||
results_embed.add_field(name=f"{poll.get_emoji(option)} {option}", value=f"{str_bar} {str_percent} {str_votes}", inline=False)
|
||||
results_embed.set_footer(text=f"Poll queried on • {date.today().strftime('%m/%d/%y')}")
|
||||
|
||||
await ctx.send(embed=results_embed)
|
||||
|
||||
@staticmethod
|
||||
def poll_vote(event: RawReactionActionEvent) -> None:
|
||||
"""Handles a user voting on a poll."""
|
||||
|
||||
# check if message is a poll and emoji is a valid option
|
||||
if event.message_id in polls and event.emoji.name in Poll.OPTION_EMOJIS:
|
||||
# get poll from cache
|
||||
poll = Poll.create_from(json.loads(polls[event.message_id]))
|
||||
|
||||
print(event)
|
||||
|
||||
# check reaction emoji type
|
||||
if event.event_type == "REACTION_ADD":
|
||||
poll.add_vote(event.user_id, event.emoji.name)
|
||||
elif event.event_type == "REACTION_REMOVE":
|
||||
poll.remove_vote(event.user_id, event.emoji.name)
|
||||
|
||||
# update cache
|
||||
polls[event.message_id] = json.dumps(poll.__dict__)
|
||||
|
||||
Reference in New Issue
Block a user