1
Fork 0
mirror of https://github.com/wlinator/luminara.git synced 2024-10-02 18:23:12 +00:00

chore: Update pyproject.toml with python-dotenv and pyyaml dependencies

This commit is contained in:
wlinator 2024-07-16 15:53:42 -04:00
parent ecd3c5d14e
commit 10a45dd85c
10 changed files with 148 additions and 136 deletions

View file

@ -1,15 +0,0 @@
TOKEN=
INSTANCE=
OWNER_ID=784783517845946429
XP_GAIN_PER_MESSAGE=
XP_GAIN_COOLDOWN=
DBX_OAUTH2_REFRESH_TOKEN=
DBX_APP_KEY=
DBX_APP_SECRET=
MARIADB_USER=wlinator
MARIADB_PASSWORD=
MARIADB_ROOT_PASSWORD=
MARIADB_DATABASE=lumidb

View file

@ -8,6 +8,7 @@ import Client
import config.parser
import services.config_service
import services.help_service
from lib.constants import CONST
from services.blacklist_service import BlacklistUserService
# Remove the default logger configuration
@ -29,22 +30,16 @@ async def get_prefix(bot, message):
except AttributeError:
return "."
_token: str | None = os.environ.get('LUMI_TOKEN')
_owner_id: str | None = os.environ.get('LUMI_OWNER_ID')
if not _token:
logger.error("LUMI_TOKEN is not set in the environment variables.")
exit(1)
client = Client.LumiBot(
owner_id=int(_owner_id) if _owner_id else None,
owner_ids=CONST.OWNER_IDS,
command_prefix=get_prefix,
intents=discord.Intents.all(),
status=discord.Status.online,
help_command=services.help_service.LumiHelp()
help_command=services.help_service.LumiHelp(),
)
@client.check
async def blacklist_check(ctx):
if BlacklistUserService.is_user_blacklisted(ctx.author.id):
@ -61,8 +56,15 @@ def load_modules():
if not os.path.isdir(directory_path):
continue
items = [d for d in os.listdir(directory_path) if os.path.isdir(os.path.join(directory_path, d))] \
if directory == "modules" else [f[:-3] for f in os.listdir(directory_path) if f.endswith('.py')]
items = (
[
d
for d in os.listdir(directory_path)
if os.path.isdir(os.path.join(directory_path, d))
]
if directory == "modules"
else [f[:-3] for f in os.listdir(directory_path) if f.endswith(".py")]
)
for item in items:
if item in loaded:
@ -71,13 +73,13 @@ def load_modules():
try:
client.load_extension(f"{directory}.{item}")
loaded.add(item)
logger.debug(f'{item.upper()} loaded.')
logger.debug(f"{item.upper()} loaded.")
except Exception as e:
logger.exception(f'Failed to load {item.upper()}: {e}')
logger.exception(f"Failed to load {item.upper()}: {e}")
if __name__ == '__main__':
if __name__ == "__main__":
"""
This code is only ran when Lumi.py is the primary module,
so NOT when main is imported from a cog. (sys.modules)
@ -86,9 +88,17 @@ if __name__ == '__main__':
logger.info("LUMI IS BOOTING")
# cache all JSON
[config.parser.JsonCache.read_json(file[:-5]) for file in os.listdir("config/JSON") if file.endswith(".json")]
[
config.parser.JsonCache.read_json(file[:-5])
for file in os.listdir("config/JSON")
if file.endswith(".json")
]
# load command and listener cogs
load_modules()
client.run(_token)
if not CONST.TOKEN:
logger.error("token is not set in creds.yaml")
exit(1)
client.run(CONST.TOKEN)

View file

@ -1,4 +1,5 @@
import json
import yaml
from loguru import logger
@ -9,8 +10,23 @@ class JsonCache:
def read_json(path):
"""Read and cache the JSON data if not already cached."""
if path not in JsonCache._cache:
with open(f"config/JSON/{path}.json", 'r') as file:
with open(f"config/JSON/{path}.json", "r") as file:
JsonCache._cache[path] = json.load(file)
logger.debug(f"{path}.json was loaded and cached.")
return JsonCache._cache[path]
class YamlCache:
_cache = {}
@staticmethod
def read_credentialsl():
"""Read and cache the creds.yaml data if not already cached."""
path = "creds"
if path not in YamlCache._cache:
with open(f"{path}.yaml", "r") as file:
YamlCache._cache[path] = yaml.safe_load(file)
logger.debug(f"{path}.yaml was loaded and cached.")
return YamlCache._cache[path]

View file

@ -1,24 +1,22 @@
from lib.constants import CONST
from loguru import logger
import os
import mysql.connector
from mysql.connector import pooling
def create_connection_pool(name: str, size: int) -> pooling.MySQLConnectionPool:
pool = pooling.MySQLConnectionPool(
return pooling.MySQLConnectionPool(
pool_name=name,
pool_size=size,
host="db",
port=3306,
database=os.environ.get("MARIADB_DATABASE"),
user=os.environ.get("MARIADB_USER"),
password=os.environ.get("MARIADB_PASSWORD"),
database=CONST.MARIADB_DATABASE,
user=CONST.MARIADB_USER,
password=CONST.MARIADB_PASSWORD,
charset="utf8mb4",
collation="utf8mb4_unicode_ci",
)
return pool
try:
_cnxpool = create_connection_pool("core-pool", 25)
@ -28,48 +26,23 @@ except mysql.connector.Error as e:
def execute_query(query, values=None):
conn = _cnxpool.get_connection()
cursor = conn.cursor()
if values:
cursor.execute(query, values)
else:
cursor.execute(query)
conn.commit()
conn.close()
return cursor
with _cnxpool.get_connection() as conn:
with conn.cursor() as cursor:
cursor.execute(query, values)
conn.commit()
return cursor
def select_query(query, values=None):
conn = _cnxpool.get_connection()
cursor = conn.cursor()
if values:
cursor.execute(query, values)
output = cursor.fetchall()
else:
cursor.execute(query)
output = cursor.fetchall()
conn.close()
return output
with _cnxpool.get_connection() as conn:
with conn.cursor() as cursor:
cursor.execute(query, values)
return cursor.fetchall()
def select_query_one(query, values=None):
conn = _cnxpool.get_connection()
cursor = conn.cursor()
if values:
cursor.execute(query, values)
output = cursor.fetchone()
else:
cursor.execute(query)
output = cursor.fetchone()
conn.close()
if output:
return output[0]
return None
with _cnxpool.get_connection() as conn:
with conn.cursor() as cursor:
cursor.execute(query, values)
output = cursor.fetchone()
return output[0] if output else None

View file

@ -1,28 +1,15 @@
services:
core:
build: .
container_name: lumi_core
restart: always
environment:
LUMI_TOKEN: ${TOKEN}
LUMI_INSTANCE: ${INSTANCE}
LUMI_OWNER_ID: ${OWNER_ID}
LUMI_XP_GAIN_PER_MESSAGE: ${XP_GAIN_PER_MESSAGE}
LUMI_XP_GAIN_COOLDOWN: ${XP_GAIN_COOLDOWN}
LUMI_DBX_OAUTH2_REFRESH_TOKEN: ${DBX_OAUTH2_REFRESH_TOKEN}
LUMI_DBX_APP_KEY: ${DBX_APP_KEY}
LUMI_DBX_APP_SECRET: ${DBX_APP_SECRET}
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
MARIADB_USER: ${MARIADB_USER}
MARIADB_PASSWORD: ${MARIADB_PASSWORD}
MARIADB_DATABASE: ${MARIADB_DATABASE}
volumes:
- debug_log:/usr/src/app/logs
depends_on:
db:
condition: service_healthy
db:
image: mariadb
container_name: lumi_db
restart: always
environment:
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
@ -40,10 +27,10 @@ services:
adminer:
image: adminer
container_name: lumi_adminer
restart: always
ports:
- 8080:8080
volumes:
database:
debug_log:

View file

@ -1,33 +1,68 @@
import os
from config.parser import JsonCache
from typing import Optional, Set
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
art = JsonCache.read_json("art")
resources = JsonCache.read_json("resources")
class Constants:
# bot credentials
TOKEN: Optional[str] = os.environ.get("TOKEN", None)
INSTANCE: Optional[str] = os.environ.get("INSTANCE", None)
OWNER_IDS: Optional[Set[int]] = (
{
int(id.strip())
for id in os.environ.get("OWNER_ID", "").split(",")
if id.strip()
}
if os.environ.get("OWNER_ID")
else None
)
XP_GAIN_PER_MESSAGE: int = int(os.environ.get("XP_GAIN_PER_MESSAGE", 1))
XP_GAIN_COOLDOWN: int = int(os.environ.get("XP_GAIN_COOLDOWN", 8))
DBX_TOKEN: Optional[str] = os.environ.get("DBX_OAUTH2_REFRESH_TOKEN", None)
DBX_APP_KEY: Optional[str] = os.environ.get("DBX_APP_KEY", None)
DBX_APP_SECRET: Optional[str] = os.environ.get("DBX_APP_SECRET", None)
MARIADB_USER: Optional[str] = os.environ.get("MARIADB_USER", None)
MARIADB_PASSWORD: Optional[str] = os.environ.get("MARIADB_PASSWORD", None)
MARIADB_ROOT_PASSWORD: Optional[str] = os.environ.get("MARIADB_ROOT_PASSWORD", None)
MARIADB_DATABASE: Optional[str] = os.environ.get("MARIADB_DATABASE", None)
# emotes
EMOTES_GUILD_ID = 1038051105642401812
# color scheme
COLOR_DEFAULT = int(0xFF8C00)
COLOR_WARNING = int(0xFF7600)
COLOR_ERROR = int(0xFF4500)
# strings
STRINGS = JsonCache.read_json("strings")
# repository
REPO_URL = "https://git.wlinator.org/Luminara/Lumi"
INVITE_LINK = "https://discord.com/oauth2/authorize?client_id=1038050427272429588&permissions=8&scope=bot"
# KRC
KRC_GUILD_ID: int = 719227135151046699
KRC_INTRO_CHANNEL_ID: int = 973619250507972618
KRC_QUESTION_MAPPING: dict[str, str] = resources["guild_specific"]["question_mapping"]
KRC_QUESTION_MAPPING: dict[str, str] = resources["guild_specific"][
"question_mapping"
]
# logo
LUMI_LOGO_TRANSPARENT = art["logo"]["transparent"]
LUMI_LOGO_OPAQUE = art["logo"]["opaque"]
# icons art
BOOST_ICON = art["icons"]["boost"]
CHECK_ICON = art["icons"]["check"]
@ -39,18 +74,15 @@ class Constants:
QUESTION_ICON = art["icons"]["question"]
STREAK_ICON = art["icons"]["streak"]
WARNING_ICON = art["icons"]["warning"]
# art by JuicyBblue
FLOWERS_ART = art["juicybblue"]["flowers"]
TEAPOT_ART = art["juicybblue"]["teapot"]
MUFFIN_ART = art["juicybblue"]["muffin"]
# birthdays
BIRTHDAY_MESSAGES = JsonCache.read_json("birthday")["birthday_messages"]
BIRTHDAY_MONTHS = JsonCache.read_json("birthday")["months"]
# economy
CONST = Constants()

View file

@ -1,5 +1,5 @@
from lib.constants import CONST
from loguru import logger
import os
import subprocess
from datetime import datetime
from typing import List, Optional
@ -7,21 +7,17 @@ from typing import List, Optional
import dropbox
from dropbox.files import FileMetadata
# Fetch environment variables once and store them in constants
OAUTH2_REFRESH_TOKEN: Optional[str] = os.environ.get("LUMI_DBX_OAUTH2_REFRESH_TOKEN")
APP_KEY: Optional[str] = os.environ.get("LUMI_DBX_APP_KEY")
APP_SECRET: Optional[str] = os.environ.get("LUMI_DBX_APP_SECRET")
INSTANCE: Optional[str] = os.environ.get("LUMI_INSTANCE")
MARIADB_USER: Optional[str] = os.environ.get("MARIADB_USER")
MARIADB_PASSWORD: Optional[str] = os.environ.get("MARIADB_PASSWORD")
# Initialize Dropbox client if instance is "main"
_dbx: Optional[dropbox.Dropbox] = None
if INSTANCE and INSTANCE.lower() == "main":
if CONST.INSTANCE and CONST.INSTANCE.lower() == "main":
_app_key: Optional[str] = CONST.DBX_APP_KEY
_dbx_token: Optional[str] = CONST.DBX_TOKEN
_app_secret: Optional[str] = CONST.DBX_APP_SECRET
_dbx = dropbox.Dropbox(
app_key=APP_KEY,
app_secret=APP_SECRET,
oauth2_refresh_token=OAUTH2_REFRESH_TOKEN
app_key=_app_key,
app_secret=_app_secret,
oauth2_refresh_token=_dbx_token,
)
@ -29,9 +25,9 @@ async def create_db_backup() -> None:
if not _dbx:
raise ValueError("Dropbox client is not initialized")
backup_name: str = datetime.today().strftime('%Y-%m-%d_%H%M') + "_lumi.sql"
backup_name: str = datetime.today().strftime("%Y-%m-%d_%H%M") + "_lumi.sql"
command: str = (
f"mariadb-dump --user={MARIADB_USER} --password={MARIADB_PASSWORD} "
f"mariadb-dump --user={CONST.MARIADB_USER} --password={CONST.MARIADB_PASSWORD} "
f"--host=db --single-transaction --all-databases > ./db/migrations/100-dump.sql"
)
@ -45,17 +41,20 @@ async def backup_cleanup() -> None:
if not _dbx:
raise ValueError("Dropbox client is not initialized")
result = _dbx.files_list_folder('')
result = _dbx.files_list_folder("")
all_backup_files: List[str] = [
entry.name for entry in result.entries if isinstance(entry, FileMetadata) # type: ignore
entry.name
for entry in result.entries
if isinstance(entry, FileMetadata) # type: ignore
]
for file in sorted(all_backup_files)[:-48]:
_dbx.files_delete_v2('/' + file)
_dbx.files_delete_v2("/" + file)
async def backup() -> None:
if INSTANCE and INSTANCE.lower() == "main":
if CONST.INSTANCE and CONST.INSTANCE.lower() == "main":
logger.debug("Backing up the database.")
try:
await create_db_backup()
@ -64,4 +63,4 @@ async def backup() -> None:
except Exception as error:
logger.error(f"Backup failed: {error}")
else:
logger.debug("No backup, instance not \"MAIN\".")
logger.debug('No backup, instance not "MAIN".')

16
poetry.lock generated
View file

@ -771,6 +771,20 @@ nodeenv = ">=1.6.0"
all = ["twine (>=3.4.1)"]
dev = ["twine (>=3.4.1)"]
[[package]]
name = "python-dotenv"
version = "1.0.1"
description = "Read key-value pairs from a .env file and set them as environment variables"
optional = false
python-versions = ">=3.8"
files = [
{file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
{file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
]
[package.extras]
cli = ["click (>=5.0)"]
[[package]]
name = "pytz"
version = "2024.1"
@ -1085,4 +1099,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.12"
content-hash = "bfcd06ad073bbdf00a8b37ce2297f87380dbd58c59283525bad3908a17269475"
content-hash = "f99a624c8fbf0661b2dfe3a937f1182c527ed3d565715bb868b1cbac95221405"

View file

@ -17,9 +17,9 @@ psutil = "^6.0.0"
py-cord = "2.5.0"
pyright = "^1.1.371"
python = "^3.12"
python-dotenv = "^1.0.1"
pytz = "^2024.1"
ruff = "^0.5.2"
pyyaml = "^6.0.1"
[build-system]
build-backend = "poetry.core.masonry.api"

View file

@ -1,4 +1,4 @@
import os
from lib.constants import CONST
import time
from typing import Callable, Dict, List, Optional, Tuple
@ -7,10 +7,6 @@ from discord.ext import commands
from db import database
xp_gain_per_message: int = int(os.environ.get("LUMI_XP_GAIN_PER_MESSAGE", 1))
xp_gain_cooldown: int = int(os.environ.get("LUMI_XP_GAIN_COOLDOWN", 8))
class XpService:
"""
Manages XP for a user, including storing, retrieving, and updating XP in the database.
@ -29,8 +25,8 @@ class XpService:
self.xp: int = 0
self.level: int = 0
self.cooldown_time: Optional[float] = None
self.xp_gain: int = xp_gain_per_message
self.new_cooldown: int = xp_gain_cooldown
self.xp_gain: int = CONST.XP_GAIN_PER_MESSAGE
self.new_cooldown: int = CONST.XP_GAIN_COOLDOWN
self.fetch_or_create_xp()