Move update clan messages into utils, a slash command will need the functionality.

This commit is contained in:
2024-05-15 13:57:51 -04:00
parent ee6b301791
commit cf5b5f8068
2 changed files with 119 additions and 104 deletions
+4 -103
View File
@@ -9,16 +9,12 @@ import uvicorn
from fastapi import FastAPI
from git import Repo
from nextcord.ext import commands
from sqlalchemy import select, update
from sqlalchemy.orm import Session
from config import DakinyConfig
from database_setup.sql_data_classes import Messages, engine
from utils import REPO_DIR, update_clan_messages
app = FastAPI()
REPO_URL = "https://gitea.cheezers.org/imcompiling/dakiny-messages.git"
REPO_DIR = "./dakiny-messages"
MESSAGES_DIR = f"{REPO_DIR}/messages"
class ClanMessages(commands.Cog, name="Clan Messages"):
@@ -45,112 +41,17 @@ class ClanMessages(commands.Cog, name="Clan Messages"):
async def update_messages(self):
"""
Pulls from git and then updates all the discord messages as described by the files in the git repo.
Pulls from git and then calls method to update all the discord messages as described by the
files in the git repo.
"""
self.origin.pull()
guild: nextcord.Guild = self.bot.get_guild(self.config.params.guild_id)
# for ever directory, sort the files by number then post
# posting involves checking if there is a message for that particular file then editing it or creating a
# new one. the message could be deleted, which would cause a new message to be sent and database updated.
dirs = [
dir_name
for dir_name in os.listdir(MESSAGES_DIR)
if os.path.isdir(f"{MESSAGES_DIR}/{dir_name}")
]
with Session(engine) as session:
for dir_name in dirs:
dir_path = f"{MESSAGES_DIR}/{dir_name}"
channel = await self.get_clan_message_channel(session, dir_name, guild)
sorted_files = sorted(
os.listdir(dir_path),
key=lambda filename: int(filename.split(".")[0]),
)
for file_name in sorted_files:
message_name = f"{dir_name}/{file_name}"
file_path = f"{dir_path}/{file_name}"
with open(file_path, "r", encoding="utf8") as reader:
stmt = select(Messages.Id).where(Messages.Path == message_name)
msg_id = session.scalar(stmt)
if msg_id is None:
# don't have a message for this file
msg = await channel.send(reader.read(2000))
new_message = Messages(Path=message_name, Id=msg.id)
session.add(new_message)
session.commit()
else:
try:
msg: nextcord.Message = await channel.fetch_message(
msg_id
)
await msg.edit(reader.read(2000))
except nextcord.NotFound:
msg = await channel.send(reader.read(2000))
stmt = (
update(Messages)
.where(Messages.Path == message_name)
.values(Id=msg.id)
)
session.execute(stmt)
session.commit()
await update_clan_messages(guild)
return {"message": "Successfully updated all discord messages."}
async def get_clan_message_channel(
self, session: Session, channel_name: str, guild: nextcord.Guild
) -> nextcord.TextChannel:
"""
Used to obtain a channel from the guild object. Searches database for an id to get the channel. If that is not
found, then searches through all channels in the guild to find one with a matching name. If that also doesn't
turn up a channel, then creates it. Adds an entry into database for last two paths.
Assumes that there is an open session to the database.
Args:
session (Session): Open connection to database.
channel_name (str): Name of channel to obtain.
guild (nextcord.Guild): Guild object to get channel from.
Returns:
nextcord.TextChannel: Channel object with name channel_name.
"""
stmt = select(Messages.Id).where(Messages.Path == channel_name)
channel_id = session.scalar(stmt)
if channel_id is None:
ret_channel = None
# channel is not tracked. see if it exists
channels = await guild.fetch_channels()
for channel in channels:
if (
channel.name == channel_name
and channel.__class__ is nextcord.TextChannel
):
ret_channel = channel
if ret_channel is None:
# channel doesn't exist, we must create it
ret_channel = await guild.create_text_channel(
channel_name,
reason="Creating channel as required for by design of Dakiny-Messages repo.",
)
# record channel information
new_item = Messages(Path=channel_name, Id=ret_channel.id)
session.add(new_item)
session.commit()
return ret_channel
try:
return await guild.fetch_channel(channel_id)
except nextcord.NotFound:
# the channel was deleted for some reason
return await guild.create_text_channel(
channel_name,
reason="Creating channel as required for by design of Dakiny-Messages repo.",
)
def repo_setup(self):
"""
Checks if the repo exists and creates repo object, clones if it does not.
+115 -1
View File
@@ -2,21 +2,25 @@
File contains util functions.
"""
import os
from datetime import datetime
import nextcord
from sqlalchemy import select
from sqlalchemy import select, update
from sqlalchemy.orm import Session
from config import DakinyConfig
from database_setup.sql_data_classes import (
CouncilMembers,
Messages,
ParticipationPoints,
Votes,
engine,
)
NOMINEE_SPLITTER = "========================================\n\n"
REPO_DIR = "./dakiny-messages"
MESSAGES_DIR = f"{REPO_DIR}/messages"
def get_datetime(day: str) -> datetime:
@@ -386,3 +390,113 @@ def record_event_host(config: DakinyConfig, user: int):
points.Points += host_point_value
session.commit()
async def update_clan_messages(guild: nextcord.Guild):
"""
Updates all clan messages to contents in MESSAGES_DIR.
Does not to any git work. Is expected to be called after git is pulled.
for ever directory, sort the files by number then post
posting involves checking if there is a message for that particular file then editing it or creating a
new one. the message could be deleted, which would cause a new message to be sent and database updated.
Channel fetching/management is handled by another function.
Args:
guild (nextcord.Guild): Guild object that all channels and messages belong to.
"""
dirs = [
dir_name
for dir_name in os.listdir(MESSAGES_DIR)
if os.path.isdir(f"{MESSAGES_DIR}/{dir_name}")
]
with Session(engine) as session:
for dir_name in dirs:
dir_path = f"{MESSAGES_DIR}/{dir_name}"
channel = await get_clan_message_channel(session, dir_name, guild)
sorted_files = sorted(
os.listdir(dir_path),
key=lambda filename: int(filename.split(".")[0]),
)
for file_name in sorted_files:
message_name = f"{dir_name}/{file_name}"
file_path = f"{dir_path}/{file_name}"
with open(file_path, "r", encoding="utf8") as reader:
stmt = select(Messages.Id).where(Messages.Path == message_name)
msg_id = session.scalar(stmt)
if msg_id is None:
# don't have a message for this file
msg = await channel.send(reader.read(2000))
new_message = Messages(Path=message_name, Id=msg.id)
session.add(new_message)
session.commit()
else:
try:
msg: nextcord.Message = await channel.fetch_message(msg_id)
await msg.edit(reader.read(2000))
except nextcord.NotFound:
msg = await channel.send(reader.read(2000))
stmt = (
update(Messages)
.where(Messages.Path == message_name)
.values(Id=msg.id)
)
session.execute(stmt)
session.commit()
async def get_clan_message_channel(
session: Session, channel_name: str, guild: nextcord.Guild
) -> nextcord.TextChannel:
"""
Used to obtain a channel from the guild object. Searches database for an id to get the channel. If that is not
found, then searches through all channels in the guild to find one with a matching name. If that also doesn't
turn up a channel, then creates it. Adds an entry into database for last two paths.
Assumes that there is an open session to the database.
Args:
session (Session): Open connection to database.
channel_name (str): Name of channel to obtain.
guild (nextcord.Guild): Guild object to get channel from.
Returns:
nextcord.TextChannel: Channel object with name channel_name.
"""
stmt = select(Messages.Id).where(Messages.Path == channel_name)
channel_id = session.scalar(stmt)
if channel_id is None:
ret_channel = None
# channel is not tracked. see if it exists
channels = await guild.fetch_channels()
for channel in channels:
if (
channel.name == channel_name
and channel.__class__ is nextcord.TextChannel
):
ret_channel = channel
if ret_channel is None:
# channel doesn't exist, we must create it
ret_channel = await guild.create_text_channel(
channel_name,
reason="Creating channel as required for by design of Dakiny-Messages repo.",
)
# record channel information
new_item = Messages(Path=channel_name, Id=ret_channel.id)
session.add(new_item)
session.commit()
return ret_channel
try:
return await guild.fetch_channel(channel_id)
except nextcord.NotFound:
# the channel was deleted for some reason
return await guild.create_text_channel(
channel_name,
reason="Creating channel as required for by design of Dakiny-Messages repo.",
)