feat: add ability to query poll results

This commit is contained in:
2021-07-30 15:19:21 -04:00
parent f9f93afcd1
commit 2336e159c7
4 changed files with 114 additions and 7 deletions

15
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: pyvis.py File",
"type": "python",
"request": "launch",
"program": "pyvis.py",
"console": "integratedTerminal"
}
]
}

View File

@@ -1,16 +1,21 @@
from os import name
import random import random
import discord import discord
from discord.ext.commands.core import command
import requests import requests
import json import json
import requests import requests
from data import poll_cache
from datetime import date from datetime import date
from discord.ext import commands from discord.ext import commands
OPTION_EMOJIS = ["1", "2", "3", "4", "5"]
class Fun(commands.Cog): class Fun(commands.Cog):
"""Commands that are good for the soul!""" """Commands that are good for the soul!"""
OPTION_EMOJIS = ["1", "2", "3", "4", "5"]
FULL_CHAR = ""
BAR_LENGTH = 20
@commands.command() @commands.command()
async def flip(self, ctx) -> None: async def flip(self, ctx) -> None:
"""Flips a coin and return either heads or tails.""" """Flips a coin and return either heads or tails."""
@@ -46,8 +51,14 @@ class Fun(commands.Cog):
await ctx.send(embed=github_embed) await ctx.send(embed=github_embed)
@commands.command(usage="\"<question>\" <options>") @commands.group(invoke_without_command=True)
async def poll(self, ctx, *params: str) -> None: async def poll(self, ctx) -> None:
"""Allows for creating polls and querying results."""
await ctx.send("**poll create ->** `!poll create \"My question?\" option1 option2`")
await ctx.send("**poll results ->** `!poll results 870733802190807050`")
@poll.command(usage="\"<question>\" <options>", name="create")
async def poll_create(self, ctx, *params: str) -> None:
"""Creates a poll with the given parameters.""" """Creates a poll with the given parameters."""
if len(params) <= 1: if len(params) <= 1:
@@ -60,9 +71,51 @@ class Fun(commands.Cog):
# create embed response # create embed response
poll_embed = discord.Embed(title=question, description="\u200b", color=0x3DCCDD) poll_embed = discord.Embed(title=question, description="\u200b", color=0x3DCCDD)
for i in range(len(options)): for i in range(len(options)):
poll_embed.add_field(value="\u200b", name=f"{OPTION_EMOJIS[i]} {options[i]}", inline=False) poll_embed.add_field(value="\u200b", name=f"{self.OPTION_EMOJIS[i]} {options[i]}", inline=False)
poll_embed.set_footer(text=f"Poll created on • {date.today().strftime('%m/%d/%y')}") poll_embed.set_footer(text=f"Poll created on • {date.today().strftime('%m/%d/%y')}")
message = await ctx.send(embed=poll_embed) message = await ctx.send(embed=poll_embed)
# add poll to cache
poll_cache[message.id] = {}
for i in range(len(options)): for i in range(len(options)):
await message.add_reaction(OPTION_EMOJIS[i]) poll_cache[message.id][f"{self.OPTION_EMOJIS[i]}"] = []
poll_cache[message.id]["question"] = question
poll_cache[message.id]["options"] = ",".join(options)
# add option emojis to poll
for i in range(len(options)):
await message.add_reaction(self.OPTION_EMOJIS[i])
@poll.command(usage="<message_id>", name="results")
async def poll_results(self, ctx, message_id: int = None) -> None:
"""Shows results of a poll given a message id."""
if not message_id:
await ctx.send("**Please provide the message id of a poll. ex.** `!poll results 870733802190807050")
return
if message_id not in poll_cache:
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)
# 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.set_footer(text=f"Poll queried on • {date.today().strftime('%m/%d/%y')}")
await ctx.send(embed=results_embed)

View File

@@ -1 +1 @@
DUMMY_CACHE = {} poll_cache = {} # TODO: use a real cache

View File

@@ -1,11 +1,13 @@
import discord import discord
import os import os
from discord.flags import MessageFlags
import requests import requests
import json import json
import random import random
from cogs import Programming from cogs import Programming
from cogs import Fun from cogs import Fun
from cogs import Finance from cogs import Finance
from data import poll_cache
from discord.ext import commands from discord.ext import commands
from dotenv import load_dotenv from dotenv import load_dotenv
from pretty_help import DefaultMenu, PrettyHelp from pretty_help import DefaultMenu, PrettyHelp
@@ -20,6 +22,7 @@ PREFIX = "!"
intents = discord.Intents.default() intents = discord.Intents.default()
intents.members = True intents.members = True
intents.reactions = True
bot = commands.Bot(command_prefix=PREFIX, intents=intents) bot = commands.Bot(command_prefix=PREFIX, intents=intents)
@bot.event @bot.event
@@ -33,6 +36,7 @@ async def on_ready():
@bot.event @bot.event
async def on_member_join(member): async def on_member_join(member):
""" WELCOME START """
guild = discord.utils.find(lambda g: g.name == DISCORD_GUILD_NAME, bot.guilds) # TODO: check if find will throw an error guild = discord.utils.find(lambda g: g.name == DISCORD_GUILD_NAME, bot.guilds) # TODO: check if find will throw an error
welcome_channel = discord.utils.find(lambda c: c.name == "👋welcome", guild.channels) # TODO: remove welcome channel hardcode welcome_channel = discord.utils.find(lambda c: c.name == "👋welcome", guild.channels) # TODO: remove welcome channel hardcode
@@ -45,6 +49,7 @@ async def on_member_join(member):
await welcome_channel.send(embed=gif_embed) await welcome_channel.send(embed=gif_embed)
await welcome_channel.send(f"<@!{member.id}> **Welcome to {DISCORD_GUILD_NAME}!** :wave:") await welcome_channel.send(f"<@!{member.id}> **Welcome to {DISCORD_GUILD_NAME}!** :wave:")
""" WELCOME END """
@bot.event @bot.event
async def on_message(message): async def on_message(message):
@@ -52,6 +57,8 @@ async def on_message(message):
if message.author == bot.user: if message.author == bot.user:
return return
# TODO: is channel is a proposal channel check for poll command
# repsond with command prefix # repsond with command prefix
if bot.user.mentioned_in(message) and not message.mention_everyone: if bot.user.mentioned_in(message) and not message.mention_everyone:
await message.channel.send(f"**Learn more about me by running:** `{PREFIX}help`") await message.channel.send(f"**Learn more about me by running:** `{PREFIX}help`")
@@ -59,6 +66,38 @@ async def on_message(message):
# allow cogs to handle messages too # allow cogs to handle messages too
await bot.process_commands(message) await bot.process_commands(message)
@bot.event
async def on_raw_reaction_add(event):
# avoid bot self trigger
if event.user_id == bot.user.id:
return
""" POLL START """
# check if message is in cache and if reaction is valid
if event.message_id in poll_cache and event.emoji.name in Fun.OPTION_EMOJIS:
# if user has not voted yet, add their vote
if event.user_id not in poll_cache[event.message_id][event.emoji.name]:
poll_cache[event.message_id][event.emoji.name].append(event.user_id)
""" POLL END """
print(poll_cache)
@bot.event
async def on_raw_reaction_remove(event):
# avoid bot self trigger
if event.user_id == bot.user.id:
return
""" POLL START """
# check if message is in cache and if reaction is valid
if event.message_id in poll_cache and event.emoji.name in Fun.OPTION_EMOJIS:
# if user has voted, remove their vote
if event.user_id in poll_cache[event.message_id][event.emoji.name]:
poll_cache[event.message_id][event.emoji.name].remove(event.user_id)
""" POLL END """
print(poll_cache)
# override default help command # override default help command
menu = DefaultMenu('◀️', '▶️', '') menu = DefaultMenu('◀️', '▶️', '')
bot.help_command = PrettyHelp(navigation=menu, color=discord.Colour.green()) bot.help_command = PrettyHelp(navigation=menu, color=discord.Colour.green())