The main idea of the project is to create a platform for interactive audiobooks.
Users can listen to audiobooks and follow the story by listening to the chapters and picking the choices that will lead to different outcomes when prompted.
Current repository is a backend part of the project.
Concept:
- Python 3.11
- FastAPI
- SQLAlchemy + Alembic
- PostgreSQL
.
├── src <-- Main source code folder
│ ├── app.py <-- Entrypoint for FastAPI web-server
│ ├── settings.py <-- Settings file where all the environment variables are loaded
│ ├── core <-- Core folder where all the bussiness logic is stored
│ │ └── ...
│ ├── db <-- Models, db configuration and migrations are stored here
│ │ ├── models.py
│ │ └── migrations <-- Migrations folder
│ ├── repo <-- All the database operations related to each table are stored here
│ │ └── ...
│ ├── apis <-- All the endpoints are stored here
│ ├── schemas <-- Pydantic schemas for each model/endpoint response are stored here
│ ├── web <-- Includes the initialization of the web-server, auth and admin
│ │ └── ...
│ ├── exceptions
│ │ └── ...
│ ├── utils
│ │ └── ...
│ ├── templates
│ │ └── ...
│ └── scripts <-- Scripts for various tasks are stored here
│ └── ...
├── tests <-- Unit/Integration tests folder
│ └── ...
├── README.md
├── .gitignore
├── .flake8
├── alembic.ini <-- Alembic configuration
├── github/workflows/build.yaml <-- CI/CD pipeline
├── pyproject.toml <-- Poetry configuration file (all packages and their corresponding versions are stored here)
├── poetry.lock
├── Dockerfile
├── docker-compose.yml
├── docker_deploy.sh <-- Used for deploying the project to the server
├── db.env
├── web.env
Make sure that you have those environment files in the project root before running the application:
- db.env - all of the database related environment variables
- web.env
Example of db.env:
POSTGRES_PASSWORD=postgres
POSTGRES_DB=funny_dolphine
Example of web.env:
JWT_SECRET_KEY=secret
ADMIN_PASSWORD=***
API_KEY=***
- API_KEY - API key for all the application endpoints
- JWT_SECRET_KEY - secret key for JWT token
- ADMIN_PASSWORD - hash of the password for admin user generated by:
from passlib.context import CryptContext
print(CryptContext(schemes=["sha256_crypt"], deprecated="auto").hash("password"))
Create a new revision first:
$ alembic revision --autogenerate -m "Add new table"
Then run the migration:
$ alembic upgrade head
See more in Alembic documentation.
$ pytest
See more in pytest documentation.
Configuration of the app can be found at src/settings.py.
The alternative way to configure those variables is to set them up in the settings.py file or using export command in the terminal.
$ uvicorn main:app --reload
$ docker-compose up --build
You would need to create following Database trigger:
-- Create a function to update first_chapter_id in Audiobook
CREATE OR REPLACE FUNCTION update_first_chapter_id()
RETURNS TRIGGER AS $$
BEGIN
-- Check if first_chapter_id is NULL in Audiobook
IF NEW.audiobook_id IS NOT NULL AND NEW.parent_id IS NULL THEN
UPDATE audiobook
SET first_chapter_id = NEW.chapter_id
WHERE audiobook_id = NEW.audiobook_id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create a trigger to call the function before insert on Chapter
CREATE TRIGGER before_insert_chapter_trigger
AFTER INSERT ON chapter
FOR EACH ROW
EXECUTE FUNCTION update_first_chapter_id();
This will change in the future to be done automatically by alembic.