Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add static typecheck system to poetry #114

Merged
merged 10 commits into from
Jun 30, 2023
Merged
287 changes: 192 additions & 95 deletions poetry.lock

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,15 @@ pytest = "^7.3.1"
pytest-datafiles = "^3.0.0"
python-dotenv = "^1.0.0"
black = "^23.3.0"
pyright = "^1.1.0"
types-requests = "^2.30.0.0"
types-beautifulsoup4 = "^4.12.0.4"
types-python-dateutil = "^2.8.19.12"
types-pytz = "^2023.3.0.0"

[build-system]
requires = ["poetry-core>=1.3.0"]
build-backend = "poetry.core.masonry.api"

[tool.pyright]
strict = ['**']
18 changes: 15 additions & 3 deletions uqcsbot/advent.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,21 @@
from uqcsbot.bot import UQCSBot
from uqcsbot.models import AOCWinner
from uqcsbot.utils.command_utils import loading_status
from uqcsbot.utils.err_log_utils import FatalErrorWithLog

# Leaderboard API URL with placeholders for year and code.
LEADERBOARD_URL = "https://adventofcode.com/{year}/leaderboard/private/view/{code}.json"

# Session cookie (will expire in approx 30 days).
# See: https://github.com/UQComputingSociety/uqcsbot-discord/wiki/Tokens-and-Environment-Variables#aoc_session_id
SESSION_ID = os.environ.get("AOC_SESSION_ID")
SESSION_ID: str = ""

# UQCS leaderboard ID.
UQCS_LEADERBOARD = 989288

# Days in Advent of Code. List of numbers 1 to 25.
ADVENT_DAYS = list(range(1, 25 + 1))

# Puzzles are unlocked at midnight EST.
EST_TIMEZONE = timezone(timedelta(hours=-5))

Expand Down Expand Up @@ -334,7 +338,7 @@ def parse_arguments(self, argv: List[str]) -> Namespace:
def usage_error(message, *args, **kwargs):
raise ValueError(message)

parser.error = usage_error # type: ignore
parser.error = usage_error

args = parser.parse_args(argv)

Expand All @@ -343,7 +347,7 @@ def usage_error(message, *args, **kwargs):

return args

def get_leaderboard(self, year: int, code: int) -> Dict:
def get_leaderboard(self, year: int, code: int) -> Optional[Dict]:
"""
Returns a json dump of the leaderboard
"""
Expand Down Expand Up @@ -542,5 +546,13 @@ async def advent_winners(


async def setup(bot: UQCSBot):
if os.environ.get("AOC_SESSION_ID") is not None:
SESSION_ID = os.environ.get("AOC_SESSION_ID")
andrewj-brown marked this conversation as resolved.
Show resolved Hide resolved
else:
raise FatalErrorWithLog(
bot, "Unable to find AoC session ID. Not loading advent cog."
)

cog = Advent(bot)

await bot.add_cog(cog)
6 changes: 3 additions & 3 deletions uqcsbot/basic.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import List
from typing import List, Any
from mypy_extensions import VarArg, KwArg

import discord
from discord import app_commands
Expand Down Expand Up @@ -98,8 +99,7 @@ async def repo_list(self, interaction: discord.Interaction):
+ self.format_repo_message(list(REPOS.keys()))
)

@repo_group.command(name="find")
@app_commands.describe(name="Name of the repo to find")
@repo_group.command(name="find", description="Name of the repo to find")
async def repo_find(self, interaction: discord.Interaction, name: str):
"""Finds a specific UQCS GitHub repository"""
await interaction.response.send_message(
Expand Down
8 changes: 4 additions & 4 deletions uqcsbot/bot.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging
import os
from typing import List
from typing import List, Optional
import discord
from discord.ext import commands
from apscheduler.schedulers.asyncio import AsyncIOScheduler
Expand Down Expand Up @@ -35,9 +35,9 @@ async def admin_alert(
self,
title: str,
colour: discord.Colour,
description: str = None,
footer: str = None,
fields: List[tuple] = None,
description: Optional[str] = None,
footer: Optional[str] = None,
fields: Optional[List[tuple]] = None,
andrewj-brown marked this conversation as resolved.
Show resolved Hide resolved
fields_inline: bool = True,
):
"""Sends an alert to the admin channel for logging."""
Expand Down
6 changes: 3 additions & 3 deletions uqcsbot/cowsay.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def draw_cow(
"""

# Set the tongue if the cow is dead or if the tongue is set to True.
tongue = "U" if tongue or mood == "Dead" else " "
tongue_out = "U" if tongue or mood == "Dead" else " "

# Set the bubble connection based on whether the cow is thinking or
# speaking.
Expand All @@ -157,7 +157,7 @@ def draw_cow(
cow = f" {bubble_connect} ^__^\n"
cow += f" {bubble_connect} ({cow_eyes})\_______\n"
cow += f" (__)\ )\/\ \n"
cow += f" {tongue} ||----w |\n"
cow += f" {tongue_out} ||----w |\n"
cow += f" || ||\n"
return cow

Expand Down Expand Up @@ -242,7 +242,7 @@ def word_wrap(message: str, wrap: int) -> List[str]:
# As requested by the audience, you can manually break lines by
# adding "\n" anywhere in the message and it will be respected.
if "\\n" in word:
parts: str = word.split("\\n", 1)
parts: List[str] = word.split("\\n", 1)

# The `\n` is by itself, so start a new line.
if parts[0] == "" and parts[1] == "":
Expand Down
66 changes: 36 additions & 30 deletions uqcsbot/models.py
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
from sqlalchemy.orm import declarative_base
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import (
BigInteger,
Boolean,
Column,
Date,
DateTime,
Integer,
String,
Time,
)
from typing import Optional
from datetime import datetime

Base = declarative_base()


# Used for linking a message to a bot function.
# Previously used for the channel cog, currently unused.
class Message(Base):
__tablename__ = "messages"

id = Column("id", BigInteger, primary_key=True, nullable=False)
type = Column("type", String, nullable=False)
class Base(DeclarativeBase):
pass


class AOCWinner(Base):
__tablename__ = "aoc_winner"

id = Column("id", BigInteger, primary_key=True, nullable=False)
aoc_userid = Column("aoc_userid", Integer, nullable=False)
year = Column("year", Integer, nullable=False)
id: Mapped[int] = mapped_column("id", BigInteger, primary_key=True, nullable=False)
aoc_userid: Mapped[int] = mapped_column("aoc_userid", Integer, nullable=False)
year: Mapped[int] = mapped_column("year", Integer, nullable=False)


class MCWhitelist(Base):
__tablename__ = "mc_whitelisted"

mc_username = Column("mcuser", String, primary_key=True, nullable=False)
discord_id = Column("discordid", BigInteger, nullable=False)
admin_whitelisted = Column("adminwl", Boolean)
added_dt = Column("added_dt", DateTime, nullable=False)
mc_username: Mapped[str] = mapped_column(
"mcuser", String, primary_key=True, nullable=False
)
discord_id: Mapped[str] = mapped_column("discordid", BigInteger, nullable=False)
admin_whitelisted: Mapped[Optional[bool]] = mapped_column("adminwl", Boolean)
added_dt: Mapped[datetime] = mapped_column("added_dt", DateTime, nullable=False)


class Reminders(Base):
__tablename__ = "reminders"

id = Column("id", BigInteger, primary_key=True, nullable=False)
user_id = Column("user_id", BigInteger, nullable=False)
channel_id = Column("channel_id", BigInteger, nullable=True)
time_created = Column("time_created", DateTime, nullable=False)
message = Column("message", String, nullable=False)
time = Column("time", Time, nullable=False)
start_date = Column("start_date", Date, nullable=False)
end_date = Column("end_date", Date, nullable=True)
week_frequency = Column("week_frequency", Integer, nullable=True)
id: Mapped[int] = mapped_column("id", BigInteger, primary_key=True, nullable=False)
user_id: Mapped[int] = mapped_column("user_id", BigInteger, nullable=False)
channel_id: Mapped[Optional[int]] = mapped_column(
andrewj-brown marked this conversation as resolved.
Show resolved Hide resolved
"channel_id", BigInteger, nullable=True
)
time_created: Mapped[int] = mapped_column("time_created", DateTime, nullable=False)
message: Mapped[str] = mapped_column("message", String, nullable=False)
time = mapped_column("time", Time, nullable=False)
start_date = mapped_column("start_date", Date, nullable=False)
end_date = mapped_column("end_date", Date, nullable=True)
andrewj-brown marked this conversation as resolved.
Show resolved Hide resolved
week_frequency: Mapped[int] = mapped_column(
"week_frequency", Integer, nullable=True
)


class Starboard(Base):
Expand All @@ -61,6 +61,12 @@ class Starboard(Base):
# recv == null implies deleted recv message.
# recv_location == null implies deleted recv channel. recv should also be null.
# sent == null implies blacklisted recv message.
recv = Column("recv", BigInteger, primary_key=True, nullable=True)
recv_location = Column("recv_location", BigInteger, nullable=True, unique=False)
sent = Column("sent", BigInteger, primary_key=True, nullable=True, unique=True)
recv: Mapped[int] = mapped_column(
"recv", BigInteger, primary_key=True, nullable=True
)
recv_location: Mapped[int] = mapped_column(
"recv_location", BigInteger, nullable=True, unique=False
)
sent: Mapped[int] = mapped_column(
"sent", BigInteger, primary_key=True, nullable=True, unique=True
)