Skip to main content

Data Models & Core Design

·531 words·3 mins
Movie-Night Discord Bot - This article is part of a series.
Part 1: This Article

Data Models
#

Before going into any logic and what the bot itself is able to do, I would need to explain the building blocks and the foundations of bot, which are data classes. From the very begging of the first single file script I have decided I wanted to use a sqlite database, and not a CSV file, JSON or “sudo database”

The core design of the bot is made around a few key python classes, which are also what the database scheme was designed around. Most of the logic of the bot is in its custom light ORM layer which is made to map the sqlite data to the python object as all of the bot logic is written around this Python classes . The idea was to mimic how larger ORM’s like Sql alchemy and sqlmodel map attributes to database columns. The movies object is the most basic building block of the data structure of the bot.

The first basic building block of the data structure if the “Movie” class. It hold information about the movie itself. From the very begging I have decided to standardize the user input being an IMDb link, as its the most well known “Movie database”.

You might ask yourself where does the movie data come from? I have settled on the TMDB as the single source of truth for all the external data the bot requires. I will cover more about the TMDB in another section.

# The movie object which hold all the data for a movie (some methods are not included in this snippit)
@dataclass(kw_only=True)
class Movie:
    imdb_id: str
    tmdb_id: int
    title: str
    release_date: date | None
    runtime_mins: int
    genres: str
    original_language: str
    plot: str
    budget: int
    revenue: int
    tmdb_vote_average: float
    tmdb_vote_count: int
    poster_link: str

    __db_table_name__ = "movie_data"

    @classmethod
    def build_from_row(cls, row: Row) -> Movie:
        return cls(
            imdb_id=row["imdb_id"],
            tmdb_id=row["tmdb_id"],
            title=row["title"],
            release_date=date.fromisoformat(row["release_date"]) if row["release_date"] else None,
            runtime_mins=row["runtime_mins"],
            original_language=row["original_language"],
            genres=row["genres"],
            plot=row["plot"],
            budget=row["budget"],
            revenue=row["revenue"],
            tmdb_vote_average=row["tmdb_vote_average"],
            tmdb_vote_count=row["tmdb_vote_count"],
            poster_link=row["poster_link"],
        )

The other basic building block of the data structure of the bot is the Submission class, which holds in itself the submitter_id which is the snowflake id discord provides each user. As well as the IMDb id of the movie the user is submitting, the current season, as well as the status of the movie (which defaults to the “nominated” status)

# Submission class which hold infomraion about the submission user and movie id
@dataclass(kw_only=True)
class Submission:
    submitter_id: str
    imdb_id: str
    season_id: int
    status: str = "nominated"
    watched_date: Optional[date] = None
    __db_table_name__ = "movie_submissions"

    @classmethod
    def build_from_row(cls, row: Row) -> Submission:
        return Submission(
            submitter_id=row["submitter_id"],
            imdb_id=row["imdb_id"],
            season_id=row["season_id"],
            status=row["status"],
            watched_date=date.fromisoformat(row["watched_date"]) if row["watched_date"] else None,
        )

When combining both together they result in the core logic class which is used by almost every action in the bot has to preforms. They create the Movie Submissionclass, which is a child class of the Submission class, as it hold exactly the same information as the Submission class plus the nested Movie object that holds all the information about the movie which the submission is about.

@dataclass(kw_only=True)
class MovieSubmission(Submission):
    movie: Movie

    @classmethod
    def build_from_row(cls, row: Row) -> MovieSubmission:
        return MovieSubmission(
            submitter_id=row["submitter_id"],
            imdb_id=row["imdb_id"],
            season_id=row["season_id"],
            status=row["status"],
            watched_date=date.fromisoformat(row["watched_date"]) if row["watched_date"] else None,
            movie=Movie.build_from_row(row),
        )
Movie-Night Discord Bot - This article is part of a series.
Part 1: This Article