initial commit

This commit is contained in:
Corban-Lee Jones 2025-01-15 14:17:35 +00:00
commit a94f1bee77
11 changed files with 186 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
__pycache__
*.pyc
venv/
.env
*.log
*.log.*
.vscode/

4
FEATURES.md Normal file
View File

@ -0,0 +1,4 @@
- Web UI [ ]
- Filters [ ]
-

0
README.md Normal file
View File

0
bot/__init__.py Normal file
View File

25
bot/bot.py Normal file
View File

@ -0,0 +1,25 @@
import logging
from discord import Intents
from discord.ext import commands
log = logging.getLogger(__name__)
class DiscordBot(commands.Bot):
def __init__(self):
super().__init__(
command_prefix="@",
intents=Intents.all()
)
async def on_ready(self):
await self.wait_until_ready()
await self.tree.sync()
log.info("Bot is synced and ready")
async def load_cogs(self, cog_path: str):
log.info("Loading cogs")
for path in cog_path.iterdir():
if path.suffix == ".py":
await self.load_extension(f"cogs.{path.stem}")

51
logs/config.json Normal file
View File

@ -0,0 +1,51 @@
{
"version": 1,
"disable_existing_loggers": false,
"formatters": {
"simple": {
"format": "%(levelname)s %(message)s"
},
"detail": {
"format": "[%(asctime)s] [%(levelname)s] [%(name)s]: %(message)s"
},
"complex": {
"format": "[%(levelname)s|%(module)s|L%(lineno)d] %(asctime)s %(message)s",
"datefmt": "%Y-%m-%dT%H:%M:%S%z"
}
},
"handlers": {
"stdout": {
"class": "logging.StreamHandler",
"level": "DEBUG",
"formatter": "simple",
"stream": "ext://sys.stdout"
},
"file": {
"class": "logging.handlers.RotatingFileHandler",
"level": "DEBUG",
"formatter": "complex",
"filename": "logs/pyrss.log",
"maxBytes": 1048576,
"backupCount": 3
},
"queue_handler": {
"class": "logging.handlers.QueueHandler",
"handlers": [
"stdout",
"file"
],
"respect_handler_level": true
}
},
"loggers": {
"root": {
"level": "DEBUG",
"handlers": [
"queue_handler"
]
},
"discord": {
"level": "INFO"
}
}
}

53
main.py Normal file
View File

@ -0,0 +1,53 @@
import json
import atexit
import asyncio
import logging
import logging.config
from os import getenv
from pathlib import Path
from dotenv import load_dotenv
load_dotenv(override=True)
from bot.bot import DiscordBot
from web.app import create_app
BASE_DIR = Path(__file__).parent
async def start_web():
app = create_app()
await app.run_task(host="0.0.0.0", port=5000)
async def start_bot(token: str):
async with DiscordBot() as bot:
await bot.load_cogs(BASE_DIR / "bot" / "cogs")
await bot.start(token, reconnect=True)
def setup_logging():
# load config from file
log_config_path = BASE_DIR / "logs" / "config.json"
if not log_config_path.exists():
raise FileNotFoundError("Logging config not found")
with open(log_config_path, "r") as file:
logging_config = json.load(file)
logging.config.dictConfig(logging_config)
# create queue handler for non-blocking logs
queue_handler = logging.getHandlerByName("queue_handler")
if queue_handler is not None:
queue_handler.listener.start()
atexit.register(queue_handler.listener.stop)
async def main():
bot_token = getenv("BOT_TOKEN")
if not bot_token:
raise ValueError("'BOT_TOKEN' is missing")
setup_logging()
await asyncio.gather(start_web(), start_bot(bot_token))
if __name__ == "__main__":
asyncio.run(main())

27
requirements.txt Normal file
View File

@ -0,0 +1,27 @@
aiofiles==24.1.0
aiohappyeyeballs==2.4.4
aiohttp==3.11.11
aiosignal==1.3.2
attrs==24.3.0
blinker==1.9.0
click==8.1.8
discord.py==2.4.0
Flask==3.1.0
frozenlist==1.5.0
h11==0.14.0
h2==4.1.0
hpack==4.0.0
Hypercorn==0.17.3
hyperframe==6.0.1
idna==3.10
itsdangerous==2.2.0
Jinja2==3.1.5
MarkupSafe==3.0.2
multidict==6.1.0
priority==2.0.0
propcache==0.2.1
python-dotenv==1.0.1
Quart==0.20.0
Werkzeug==3.1.3
wsproto==1.2.0
yarl==1.18.3

0
web/__init__.py Normal file
View File

12
web/app.py Normal file
View File

@ -0,0 +1,12 @@
import logging
from quart import Quart
from .routes.dashboard import dashboard
log = logging.getLogger(__name__)
def create_app():
log.info("Creating web app and registering blueprints")
app = Quart(__name__)
app.register_blueprint(dashboard, url_prefix="/dashboard")
return app

7
web/routes/dashboard.py Normal file
View File

@ -0,0 +1,7 @@
from quart import Blueprint
dashboard = Blueprint("dashboard", __name__)
@dashboard.route("/")
async def home():
return "Dashboard page"