diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..99bd07d --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +logs/ +data/ +src/__pycache__/ +.git +*.md +.venv +LICENSE +MAKEFILE +pytest.ini +test/ + diff --git a/.gitignore b/.gitignore index 6e93763..be40467 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,9 @@ # Test running file main_test.py -# databases -*.db - -# Custom Tokens file/rotator -tokens.json +# data dir +data/* +data-docker/ # Visual Studio Code .vscode/ diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 45f0f04..0000000 --- a/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM alpine:latest - -WORKDIR /root - -RUN apk update && \ - apk add --no-cache \ - openssh \ - python3 \ - py3-pip \ - sqlite - -EXPOSE 22 - -RUN mkdir /root/src - -COPY ./startup.sh /root -COPY ./requirements.txt /root -COPY ./src/ /root/src/ - -RUN ls -la - -VOLUME /root - -ENTRYPOINT ["/bin/sh", "/root/startup.sh"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..89a5710 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +.PHONY: all dockerfile clean + +TAG="unstable" +PROJ_NAME="predictify" + +all: install dockerfile + +install: + mkdir -p ./data + +dockerfile: ./docker/Dockerfile + docker build \ + --tag "$(PROJ_NAME):$(TAG)" \ + --build-arg PROJ_NAME=$(PROJ_NAME) \ + --file ./docker/Dockerfile \ + . + +clean: ./spotify_scraped.db + rm -r ./data/spotify_scraped.db diff --git a/README.md b/README.md index f0a6c4a..b6a4366 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,41 @@ A Data analysis tool to scrape your Spotify History usage and let a ML-Model pre ## Usable possible APIs -Recently Played Tracks: /me/player/recently-played [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-recently-played) +Recently Played Tracks: `/me/player/recently-played` [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-recently-played) -Get Track: /tracks/{id} [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-track) +Get Track: `/tracks/{id}` [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-track) -Get Track's Audio Features - Deprecated: /audio-features/{id} [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-audio-features) +Get Track's Audio Features _(Deprecated)_: `/audio-features/{id}` [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-audio-features) -Get Track's Audio Analysis - Deprecated: /audio-analysis/{id} [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-audio-analysis) +Get Track's Audio Analysis _(Deprecated)_: `/audio-analysis/{id}` [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-audio-analysis) -Get Artist: /artists/{id} [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-an-artist) +Get Artist: `/artists/{id}` [Official Spotify Documentation](https://developer.spotify.com/documentation/web-api/reference/get-an-artist) + +## Docker usage + +`cd` inside the projects directory: +```sh +cd predictify +``` +To run predictify inside a container, first make sure to build the image: +```sh +make dockerfile +``` +Create a seperate data directory (e.g. `docker-data`): +```sh +mkdir docker-data +``` +> [!NOTE] +> To detatch the container to run it in the background add the `--detach` directly after the `run` command. +Then run the following docker command, to run the container in the foreground: +```sh +docker run \ + --name predictify \ + --network=host \ + --volume $(pwd)/data-docker:/app/predictify/data \ + --volume $(pwd)/config:/app/predictify/config \ + predictify:unstable +``` ## Authors diff --git a/src/env/.env.example b/config/.env.example similarity index 100% rename from src/env/.env.example rename to config/.env.example diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..5e86c2c --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,35 @@ +FROM alpine:3.21.3 + +# Set environment variables +ARG PROJ_NAME +ENV PROJ_NAME=${PROJ_NAME} + +RUN mkdir -p /app/${PROJ_NAME} + +# The following steps are executed from the specified directory below +WORKDIR /app/${PROJ_NAME} + +# Install all necessary software +RUN apk add --no-cache python3 sqlite + +# Create the directories, needed for persistent storage (e.g. database, tokens) +RUN mkdir ./data ./src ./config + +# Create mount points for logs, data, src and config +VOLUME /var/log ./data ./src ./config + +# Copy the application source code +COPY ./src/ ./src/ + +# Create a seperate venv inside the container & install requirements +COPY ./requirements.txt ./requirements.txt +RUN \ + python -m venv .venv && \ + source .venv/bin/activate && \ + ./.venv/bin/pip install -r ./requirements.txt && \ + deactivate + +COPY ./docker/startup.sh ./startup.sh + +# When starting the contianer the following is executed +ENTRYPOINT ["./startup.sh"] diff --git a/docker/startup.sh b/docker/startup.sh new file mode 100755 index 0000000..f6092ad --- /dev/null +++ b/docker/startup.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# +# Startup predictify. Don't use this. This is for docker specifically. +source .venv/bin/activate +.venv/bin/python src/runtime.py diff --git a/src/auth.py b/src/auth.py index 7f714da..57785aa 100644 --- a/src/auth.py +++ b/src/auth.py @@ -9,7 +9,7 @@ from urllib.parse import parse_qs, urlencode, urlparse import dotenv import requests -TOKEN_FILE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'env', 'tokens.json') +TOKEN_FILE_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../data', 'tokens.json') def simple_authenticate(grant_type: str = "client_credentials") -> str: @@ -102,7 +102,7 @@ def _read_env_file() -> tuple: :return: tuple """ current_dir = os.path.dirname(os.path.abspath(__file__)) - dotenv_folder_path = os.path.join(current_dir, 'env') + dotenv_folder_path = os.path.join(current_dir, '../config') dotenv_path = os.path.join(dotenv_folder_path, '.env') contents = dotenv.dotenv_values(dotenv_path=dotenv_path) spotify_client_id = contents['SPOTIFY_CLIENT_ID'] diff --git a/src/scraper.py b/src/scraper.py index 794b444..3f57274 100644 --- a/src/scraper.py +++ b/src/scraper.py @@ -3,7 +3,7 @@ import requests from auth import authenticate, simple_authenticate from database_handler import Database, Table -db = Database('spotify_scraped.db') +db = Database('./data/spotify_scraped.db') def scraping(): diff --git a/startup.sh b/startup.sh deleted file mode 100755 index 5fb7fd1..0000000 --- a/startup.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# -# Starup the predictify scraper - -if test -f ./requirements.txt -then - python3 -m venv .venv - .venv/bin/pip install -r ./requirements.txt -else - printf "Missing requirements file! aborting...\n" - exit 1 -fi - -.venv/bin/python3 src/scraper.py