Use SQLite instead of Postgres
This commit is contained in:
@ -3,5 +3,3 @@ DEBUG=True
|
|||||||
EMAIL_HOST_USER=
|
EMAIL_HOST_USER=
|
||||||
EMAIL_HOST_PASSWORD=
|
EMAIL_HOST_PASSWORD=
|
||||||
DISCORD_WEBHOOK_URL=
|
DISCORD_WEBHOOK_URL=
|
||||||
TWITCH_CLIENT_ID=
|
|
||||||
TWITCH_CLIENT_SECRET=
|
|
||||||
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@ -11,6 +11,8 @@
|
|||||||
"cacd",
|
"cacd",
|
||||||
"cellspacing",
|
"cellspacing",
|
||||||
"collectstatic",
|
"collectstatic",
|
||||||
|
"createcachetable",
|
||||||
|
"createsuperuser",
|
||||||
"djade",
|
"djade",
|
||||||
"docstrings",
|
"docstrings",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
@ -41,6 +43,7 @@
|
|||||||
"pyupgrade",
|
"pyupgrade",
|
||||||
"requirepass",
|
"requirepass",
|
||||||
"rewardcampaign",
|
"rewardcampaign",
|
||||||
|
"runserver",
|
||||||
"sitewide",
|
"sitewide",
|
||||||
"socialaccount",
|
"socialaccount",
|
||||||
"staticfiles",
|
"staticfiles",
|
||||||
@ -55,6 +58,7 @@
|
|||||||
"ttvdrops",
|
"ttvdrops",
|
||||||
"ulimits",
|
"ulimits",
|
||||||
"Valair",
|
"Valair",
|
||||||
|
"venv",
|
||||||
"whitenoise",
|
"whitenoise",
|
||||||
"xdefiant"
|
"xdefiant"
|
||||||
],
|
],
|
||||||
|
40
README.md
40
README.md
@ -1,3 +1,43 @@
|
|||||||
# twitch-drop-notifier
|
# twitch-drop-notifier
|
||||||
|
|
||||||
Get notified when a new drop is available on Twitch
|
Get notified when a new drop is available on Twitch
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
- [Python 3.13](https://www.python.org/downloads/) is required to run this project.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create and activate a virtual environment.
|
||||||
|
python -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
|
||||||
|
# Remember to run `source .venv/bin/activate` before running the following commands:
|
||||||
|
# You will need to run this command every time you open a new terminal.
|
||||||
|
# VSCode will automatically activate the virtual environment if you have the Python extension installed.
|
||||||
|
|
||||||
|
# Install dependencies.
|
||||||
|
pip install -r requirements.txt
|
||||||
|
pip install -r requirements-dev.txt
|
||||||
|
|
||||||
|
# Run the following to get passwords for the .env file.
|
||||||
|
python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
|
||||||
|
|
||||||
|
# Rename .env.example to .env and fill in the required values.
|
||||||
|
# DISCORD_WEBHOOK_URL and EMAIL_* can be left empty.
|
||||||
|
mv .env.example .env
|
||||||
|
|
||||||
|
# Run the migrations.
|
||||||
|
python manage.py migrate
|
||||||
|
|
||||||
|
# Create cache table.
|
||||||
|
python manage.py createcachetable
|
||||||
|
|
||||||
|
# Create a superuser.
|
||||||
|
python manage.py createsuperuser
|
||||||
|
|
||||||
|
# Run the server.
|
||||||
|
python manage.py runserver
|
||||||
|
|
||||||
|
# Run the tests.
|
||||||
|
pytest
|
||||||
|
```
|
||||||
|
@ -4,7 +4,6 @@ import logging
|
|||||||
from typing import TYPE_CHECKING, ClassVar, Self
|
from typing import TYPE_CHECKING, ClassVar, Self
|
||||||
|
|
||||||
import auto_prefetch
|
import auto_prefetch
|
||||||
import pghistory
|
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
@ -46,7 +45,6 @@ class ScrapedJson(auto_prefetch.Model):
|
|||||||
return f"{'' if self.imported_at else 'Not imported - '}{self.created_at}"
|
return f"{'' if self.imported_at else 'Not imported - '}{self.created_at}"
|
||||||
|
|
||||||
|
|
||||||
@pghistory.track()
|
|
||||||
class Owner(auto_prefetch.Model):
|
class Owner(auto_prefetch.Model):
|
||||||
"""The company or person that owns the game.
|
"""The company or person that owns the game.
|
||||||
|
|
||||||
@ -102,7 +100,6 @@ class Owner(auto_prefetch.Model):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
@pghistory.track()
|
|
||||||
class Game(auto_prefetch.Model):
|
class Game(auto_prefetch.Model):
|
||||||
"""The game the drop campaign is for. Note that some reward campaigns are not tied to a game.
|
"""The game the drop campaign is for. Note that some reward campaigns are not tied to a game.
|
||||||
|
|
||||||
@ -240,7 +237,6 @@ class Game(auto_prefetch.Model):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
@pghistory.track()
|
|
||||||
class DropCampaign(auto_prefetch.Model):
|
class DropCampaign(auto_prefetch.Model):
|
||||||
"""This is the drop campaign we will see on the front end."""
|
"""This is the drop campaign we will see on the front end."""
|
||||||
|
|
||||||
@ -345,7 +341,6 @@ class DropCampaign(auto_prefetch.Model):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
@pghistory.track()
|
|
||||||
class TimeBasedDrop(auto_prefetch.Model):
|
class TimeBasedDrop(auto_prefetch.Model):
|
||||||
"""This is the drop we will see on the front end.
|
"""This is the drop we will see on the front end.
|
||||||
|
|
||||||
@ -475,7 +470,6 @@ class TimeBasedDrop(auto_prefetch.Model):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
@pghistory.track()
|
|
||||||
class Benefit(auto_prefetch.Model):
|
class Benefit(auto_prefetch.Model):
|
||||||
"""Benefits are the rewards for the drops."""
|
"""Benefits are the rewards for the drops."""
|
||||||
|
|
||||||
|
@ -2,15 +2,10 @@ import os
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
import django_stubs_ext
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from platformdirs import user_data_dir
|
from platformdirs import user_data_dir
|
||||||
|
|
||||||
# Monkeypatching Django, so stubs will work for all generics,
|
|
||||||
# see: https://github.com/typeddjango/django-stubs
|
|
||||||
django_stubs_ext.monkeypatch()
|
|
||||||
|
|
||||||
# Parse a .env file and then load all the variables found as environment variables.
|
# Parse a .env file and then load all the variables found as environment variables.
|
||||||
load_dotenv(verbose=True)
|
load_dotenv(verbose=True)
|
||||||
|
|
||||||
@ -109,7 +104,6 @@ DISCORD_WEBHOOK_URL: str = os.getenv(key="DISCORD_WEBHOOK_URL", default="")
|
|||||||
# Be sure to add pghistory.admin above the django.contrib.admin, otherwise the custom admin templates won't be used.
|
# Be sure to add pghistory.admin above the django.contrib.admin, otherwise the custom admin templates won't be used.
|
||||||
INSTALLED_APPS: list[str] = [
|
INSTALLED_APPS: list[str] = [
|
||||||
"core.apps.CoreConfig",
|
"core.apps.CoreConfig",
|
||||||
"pghistory.admin",
|
|
||||||
"django.contrib.admin",
|
"django.contrib.admin",
|
||||||
"django.contrib.auth",
|
"django.contrib.auth",
|
||||||
"django.contrib.contenttypes",
|
"django.contrib.contenttypes",
|
||||||
@ -118,10 +112,6 @@ INSTALLED_APPS: list[str] = [
|
|||||||
"django.contrib.staticfiles",
|
"django.contrib.staticfiles",
|
||||||
"django.contrib.sites",
|
"django.contrib.sites",
|
||||||
"debug_toolbar",
|
"debug_toolbar",
|
||||||
"pgclone",
|
|
||||||
"pghistory",
|
|
||||||
"pgstats",
|
|
||||||
"pgtrigger",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# Middleware is a framework of hooks into Django's request/response processing.
|
# Middleware is a framework of hooks into Django's request/response processing.
|
||||||
@ -161,18 +151,20 @@ TEMPLATES: list[dict[str, str | list[Path] | bool | dict[str, list[str] | list[t
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
# TODO(TheLovinator): Run psycopg[c] in production.
|
DATABASES: dict[str, dict[str, str | Path | dict[str, str | int]]] = {
|
||||||
# https://www.psycopg.org/psycopg3/docs/basic/install.html#local-installation
|
|
||||||
DATABASES: dict[str, dict[str, str | dict[str, bool]]] = {
|
|
||||||
"default": {
|
"default": {
|
||||||
"ENGINE": "django.db.backends.postgresql",
|
"ENGINE": "django.db.backends.sqlite3",
|
||||||
"NAME": os.getenv(key="DB_NAME", default=""),
|
"NAME": DATA_DIR / "db.sqlite3",
|
||||||
"USER": os.getenv(key="DB_USER", default=""),
|
|
||||||
"PASSWORD": os.getenv(key="DB_PASSWORD", default=""),
|
|
||||||
"HOST": os.getenv(key="DB_HOST", default=""),
|
|
||||||
"PORT": os.getenv(key="DB_PORT", default=""),
|
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
"pool": True, # TODO(TheLovinator): Benchmark this. # noqa: TD003
|
"transaction_mode": "IMMEDIATE",
|
||||||
|
"timeout": 5,
|
||||||
|
"init_command": """
|
||||||
|
PRAGMA journal_mode=WAL;
|
||||||
|
PRAGMA synchronous=NORMAL;
|
||||||
|
PRAGMA mmap_size=134217728;
|
||||||
|
PRAGMA journal_size_limit=27103364;
|
||||||
|
PRAGMA cache_size=2000;
|
||||||
|
""",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
services:
|
|
||||||
garnet:
|
|
||||||
container_name: garnet
|
|
||||||
image: "ghcr.io/microsoft/garnet"
|
|
||||||
user: "1000:1000"
|
|
||||||
restart: always
|
|
||||||
ulimits:
|
|
||||||
memlock: -1
|
|
||||||
command: [ "--auth", "Password", "--password", "${GARNET_PASSWORD}", "--storage-tier", "--logdir", "/logs", "--aof", "--port", "6380" ]
|
|
||||||
ports:
|
|
||||||
- "6380:6380"
|
|
||||||
volumes:
|
|
||||||
- /Docker/ttvdrops/Garnet/data:/data
|
|
||||||
- /Docker/ttvdrops/Garnet/logs:/logs
|
|
||||||
networks:
|
|
||||||
- ttvdrops_garnet
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
container_name: ttvdrops_postgres
|
|
||||||
image: postgres:16
|
|
||||||
user: "1000:1000"
|
|
||||||
ports:
|
|
||||||
- 5433:5432
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
- POSTGRES_USER=${POSTGRES_USER}
|
|
||||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
||||||
- POSTGRES_DB=${POSTGRES_DB}
|
|
||||||
volumes:
|
|
||||||
- /Docker/ttvdrops/Postgres:/var/lib/postgresql/data
|
|
||||||
networks:
|
|
||||||
- ttvdrops_db
|
|
||||||
|
|
||||||
networks:
|
|
||||||
ttvdrops_garnet:
|
|
||||||
ttvdrops_db:
|
|
@ -7,14 +7,9 @@ requires-python = ">=3.13"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"discord-webhook",
|
"discord-webhook",
|
||||||
"django-debug-toolbar",
|
"django-debug-toolbar",
|
||||||
"django-stubs-ext",
|
|
||||||
"django",
|
"django",
|
||||||
"platformdirs",
|
"platformdirs",
|
||||||
"psycopg[binary,pool]",
|
|
||||||
"python-dotenv",
|
"python-dotenv",
|
||||||
"django-pghistory",
|
|
||||||
"django-pgclone",
|
|
||||||
"django-pgstats",
|
|
||||||
"django-auto-prefetch",
|
"django-auto-prefetch",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -22,15 +17,7 @@ dependencies = [
|
|||||||
# Or you can install them with `uv install --dev -r requirements-dev.txt`.
|
# Or you can install them with `uv install --dev -r requirements-dev.txt`.
|
||||||
# uv can be replaced with `pip`if you don't have uv installed.
|
# uv can be replaced with `pip`if you don't have uv installed.
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = ["pre-commit", "pytest", "pytest-django", "ruff"]
|
||||||
"djlint",
|
|
||||||
"pre-commit",
|
|
||||||
"pytest",
|
|
||||||
"pytest-django",
|
|
||||||
"ruff",
|
|
||||||
"django-stubs[compatible-mypy]",
|
|
||||||
"black",
|
|
||||||
]
|
|
||||||
|
|
||||||
# https://docs.astral.sh/ruff/settings/
|
# https://docs.astral.sh/ruff/settings/
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
django-stubs[compatible-mypy]
|
|
||||||
djlint
|
|
||||||
pre-commit
|
pre-commit
|
||||||
pytest
|
pytest
|
||||||
pytest-django
|
pytest-django
|
||||||
|
@ -2,5 +2,4 @@ discord-webhook
|
|||||||
django
|
django
|
||||||
django-debug-toolbar
|
django-debug-toolbar
|
||||||
platformdirs
|
platformdirs
|
||||||
psycopg[binary,pool]
|
|
||||||
python-dotenv
|
python-dotenv
|
||||||
|
Reference in New Issue
Block a user