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
59 changes: 37 additions & 22 deletions mqttbridge/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ async def setup_database(self):
)
''')

# Migrate existing node_id_hex values to zero-padded 8-char format
c.execute("""
UPDATE nodes
SET node_id_hex = '!' || printf('%08x', node_num)
WHERE length(node_id_hex) < 9
""")

conn.commit()
except Exception as e:
print(f"Error setting up database: {str(e)}")
Expand Down Expand Up @@ -365,7 +372,7 @@ async def process_mqtt_message(self, msg):
if mp.to != 4294967295:
return # Ignore messages not sent to broadcast

message_text = mp.decoded.payload.decode('utf-8')
message_text = mp.decoded.payload.decode('utf-8').strip(' \t\n\r"\'"\u201c\u201d\u2018\u2019')

# Store this message in database
await self.store_message_history(mp, se, message_text)
Expand Down Expand Up @@ -463,7 +470,7 @@ async def process_node_info(self, mp, se):

# Get sender node ID
node_id = getattr(mp, "from") if hasattr(mp, "from") else 0
node_id_hex = format(node_id, 'x')
node_id_hex = format(node_id, '08x')

# Convert enum values to string representations
hw_model = node_info.hw_model
Expand Down Expand Up @@ -631,7 +638,7 @@ async def send_to_discord(self, mp, se, message_text):

# Get sender info - convert int to hex string
sender_int = getattr(mp, "from") if hasattr(mp, "from") else 0
sender_id = format(sender_int, 'x') # Format as hex string without '0x' prefix
sender_id = format(sender_int, '08x') # Format as zero-padded hex string

# Get gateway ID from ServiceEnvelope
via = int(se.gateway_id[1:], 16) if hasattr(se, 'gateway_id') and se.gateway_id else None
Expand Down Expand Up @@ -1212,8 +1219,8 @@ async def store_message_history(self, mp, se, message_text):
async def check_claim_code(self, mp):
"""Check if the message contains a claim code and process it"""
try:
# Extract message text
message_text = mp.decoded.payload.decode('utf-8').strip()
# Extract message text, stripping whitespace and surrounding quotes
message_text = mp.decoded.payload.decode('utf-8').strip(' \t\n\r"\'"\u201c\u201d\u2018\u2019')

# Check if this looks like a claim code (format: CLAIM-XXXX)
if message_text.startswith("CLAIM-"):
Expand Down Expand Up @@ -1250,7 +1257,7 @@ async def check_claim_code(self, mp):
try:
user = await self.bot.fetch_user(int(discord_id))
if user:
await user.send(f"✅ Node !{format(sender_node_num, 'x')} has been successfully claimed as your node!")
await user.send(f"✅ Node !{format(sender_node_num, '08x')} has been successfully claimed as your node!")
except Exception as e:
print(f"Error notifying user: {str(e)}")

Expand Down Expand Up @@ -1394,6 +1401,14 @@ def format_time_ago(self, timestamp_str):
print(f"Error formatting timestamp: {str(e)}")
return "Unknown time"

@staticmethod
def normalize_node_hex(node_identifier: str) -> str:
"""Normalize a !hex node identifier to zero-padded 8-character form."""
try:
return f"!{format(int(node_identifier[1:], 16), '08x')}"
except (ValueError, IndexError):
return node_identifier.lower()

def create_node_pages(self, nodes, title, nodes_per_page=10):
"""Helper method to create embed pages for node listings"""
pages = []
Expand Down Expand Up @@ -1604,7 +1619,7 @@ async def node_command(self, interaction: discord.Interaction,

async def claim_node(self, interaction: discord.Interaction, node_identifier: str):
"""Claim a node as yours"""
try:
try:
node_num = None
found_node = False
node_data = {}
Expand All @@ -1615,7 +1630,7 @@ async def claim_node(self, interaction: discord.Interaction, node_identifier: st

# Check if we're looking for a node ID (hex with ! prefix)
if node_identifier.startswith('!'):
hex_id = node_identifier.lower()
hex_id = self.normalize_node_hex(node_identifier)
# Search through nodes to find matching nodeId
c.execute("""
SELECT n.node_num, n.node_id_hex, n.long_name, o.discord_id
Expand Down Expand Up @@ -1789,13 +1804,13 @@ async def node_id_lookup(self, interaction: discord.Interaction, node_identifier

# Check if we're looking for a node ID (hex with ! prefix)
if node_identifier.startswith('!'):
hex_id = node_identifier.lower()
hex_id = self.normalize_node_hex(node_identifier)
# Search through nodes to find matching nodeId
c.execute("""
SELECT n.*, o.discord_id, o.discord_username, o.claimed_at
FROM nodes n
LEFT JOIN node_owners o ON n.node_id = o.node_id
WHERE lower(n.node_id_hex) = ?
WHERE n.node_id_hex = ?
""", (hex_id,))
node_row = c.fetchone()
else:
Expand Down Expand Up @@ -2045,13 +2060,13 @@ async def toggle_node_notifications(self, interaction: discord.Interaction, node

# Check if we're looking for a node ID (hex with ! prefix)
if node_identifier.startswith('!'):
hex_id = node_identifier.lower()
hex_id = self.normalize_node_hex(node_identifier)
# Search through nodes to find matching nodeId
c.execute("""
SELECT n.node_id, n.node_id_hex, n.long_name, o.discord_id, o.notifications
FROM nodes n
LEFT JOIN node_owners o ON n.node_id = o.node_id
WHERE lower(n.node_id_hex) = ?
WHERE n.node_id_hex = ?
""", (hex_id,))
node_row = c.fetchone()
else:
Expand Down Expand Up @@ -2128,12 +2143,12 @@ async def unclaim_own_node(self, interaction: discord.Interaction, node_identifi

# Resolve node by !hex id or decimal node number
if node_identifier.startswith('!'):
hex_id = node_identifier.lower()
hex_id = self.normalize_node_hex(node_identifier)
c.execute("""
SELECT n.node_id, n.node_id_hex, n.long_name, o.discord_id
FROM nodes n
LEFT JOIN node_owners o ON n.node_id = o.node_id
WHERE lower(n.node_id_hex) = ?
WHERE n.node_id_hex = ?
""", (hex_id,))
node_row = c.fetchone()
else:
Expand Down Expand Up @@ -2209,13 +2224,13 @@ async def unclaim_node(self, ctx: commands.Context, node_identifier: str):

# Check if we're looking for a node ID (hex with ! prefix)
if node_identifier.startswith('!'):
hex_id = node_identifier.lower()
hex_id = self.normalize_node_hex(node_identifier)
# Search for the node to get its node_id
c.execute("""
SELECT n.node_id, n.node_id_hex, n.long_name, o.discord_id
FROM nodes n
LEFT JOIN node_owners o ON n.node_id = o.node_id
WHERE lower(n.node_id_hex) = ?
WHERE n.node_id_hex = ?
""", (hex_id,))
result = c.fetchone()
if result:
Expand Down Expand Up @@ -2274,13 +2289,13 @@ async def set_node_owner(self, ctx: commands.Context, node_identifier: str, user

# Check if we're looking for a node ID (hex with ! prefix)
if node_identifier.startswith('!'):
hex_id = node_identifier.lower()
hex_id = self.normalize_node_hex(node_identifier)
# Search for the node to get its node_id
c.execute("""
SELECT n.node_id, n.node_id_hex, n.long_name, o.discord_id
FROM nodes n
LEFT JOIN node_owners o ON n.node_id = o.node_id
WHERE lower(n.node_id_hex) = ?
WHERE n.node_id_hex = ?
""", (hex_id,))
result = c.fetchone()
if result:
Expand Down Expand Up @@ -2368,12 +2383,12 @@ async def mute_node(self, ctx: commands.Context, node_identifier: str,

# Check if we're looking for a node ID (hex with ! prefix)
if node_identifier.startswith('!'):
hex_id = node_identifier.lower()
hex_id = self.normalize_node_hex(node_identifier)
# Search for the node to get its node_id
c.execute("""
SELECT node_id, node_id_hex, node_num, long_name
FROM nodes
WHERE lower(node_id_hex) = ?
WHERE node_id_hex = ?
""", (hex_id,))
result = c.fetchone()
if result:
Expand Down Expand Up @@ -2484,11 +2499,11 @@ async def unmute_node(self, ctx: commands.Context, node_identifier: str):

# Check if we're looking for a node ID (hex with ! prefix)
if node_identifier.startswith('!'):
hex_id = node_identifier.lower()
hex_id = self.normalize_node_hex(node_identifier)
c.execute("""
SELECT node_id, node_id_hex, node_num, long_name
FROM nodes
WHERE lower(node_id_hex) = ?
WHERE node_id_hex = ?
""", (hex_id,))
result = c.fetchone()
if result:
Expand Down
Loading