From 84bb04b7116f2faed3fb7a6d157482283c308111 Mon Sep 17 00:00:00 2001 From: Stijn De Clercq Date: Mon, 21 Jun 2021 20:43:36 +0200 Subject: [PATCH] Set up basics of SQLAlchemy --- database/__init__.py | 2 ++ database/db.py | 16 ++++++++++++++++ database/models.py | 16 ++++++++++++++++ database/utils.py | 11 +++++++++++ requirements.txt | 1 + settings.py | 28 +++++++++++++++------------- startup/didier.py | 4 ++++ 7 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 database/__init__.py create mode 100644 database/db.py create mode 100644 database/models.py create mode 100644 database/utils.py diff --git a/database/__init__.py b/database/__init__.py new file mode 100644 index 0000000..45576aa --- /dev/null +++ b/database/__init__.py @@ -0,0 +1,2 @@ +from .db import engine, session, Base +from .models import * diff --git a/database/db.py b/database/db.py new file mode 100644 index 0000000..5129ab7 --- /dev/null +++ b/database/db.py @@ -0,0 +1,16 @@ +from settings import DB_HOST, DB_NAME, DB_PASSWORD, DB_USERNAME, DB_DIALECT, DB_DRIVER +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker +from urllib.parse import quote_plus + +# Encode password +_encoded_pw = quote_plus(DB_PASSWORD) + +engine = create_engine( + # Format: dialect+driver://username:password@host:port/database + f"{DB_DIALECT}{'+' if DB_DRIVER else ''}{DB_DRIVER}://{DB_USERNAME}:{_encoded_pw}@{DB_HOST}/{DB_NAME}" +) +session = sessionmaker(bind=engine)() + +Base = declarative_base() diff --git a/database/models.py b/database/models.py new file mode 100644 index 0000000..f6a8072 --- /dev/null +++ b/database/models.py @@ -0,0 +1,16 @@ +from database import Base +from sqlalchemy import Column, String, Integer +from typing import List + + +class TestTable(Base): + + __tablename__ = "test_table" + + id = Column(Integer, autoincrement=True, primary_key=True) + name = Column(String, nullable=False) + + +# A list of all models in this file, this is used to +# create all tables later on +all_models: List[Base] = [TestTable] diff --git a/database/utils.py b/database/utils.py new file mode 100644 index 0000000..cd4b05e --- /dev/null +++ b/database/utils.py @@ -0,0 +1,11 @@ +from database import all_models, engine + + +def create_all_tables(): + """ + Create all tables in case they don't exist yet + so the user doesn't have to do this manually + when a new table is added + """ + for model in all_models: + model.__table__.create(engine, checkfirst=True) diff --git a/requirements.txt b/requirements.txt index 3f96792..5b66fd4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +sqlalchemy==1.4.18 python-dotenv==0.14.0 beautifulsoup4==4.9.1 discord.py==1.7.3 diff --git a/settings.py b/settings.py index 038fd89..b503dd7 100644 --- a/settings.py +++ b/settings.py @@ -15,25 +15,27 @@ def _to_bool(value: str) -> bool: # Sandbox or live -SANDBOX = _to_bool(os.getenv("SANDBOX", "true")) +SANDBOX: bool = _to_bool(os.getenv("SANDBOX", "true")) # Tokens & API keys -URBANDICTIONARY = os.getenv("URBANDICTIONARY", "") -IMGFLIP_NAME = os.getenv("IMGFLIPNAME", "") -IMGFLIP_PASSWORD = os.getenv("IMGFLIPPASSWORD", "") -UFORA_TOKEN = os.getenv("UFORA_TOKEN", "") +URBANDICTIONARY: str = os.getenv("URBANDICTIONARY", "") +IMGFLIP_NAME: str = os.getenv("IMGFLIPNAME", "") +IMGFLIP_PASSWORD: str = os.getenv("IMGFLIPPASSWORD", "") +UFORA_TOKEN: str = os.getenv("UFORA_TOKEN", "") # Database credentials -DB_USERNAME = os.getenv("DBUSERNAME", "") -DB_PASSWORD = os.getenv("DBPASSWORD", "") -DB_HOST = os.getenv("DBHOST", "") -DB_NAME = os.getenv("DBNAME", "") +DB_USERNAME: str = os.getenv("DBUSERNAME", "postgres") +DB_PASSWORD: str = os.getenv("DBPASSWORD", "") +DB_HOST: str = os.getenv("DBHOST", "localhost") +DB_NAME: str = os.getenv("DBNAME", "") +DB_DIALECT: str = os.getenv("DBDIALECT", "postgresql") +DB_DRIVER: str = os.getenv("DBDRIVER", "") # Discord-related -TOKEN = os.getenv("TOKEN", "") -HOST_IPC = _to_bool(os.getenv("HOSTIPC", "false")) -READY_MESSAGE = os.getenv("READYMESSAGE", "I'M READY I'M READY I'M READY I'M READY") # Yes, this is a Spongebob reference -STATUS_MESSAGE = os.getenv("STATUSMESSAGE", "with your Didier Dinks.") +TOKEN: str = os.getenv("TOKEN", "") +HOST_IPC: bool = _to_bool(os.getenv("HOSTIPC", "false")) +READY_MESSAGE: str = os.getenv("READYMESSAGE", "I'M READY I'M READY I'M READY I'M READY") # Yes, this is a Spongebob reference +STATUS_MESSAGE: str = os.getenv("STATUSMESSAGE", "with your Didier Dinks.") # Guilds to test slash commands in # Ex: 123,456,789 diff --git a/startup/didier.py b/startup/didier.py index 365df73..7110587 100644 --- a/startup/didier.py +++ b/startup/didier.py @@ -1,3 +1,4 @@ +from database.utils import create_all_tables from data.snipe import Snipe from discord.ext import commands, ipc from dislash import InteractionClient @@ -38,6 +39,9 @@ class Didier(commands.Bot): # Load all extensions self.init_extensions() + # Initialize database tables + create_all_tables() + # Check missing files check_all()