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

Code clean-up

This commit is contained in:
wlinator 2024-03-29 13:17:51 -04:00
parent 37008b685a
commit 8cca12b29c
47 changed files with 153 additions and 166 deletions

View file

@ -3,26 +3,33 @@
![Racu art](art/racu_logo.png)
## Self host
**The next part of this README explains how to self-host Racu, this allows you to host your own version of my code and create a personalized Discord bot.**
**The next part of this README explains how to self-host Racu, this allows you to host your own version of my code and
create a personalized Discord bot.**
### 📲 Installation
Racu is containerized: its core, database, database admin platform and logger run on Docker without any extra configuration.
However, you CAN run it locally without Docker by hosting MariaDB on your machine with the login credentials specified in [.env](.env.template) and installing **Python 3.11** with the [required pip packages](requirements.txt). **Note: I won't explain how to do this. Figure it out on your own.**
Racu is containerized: its core, database, database admin platform and logger run on Docker without any extra
configuration.
However, you CAN run it locally without Docker by hosting MariaDB on your machine with the login credentials specified
in [.env](.env.template) and installing **Python 3.11** with the [required pip packages](requirements.txt). **Note: I
won't explain how to do this. Figure it out on your own.**
```sh
git clone https://gitlab.com/wlinator/racu && cd racu
```
Copy `.env.template` to `.env` and fill out the [variables](#env-keys).
Copy `.env.template` to `.env` and fill out the [variables](#env-keys).
**Optional:** copy `users.yml.example` to `users.yml` to properly configure Dozzle logs. Check the file for more information.
**Optional:** copy `users.yml.example` to `users.yml` to properly configure Dozzle logs. Check the file for more
information.
```sh
docker compose up -d --build
```
## ⚙️ Environment variables
- `TOKEN`: your Discord Bot Token, you can get this [here](https://discord.com/developers/applications).
- `INSTANCE`: this should always be "MAIN" unless you plan to run multiple bots (for testing purposes).
- `OWNER_ID`: the Discord user ID of the person who will act as owner of this bot.
@ -30,7 +37,8 @@ docker compose up -d --build
- `XP_GAIN_PER_MESSAGE`: how much XP should be awarded to a user per message.
- `XP_GAIN_COOLDOWN`: XP earning cooldown time in seconds.
- The values with "DBX" can be ignored unless you plan to make database backups with Dropbox. In that case enter your Dropbox API credentials.
- The values with "DBX" can be ignored unless you plan to make database backups with Dropbox. In that case enter your
Dropbox API credentials.
- `MARIADB_USER`: the username for your MariaDB database.
- `MARIADB_PASSWORD`: the password for your database.

View file

@ -8,12 +8,10 @@
"question": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_question.png?_=2",
"hammer": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_hammer.png?_=1",
"cross": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_cross.png?_=1",
"streak": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_streak.png?_=2",
"streak_bronze": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_streak_bronze.png?_=1",
"streak_silver": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_streak_silver.png?_=1",
"streak_gold": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_streak_gold.png?_=1",
"money_bag": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_money_bag.png?_=1",
"money_coins": "https://gitlab.com/wlinator/Racu/-/raw/main/art/racu_money_coins.png?_=1"
}

View file

@ -7,15 +7,15 @@
"intro_channel_id": 973619250507972618,
"question_mapping": {
"(Nick)name": "Let's start with your nickname. How would you like to be identified in the server?",
"Age": "How old are you?",
"Region": "Where do you live?",
"Languages": "Which languages do you speak?",
"Pronouns": "What are your preferred pronouns?",
"Sexuality": "What's your sexuality?",
"Relationship status": "What's your current relationship status?",
"Likes & interests": "Likes & interests",
"Dislikes": "Dislikes",
"EXTRAS": "EXTRAS: job status, zodiac sign, hobbies, etc. Tell us about yourself!"
"Age": "How old are you?",
"Region": "Where do you live?",
"Languages": "Which languages do you speak?",
"Pronouns": "What are your preferred pronouns?",
"Sexuality": "What's your sexuality?",
"Relationship status": "What's your current relationship status?",
"Likes & interests": "Likes & interests",
"Dislikes": "Dislikes",
"EXTRAS": "EXTRAS: job status, zodiac sign, hobbies, etc. Tell us about yourself!"
}
},
"daily_reward": 500,

View file

@ -1,12 +1,12 @@
import logging
import os
import mysql.connector
from dotenv import load_dotenv
import os
logs = logging.getLogger('Racu.Core')
load_dotenv('.env')
cnxpool = mysql.connector.pooling.MySQLConnectionPool(
pool_name='core-pool',
pool_size=25,

View file

@ -1,64 +1,64 @@
version: '3.8'
services:
core:
build: .
restart: always
logging:
driver: "json-file"
options:
max-size: "50m"
volumes:
- debuglog:/usr/src/app/logs
depends_on:
db:
condition: service_healthy
core:
build: .
restart: always
logging:
driver: "json-file"
options:
max-size: "50m"
volumes:
- debuglog:/usr/src/app/logs
depends_on:
db:
condition: service_healthy
db:
image: mariadb
restart: always
environment:
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
MARIADB_USER: ${MARIADB_USER}
MARIADB_PASSWORD: ${MARIADB_PASSWORD}
MARIADB_DATABASE: racudb
volumes:
- ./db/init:/docker-entrypoint-initdb.d/
- dbdata:/var/lib/mysql
logging:
driver: "json-file"
options:
max-size: "50m"
ports:
- 3306:3306
healthcheck:
test: [ "CMD", "mariadb", "-h", "localhost", "-u", "${MARIADB_USER}", "-p${MARIADB_PASSWORD}", "-e", "SELECT 1" ]
interval: 5s
timeout: 10s
retries: 5
db:
image: mariadb
restart: always
environment:
MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
MARIADB_USER: ${MARIADB_USER}
MARIADB_PASSWORD: ${MARIADB_PASSWORD}
MARIADB_DATABASE: racudb
volumes:
- ./db/init:/docker-entrypoint-initdb.d/
- dbdata:/var/lib/mysql
logging:
driver: "json-file"
options:
max-size: "50m"
ports:
- 3306:3306
healthcheck:
test: [ "CMD", "mariadb", "-h", "localhost", "-u", "${MARIADB_USER}", "-p${MARIADB_PASSWORD}", "-e", "SELECT 1" ]
interval: 5s
timeout: 10s
retries: 5
adminer:
image: adminer
restart: always
logging:
driver: "json-file"
options:
max-size: "50m"
ports:
- 8085:8080
dozzle:
container_name: dozzle
image: amir20/dozzle:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- .:/data
ports:
- 8080:8080
environment:
DOZZLE_AUTH_PROVIDER: simple
adminer:
image: adminer
restart: always
logging:
driver: "json-file"
options:
max-size: "50m"
ports:
- 8085:8080
dozzle:
container_name: dozzle
image: amir20/dozzle:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- .:/data
ports:
- 8080:8080
environment:
DOZZLE_AUTH_PROVIDER: simple
volumes:
dbdata:
debuglog:
dbdata:
debuglog:

View file

@ -1,10 +1,11 @@
import logging
import traceback
import sys
import traceback
import discord
from discord.ext import commands
from lib.embeds.error import GenericErrors,BdayErrors
from lib.embeds.error import GenericErrors, BdayErrors
from lib.exceptions import RacuExceptions
logs = logging.getLogger('Racu.Core')
@ -61,4 +62,4 @@ 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()}")
traceback.print_exc()
traceback.print_exc()

View file

@ -1,9 +1,10 @@
import logging
from logging.handlers import RotatingFileHandler
from datetime import datetime
import pytz
import re
import os
import re
from datetime import datetime
from logging.handlers import RotatingFileHandler
import pytz
class RacuFormatter(logging.Formatter):
@ -29,11 +30,10 @@ class RacuFormatter(logging.Formatter):
def setup_logger():
logs_folder = 'logs'
if not os.path.exists(logs_folder):
os.makedirs(logs_folder)
debug_log_file = os.path.join(logs_folder, 'debug.log')
with open(debug_log_file, 'w') as f:
@ -45,28 +45,28 @@ def setup_logger():
if logger.handlers:
# Handlers already exist, no need to add more
return logger
logger.setLevel(logging.DEBUG)
# CONSOLE HANDLER
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_formatter = RacuFormatter('[%(asctime)s] [%(name)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
datefmt='%Y-%m-%d %H:%M:%S')
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)
# DEBUG LOG TO FILE HANDLER
max_log_size_bytes = 10 * 1024 * 1024 # max. 10 MB
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 = RacuFormatter('[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
datefmt='%Y-%m-%d %H:%M:%S')
debug_file_handler.setFormatter(debug_file_formatter)
logger.addHandler(debug_file_handler)
logger.propagate = False
logging.captureWarnings(True)
return logger
return logger

View file

@ -1,6 +1,6 @@
import random
from config.parser import JsonCache
from lib import checks
class ReactionHandler:

View file

@ -84,7 +84,7 @@ class XPHandler:
if not guild_config.level_message:
level_message = XPHandler.level_message_generic(level_config.level, author)
else:
level_message = formatter.template(guild_config.level_message,author.name, level_config.level)
level_message = formatter.template(guild_config.level_message, author.name, level_config.level)
case _:
raise Exception
@ -125,8 +125,8 @@ class XPHandler:
guild = user.guild
if (
guild.id != 719227135151046699 or
not (level % 5 == 0 and 5 <= level <= 100)
guild.id != 719227135151046699 or
not (level % 5 == 0 and 5 <= level <= 100)
):
return

View file

@ -1,4 +1,5 @@
from discord.ext import commands
from lib.exceptions import RacuExceptions
from services.GuildConfig import GuildConfig

View file

@ -12,7 +12,6 @@ exclam_icon = resources["icons"]["exclam"]
class Greet:
@staticmethod
def message(member, template=None):
embed = discord.Embed(
color=discord.Color.embed_background(),
description=f"_ _\n**Welcome** to **{member.guild.name}**"
@ -24,4 +23,3 @@ class Greet:
embed.set_thumbnail(url=member.display_avatar)
return embed

View file

@ -1,4 +1,5 @@
import discord
from config.parser import JsonCache
resources = JsonCache.read_json("art")

View file

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

View file

@ -1,5 +1,5 @@
from discord.ext import commands
import discord
from discord.ext import commands
class NotAllowedInChannel(commands.CheckFailure):

View file

@ -1,5 +1,7 @@
import discord
import textwrap
import discord
from services.GuildConfig import GuildConfig

View file

@ -1,11 +1,10 @@
import discord
from discord.ext import commands, bridge
from modules.admin import award, sql
from lib.embeds.error import EconErrors
class BotAdmin(commands.Cog):
"""
This module is intended for commands that only bot owners can do.
For server configuration with Racu, see the "config" module.

View file

@ -1,4 +1,5 @@
import discord
from services.Currency import Currency
@ -13,4 +14,4 @@ async def cmd(ctx, user: discord.User, amount: int):
description=f"Awarded **${Currency.format(amount)}** to {user.name}."
)
await ctx.respond(embed=embed)
await ctx.respond(embed=embed)

View file

@ -1,4 +1,5 @@
import sqlite3
from db import database
@ -19,4 +20,4 @@ async def inject_cmd(ctx, query: str):
database.execute_query(query)
await ctx.respond(content=f"That worked!\n```{query}```", ephemeral=True)
except sqlite3.Error as error:
await ctx.respond(content=f"Query:\n```{query}```\nError message:\n```{error}```", ephemeral=True)
await ctx.respond(content=f"Query:\n```{query}```\nError message:\n```{error}```", ephemeral=True)

View file

@ -7,7 +7,6 @@ from discord.ext import commands, tasks, bridge
from config.parser import JsonCache
from lib import time, checks
from lib.embeds.error import BdayErrors
from modules.birthdays import upcoming, birthday
from services.Birthday import Birthday
from services.GuildConfig import GuildConfig

View file

@ -3,13 +3,11 @@ import datetime
from discord.ext import commands
from lib.embeds.error import BdayErrors
from lib.embeds.info import BdayInfo
from services.Birthday import Birthday
async def cmd(ctx, month, month_index, day):
leap_year = 2020
max_days = calendar.monthrange(leap_year, month_index)[1]

View file

@ -1,7 +1,9 @@
from services.Birthday import Birthday
import discord
import datetime
import discord
from services.Birthday import Birthday
async def cmd(ctx):
upcoming_birthdays = Birthday.get_upcoming_birthdays(ctx.guild.id)
@ -19,7 +21,7 @@ async def cmd(ctx):
member = await ctx.guild.fetch_member(user_id)
name = member.name
except discord.HTTPException:
continue # skip user if not in guild
continue # skip user if not in guild
try:
birthday_date = datetime.datetime.strptime(birthday, "%m-%d")
@ -34,8 +36,8 @@ async def cmd(ctx):
inline=False
)
found_birthdays +=1
found_birthdays += 1
if found_birthdays >= 5:
break
await ctx.respond(embed=embed)
await ctx.respond(embed=embed)

View file

@ -6,7 +6,6 @@ from discord.ext import commands, bridge
from config.parser import JsonCache
from lib import formatter
from lib.embeds.error import MiscErrors
from lib.embeds.greet import Greet
from modules.config import config, set_prefix
from services.GuildConfig import GuildConfig

View file

@ -10,8 +10,8 @@ async def cmd(self, ctx):
guild_config = GuildConfig(ctx.guild.id)
embed = discord.Embed(
color = discord.Color.embed_background(),
description = f"Guide: https://gitlab.com/wlinator/Racu/-/wikis/Server-Configuration"
color=discord.Color.embed_background(),
description=f"Guide: https://gitlab.com/wlinator/Racu/-/wikis/Server-Configuration"
)
icon = ctx.guild.icon if ctx.guild.icon else "https://i.imgur.com/79XfsbS.png"
embed.set_author(name=f"{ctx.guild.name} config", icon_url=icon)
@ -92,4 +92,3 @@ async def cmd(self, ctx):
embed.add_field(name="LEVELS", value=level_config, inline=False)
await ctx.respond(embed=embed)

View file

@ -1,10 +1,9 @@
from services.GuildConfig import GuildConfig
from lib.embeds.info import MiscInfo
from lib.embeds.error import MiscErrors
from lib.embeds.info import MiscInfo
from services.GuildConfig import GuildConfig
async def set_cmd(ctx, prefix):
if len(prefix) > 25:
return await ctx.respond(embed=MiscErrors.prefix_too_long(ctx))

View file

@ -2,7 +2,6 @@ import discord
from discord.ext import commands, bridge
from lib import checks
from lib.embeds.error import EconErrors
from modules.economy import blackjack, slots, balance, stats, give, inventory, daily

View file

@ -1,4 +1,5 @@
import discord
from services.Currency import Currency
@ -14,4 +15,4 @@ async def cmd(ctx):
)
embed.set_author(name=f"{ctx.author.name}'s wallet", icon_url=ctx.author.avatar.url)
await ctx.respond(embed=embed)
await ctx.respond(embed=embed)

View file

@ -1,16 +1,16 @@
import random
import logging
import random
from datetime import datetime
import discord
from discord.ext import commands
import pytz
from discord.ext import commands
from dotenv import load_dotenv
from config.parser import JsonCache
from lib import interaction
from lib.embeds.error import EconErrors
from lib.embeds.error import GenericErrors
from config.parser import JsonCache
from services.BlackJackStats import BlackJackStats
from services.Currency import Currency
@ -228,7 +228,7 @@ def blackjack_finished(ctx, bet, player_hand_value, dealer_hand_value, payout, s
value = f"You lost **${bet}**."
thumbnail_url = "https://i.imgur.com/rc68c43.png"
color = discord.Color.red()
elif status == 2:
name = "You won with a score of 21!"
value = f"You won **${payout}**."

View file

@ -1,8 +1,8 @@
from datetime import datetime, timedelta
import lib.time
from lib.embeds.info import EconInfo
from lib.embeds.error import EconErrors
from lib.embeds.info import EconInfo
from services.Currency import Currency
from services.Dailies import Dailies

View file

@ -1,7 +1,6 @@
import discord
from discord.ext import commands
from lib.embeds.error import EconErrors
from services.Currency import Currency

View file

@ -4,10 +4,9 @@ import random
from collections import Counter
import discord
from discord.ext import commands
import pytz
from discord.ext import commands
from lib.embeds.error import EconErrors
from config.parser import JsonCache
from services.Currency import Currency
from services.SlotsStats import SlotsStats

View file

@ -6,6 +6,7 @@ from services.SlotsStats import SlotsStats
strings = JsonCache.read_json("strings")
resources = JsonCache.read_json("resources")
async def cmd(self, ctx, game):
output = ""

View file

@ -1,11 +1,11 @@
import datetime
import discord
from discord.ext import commands, bridge, tasks
from lib import checks
from lib.embeds.info import MiscInfo
from modules.misc import introduction, invite, backup, info
from modules.config import set_prefix
from modules.misc import introduction, invite, backup, info
class Misc(commands.Cog):
@ -37,7 +37,6 @@ class Misc(commands.Cog):
)
@checks.allowed_in_channel()
async def uptime(self, ctx):
unix_timestamp = int(round(self.start_time.timestamp()))
return await ctx.respond(embed=MiscInfo.uptime(ctx, self.client, unix_timestamp))

View file

@ -51,7 +51,6 @@ async def backup_cleanup(dbx):
async def backup(self):
if instance.lower() == "main":
try:
await create_db_backup(dbx)

View file

@ -2,11 +2,11 @@ import asyncio
import logging
import discord
from config.parser import JsonCache
from config.parser import JsonCache
from lib import interaction
from lib.embeds.error import MiscErrors, IntroErrors
from lib.embeds.intro import General, Questions
from lib import interaction
resources = JsonCache.read_json("resources")
logs = logging.getLogger('Racu.Core')

View file

@ -1,6 +1,8 @@
import logging
import discord
from discord.ui import View
from lib.embeds.info import MiscInfo
logs = logging.getLogger('Racu.Core')
@ -18,4 +20,4 @@ class InviteButton(View):
def __init__(self):
super().__init__(timeout=None)
invite_button = discord.ui.Button(label="Invite Racu", style=discord.ButtonStyle.url, url=url)
self.add_item(invite_button)
self.add_item(invite_button)

View file

@ -1,14 +1,7 @@
import datetime
import discord
from discord import ApplicationContext
from discord.ext import commands, bridge, tasks
from discord.ext import commands, bridge
from modules.moderation import ban
from lib.embeds.error import ModErrors
from lib import checks
from lib.embeds.info import MiscInfo
from modules.misc import introduction, invite, backup, info
from modules.config import set_prefix
class Moderation(commands.Cog):

View file

@ -1,10 +1,10 @@
import logging
import discord
from modules.moderation import functions
from lib.embeds.moderation import ModEmbeds, ModErrors
from lib import formatter
from lib import formatter
from lib.embeds.moderation import ModEmbeds, ModErrors
from modules.moderation import functions
_logs = logging.getLogger('Racu.Core')
@ -42,7 +42,6 @@ async def ban_user(cog, ctx, target: discord.User, reason):
async def unban_user(ctx, target: discord.User, reason):
if not reason:
reason = "No reason provided."
@ -52,5 +51,3 @@ async def unban_user(ctx, target: discord.User, reason):
except (discord.NotFound, discord.HTTPException):
return await ctx.respond(embed=ModErrors.user_not_banned(ctx, target.id))

View file

@ -1,4 +1,5 @@
import discord
from lib.exceptions import RacuExceptions

View file

@ -52,4 +52,3 @@ class Birthday:
upcoming.append((user_id, birthday))
return upcoming

View file

@ -1,8 +1,8 @@
import logging
import os
import discord
import platform
import discord
from discord.ext import bridge
logs = logging.getLogger('Racu.Core')

View file

@ -2,8 +2,8 @@ from datetime import datetime, timedelta
import pytz
from db import database
from config.parser import JsonCache
from db import database
from services.Currency import Currency
resources = JsonCache.read_json("resources")
@ -111,4 +111,3 @@ class Dailies:
rank += 1
return leaderboard

View file

@ -1,7 +1,3 @@
import datetime
import pytz
from db import database

View file

@ -1,9 +1,8 @@
import discord
from discord.ext import commands
from lib.embeds.error import HelpErrors
from dotenv import load_dotenv
from lib import checks
import os
from lib.embeds.error import HelpErrors
load_dotenv('.env')

View file

@ -1,7 +1,7 @@
import logging
from services import Item
from db import database
from services import Item
logs = logging.getLogger('Racu.Core')

View file

@ -1,4 +1,3 @@
import json
import logging
import sqlite3

View file

@ -7,6 +7,7 @@ class SlotsStats:
"""
Handles statistics for the /slots command
"""
def __init__(self, user_id, is_won, bet, payout, spin_type, icons):
self.user_id = user_id
self.is_won = is_won

View file

@ -1,5 +1,4 @@
import os
import random
import time
from dotenv import load_dotenv
@ -148,4 +147,3 @@ class Xp:
# For levels below 10 and levels 110 and above
return 10 * current_level + 27 if current_level < 10 else 42 * current_level + 37