diff --git a/README.md b/README.md index 83858ec..8cda6fe 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ - **Discord Admninistration**: Manage your discord server directly from the bot. - **Admin Commands**: Effortlessly manage members with commands like kick, ban, timeout, and more. - **Ticket System**: Create a customized thread based ticket system with ease. + - **Chat Relay**: This will allow you to send and receive messages between the server and discord. ## Installation: Please check our [wiki](https://github.com/dkoz/palworld-bot/wiki) for all guides related to the bot. \ No newline at end of file diff --git a/cogs/palchat/chatfeed.py b/cogs/palchat/chatfeed.py new file mode 100644 index 0000000..415575b --- /dev/null +++ b/cogs/palchat/chatfeed.py @@ -0,0 +1,91 @@ +import nextcord +from nextcord.ext import commands, tasks +import utils.settings as s +import requests +import re +import logging +import os +import asyncio + +log_directory = s.chatlog_path +webhook_url = s.chatlog_webhookurl + +class ChatFeedCog(commands.Cog): + def __init__(self, bot): + self.bot = bot + self.log_directory = log_directory + self.webhook_url = webhook_url + self.first_check_done = False + self.last_processed_line = None + self.current_log_file = None + self.check_logs.start() + self.blocked_phrases = ["/adminpassword", "/creativemenu", "/"] + + def cog_unload(self): + self.check_logs.cancel() + + @tasks.loop(seconds=8) + async def check_logs(self): + try: + files = sorted( + [ + f for f in os.listdir(self.log_directory) + if f.endswith(".txt") or f.endswith(".log") + ], + key=lambda x: os.stat(os.path.join(self.log_directory, x)).st_mtime, + reverse=True + ) + if not files: + return + + newest_file = os.path.join(self.log_directory, files[0]) + if self.current_log_file != newest_file: + self.current_log_file = newest_file + self.last_processed_line = None + self.first_check_done = False + + with open(self.current_log_file, "r", encoding="utf-8", errors="ignore") as file: + content = file.read() + lines = content.splitlines() + + if not self.first_check_done: + if lines: + self.last_processed_line = lines[-1] + self.first_check_done = True + return + + new_lines_start = False + for line in lines: + if line == self.last_processed_line: + new_lines_start = True + continue + if new_lines_start or self.last_processed_line is None: + if "[Chat::" in line: + await self.process_and_send(line) + + if lines: + self.last_processed_line = lines[-1] + except: + pass + + async def process_and_send(self, line): + try: + match = re.search(r"\[Chat::(?:Global|Local|Guild)\]\['([^']+)'.*\]: (.*)", line) + if match: + username, message = match.groups() + if any(bp in message for bp in self.blocked_phrases): + return + requests.post(self.webhook_url, json={"username": username, "content": message}) + await asyncio.sleep(1) + except: + pass + + @check_logs.before_loop + async def before_check_logs(self): + await self.bot.wait_until_ready() + +def setup(bot): + if not os.getenv("CHATLOG_PATH") or not os.getenv("CHATLOG_WEBHOOKURL"): + logging.error("Chatlog path or webhook URL not set.") + return + bot.add_cog(ChatFeedCog(bot)) diff --git a/cogs/palchat/chatrelay.py b/cogs/palchat/chatrelay.py new file mode 100644 index 0000000..587f8e3 --- /dev/null +++ b/cogs/palchat/chatrelay.py @@ -0,0 +1,48 @@ +import nextcord +from nextcord.ext import commands +import os +from utils.database import get_server_details +from utils.rconutility import RconUtility +import utils.settings as s +import logging + +sftp_channel_id = s.chatlog_channel +server_name = s.chatlog_servername + +class ChatRelayCog(commands.Cog): + def __init__(self, bot): + self.bot = bot + self.sftp_channel_id = sftp_channel_id + self.server_name = server_name + self.rcon_util = RconUtility() + + @commands.Cog.listener() + async def on_message(self, message: nextcord.Message): + if message.author.bot: + return + + if message.channel.id != self.sftp_channel_id: + return + + if not message.content: + return + + server_details = await get_server_details(self.server_name) + if not server_details: + return + + broadcast_message = f"[Discord] {message.content}" + server_info = { + "name": self.server_name, + "host": server_details[0], + "port": server_details[1], + "password": server_details[2], + } + + await self.rcon_util.rcon_command(server_info, f"Broadcast {broadcast_message}") + +def setup(bot): + if not os.getenv("CHATLOG_CHANNEL"): + logging.error("Chat log channel env variable not set. Chat feed will not be loaded.") + return + bot.add_cog(ChatRelayCog(bot)) diff --git a/utils/constants.py b/utils/constants.py index 0d99150..b17a309 100644 --- a/utils/constants.py +++ b/utils/constants.py @@ -1,7 +1,7 @@ FOOTER_IMAGE = "https://palbot.gg/assets/images/rexavatar.png" FOOTER_TEXT = "Powered by Palbot" TITLE_URL = "https://github.com/dkoz/palworld-palbot" -PALBOT_VERSION = "v0.3.7" +PALBOT_VERSION = "v0.3.8" PALBOT_ART = r""" __________ .__ ___. __ \______ \_____ | |\_ |__ _____/ |_ diff --git a/utils/settings.py b/utils/settings.py index 81e99a5..a5fbfe6 100644 --- a/utils/settings.py +++ b/utils/settings.py @@ -10,6 +10,10 @@ bot_activity = os.getenv("BOT_ACTIVITY", "Palworld") steam_api_key = os.getenv("STEAM_API_KEY", "No key found") bot_language = os.getenv("BOT_LANGUAGE", "en") +chatlog_path = os.getenv("CHATLOG_PATH", r"C:\path\to\server\Pal\Binaries\Win64\palguard\logs") +chatlog_webhookurl = os.getenv("CHATLOG_WEBHOOKURL", "https://discord.com/api/webhooks/yourwebhookurl") +chatlog_servername = os.getenv("CHATLOG_SERVERNAME", "Palworld Server") +chatlog_channel = int(os.getenv("CHATLOG_CHANNEL", 12345678910)) whitelist_check = os.getenv('GUILD_WHITELIST') # Logic for the guild whitelist.