diff options
| -rw-r--r-- | bot/exts/__init__.py | 169 | ||||
| -rw-r--r-- | bot/exts/evergreen/branding.py | 2 | ||||
| -rw-r--r-- | bot/seasons.py | 157 | 
3 files changed, 160 insertions, 168 deletions
| diff --git a/bot/exts/__init__.py b/bot/exts/__init__.py index 5ebf34d8..ceb472d2 100644 --- a/bot/exts/__init__.py +++ b/bot/exts/__init__.py @@ -1,144 +1,13 @@  import logging  import pkgutil -from datetime import datetime  from pathlib import Path -from typing import List, Optional, Set, Type +from typing import List -from bot.constants import Colours, Month - -__all__ = ( -    "SeasonBase", -    "Christmas", -    "Easter", -    "Halloween", -    "Pride", -    "Valentines", -    "Wildcard", -    "get_season_names", -    "get_extensions", -    "get_current_season", -    "get_season", -) +__all__ = ("get_season_names", "get_extensions")  log = logging.getLogger(__name__) -class SeasonBase: -    """ -    Base for Seasonal classes. - -    This serves as the off-season fallback for when no specific -    seasons are active. - -    Seasons are 'registered' simply by inheriting from `SeasonBase`. -    We discover them by calling `__subclasses__`. -    """ - -    season_name: str = "Evergreen" -    bot_name: str = "SeasonalBot" - -    colour: str = Colours.soft_green -    description: str = "The default season!" - -    branding_path: str = "seasonal/evergreen" - -    months: Set[Month] = set(Month) - - -class Christmas(SeasonBase): -    """Branding for december.""" - -    season_name = "Festive season" -    bot_name = "Merrybot" - -    colour = Colours.soft_red -    description = ( -        "The time is here to get into the festive spirit! No matter who you are, where you are, " -        "or what beliefs you may follow, we hope every one of you enjoy this festive season!" -    ) - -    branding_path = "seasonal/christmas" - -    months = {Month.december} - - -class Easter(SeasonBase): -    """Branding for april.""" - -    season_name = "Easter" -    bot_name = "BunnyBot" - -    colour = Colours.bright_green -    description = ( -        "Bunny here, bunny there, bunny everywhere! Here at Python Discord, we celebrate " -        "our version of Easter during the entire month of April." -    ) - -    branding_path = "seasonal/easter" - -    months = {Month.april} - - -class Halloween(SeasonBase): -    """Branding for october.""" - -    season_name = "Halloween" -    bot_name = "NeonBot" - -    colour = Colours.orange -    description = "Trick or treat?!" - -    branding_path = "seasonal/halloween" - -    months = {Month.october} - - -class Pride(SeasonBase): -    """Branding for june.""" - -    season_name = "Pride" -    bot_name = "ProudBot" - -    colour = Colours.pink -    description = ( -        "The month of June is a special month for us at Python Discord. It is very important to us " -        "that everyone feels welcome here, no matter their origin, identity or sexuality. During the " -        "month of June, while some of you are participating in Pride festivals across the world, " -        "we will be celebrating individuality and commemorating the history and challenges " -        "of the LGBTQ+ community with a Pride event of our own!" -    ) - -    branding_path = "seasonal/pride" - -    months = {Month.june} - - -class Valentines(SeasonBase): -    """Branding for february.""" - -    season_name = "Valentines" -    bot_name = "TenderBot" - -    colour = Colours.pink -    description = "Love is in the air!" - -    branding_path = "seasonal/valentines" - -    months = {Month.february} - - -class Wildcard(SeasonBase): -    """Branding for august.""" - -    season_name = "Wildcard" -    bot_name = "RetroBot" - -    colour = Colours.purple -    description = "A season full of surprises!" - -    months = {Month.august} - -  def get_season_names() -> List[str]:      """Return names of all packages located in /bot/exts/."""      seasons = [ @@ -165,37 +34,3 @@ def get_extensions() -> List[str]:              extensions.append(f"bot.exts.{season}.{module.name}")      return extensions - - -def get_current_season() -> Type[SeasonBase]: -    """Give active season, based on current UTC month.""" -    current_month = Month(datetime.utcnow().month) - -    active_seasons = tuple( -        season -        for season in SeasonBase.__subclasses__() -        if current_month in season.months -    ) - -    if not active_seasons: -        return SeasonBase - -    if len(active_seasons) > 1: -        log.warning(f"Multiple active season in month {current_month.name}") - -    return active_seasons[0] - - -def get_season(name: str) -> Optional[Type[SeasonBase]]: -    """ -    Give season such that its class name or its `season_name` attr match `name` (caseless). - -    If no such season exists, return None. -    """ -    name = name.casefold() - -    for season in [SeasonBase] + SeasonBase.__subclasses__(): -        matches = (season.__name__.casefold(), season.season_name.casefold()) - -        if name in matches: -            return season diff --git a/bot/exts/evergreen/branding.py b/bot/exts/evergreen/branding.py index 6cbe3bd8..2eb563ea 100644 --- a/bot/exts/evergreen/branding.py +++ b/bot/exts/evergreen/branding.py @@ -12,7 +12,7 @@ from discord.ext import commands  from bot.bot import SeasonalBot  from bot.constants import Branding, Colours, Emojis, MODERATION_ROLES, Tokens -from bot.exts import SeasonBase, get_current_season, get_season +from bot.seasons import SeasonBase, get_current_season, get_season  from bot.utils.decorators import with_role  from bot.utils.exceptions import BrandingError diff --git a/bot/seasons.py b/bot/seasons.py new file mode 100644 index 00000000..83a584fd --- /dev/null +++ b/bot/seasons.py @@ -0,0 +1,157 @@ +import logging +import typing as t +from datetime import datetime + +from bot.constants import Colours, Month + +log = logging.getLogger(__name__) + + +class SeasonBase: +    """ +    Base for Seasonal classes. + +    This serves as the off-season fallback for when no specific +    seasons are active. + +    Seasons are 'registered' simply by inheriting from `SeasonBase`. +    We discover them by calling `__subclasses__`. +    """ + +    season_name: str = "Evergreen" +    bot_name: str = "SeasonalBot" + +    colour: str = Colours.soft_green +    description: str = "The default season!" + +    branding_path: str = "seasonal/evergreen" + +    months: t.Set[Month] = set(Month) + + +class Christmas(SeasonBase): +    """Branding for december.""" + +    season_name = "Festive season" +    bot_name = "Merrybot" + +    colour = Colours.soft_red +    description = ( +        "The time is here to get into the festive spirit! No matter who you are, where you are, " +        "or what beliefs you may follow, we hope every one of you enjoy this festive season!" +    ) + +    branding_path = "seasonal/christmas" + +    months = {Month.december} + + +class Easter(SeasonBase): +    """Branding for april.""" + +    season_name = "Easter" +    bot_name = "BunnyBot" + +    colour = Colours.bright_green +    description = ( +        "Bunny here, bunny there, bunny everywhere! Here at Python Discord, we celebrate " +        "our version of Easter during the entire month of April." +    ) + +    branding_path = "seasonal/easter" + +    months = {Month.april} + + +class Halloween(SeasonBase): +    """Branding for october.""" + +    season_name = "Halloween" +    bot_name = "NeonBot" + +    colour = Colours.orange +    description = "Trick or treat?!" + +    branding_path = "seasonal/halloween" + +    months = {Month.october} + + +class Pride(SeasonBase): +    """Branding for june.""" + +    season_name = "Pride" +    bot_name = "ProudBot" + +    colour = Colours.pink +    description = ( +        "The month of June is a special month for us at Python Discord. It is very important to us " +        "that everyone feels welcome here, no matter their origin, identity or sexuality. During the " +        "month of June, while some of you are participating in Pride festivals across the world, " +        "we will be celebrating individuality and commemorating the history and challenges " +        "of the LGBTQ+ community with a Pride event of our own!" +    ) + +    branding_path = "seasonal/pride" + +    months = {Month.june} + + +class Valentines(SeasonBase): +    """Branding for february.""" + +    season_name = "Valentines" +    bot_name = "TenderBot" + +    colour = Colours.pink +    description = "Love is in the air!" + +    branding_path = "seasonal/valentines" + +    months = {Month.february} + + +class Wildcard(SeasonBase): +    """Branding for august.""" + +    season_name = "Wildcard" +    bot_name = "RetroBot" + +    colour = Colours.purple +    description = "A season full of surprises!" + +    months = {Month.august} + + +def get_current_season() -> t.Type[SeasonBase]: +    """Give active season, based on current UTC month.""" +    current_month = Month(datetime.utcnow().month) + +    active_seasons = tuple( +        season +        for season in SeasonBase.__subclasses__() +        if current_month in season.months +    ) + +    if not active_seasons: +        return SeasonBase + +    if len(active_seasons) > 1: +        log.warning(f"Multiple active season in month {current_month.name}") + +    return active_seasons[0] + + +def get_season(name: str) -> t.Optional[t.Type[SeasonBase]]: +    """ +    Give season such that its class name or its `season_name` attr match `name` (caseless). + +    If no such season exists, return None. +    """ +    name = name.casefold() + +    for season in [SeasonBase] + SeasonBase.__subclasses__(): +        matches = (season.__name__.casefold(), season.season_name.casefold()) + +        if name in matches: +            return season | 
