Skip to content

Commit

Permalink
Generic cleaning.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sachaa-Thanasius committed Jul 23, 2024
1 parent 4820311 commit 21cdcfe
Show file tree
Hide file tree
Showing 20 changed files with 178 additions and 578 deletions.
23 changes: 12 additions & 11 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "Beira"
version = "2024.06.22"
version = "2024.07.22"
description = "An personal Discord bot made in Python."
readme = "README.md"
license = { file = "LICENSE" }
Expand All @@ -13,7 +13,7 @@ authors = [
Homepage = "https://github.com/Sachaa-Thanasius/Beira"

[tool.ruff]
include = ["src/beira/**/*.py", "misc/**/*.py"]
include = ["src/**/*.py", "misc/**/*.py"]
line-length = 120
target-version = "py312"

Expand Down Expand Up @@ -56,10 +56,11 @@ ignore = [
"SIM105", # Suppressable exception. contextlib.suppress is a stylistic choice with overhead.
"ANN101", # Type of Self for self is usually implicit.
"ANN102", # Type of type[Self] for cls is usually implicit.
"ANN204", # Special method return types are usually implicit or known by type checkers.
"ANN204", # Return types for magic methods are usually inferred or known.
"ANN401", # Any is necessary sometimes.
"PT001", # pytest recommends against empty parentheses on pytest.fixture.
"UP038", # isinstance performs better with tuples than unions.
"RUF001", # Allow ambiguous characters.
# == Recommended ignores by ruff when using ruff format.
"E111",
"E114",
Expand All @@ -72,11 +73,8 @@ ignore = [
"ISC001",
"ISC002",
# == Project-specific ignores.
"S311", # No need for cryptographically secure number generation in this use case; it's just dice rolls.
"PLR0911", # Unlimited returns.
"PLR0912", # Unlimited branches.
"PLR0913", # Unlimited arguments.
"PYI036", # Bug with annotations for __(a)exit__ if a placeholder for a needed type exists in the else clause of an `if TYPE_CHECKING` block.
"S311", # No need for cryptographically secure number generation in this use case; it's just dice rolls.
# "PLR", # Allow complexity.
]
unfixable = [
"ERA", # Don't want erroneous deletion of comments.
Expand All @@ -94,11 +92,14 @@ lines-after-imports = 2
combine-as-imports = true

[tool.pyright]
include = ["src/beira"]
include = ["src"]
pythonVersion = "3.12"
typeCheckingMode = "strict"

# reportImportCycles = "warning"
reportCallInDefaultInitializer = "warning"
reportImportCycles = "warning"
reportPropertyTypeMismatch = "warning"
reportShadowedImports = "error"
reportUninitializedInstanceVariable = "warning"
reportUnnecessaryTypeIgnoreComment = "warning"
enableExperimentalFeatures = true

12 changes: 8 additions & 4 deletions src/beira/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,21 +90,21 @@ class Beira(commands.Bot):
Arbitrary keyword arguments, primarily for `commands.Bot`. See that class for more information.
"""

logging_manager: LoggingManager

def __init__(
self,
*args: Any,
config: Config,
db_pool: Pool_alias,
web_session: aiohttp.ClientSession,
logging_manager: LoggingManager,
initial_extensions: list[str] | None = None,
**kwargs: Any,
) -> None:
super().__init__(*args, **kwargs)
self.config = config
self.db_pool = db_pool
self.web_session = web_session
self.logging_manager = logging_manager
self.initial_extensions: list[str] = initial_extensions or []

# Various webfiction-related clients.
Expand Down Expand Up @@ -160,7 +160,11 @@ async def get_context(self, origin: discord.Message | discord.Interaction, /) ->

@overload
async def get_context[ContextT: commands.Context[Any]](
self, origin: discord.Message | discord.Interaction, /, *, cls: type[ContextT]
self,
origin: discord.Message | discord.Interaction,
/,
*,
cls: type[ContextT],
) -> ContextT: ...

async def get_context[ContextT: commands.Context[Any]](
Expand Down Expand Up @@ -353,10 +357,10 @@ async def main() -> None:
config=config,
db_pool=pool,
web_session=web_session,
logging_manager=logging_manager,
intents=intents,
tree_cls=HookableTree,
) as bot:
bot.logging_manager = logging_manager
await bot.start(config.discord.token)

# Needed for graceful exit?
Expand Down
2 changes: 1 addition & 1 deletion src/beira/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


if TYPE_CHECKING:
from discord.ext.commands._types import Check # type: ignore [reportMissingTypeStubs]
from discord.ext.commands._types import Check # pyright: ignore [reportMissingTypeStubs]


class AppCheck(Protocol):
Expand Down
31 changes: 11 additions & 20 deletions src/beira/config.py
Original file line number Diff line number Diff line change
@@ -1,56 +1,45 @@
"""For loading configuration information, such as api keys and tokens, default prefixes, etc."""

import pathlib
from typing import Any

import msgspec


__all__ = ("Config", "load_config")


class Base(msgspec.Struct):
"""A base class to hold some common functions."""

def to_dict(self) -> dict[str, Any]:
return msgspec.structs.asdict(self)

def to_tuple(self) -> tuple[Any, ...]:
return msgspec.structs.astuple(self)


class UserPassConfig(Base):
class UserPassConfig(msgspec.Struct):
user: str
password: str


class KeyConfig(Base):
class KeyConfig(msgspec.Struct):
key: str


class SpotifyConfig(Base):
class SpotifyConfig(msgspec.Struct):
client_id: str
client_secret: str


class LavalinkConfig(Base):
class LavalinkConfig(msgspec.Struct):
uri: str
password: str


class PatreonConfig(Base):
class PatreonConfig(msgspec.Struct):
client_id: str
client_secret: str
creator_access_token: str
creator_refresh_token: str
patreon_guild_id: int


class DatabaseConfig(Base):
class DatabaseConfig(msgspec.Struct):
pg_url: str


class DiscordConfig(Base):
class DiscordConfig(msgspec.Struct):
token: str
default_prefix: str
logging_webhook: str
Expand All @@ -59,7 +48,7 @@ class DiscordConfig(Base):
webhooks: list[str] = msgspec.field(default_factory=list)


class Config(Base):
class Config(msgspec.Struct):
discord: DiscordConfig
database: DatabaseConfig
patreon: PatreonConfig
Expand All @@ -72,10 +61,12 @@ class Config(Base):


def decode(data: bytes | str) -> Config:
"""Decode a TOMl file with the `Config` schema."""
"""Decode a TOML file with the Config schema."""

return msgspec.toml.decode(data, type=Config)


def load_config() -> Config:
"""Load the contents of a "config.toml" file into a Config struct."""

return decode(pathlib.Path("config.toml").read_text(encoding="utf-8"))
29 changes: 17 additions & 12 deletions src/beira/errors.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
"""Custom errors used by the bot."""

from collections.abc import Callable, Coroutine
from typing import Any

import discord
from discord import app_commands
from discord.ext import commands


AppCheckFunc = app_commands.commands.Check
# Copied from discord.app_commands.commands.Check.
type AppCheckFunc = Callable[[discord.Interaction[Any]], bool | Coroutine[Any, Any, bool]]


__all__ = (
Expand All @@ -21,14 +26,14 @@
class CannotTargetSelf(commands.BadArgument):
"""Exception raised when the member provided as a target was also the command invoker.
This inherits from :exc:`commands.BadArgument`.
This inherits from commands.BadArgument.
"""


class NotOwnerOrFriend(commands.CheckFailure):
"""Exception raised when the message author is not the owner of the bot or on the special friends list.
This inherits from :exc:`CheckFailure`.
This inherits from CheckFailure.
"""

def __init__(self, message: str | None = None) -> None:
Expand All @@ -38,7 +43,7 @@ def __init__(self, message: str | None = None) -> None:
class NotAdmin(commands.CheckFailure):
"""Exception raised when the message author is not an administrator of the guild in the current context.
This inherits from :exc:`commands.CheckFailure`.
This inherits from commands.CheckFailure.
"""

def __init__(self, message: str | None = None) -> None:
Expand All @@ -48,7 +53,7 @@ def __init__(self, message: str | None = None) -> None:
class NotInBotVoiceChannel(commands.CheckFailure):
"""Exception raised when the message author is not in the same voice channel as the bot in a context's guild.
This inherits from :exc:`commands.CheckFailure`.
This inherits from commands.CheckFailure.
"""

def __init__(self, message: str | None = None) -> None:
Expand All @@ -58,7 +63,7 @@ def __init__(self, message: str | None = None) -> None:
class UserIsBlocked(commands.CheckFailure):
"""Exception raised when the message author is blocked from using the bot.
This inherits from :exc:`commands.CheckFailure`.
This inherits from commands.CheckFailure.
"""

def __init__(self, message: str | None = None) -> None:
Expand All @@ -68,23 +73,23 @@ def __init__(self, message: str | None = None) -> None:
class GuildIsBlocked(commands.CheckFailure):
"""Exception raised when the message guild is blocked from using the bot.
This inherits from :exc:`commands.CheckFailure`.
This inherits from commands.CheckFailure.
"""

def __init__(self, message: str | None = None) -> None:
super().__init__(message or "This guild is prohibited from using bot commands.")


class CheckAnyFailure(app_commands.CheckFailure):
"""Exception raised when all predicates in :func:`check_any` fail.
"""Exception raised when all predicates in `check_any` fail.
This inherits from :exc:`app_commands.CheckFailure`.
This inherits from app_commands.CheckFailure.
Attributes
------------
errors: list[`app_commands.CheckFailure`]
----------
errors: list[app_commands.CheckFailure]
A list of errors that were caught during execution.
checks: List[Callable[[`discord.Interaction`], `bool`]]
checks: List[Callable[[discord.Interaction], bool]]
A list of check predicates that failed.
"""

Expand Down
2 changes: 1 addition & 1 deletion src/beira/exts/dice.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def roll_custom_dice_expression(expression: str) -> tuple[str, int]:
components.append(sum(rolls))
else:
return f"(Invalid expression; expected number or dice expression, not {part!r})", 0
else: # noqa: PLR5501
else:
if part == "-":
operations.append(operator.sub)
elif part == "+":
Expand Down
1 change: 1 addition & 0 deletions src/beira/exts/patreon.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ def __init__(self, bot: beira.Beira) -> None:
self.bot = bot
self.access_token = bot.config.patreon.creator_access_token
self.patrons_on_discord: dict[str, list[discord.Member]] = {}
self.patreon_tiers_info: list[PatreonTierInfo] = []

@property
def cog_emoji(self) -> discord.PartialEmoji:
Expand Down
5 changes: 4 additions & 1 deletion src/beira/exts/timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ async def parse_bcp47_timezones(session: aiohttp.ClientSession) -> dict[str, str
class TimingCog(commands.Cog, name="Timing"):
def __init__(self, bot: beira.Beira) -> None:
self.bot = bot
self.timezone_aliases: dict[str, str] = {}

async def cog_load(self) -> None:
self.timezone_aliases: dict[str, str] = await parse_bcp47_timezones(self.bot.web_session)
Expand Down Expand Up @@ -155,7 +156,9 @@ async def timezone_info(self, ctx: beira.Context, tz: str) -> None:
@timezone_set.autocomplete("tz")
@timezone_info.autocomplete("tz")
async def timezone_autocomplete(
self, itx: beira.Interaction, current: str
self,
itx: beira.Interaction,
current: str,
) -> list[discord.app_commands.Choice[str]]:
if not current:
return [
Expand Down
4 changes: 2 additions & 2 deletions src/beira/exts/triggers/misc_triggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
import beira


LOGGER = logging.getLogger(__name__)

type ValidGuildChannel = (
discord.VoiceChannel | discord.StageChannel | discord.ForumChannel | discord.TextChannel | discord.CategoryChannel
)
Expand Down Expand Up @@ -49,6 +47,8 @@
LOSSY_TWITTER_LINK_PATTERN = re.compile(r"(?:http(?:s)?://|(?<!\S))(?:twitter|x)\.com/.+")
LOSSY_9GAG_LINK_PATTERN = re.compile(r"(?:http(?:s)?://)9gag\.com/gag/[\S]*")

LOGGER = logging.getLogger(__name__)


class MiscTriggersCog(commands.Cog):
def __init__(self, bot: beira.Beira) -> None:
Expand Down
1 change: 1 addition & 0 deletions src/beira/exts/triggers/rss_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class RSSNotificationsCog(commands.Cog):

def __init__(self, bot: beira.Beira) -> None:
self.bot = bot
self.records: list[NotificationRecord] = []
# self.notification_check_loop.start()

async def cog_unload(self) -> None:
Expand Down
Loading

0 comments on commit 21cdcfe

Please sign in to comment.