1
Fork 0
mirror of https://github.com/wlinator/luminara.git synced 2024-10-02 18:23:12 +00:00
This commit is contained in:
wlinator 2024-06-20 19:48:49 +02:00
parent 1ac95af5e6
commit 4cea4eb426
25 changed files with 98 additions and 81 deletions

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2022-2024 wl.inator
Copyright (c) 2022-2024 wlinator
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -1,21 +1,23 @@
import os
import discord
import Client
import config.parser
import services.config_service
import services.help_service
import services.logging_service
import config.parser
_logs = services.logging_service.setup_logger()
async def get_prefix(bot, message):
try:
return services.GuildConfig.GuildConfig.get_prefix(message.guild.id)
return services.config_service.GuildConfig.get_prefix(message.guild.id)
except AttributeError:
return "."
client = Client.LumiBot(
owner_id=int(os.environ.get('LUMI_OWNER_ID')),
command_prefix=get_prefix,

View file

@ -7,41 +7,47 @@
**The next part of this README explains how to self-host Lumi, this allows you to host your own version of my code and
create a personalized Discord bot.**
**Note: because the `.slots` and `.blackjack` commands use custom (animated) emoji, these commands will break when you self-host Lumi. Please replace the ID values in `config/JSON/resources.json` with your own set of emotes.**
**Note: because the `.slots` and `.blackjack` commands use custom (animated) emoji, these commands will break when you
self-host Lumi. Please replace the ID values in `config/JSON/resources.json` with your own set of emotes.**
### Installation
#### Docker
Lumi comes containerized with essential components such as MariaDB, its core application and Adminer.
Lumi comes containerized with essential components such as MariaDB, its core application and Adminer.
To install Lumi, run these commands:
```commandline
```bash
git clone https://git.wlinator.org/Luminara/Lumi && cd Lumi
```
Copy `.env.template` to `.env` and fill out the [variables](#environment-variables).
Copy `.env.template` to `.env` and fill out the [variables](#environment-variables-env).
```commandline
```bash
docker compose up -d --build
```
Please note that it's highly recommended to establish a reverse proxy setup for Adminer, ensuring better security and accessibility.
Please note that it's highly recommended to establish a reverse proxy setup for Adminer, ensuring better security and
accessibility.
- Adminer should be directed to port 8080.
#### Alternative
You can run Lumi without Docker, however I don't provide support or documentation for this. Here are some requirements to get you started.
You can run Lumi without Docker, however I don't provide support or documentation for this. Here are some requirements
to get you started.
- MariaDB server on port 3306.
- Python 3.11 with the [required pip packages](requirements.txt).
- See the environment variables in [docker-compose.yml](docker-compose.yml) and set them manually.
## Environment variables (.env)
- `TOKEN`: your Discord Bot Token, you can get this [here](https://discord.com/developers/applications).
- `DBX_*`: set these up if you want to make database backups to your Dropbox app.
- `MARIADB_USER`: the username for your MariaDB database.
- `MARIADB_PASSWORD`: the password for your database.
- `TOKEN`: your Discord Bot Token, you can get this [here](https://discord.com/developers/applications).
- `DBX_*`: set these up if you want to make database backups to your Dropbox app.
- `MARIADB_USER`: the username for your MariaDB database.
- `MARIADB_PASSWORD`: the password for your database.
- `MARIADB_ROOT_PASSWORD`: can be ignored unless you have a specific use for it.
- `MARIADB_DATABASE`: the name of your database.

View file

@ -4,7 +4,7 @@
"transparent": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_logo_transparent.png?_=1"
},
"icons": {
"exclaim": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_exclaim.png?_=2",
"exclaim": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_exclaim.png?_=3",
"question": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_question.png?_=2",
"hammer": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_hammer.png?_=1",
"cross": "https://git.wlinator.org/Luminara/Art/raw/branch/main/lumi_cross.png?_=1",

View file

@ -1,8 +1,17 @@
{
"months": [
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
],
"birthday_messages": [
"🎂 Happy Birthday, **{0}**! 🎉 Wishing you a day filled with joy and laughter.",

View file

@ -24,8 +24,27 @@
"stand": "<:stand:1118923298298929154>"
},
"reward_multiplier": 1.4,
"deck_suits": ["♠", "♡", "♢", "♣"],
"deck_ranks": ["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
"deck_suits": [
"♠",
"♡",
"♢",
"♣"
],
"deck_ranks": [
"A",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"J",
"Q",
"K"
]
},
"slots": {
"emotes": {

View file

@ -43,7 +43,7 @@
"stats_all_title": "Total Lumi Stats - {0}",
"stats_all_footer": "Want to see your own stats? Do '/stats me'.",
"stats_games": "Games played: {0}",
"stats_games_valuet": "Games played: **{0}**\nGames won: **{1}**\nGames lost: **{2}**",
"stats_games_valued": "Games played: **{0}**\nGames won: **{1}**\nGames lost: **{2}**",
"stats_games_value": "`{0}` wins & `{1}` losses.",
"stats_cashflow": "Cashflow",
"stats_cashflow_value": "Total bets/payouts: `${0}` / `${1}`",

View file

@ -9,7 +9,6 @@ from discord.ext.commands import Cog
from lib.embeds.error import GenericErrors, BdayErrors
from lib.exceptions import LumiExceptions
logs = logging.getLogger('Lumi.Core')
_logs = logging.getLogger('Lumi.Core')
@ -60,8 +59,8 @@ async def on_command_error(ctx, error):
async def on_error(event: str, *args, **kwargs) -> None:
logs.error(f"[EventHandler] on_error INFO: errors.event.{event} | '*args': {args} | '**kwargs': {kwargs}")
logs.error(f"[EventHandler] on_error EXCEPTION: {sys.exc_info()}")
_logs.error(f"[EventHandler] on_error INFO: errors.event.{event} | '*args': {args} | '**kwargs': {kwargs}")
_logs.error(f"[EventHandler] on_error EXCEPTION: {sys.exc_info()}")
traceback.print_exc()

View file

@ -3,9 +3,8 @@ import logging
from discord.ext.commands import Cog
from lib.embeds.greet import Greet
from lib.embeds.boost import Boost
import lib.embeds.boost
from lib.embeds.greet import Greet
from services.config_service import GuildConfig
_logs = logging.getLogger('Lumi.Core')

View file

@ -159,11 +159,11 @@ class XpListener(Cog):
leveled_up = _xp.process()
if leveled_up:
coros = [
coroutines = [
asyncio.create_task(_xp.notify()),
asyncio.create_task(_xp.reward())
]
await asyncio.wait(coros)
await asyncio.wait(coroutines)
def setup(client):

View file

@ -1,7 +1,7 @@
import discord
from config.parser import JsonCache
import lib.formatter
from config.parser import JsonCache
resources = JsonCache.read_json("art")
exclaim_icon = resources["icons"]["exclaim"]

View file

@ -114,9 +114,6 @@ class Confirm(View):
await interaction.response.edit_message(view=None)
self.stop()
# async def on_timeout(self):
# await self.ctx.
async def interaction_check(self, interaction) -> bool:
if interaction.user != self.ctx.author:
await interaction.response.send_message("You can't use these buttons, they're someone else's!",

View file

@ -3,8 +3,8 @@ import logging
import random
import discord
from discord.ext import commands, tasks, bridge
from discord.commands import SlashCommandGroup
from discord.ext import commands, tasks
from config.parser import JsonCache
from lib import time, checks
@ -70,7 +70,7 @@ class Birthdays(commands.Cog):
await channel.send(embed=embed, content=member.mention)
_logs.info(f"[BirthdayHandler] Success! user/guild/channel ID: {member.id}/{guild.id}/{channel.id}")
except Exception as error:
except Exception:
_logs.info(f"[BirthdayHandler] Skipped processing user/guild {user_id}/{guild_id}")
# wait one second to avoid rate limits

View file

@ -6,9 +6,9 @@ from discord.ext import commands, bridge
from config.parser import JsonCache
from lib import formatter
from lib.embeds.greet import Greet
from lib.embeds.boost import Boost
from lib.embeds.error import GenericErrors
from lib.embeds.greet import Greet
from modules.config import config, set_prefix, xp_reward
from services.config_service import GuildConfig

View file

@ -10,8 +10,8 @@ from config.parser import JsonCache
from lib import interaction
from lib.embeds.error import EconErrors
from lib.embeds.error import GenericErrors
from services.stats_service import BlackJackStats
from services.currency_service import Currency
from services.stats_service import BlackJackStats
resources = JsonCache.read_json("resources")
logs = logging.getLogger('Lumi.Core')

View file

@ -1,6 +1,6 @@
from config.parser import JsonCache
from services.stats_service import BlackJackStats, SlotsStats
from services.currency_service import Currency
from services.stats_service import BlackJackStats, SlotsStats
strings = JsonCache.read_json("strings")
resources = JsonCache.read_json("resources")

View file

@ -14,7 +14,7 @@ class Help(commands.Cog):
)
async def help_command(self, ctx):
prefix = lib.formatter.get_prefix(ctx)
return await ctx.respond(content=f"Please use Lumi's prefix to get help. Type `{prefix}help`", ephemeral=True)
return await ctx.respond(content=f'Please use Lumi\'s prefix to get help. Type `{prefix}help`', ephemeral=True)
def setup(client):

View file

@ -1,7 +1,7 @@
import datetime
from discord.ext import commands, bridge, tasks
from discord.commands import SlashCommandGroup
from discord.ext import commands, bridge, tasks
from lib import checks
from lib.embeds.info import MiscInfo

View file

@ -15,17 +15,17 @@ mariadb_user = os.environ.get("MARIADB_USER")
mariadb_password = os.environ.get("MARIADB_PASSWORD")
if instance.lower() == "main":
dbx = dropbox.Dropbox(
_dbx = dropbox.Dropbox(
app_key=app_key,
app_secret=app_secret,
oauth2_refresh_token=oauth2_refresh_token
)
else:
# can be ignored
dbx = None
_dbx = None
async def create_db_backup(dbx, path="db/rcu.db"):
async def create_db_backup():
backup_name = datetime.today().strftime('%Y-%m-%d_%H%M')
backup_name += f"_lumi.sql"
@ -35,24 +35,24 @@ async def create_db_backup(dbx, path="db/rcu.db"):
subprocess.check_output(command, shell=True)
with open("./db/migrations/100-dump.sql", "rb") as f:
dbx.files_upload(f.read(), f"/{backup_name}")
_dbx.files_upload(f.read(), f"/{backup_name}")
async def backup_cleanup(dbx):
async def backup_cleanup():
all_backup_files = []
for entry in dbx.files_list_folder('').entries:
for entry in _dbx.files_list_folder('').entries:
all_backup_files.append(entry.name)
for file in sorted(all_backup_files[:-48]):
dbx.files_delete_v2('/' + file)
_dbx.files_delete_v2('/' + file)
async def backup(self):
if instance.lower() == "main":
try:
await create_db_backup(dbx)
await backup_cleanup(dbx)
await create_db_backup()
await backup_cleanup()
logs.info("[BACKUP] database backup success.")

View file

@ -7,8 +7,8 @@ import psutil
from config.parser import JsonCache
from lib import metadata
from services.stats_service import BlackJackStats
from services.currency_service import Currency
from services.stats_service import BlackJackStats
_logs = logging.getLogger('Lumi.Core')
_art = JsonCache.read_json("art")
@ -30,7 +30,7 @@ async def cmd(command, ctx, unix_timestamp):
icon_url=_art["logo"]["transparent"])
embed.set_thumbnail(url=_art["logo"]["opaque"])
#embed.add_field(name="Author", value=f"{metadata.__author__}", inline=False)
# embed.add_field(name="Author", value=f"{metadata.__author__}", inline=False)
embed.add_field(name="Uptime", value=f"<t:{unix_timestamp}:R>")
embed.add_field(name="Latency", value=f"{round(1000 * command.client.latency)}ms")
embed.add_field(name="Memory", value=f"{memory_usage_in_mb:.2f} MB")

View file

@ -1,6 +1,7 @@
from discord.ext import commands
from services import xkcd_service
from lib.embeds.info import MiscInfo
from services import xkcd_service
_xkcd = xkcd_service.Client()

View file

@ -8,8 +8,8 @@ import pytz
class LumiFormatter(logging.Formatter):
def __init__(self, fmt=None, datefmt=None):
super().__init__(fmt, datefmt)
def __init__(self, fmt=None, dateformat=None):
super().__init__(fmt, dateformat)
self.timezone = pytz.timezone('US/Eastern')
def format(self, record):
@ -21,10 +21,10 @@ class LumiFormatter(logging.Formatter):
record.msg = message
return super().format(record)
def formatTime(self, record, datefmt=None):
def formatTime(self, record, dateformat=None):
timestamp = self.timezone.localize(datetime.fromtimestamp(record.created))
if datefmt:
return timestamp.strftime(datefmt)
if dateformat:
return timestamp.strftime(dateformat)
else:
return str(timestamp)
@ -36,7 +36,7 @@ def setup_logger():
debug_log_file = os.path.join(logs_folder, 'debug.log')
with open(debug_log_file, 'w') as f:
with open(debug_log_file, 'w'):
pass
# Initialize the logger
@ -51,8 +51,7 @@ def setup_logger():
# CONSOLE HANDLER
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_formatter = LumiFormatter('[%(asctime)s] [%(name)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
console_formatter = LumiFormatter('[%(asctime)s] [%(name)s] %(message)s')
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)
@ -61,8 +60,7 @@ def setup_logger():
max_log_size_bytes = 10 * 1024 * 1024 # max. 10 MB
debug_file_handler = RotatingFileHandler(debug_log_file, maxBytes=max_log_size_bytes, backupCount=5)
debug_file_handler.setLevel(logging.DEBUG)
debug_file_formatter = LumiFormatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
debug_file_formatter = LumiFormatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s')
debug_file_handler.setFormatter(debug_file_formatter)
logger.addHandler(debug_file_handler)

View file

@ -112,4 +112,3 @@ class SlotsStats:
"games_won_three_diamonds": games_won_three_diamonds,
"games_won_jackpot": games_won_jackpot
}

View file

@ -26,7 +26,7 @@ class HttpError(Exception):
class Comic:
"""
A class representing an xkcd comic.
A class representing a xkcd comic.
"""
def __init__(
@ -47,19 +47,15 @@ class Comic:
self.comic_url: str | None = comic_url
self.explanation_url: str | None = explanation_url
def _determine_date(self, xkcd_dict: dict[str, Any]) -> datetime.date | None:
@staticmethod
def _determine_date(xkcd_dict: dict[str, Any]) -> datetime.date | None:
"""
Determine the date of the comic.
Args:
xkcd_dict:
Parameters
----------
xkcd_dict : dict[str, Any]
The dictionary containing the comic data.
Returns:
Returns
-------
datetime.date | None
The date of the comic.
"""
try:
return datetime.date(

View file

@ -1,8 +0,0 @@
users:
# "admin" here is username
admin:
name: "Admin"
# Just sha-256 which can be computed with "echo -n password | shasum -a 256"
password: "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
# use email to generate avatars using Gravatar. It is optional.
email: me@email.net