Compare commits

...

4 Commits

Author SHA1 Message Date
1329ef8bd6 Update CHANGELOG.md
All checks were successful
Build and Push Docker Image / build (push) Successful in 13s
2024-12-11 17:39:02 +00:00
6816eb68e8 build from logs command 2024-12-11 17:39:00 +00:00
fc752d6a84 exclude dev data directories 2024-12-11 17:37:35 +00:00
6e780f5b04 init and build db earlier 2024-12-11 17:37:20 +00:00
6 changed files with 53 additions and 17 deletions

View File

@ -8,4 +8,6 @@ __pycache__/
.vscode/ .vscode/
db.sqlite db.sqlite
db.sqlite-shm db.sqlite-shm
db.sqlite-wal db.sqlite-wal
zomboid/
data/

4
.gitignore vendored
View File

@ -5,4 +5,6 @@ __pycache__/
*.pyc *.pyc
db.sqlite db.sqlite
db.sqlite-shm db.sqlite-shm
db.sqlite-wal db.sqlite-wal
zomboid/
data/

View File

@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Debug environment variable flag
### Changed
- Log level dependent on the debug flag
## [0.0.3] - 2024-12-09 ## [0.0.3] - 2024-12-09
### Added ### Added

15
bot.py
View File

@ -48,14 +48,6 @@ class DiscordBot(commands.Bot):
# Sync app commands # Sync app commands
await self.wait_until_ready() await self.wait_until_ready()
await self.tree.sync() await self.tree.sync()
# Open database connection
await Tortoise.init(
db_url= f"sqlite://{str(DATA_DIR)}/db.sqlite",
modules={"models": ["utils.models"]}
)
await Tortoise.generate_schemas()
log.info("Discord Bot is ready") log.info("Discord Bot is ready")
async def close(self): async def close(self):
@ -124,6 +116,13 @@ async def main():
setup_logging_config(debug_mode) setup_logging_config(debug_mode)
bot_token = get_bot_token() bot_token = get_bot_token()
# Open database connection
await Tortoise.init(
db_url= f"sqlite://{str(DATA_DIR)}/db.sqlite",
modules={"models": ["utils.models"]}
)
await Tortoise.generate_schemas()
async with DiscordBot(debug_mode) as bot: async with DiscordBot(debug_mode) as bot:
await bot.load_cogs() await bot.load_cogs()
await bot.start(bot_token, reconnect=True) await bot.start(bot_token, reconnect=True)

View File

@ -8,7 +8,7 @@ from os import getenv
from pathlib import Path from pathlib import Path
from datetime import datetime from datetime import datetime
from discord import Colour from discord import Colour, Interaction, Permissions, app_commands
from discord.ext import commands, tasks from discord.ext import commands, tasks
from utils.reader import LogFileReader from utils.reader import LogFileReader
@ -32,6 +32,28 @@ class PlayersCog(commands.Cog):
self.file_handler = LogFileReader(USER_LOG_FILE_PATH) self.file_handler = LogFileReader(USER_LOG_FILE_PATH)
self.listen_for_changes.start() self.listen_for_changes.start()
@app_commands.command(name="build-from-logs")
@app_commands.default_permissions(Permissions.all())
async def build_from_logs(self, inter: Interaction):
"""
Build player data from existing and older log files.
"""
await inter.response.defer()
log.info("Building player data from logs.")
# Delete the existing data, as we will reconstruct it.
await Player.all().delete()
for log_file in LOGS_FOLDER_PATH.glob("**/*.txt"):
log.debug("building from log file: %s", str(log_file))
file_handler = LogFileReader(log_file, track_from_start=True)
for line in await file_handler.read():
await self.process_log_line(line, alert=False)
await inter.followup.send("Completed")
@tasks.loop(seconds=3) @tasks.loop(seconds=3)
async def listen_for_changes(self): async def listen_for_changes(self):
""" """
@ -40,15 +62,15 @@ class PlayersCog(commands.Cog):
for line in await self.file_handler.read(): for line in await self.file_handler.read():
await self.process_log_line(line) await self.process_log_line(line)
async def process_log_line(self, line: str): async def process_log_line(self, line: str, alert: bool = True):
log.debug("processing log line") log.debug("processing log line")
if "died" in line: if "died" in line:
await self.process_player_death(line) await self.process_player_death(line, alert)
elif "fully connected" in line: elif "fully connected" in line:
await self.process_connected_player(line) await self.process_connected_player(line, alert)
elif "disconnected player" in line: elif "disconnected player" in line:
await self.process_disconnected_player(line) await self.process_disconnected_player(line, alert)
async def process_player_death(self, line: str, alert: bool = False): async def process_player_death(self, line: str, alert: bool = False):
log.debug("processing player death") log.debug("processing player death")

View File

@ -13,11 +13,12 @@ log = logging.getLogger(__name__)
class LogFileReader: class LogFileReader:
""" """
""" """
def __init__(self, file_path: Path): def __init__(self, file_path: Path, track_from_start: bool=False):
if not isinstance(file_path, Path): if not isinstance(file_path, Path):
raise TypeError(f"file_path must be type Path, not {type(file_path)}") raise TypeError(f"file_path must be type Path, not {type(file_path)}")
self.file_path = file_path self.file_path = file_path
self.track_from_start = track_from_start
self._last_line_number = 0 self._last_line_number = 0
log.debug("%s created with path %s", self.__class__.__name__, str(file_path)) log.debug("%s created with path %s", self.__class__.__name__, str(file_path))
@ -27,7 +28,7 @@ class LogFileReader:
raise FileNotFoundError(self.file_path) raise FileNotFoundError(self.file_path)
async with aiofiles.open(self.file_path, "r", encoding="utf-8") as file: async with aiofiles.open(self.file_path, "r", encoding="utf-8") as file:
if self._last_line_number == 0: if self._last_line_number == 0 and not self.track_from_start:
await file.seek(0, 2) await file.seek(0, 2)
self._last_line_number = await file.tell() self._last_line_number = await file.tell()
return [] return []