aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.py18
-rw-r--r--lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py2
-rw-r--r--lib/discordSync.py79
-rw-r--r--proxy.py24
-rw-r--r--requirements.txt10
-rw-r--r--testDiscord.py7
6 files changed, 124 insertions, 16 deletions
diff --git a/config.py b/config.py
index 321b133..7ba7ec1 100644
--- a/config.py
+++ b/config.py
@@ -52,10 +52,20 @@ SMOKE_PLANE = True
SMOKE_LIFE = 5
-#Discord chat integration
-#Make sure to enable read message privilege for the bot.
+# Discord chat integration
+# ```bash
+# pip install -r requirements.txt
+# ```
+# to install dependencies required to run the discord chat integration
+#
+# On Modern Linux distros you may need to create a virtual environment to install
+# the dependencies
-DISCORD_TOKEN = "YourDiscordBotTOKEN"
+DISCORD_ENABLED = False
+
+# Make sure to enable read message intent for the bot.
+
+DISCORD_TOKEN = "YOUR_DISCORD_BOT_TOKEN"
# Channel ID for the chat
-CHANNEL_ID = 0 # Channel ID, as an integer
+CHANNEL_ID = 0
diff --git a/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py b/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py
index f524b9f..1c683a5 100644
--- a/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py
+++ b/lib/PacketManager/packets/FSNETCMD_TEXTMESSAGE.py
@@ -14,7 +14,7 @@ class FSNETCMD_TEXTMESSAGE: #32
self.raw_message = self.buffer[12:].decode("utf-8").strip("\x00")
match = re.match(r"^\(([^)]+)\)(.+)", self.raw_message)
if match:
- self.user. self.message = match.groups()
+ self.user, self.message = match.groups()
@staticmethod
def encode(message:str, with_size:bool=False):
diff --git a/lib/discordSync.py b/lib/discordSync.py
new file mode 100644
index 0000000..e6618a9
--- /dev/null
+++ b/lib/discordSync.py
@@ -0,0 +1,79 @@
+import aiohttp
+import asyncio
+from config import *
+from lib.PacketManager.packets.FSNETCMD_TEXTMESSAGE import FSNETCMD_TEXTMESSAGE as txtMsgr
+from logging import debug, warning
+
+BOT_TOKEN = DISCORD_TOKEN
+
+# API Base URL
+BASE_URL = 'https://discord.com/api/v10'
+
+# Headers for making API requests
+HEADERS = {
+ 'Authorization': f'Bot {BOT_TOKEN}',
+ 'Content-Type': 'application/json'
+}
+
+# Function to send a message to a specific Discord channel
+async def discord_send_message(channel_id, content):
+ url = f'{BASE_URL}/channels/{channel_id}/messages'
+ payload = {
+ 'content': content
+ }
+
+ async with aiohttp.ClientSession() as session:
+ async with session.post(url, json=payload, headers=HEADERS) as response:
+ if response.status in [200, 201]:
+ pass
+ else:
+ warning(f'Failed to send message. Status Code: {response.status} | {await response.text()}')
+
+# Function to fetch messages from a specific Discord channel
+async def discord_fetch_messages(channel_id, last_message_id=None):
+ url = f'{BASE_URL}/channels/{channel_id}/messages'
+ params = {
+ 'limit': 1 # Fetch the most recent message
+ }
+ if last_message_id:
+ params['after'] = last_message_id # Fetch only new messages
+
+ async with aiohttp.ClientSession() as session:
+ async with session.get(url, headers=HEADERS, params=params) as response:
+ if response.status == 200:
+ messages = await response.json()
+ return messages # Return the list of messages
+ else:
+ print(f'Failed to fetch messages. Status Code: {response.status} | {await response.text()}')
+ return []
+
+# Callback function when a new message is detected
+def on_new_message(message):
+ author = message['author']
+ # Skip messages from bots (including this bot itself)
+ if author.get('bot'): # Safely get the 'bot' key (returns None if key does not exist)
+ return
+
+ username = author['username']
+ content = message['content']
+ debug(f'New Discord message from {username}: {content}')
+
+# Asynchronous function to monitor a Discord channel for new messages
+async def monitor_channel(channel_id, playerList:list):
+ last_message_id = None
+ while True:
+ # Fetch new messages
+ messages = await discord_fetch_messages(channel_id, last_message_id)
+ if messages:
+ # Process only the latest message
+ message = messages[0]
+ if messages:
+ message = messages[0]
+ if last_message_id is None or message['id'] > last_message_id and not message['author'].get("bot"): # Ensure only newer messages are processed and bots are ignored
+ last_message_id = message['id']
+ encoded_msg = txtMsgr.encode(f"[Discord] {message['author']['username']}: {message['content']}", True)
+ for player in playerList:
+ player.streamWriterObject.write(encoded_msg)
+ await player.streamWriterObject.drain()
+ on_new_message(message)
+ await asyncio.sleep(1) # Poll every second (adjust as needed)
diff --git a/proxy.py b/proxy.py
index f600a22..8ac4201 100644
--- a/proxy.py
+++ b/proxy.py
@@ -12,12 +12,18 @@ from lib.PacketManager.packets import *
import logging
from logging import critical, warning, info, debug
from config import *
+if DISCORD_ENABLED: from lib.discordSync import *
+import traceback
# Configuration
SERVER_HOST = SERVER_HOST
SERVER_PORT = SERVER_PORT
PROXY_PORT = PROXY_PORT
+# Hold all Connected Players
+
+CONNECTED_PLAYERS = []
+
# ANSI escape codes for colors
COLORS = {
"DEBUG": "\033[92m", # Green
@@ -60,7 +66,7 @@ async def handle_client(client_reader, client_writer):
if peername:
ipAddr, clientPort = peername
player.set_ip(ipAddr)
-
+ CONNECTED_PLAYERS.append(player)
debug("Player object initiated")
async def forward(reader, writer, direction, player=player):
@@ -108,8 +114,8 @@ async def handle_client(client_reader, client_writer):
player.login(FSNETCMD_LOGON(packet))
if player.version != YSF_VERSION and VIA_VERSION:
info(f"ViaVersion enabled : Porting {player.username} from {player.version} to {YSF_VERSION}")
- message_to_server.append(YSchat.message(f"Porting you to YSFlight {YSF_VERSION}, This is currently Experimental"))
- message_to_server.append(YSchat.message(f"Please report any bugs to the server admin or join with the correct version"))
+ message_to_client.append(YSchat.message(f"Porting you to YSFlight {YSF_VERSION}, This is currently Experimental"))
+ message_to_client.append(YSchat.message(f"Please report any bugs to the server admin or join with the correct version"))
data = YSviaversion.genViaVersion(player.username, YSF_VERSION)
writer.write(data)
continue
@@ -154,6 +160,12 @@ async def handle_client(client_reader, client_writer):
if player.aircraft.get_initial_config_value("AFTBURNR") == "TRUE": message_to_client.append(player.aircraft.set_afterburner(True))
debug("Aircraft repaired!")
+ elif packet_type == "FSNETCMD_TEXTMESSAGE":
+ msg = FSNETCMD_TEXTMESSAGE(packet)
+ finalMsg = (f"{player.username} : {msg.message}")
+ if DISCORD_ENABLED:
+ # Make it non blocking!
+ asyncio.create_task(discord_send_message(CHANNEL_ID, finalMsg))
# elif packet_type == "FSNETCMD_GETDAMAGE":
# h = FSNETCMD_GETDAMAGE(packet, True)
@@ -249,6 +261,7 @@ async def handle_client(client_reader, client_writer):
# continue
except Exception as e:
warning(f"Error parsing flight data: {e}", exc_info=True)
+ traceback.print_exc() # This will display the full traceback
else :
debug("S2C" + str(packet_type))
@@ -270,6 +283,9 @@ async def handle_client(client_reader, client_writer):
elif packet_type == "FSNETCMD_PREPARESIMULATION":
welcomeMsg = YSchat.message(WELCOME_MESSAGE.format(username=player.username))
message_to_server.append(welcomeMsg)
+ print("Here!")
+ if DISCORD_ENABLED:
+ asyncio.create_task(discord_send_message(CHANNEL_ID, f"{player.username} has joined the server!"))
# Forward the packet to the other endpoint
writer.write(data)
@@ -302,6 +318,8 @@ async def handle_client(client_reader, client_writer):
async def start_proxy():
server = await asyncio.start_server(handle_client, "0.0.0.0", PROXY_PORT)
info(f"Proxy server listening on port {PROXY_PORT}")
+ if DISCORD_ENABLED:
+ await asyncio.create_task(monitor_channel(CHANNEL_ID, CONNECTED_PLAYERS))
async with server:
await server.serve_forever()
diff --git a/requirements.txt b/requirements.txt
index 844f49a..859a08f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,9 @@
-discord.py
+aiohappyeyeballs==2.4.6
+aiohttp==3.11.12
+aiosignal==1.3.2
+attrs==25.1.0
+frozenlist==1.5.0
+idna==3.10
+multidict==6.1.0
+propcache==0.2.1
+yarl==1.18.3
diff --git a/testDiscord.py b/testDiscord.py
deleted file mode 100644
index ca084e8..0000000
--- a/testDiscord.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from lib.DiscordClient import DiscordClient
-import discord
-
-intents = discord.Intents.default()
-intents.message_content = True
-client = DiscordClient(intents)
-client.start_bot()