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

Contemplative Constellations #2

Open
wants to merge 203 commits into
base: main
Choose a base branch
from
Open

Conversation

janine9vn
Copy link
Contributor

No description provided.

ItsDrike and others added 29 commits July 28, 2024 15:27
Tvdb UI classes rework + profile command + view error handling
Prevent interaction with views by others
📝 Add presentation and images
…a5cfb91fba5f496bb93f'

git-subtree-dir: contemplative-constellations
git-subtree-mainline: 196cae3
git-subtree-split: 401cc3a
Copy link
Contributor Author

@janine9vn janine9vn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README

The README is great from a developer point of view. I would include more information from your presentation itself to describe what the project does. It's not immediately obvious that you have a presentation without a direct link, so I think either duplicating some of the content in the README itself or linking to the presentation directly can go a long way.

The presentation is solid. It explains and showcases the features nicely.

Commit Quality

Commits seem solid as a whole with good name and convention descriptions. Some commits could be improved in general ("clean up some code" or "fix"), but that's always the case with bigger projects during a time crunch.

Code Quality

The code overall is very well written and easy to follow. There are some cases where I think the code is rather dense and could use a combination of linebreaks and more descriptive docstrings. There are other cases where the comments and additional documentation provides a lot of context as to some decisions made in the code, so that was great to see.

I think the utils/ folder is a bit unnecessarily saturated and some functions could be re-located closer to where they are being used.

The care taken to implement rate limits and caching so as not to stress the API is very appreciated. The models used to represent the different API results is well done as well. The discord library is also handled well. There is one instance, when displaying favorite in the profile, where a lack of truncating or pagination could cause trouble. So I would be weary there and a few other places that end up truncating without informing the end user.

The Complete Picture

The project concept is a simple on: interact with the TVDB api to help users manage and showcase which TV shows and media they like directly from a Discord server. It fulfills our theme and tech requirement. The code implementation shows a great deal of care and thought. It's also easy to read and mostly easy to navigate as well, if you're familiar with the additional libraries being used.

It would have been nice to see a few more features supported beyond searching, favoriting, and viewing profiles. But I understand we did ask you to complete this project in 10 days from the ground up--so there's only so much you can do.

Overall, very nicely done! I really enjoyed reviewing this project and I could see this being very useful in discord servers that like to chat about TV shows and movies.

self.db_session = db_session
self.cache = cache

self.event(self.on_ready)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A slightly unusual choice to do this rather than use the typical decorator.

Comment on lines +36 to +40
type JSON_DATA = dict[str, JSON_DATA] | list[JSON_DATA] | str | int | float | bool | None # noice

type SeriesRecord = SeriesBaseRecord | SeriesExtendedRecord
type MovieRecord = MovieBaseRecord | MovieExtendedRecord
type AnyRecord = SeriesRecord | MovieRecord
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice usage of the new type statement to create type aliases

Comment on lines +43 to +47
class FetchMeta(Enum):
"""When calling fetch with extended=True, this is used if we want to fetch translations or episodes as well."""

TRANSLATIONS = "translations"
EPISODES = "episodes"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at your usage of this later, you could benefit from using StrEnum here.

Comment on lines +67 to +68
if data is None:
raise ValueError("Data can't be None but is allowed to because of the broken pydantic generated models.")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably needs a more in-depth comment to explain what's going on here. It's kind of clear what's going on, but a more detailed commented for future-you/other developers would help.

) -> Self: ...

@classmethod
async def fetch(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function could use a bit more information as to what it does, either in the docstring or as comments in the body. It wouldn't be immediately clear to me that it checks the cache in this function based on the docstring and the name.

The code is fairly efficient but also dense with no line breaks between different if-blocks. It can take someone who is new to the codebase a bit longer to parse out exactly what's happening where and why.

)
embed.add_field(name="Stats", value=stats_str, inline=False)

# TODO: What if there's too many things here, we might need to paginate this.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems for favorite you don't truncate like you do for the selections. I also don't see any checking for going over the limit of what can be contained in an embed. That case is worth checking for and, at minimum, truncating if you're in danger of going over the embed limit or truncating after a certain amount of favorites.

Comment on lines +6 to +14
async def get_cat_image_url(http_session: aiohttp.ClientSession) -> str:
"""Get a URL for a random cat image.

The produced image can also be a GIF.
"""
async with http_session.get(CAT_API_URL) as resp:
resp.raise_for_status()
data = await resp.json()
return data[0]["url"]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things here:

  1. I love that you're using the cat api to pull a random cat image/GIF
  2. As far as I can tell this is only used in the help embed. I'd rather pull this function into that cog rather than put it in the generic utils folder, where it's unclear what its purpose is.

In general I prefer the utils/ folders to be true utilities that are actively used by multiple places in a system. I don't think it's worth pre-emptively putting non-generic utils in a utils/ folder in case you might use it in a different place later.

get_logger(logger_name).setLevel(TRACE_LEVEL)


def _setup_external_log_levels(root_log: LoggerClass) -> None:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't use root_log at all, do you need it? You always do get_logger() in the function itself.

Comment on lines +6 to +8
def mention_command(command: discord.ApplicationCommand[Any, ..., Any]) -> str:
"""Mentions the command using discord markdown."""
return f"</{command.qualified_name}:{command.qualified_id}>"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only used in the help command, I would just relocate it to that file since this isn't very general in terms of usage.

Comment on lines +7 to +12
def by_season(episodes: list["Episode"]) -> dict[int, list["Episode"]]:
"""Group episodes by season."""
seasons = {}
for episode in episodes:
seasons.setdefault(episode.season_number, []).append(episode)
return seasons
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the other comments I've left, this seems hyper-specific to Episodes. Why put it in utils/?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants