aboutsummaryrefslogtreecommitdiffstats
path: root/bot
diff options
context:
space:
mode:
Diffstat (limited to 'bot')
-rw-r--r--bot/cogs/monstersurvey.py161
-rw-r--r--bot/resources/monstersurvey/monstersurvey.json34
2 files changed, 195 insertions, 0 deletions
diff --git a/bot/cogs/monstersurvey.py b/bot/cogs/monstersurvey.py
new file mode 100644
index 00000000..dd19d401
--- /dev/null
+++ b/bot/cogs/monstersurvey.py
@@ -0,0 +1,161 @@
+from discord.ext.commands import Bot, Context
+from asyncio import sleep as asleep
+from typing import Optional
+from discord.ext import commands
+from discord import Embed
+import logging
+import json
+import os
+
+log = logging.getLogger(__name__)
+
+EMOJIS = {
+ 'SUCCESS': u'\u2705',
+ 'ERROR': u'\u274C'
+}
+
+
+class MonsterSurvey:
+ """
+ Vote for your favorite monster!
+ This command allows users to vote for their favorite listed monster.
+ Users may change their vote, but only their current vote will be counted.
+ """
+
+ def __init__(self, bot: Bot):
+ """Initializes values for the bot to use within the voting commands."""
+ self.bot = bot
+ self.registry_location = os.path.join(os.getcwd(), 'resources', 'monstersurvey', 'monstersurvey.json')
+ with open(self.registry_location, 'r') as jason:
+ self.voter_registry = json.load(jason)
+
+ def json_write(self):
+ with open(self.registry_location, 'w') as jason:
+ json.dump(self.voter_registry, jason, indent=2)
+
+ @commands.group(
+ name='monster',
+ aliases=['ms']
+ )
+ async def monster_group(self, ctx: Context):
+ """
+ The base voting command. If nothing is called, then it will return an embed.
+ """
+
+ if ctx.invoked_subcommand is None:
+ default_embed = Embed(
+ title='Monster Voting',
+ color=0xFF6800,
+ description='Vote for your favorite monster!'
+ )
+ default_embed.add_field(
+ name='.monster show monster_name(optional)',
+ value='Show a specific monster. If none is listed, show a brief of all.',
+ inline=False)
+ default_embed.add_field(
+ name='.monster vote monster_name',
+ value='Vote for a specific monster. You can vote more than once, but you can only vote for one monster'
+ 'at a time.',
+ inline=False
+ )
+ default_embed.add_field(
+ name='.monster leaderboard',
+ value='Which monster has the most votes? This command will tell you.',
+ inline=False
+ )
+ return await ctx.send(embed=default_embed)
+
+ @monster_group.command(
+ name='vote'
+ )
+ async def monster_vote(self, ctx: Context, name: Optional[str] = None):
+ """Casts a vote for a particular monster, or displays a list of monsters that can be voted for
+ if one is not given."""
+ vote_embed = Embed(
+ name='Monster Voting',
+ color=0xFF6800
+ )
+ if name is None or name.lower() not in self.voter_registry.keys():
+ if name is not None:
+ vote_embed.description = f'You cannot vote for {name} because it\'s not in the running.'
+ vote_embed.add_field(
+ name='Use `.monster show {monster_name}` for more information on a specific monster',
+ value='or use `.monster vote {monster}` to cast your vote for said monster.',
+ inline=False
+ )
+ vote_embed.add_field(
+ name='You may vote for or show the following monsters:',
+ value=f"{', '.join(self.voter_registry.keys())}"
+ )
+ return await ctx.send(embed=vote_embed)
+ for monster in self.voter_registry.keys():
+ if ctx.author.id in self.voter_registry[monster]['votes']:
+ if name != monster:
+ self.voter_registry[monster]['votes'].remove(ctx.author.id)
+ break
+ else:
+ vote_embed.add_field(
+ name='Vote unsuccessful.',
+ value='You already voted for this monster. '
+ 'If you want to change your vote, use another monster.',
+ inline=False
+ )
+ await ctx.send(embed=vote_embed)
+ await asleep(.5)
+ return await ctx.invoke(self.monster_vote)
+ self.voter_registry[name]['votes'].append(ctx.author.id)
+ vote_embed.add_field(
+ name='Vote successful!',
+ value=f'You have successfully voted for {self.voter_registry[name]["full_name"]}!',
+ inline=False
+ )
+ vote_embed.set_thumbnail(url=self.voter_registry[name]['image'])
+ self.json_write()
+ return await ctx.send(embed=vote_embed)
+
+ @monster_group.command(
+ name='show'
+ )
+ async def monster_show(self, ctx: Context, name: str):
+ """
+ Shows the named monster. If one is not named, it sends the default voting embed instead.
+ :param ctx:
+ :param name:
+ :return:
+ """
+ m = self.voter_registry.get(name)
+ if not m:
+ await ctx.send('That monster does not exist.')
+ return await ctx.invoke(self.monster_vote)
+ embed = Embed(title=m['full_name'], color=0xFF6800)
+ embed.add_field(name='Summary', value=m['summary'])
+ embed.set_image(url=m['image'])
+ embed.set_footer(text=f'To vote for this monster, type .monster vote {name}')
+ return await ctx.send(embed=embed)
+
+ @monster_group.command(
+ name='leaderboard',
+ aliases=['lb']
+ )
+ async def monster_leaderboard(self, ctx: Context):
+ """
+ Shows the current standings.
+ :param ctx:
+ :return:
+ """
+ vr = self.voter_registry
+ top = sorted(vr.values(), key=lambda k: len(k['votes']), reverse=True)
+
+ embed = Embed(title="Monster Survey Leader Board", color=0xFF6800)
+ total_votes = sum(len(m['votes']) for m in self.voter_registry.values())
+ for rank, m in enumerate(top):
+ votes = len(m['votes'])
+ percentage = ((votes / total_votes) * 100) if total_votes > 0 else 0
+ embed.add_field(name=f"{rank+1}. {m['full_name']}",
+ value=f"{votes} votes. {percentage:.1f}%"
+ f" of total votes.", inline=False)
+ await ctx.send(embed=embed)
+
+
+def setup(bot):
+ bot.add_cog(MonsterSurvey(bot))
diff --git a/bot/resources/monstersurvey/monstersurvey.json b/bot/resources/monstersurvey/monstersurvey.json
new file mode 100644
index 00000000..016bda3e
--- /dev/null
+++ b/bot/resources/monstersurvey/monstersurvey.json
@@ -0,0 +1,34 @@
+{
+ "frankenstein": {
+ "full_name": "Frankenstein's Monster",
+ "summary": "His limbs were in proportion, and I had selected his features as beautiful. Beautiful! Great God! His yellow skin scarcely covered the work of muscles and arteries beneath; his hair was of a lustrous black, and flowing; his teeth of a pearly whiteness; but these luxuriances only formed a more horrid contrast with his watery eyes, that seemed almost of the same colour as the dun-white sockets in which they were set, his shrivelled complexion and straight black lips.",
+ "image": "https://upload.wikimedia.org/wikipedia/commons/a/a7/Frankenstein%27s_monster_%28Boris_Karloff%29.jpg",
+ "votes": []
+ },
+ "dracula": {
+ "full_name": "Count Dracula",
+ "summary": "Count Dracula is an undead, centuries-old vampire, and a Transylvanian nobleman who claims to be a Sz\u00c3\u00a9kely descended from Attila the Hun. He inhabits a decaying castle in the Carpathian Mountains near the Borgo Pass. Unlike the vampires of Eastern European folklore, which are portrayed as repulsive, corpse-like creatures, Dracula wears a veneer of aristocratic charm. In his conversations with Jonathan Harker, he reveals himself as deeply proud of his boyar heritage and nostalgic for the past, which he admits have become only a memory of heroism, honour and valour in modern times.",
+ "image": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/90/Bela_Lugosi_as_Dracula%2C_anonymous_photograph_from_1931%2C_Universal_Studios.jpg/250px-Bela_Lugosi_as_Dracula%2C_anonymous_photograph_from_1931%2C_Universal_Studios.jpg",
+ "votes": [
+ 224734305581137921
+ ]
+ },
+ "blob": {
+ "full_name": "The Blob",
+ "summary": "",
+ "image": "",
+ "votes": []
+ },
+ "goofy": {
+ "full_name": "Goofy in the Monster's INC World",
+ "summary": "Pure nightmare fuel.\nThis monster is nothing like its original counterpart. With two different eyes, a pointed nose, fins growing out of its blue skin, and dark spots covering his body, he's a true nightmare come to life.",
+ "image": "https://www.dailydot.com/wp-content/uploads/3a2/a8/bf38aedbef9f795f.png",
+ "votes": []
+ },
+ "refisio": {
+ "full_name": "Refisio",
+ "summary": "Who let this guy write this? That's who the real monster is.",
+ "image": "https://avatars0.githubusercontent.com/u/24819750?s=460&v=4",
+ "votes": []
+ }
+} \ No newline at end of file