diff options
-rw-r--r-- | bot/cogs/monstersurvey.py | 177 | ||||
-rw-r--r-- | bot/resources/monstersurvey/monstersurvey.json | 32 |
2 files changed, 118 insertions, 91 deletions
diff --git a/bot/cogs/monstersurvey.py b/bot/cogs/monstersurvey.py index 46ab2485..67bc9051 100644 --- a/bot/cogs/monstersurvey.py +++ b/bot/cogs/monstersurvey.py @@ -1,104 +1,107 @@ -import logging -import json -from discord.ext import commands from discord.ext.commands import Bot, Context -import discord from typing import Optional, Tuple -import aiohttp -from http import HTTPStatus +from discord.ext import commands +from discord import Embed +import discord, logging, json, os log = logging.getLogger(__name__) - EMOJIS = { - 'SUCCESS': u"\u2705", - 'ERROR': u"\u274C", + 'SUCCESS': u'\u2705', + 'ERROR': u'\u274C' } -class MonsterSurvey: - - def __init__(self, bot: Bot): - self.bot = Bot - self._monsters = None - @property - def monsters(self) -> dict: - """Always get the most up to date version""" - path = '../bot/resources/monstersurvey/monstersurvey.json' - with open(path, 'r') as f: - self._monsters = json.load(f) - return self._monsters +class MonsterServey: - async def monster_info(self, monster) -> Tuple[Optional[str], Optional[str]]: - """Gets information relating to each monster. This first checks if there - are 'summary' and 'image' keys in the json file. If this fails, it will - attempt to pull summary information from Wikipedia. - """ - async def fetch_url(session: aiohttp.ClientSession, url: str) -> dict: - """Use wikipedia api url calls""" - response = await session.get(url) - if response.status == HTTPStatus.OK: - result = json.loads(await response.text()) - return next(iter(result['query']['pages'].values())) - summary_url = "http://en.wikipedia.org/w/api.php" \ - "?format=json" \ - "&action=query" \ - "&prop=extracts" \ - "&explaintext&exintro" \ - "&redirects=1" \ - f"&titles={monster}" - image_url = "http://en.wikipedia.org/w/api.php" \ - "?action=query" \ - "&prop=pageimages" \ - "&format=json" \ - "&piprop=original" \ - f"&titles={monster}" - async with aiohttp.ClientSession() as s: - summary = self.monsters[monster].get('summary') \ - or (await fetch_url(s, summary_url)).get('extract') - - image = self.monsters[monster].get('image') \ - or (await fetch_url(s, image_url)).get('original', {}).get('source') - return summary, image - - @commands.group(name='monster', aliases=('ms',), invoke_without_command=True) + def __init__(self, bot: Bot): + 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) + + @commands.group( + name='monster', + aliases=['ms'] + ) async def monster_group(self, ctx: Context): - pass - - @monster_group.command(name='vote') + 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 + ) + 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 all - monsters that are available for voting. - """ - embed = discord.Embed(name='Vote for your favorite monster') - if not name: - for k,v in self.monsters.items(): - msg = f"`.monster show {k}` for more information\n" \ - f"`.monster vote {k}` to cast your vote for this monster." - embed.add_field(name=f"{k}", value=f"{msg}", inline=False) - # TODO: Add logic for voting - await ctx.send(embed=embed) - - @monster_group.command(name='show') - async def monster_show(self, ctx: Context, *monster: str): - """Display a detailed description for the monster, and image.""" - monster = ' '.join(monster) - if self.monsters.get(monster, None): - summary, image = await self.monster_info(monster) - embed = discord.Embed(name=monster) - embed.add_field(name=f"About {monster}", value=summary or "No information") - if image: - embed.set_image(url=image) - embed.set_footer(text=f"To vote for {monster}, type `.monster vote {monster}`") - await ctx.send(embed=embed) - else: - await ctx.message.add_reaction(EMOJIS['ERROR']) - - -def setup(bot: Bot): - bot.add_cog(MonsterSurvey(bot)) + """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 not in self.voter_registry.keys() and 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 the following monsters:', + value=f"{', '.join(self.voter_registry.keys())}" + ) + return await ctx.send(embed=vote_embed) + if name is None: + pass + @monster_group.command(name='show') + async def monster_show(self, ctx: Context, name: str): + m = self.voter_registry.get(name) + if not m: + # TODO: invoke .monster vote command to display list + raise commands.BadArgument("Monster does not exist.") + + 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}') + await ctx.send(embed=embed) + @monster_group.command(name='leaderboard') + async def monster_leaderboard(self, ctx: Context): + vr = self.voter_registry + top = sorted(vr.values(), key=lambda k: len(k['votes']), reverse=True) + + embed = Embed(title="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(MonsterServey(bot)) diff --git a/bot/resources/monstersurvey/monstersurvey.json b/bot/resources/monstersurvey/monstersurvey.json index 7e923dcc..a98870c3 100644 --- a/bot/resources/monstersurvey/monstersurvey.json +++ b/bot/resources/monstersurvey/monstersurvey.json @@ -1,8 +1,32 @@ { - "Frankenstein's Monster": { - "votes": [] - }, - "Count Dracula": { + "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ékely 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": [] + }, + "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": [] } } |