Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 108 additions & 10 deletions mqttbridge/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,12 @@ async def setup_database(self):
WHERE length(node_id_hex) < 9
""")

# Add discord_message_id to traceroute if it doesn't exist
try:
c.execute("ALTER TABLE traceroute ADD COLUMN discord_message_id INTEGER")
except sqlite3.OperationalError:
pass

conn.commit()
except Exception as e:
print(f"Error setting up database: {str(e)}")
Expand Down Expand Up @@ -806,7 +812,7 @@ async def append_reaction_to_discord(self, mp, message_text, discord_msg_id):
node_name = node_row[0]

settings = await self.config.all()
reaction_str = f"{message_text} - [{node_name}]({settings['meshview_domain']}/packet/{mp.id})"
user_link = f"[{node_name}]({settings['meshview_domain']}/packet/{mp.id})"

# Find existing Reactions field
reactions_idx = -1
Expand All @@ -818,14 +824,28 @@ async def append_reaction_to_discord(self, mp, message_text, discord_msg_id):
REACTIONS_FIELD_LIMIT = 1024

if reactions_idx >= 0:
# Append to existing
current_value = embed.fields[reactions_idx].value
new_value = f"{current_value}\n{reaction_str}"
lines = current_value.split('\n')

updated = False
for i, line in enumerate(lines):
if line.startswith(f"{message_text} - ") or line.startswith(f"{message_text}- "):
lines[i] = f"{line}, {user_link}"
updated = True
break

if not updated:
lines.append(f"{message_text} - {user_link}")

# Sort lines natively
lines.sort()
new_value = '\n'.join(lines)

if len(new_value) > REACTIONS_FIELD_LIMIT:
new_value = new_value[:REACTIONS_FIELD_LIMIT - 3] + "..."
embed.set_field_at(reactions_idx, name="Reactions", value=new_value, inline=False)
else:
# Add new field
reaction_str = f"{message_text} - {user_link}"
if len(reaction_str) > REACTIONS_FIELD_LIMIT:
reaction_str = reaction_str[:REACTIONS_FIELD_LIMIT - 3] + "..."
embed.add_field(name="Reactions", value=reaction_str, inline=False)
Expand Down Expand Up @@ -1195,12 +1215,90 @@ async def process_traceroute(self, mp, se):

if self.traceroute_channel:
if "owner" in sender_info and sender_info['owner'] and sender_info['owner']['notifications']:
await self.traceroute_channel.send(f"<@{sender_info['owner']['discord_id']}>", embed=embed)
message = await self.traceroute_channel.send(f"<@{sender_info['owner']['discord_id']}>", embed=embed)
else:
await self.traceroute_channel.send(embed=embed)
message = await self.traceroute_channel.send(embed=embed)

with self.get_db() as conn:
c = conn.cursor()
c.execute("""
UPDATE traceroute
SET discord_message_id = ?
WHERE trace_id = ?
""", (message.id, mp.id))
conn.commit()
else:
return

elif trace_direction == "REPLY":
original_trace_id = mp.decoded.request_id
discord_msg_id = None
with self.get_db() as conn:
c = conn.cursor()
c.execute("SELECT discord_message_id FROM traceroute WHERE trace_id = ?", (original_trace_id,))
row = c.fetchone()
if row and row[0]:
discord_msg_id = int(row[0])

# Parse RouteDiscovery
route_discovery = mesh_pb2.RouteDiscovery()
route_names = []
try:
route_discovery.ParseFromString(mp.decoded.payload)
with self.get_db() as conn:
c = conn.cursor()
for hop_num in route_discovery.route:
hop_str = str(hop_num)
c.execute("SELECT short_name, node_id_hex FROM nodes WHERE node_id = ?", (hop_str,))
node_row = c.fetchone()
if node_row and node_row[0]:
route_names.append(node_row[0])
elif node_row and node_row[1]:
route_names.append(node_row[1])
else:
route_names.append(f"!{format(hop_num, '08x')}")
except Exception as e:
print(f"Error parsing RouteDiscovery: {e}")

route_display = " β†’ ".join(route_names) if route_names else "Unknown"

if discord_msg_id and self.traceroute_channel:
try:
original_msg = await self.traceroute_channel.fetch_message(discord_msg_id)
if original_msg.embeds:
# Create a new embed from the original to ensure safe editing
new_embed = discord.Embed.from_dict(original_msg.embeds[0].to_dict())

# Update Description
desc = new_embed.description
if desc:
desc = desc.replace("Direction: SEND", "Direction: REPLY (Complete)")
else:
desc = "Direction: REPLY (Complete)"
new_embed.description = desc

new_embed.add_field(name="Route Taken", value=route_display, inline=False)
await original_msg.edit(embed=new_embed)
# Flag that we successfully edited the message
else:
discord_msg_id = None # Fallback to new message
except (discord.NotFound, discord.HTTPException) as e:
print(f"Error editing original traceroute message: {e}")
# Fallback if message not found or edit fails
discord_msg_id = None

# If we couldn't find/edit the message, post a new one
if not discord_msg_id and self.traceroute_channel:
settings = await self.config.all()
embed = discord.Embed(
title=f"Traceroute Reply Received",
description=f"Response to trace ID [{original_trace_id}]({settings['meshview_domain']}/packet/{original_trace_id})",
color=discord.Color.purple(),
timestamp=datetime.now()
)
embed.add_field(name="Route Taken", value=route_display, inline=False)
await self.traceroute_channel.send(embed=embed)

except Exception as e:
print(f"Error processing traceroute: {str(e)}")

Expand Down Expand Up @@ -1324,20 +1422,20 @@ async def store_message_history(self, mp, se, message_text):
timestamp
))

# Prune old messages if we have too many (keep last 50)
# Prune old messages if we have too many (keep last 10000)
c.execute("SELECT COUNT(*) FROM message_history")
count = c.fetchone()[0]

if count > 50:
# Delete oldest messages to keep only the newest 45
if count > 10000:
# Delete oldest messages to keep only the newest 9500
c.execute("""
DELETE FROM message_history
WHERE timestamp IN (
SELECT timestamp FROM message_history
ORDER BY timestamp ASC
LIMIT ?
)
""", (count - 45,))
""", (count - 9500,))

conn.commit()

Expand Down
Loading