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
95 changes: 90 additions & 5 deletions mqttbridge/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,24 @@ async def process_mqtt_message(self, msg):
await self.check_claim_code(mp)
return

await self.send_to_discord(mp, se, message_text)
reply_id = getattr(mp.decoded, 'reply_id', 0)
emoji_flag = getattr(mp.decoded, 'emoji', 0)

discord_msg_id = None
if reply_id > 0:
with self.get_db() as conn:
c = conn.cursor()
c.execute("SELECT discord_message_id FROM message_history WHERE message_id = ?", (reply_id,))
result = c.fetchone()
if result and result[0]:
discord_msg_id = result[0]

if reply_id > 0 and emoji_flag != 0 and discord_msg_id:
# Emoji Reaction (Tapback)
await self.append_reaction_to_discord(mp, message_text, discord_msg_id)
else:
# Threaded Reply or Standard Message
await self.send_to_discord(mp, se, message_text, reply_to_discord_id=discord_msg_id if reply_id > 0 and emoji_flag == 0 else None)

if mp.decoded.portnum == portnums_pb2.NODEINFO_APP:
try:
Expand Down Expand Up @@ -635,7 +652,7 @@ async def save_node_info(self, node_id, node_data):
except Exception as e:
print(f"Error saving node to database: {str(e)}")

async def send_to_discord(self, mp, se, message_text):
async def send_to_discord(self, mp, se, message_text, reply_to_discord_id=None):
"""Send a decoded Meshtastic message to the configured Discord channel"""
try:
# Process channel information
Expand Down Expand Up @@ -728,10 +745,19 @@ async def send_to_discord(self, mp, se, message_text):

# Send to Discord
if self.messages_channel:
if "owner" in node_info and node_info["owner"] and node_info["owner"]["notifications"]:
message = await self.messages_channel.send(f"<@{node_info['owner']['discord_id']}>", embed=embed)
reference = None
if reply_to_discord_id:
try:
reference = await self.messages_channel.fetch_message(reply_to_discord_id)
except (discord.NotFound, discord.HTTPException):
pass

content = f"<@{node_info['owner']['discord_id']}>" if "owner" in node_info and node_info["owner"] and node_info["owner"]["notifications"] else None

if reference:
message = await self.messages_channel.send(content=content, embed=embed, reference=reference)
else:
message = await self.messages_channel.send(embed=embed)
message = await self.messages_channel.send(content=content, embed=embed)

with self.get_db() as conn:
c = conn.cursor()
Expand All @@ -750,6 +776,65 @@ async def send_to_discord(self, mp, se, message_text):
import traceback
print(traceback.format_exc())

async def append_reaction_to_discord(self, mp, message_text, discord_msg_id):
"""Append an emoji reaction to the original Discord message's embed"""
try:
if not self.messages_channel:
return

try:
original_msg = await self.messages_channel.fetch_message(discord_msg_id)
except (discord.NotFound, discord.HTTPException):
return

if not original_msg.embeds:
return

embed = original_msg.embeds[0]

# Get sender info
sender_int = getattr(mp, "from") if hasattr(mp, "from") else 0
sender_id = format(sender_int, '08x')

node_name = f"!{sender_id}"

with self.get_db() as conn:
c = conn.cursor()
c.execute("SELECT short_name FROM nodes WHERE node_id = ?", (str(sender_int),))
node_row = c.fetchone()
if node_row and node_row[0]:
node_name = node_row[0]

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

# Find existing Reactions field
reactions_idx = -1
for i, field in enumerate(embed.fields):
if field.name == "Reactions":
reactions_idx = i
break

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}"
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
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)

await original_msg.edit(embed=embed)

except Exception as e:
print(f"Error appending reaction to Discord: {e}")

async def process_telemetry(self, mp):
"""Process telemetry information and save it to the database"""
try:
Expand Down
Loading