diff options
Diffstat (limited to 'bot/exts')
| -rw-r--r-- | bot/exts/valentines/valentine_zodiac.py | 145 | 
1 files changed, 117 insertions, 28 deletions
| diff --git a/bot/exts/valentines/valentine_zodiac.py b/bot/exts/valentines/valentine_zodiac.py index ef9ddc78..2696999f 100644 --- a/bot/exts/valentines/valentine_zodiac.py +++ b/bot/exts/valentines/valentine_zodiac.py @@ -1,7 +1,10 @@ +import calendar +import json  import logging  import random -from json import load +from datetime import datetime  from pathlib import Path +from typing import Tuple, Union  import discord  from discord.ext import commands @@ -19,37 +22,123 @@ class ValentineZodiac(commands.Cog):      def __init__(self, bot: commands.Bot):          self.bot = bot -        self.zodiacs = self.load_json() +        self.zodiacs, self.zodiac_fact = self.load_comp_json()      @staticmethod -    def load_json() -> dict: +    def load_comp_json() -> Tuple[dict, dict]:          """Load zodiac compatibility from static JSON resource.""" -        p = Path("bot/resources/valentines/zodiac_compatibility.json") -        with p.open(encoding="utf8") as json_data: -            zodiacs = load(json_data) -            return zodiacs - -    @commands.command(name="partnerzodiac") -    async def counter_zodiac(self, ctx: commands.Context, zodiac_sign: str) -> None: -        """Provides a counter compatible zodiac sign to the given user's zodiac sign.""" -        try: -            compatible_zodiac = random.choice(self.zodiacs[zodiac_sign.lower()]) -        except KeyError: -            return await ctx.send(zodiac_sign.capitalize() + " zodiac sign does not exist.") - -        emoji1 = random.choice(HEART_EMOJIS) -        emoji2 = random.choice(HEART_EMOJIS) -        embed = discord.Embed( -            title="Zodic Compatibility", -            description=f'{zodiac_sign.capitalize()}{emoji1}{compatible_zodiac["Zodiac"]}\n' -                        f'{emoji2}Compatibility meter : {compatible_zodiac["compatibility_score"]}{emoji2}', -            color=Colours.pink -        ) -        embed.add_field( -            name=f'A letter from Dr.Zodiac {LETTER_EMOJI}', -            value=compatible_zodiac['description'] -        ) +        explanation_file = Path("bot/resources/valentines/zodiac_explanation.json") +        compatibility_file = Path("bot/resources/valentines/zodiac_compatibility.json") +        with explanation_file.open(encoding="utf8") as json_data: +            zodiac_fact = json.load(json_data) +            for zodiac_data in zodiac_fact.values(): +                zodiac_data['start_at'] = datetime.fromisoformat(zodiac_data['start_at']) +                zodiac_data['end_at'] = datetime.fromisoformat(zodiac_data['end_at']) + +        with compatibility_file.open(encoding="utf8") as json_data: +            zodiacs = json.load(json_data) + +        return zodiacs, zodiac_fact + +    def generate_invalidname_embed(self, zodiac: str) -> discord.Embed: +        """Returns error embed.""" +        embed = discord.Embed() +        embed.color = Colours.soft_red +        error_msg = f"**{zodiac}** is not a valid zodiac sign, here is the list of valid zodiac signs.\n" +        names = list(self.zodiac_fact) +        middle_index = len(names) // 2 +        first_half_names = ", ".join(names[:middle_index]) +        second_half_names = ", ".join(names[middle_index:]) +        embed.description = error_msg + first_half_names + ",\n" + second_half_names +        log.info("Invalid zodiac name provided.") +        return embed + +    def zodiac_build_embed(self, zodiac: str) -> discord.Embed: +        """Gives informative zodiac embed.""" +        zodiac = zodiac.capitalize() +        embed = discord.Embed() +        embed.color = Colours.pink +        if zodiac in self.zodiac_fact: +            log.trace("Making zodiac embed.") +            embed.title = f"__{zodiac}__" +            embed.description = self.zodiac_fact[zodiac]["About"] +            embed.add_field(name='__Motto__', value=self.zodiac_fact[zodiac]["Motto"], inline=False) +            embed.add_field(name='__Strengths__', value=self.zodiac_fact[zodiac]["Strengths"], inline=False) +            embed.add_field(name='__Weaknesses__', value=self.zodiac_fact[zodiac]["Weaknesses"], inline=False) +            embed.add_field(name='__Full form__', value=self.zodiac_fact[zodiac]["full_form"], inline=False) +            embed.set_thumbnail(url=self.zodiac_fact[zodiac]["url"]) +        else: +            embed = self.generate_invalidname_embed(zodiac) +        log.trace("Successfully created zodiac information embed.") +        return embed + +    def zodiac_date_verifier(self, query_date: datetime) -> str: +        """Returns zodiac sign by checking date.""" +        for zodiac_name, zodiac_data in self.zodiac_fact.items(): +            if zodiac_data["start_at"].date() <= query_date.date() <= zodiac_data["end_at"].date(): +                log.trace("Zodiac name sent.") +                return zodiac_name + +    @commands.group(name='zodiac', invoke_without_command=True) +    async def zodiac(self, ctx: commands.Context, zodiac_sign: str) -> None: +        """Provides information about zodiac sign by taking zodiac sign name as input.""" +        final_embed = self.zodiac_build_embed(zodiac_sign) +        await ctx.send(embed=final_embed) +        log.trace("Embed successfully sent.") + +    @zodiac.command(name="date") +    async def date_and_month(self, ctx: commands.Context, date: int, month: Union[int, str]) -> None: +        """Provides information about zodiac sign by taking month and date as input.""" +        if isinstance(month, str): +            month = month.capitalize() +            try: +                month = list(calendar.month_abbr).index(month[:3]) +                log.trace('Valid month name entered by user') +            except ValueError: +                log.info('Invalid month name entered by user') +                await ctx.send(f"Sorry, but `{month}` is not a valid month name.") +                return +        if (month == 1 and 1 <= date <= 19) or (month == 12 and 22 <= date <= 31): +            zodiac = "capricorn" +            final_embed = self.zodiac_build_embed(zodiac) +        else: +            try: +                zodiac_sign_based_on_date = self.zodiac_date_verifier(datetime(2020, month, date)) +                log.trace("zodiac sign based on month and date received.") +            except ValueError as e: +                final_embed = discord.Embed() +                final_embed.color = Colours.soft_red +                final_embed.description = f"Zodiac sign could not be found because.\n```{e}```" +                log.info(f'Error in "zodiac date" command:\n{e}.') +            else: +                final_embed = self.zodiac_build_embed(zodiac_sign_based_on_date) + +        await ctx.send(embed=final_embed) +        log.trace("Embed from date successfully sent.") + +    @zodiac.command(name="partnerzodiac", aliases=['partner']) +    async def partner_zodiac(self, ctx: commands.Context, zodiac_sign: str) -> None: +        """Provides a random counter compatible zodiac sign to the given user's zodiac sign.""" +        embed = discord.Embed() +        embed.color = Colours.pink +        zodiac_check = self.zodiacs.get(zodiac_sign.capitalize()) +        if zodiac_check: +            compatible_zodiac = random.choice(self.zodiacs[zodiac_sign.capitalize()]) +            emoji1 = random.choice(HEART_EMOJIS) +            emoji2 = random.choice(HEART_EMOJIS) +            embed.title = "Zodiac Compatibility" +            embed.description = ( +                f'{zodiac_sign.capitalize()}{emoji1}{compatible_zodiac["Zodiac"]}\n' +                f'{emoji2}Compatibility meter : {compatible_zodiac["compatibility_score"]}{emoji2}' +            ) +            embed.add_field( +                name=f'A letter from Dr.Zodiac {LETTER_EMOJI}', +                value=compatible_zodiac['description'] +            ) +        else: +            embed = self.generate_invalidname_embed(zodiac_sign)          await ctx.send(embed=embed) +        log.trace("Embed from date successfully sent.")  def setup(bot: commands.Bot) -> None: | 
