Skip to content

Commit 948828c

Browse files
committed
Add DM retry settings and improve message sending reliability with meshcore-2.1.6+ integration
1 parent 01d6fc1 commit 948828c

File tree

4 files changed

+65
-9
lines changed

4 files changed

+65
-9
lines changed

config.ini.example

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ bot_tx_rate_limit_seconds = 1.0
5555
# Recommended: 100-500ms for busy networks, 0 for quiet networks
5656
tx_delay_ms = 250
5757

58+
# DM retry settings for improved reliability (meshcore-2.1.6+)
59+
# Maximum number of retry attempts for failed DM sends
60+
dm_max_retries = 3
61+
62+
# Maximum flood attempts (when path reset is needed)
63+
dm_max_flood_attempts = 2
64+
65+
# Number of attempts before switching to flood mode
66+
dm_flood_after = 2
67+
5868
# Timezone for bot operations
5969
# Use standard timezone names (e.g., "America/New_York", "Europe/London", "UTC")
6070
# Leave empty to use system timezone

modules/command_manager.py

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,30 +197,65 @@ async def send_dm(self, recipient_id: str, content: str) -> bool:
197197
contact_name = contact.get('name', contact.get('adv_name', recipient_id))
198198
self.logger.info(f"Sending DM to {contact_name}: {content}")
199199

200-
# Import send_msg from meshcore-cli
201-
from meshcore_cli.meshcore_cli import send_msg
202-
203-
# Use send_msg to send the actual message (not a command)
204-
result = await send_msg(self.bot.meshcore, contact, content)
200+
# Try to use send_msg_with_retry if available (meshcore-2.1.6+)
201+
try:
202+
# Use the meshcore commands interface for send_msg_with_retry
203+
if hasattr(self.bot.meshcore, 'commands') and hasattr(self.bot.meshcore.commands, 'send_msg_with_retry'):
204+
self.logger.debug("Using send_msg_with_retry for improved reliability")
205+
206+
# Use send_msg_with_retry with configurable retry parameters
207+
max_attempts = self.bot.config.getint('Bot', 'dm_max_retries', fallback=3)
208+
max_flood_attempts = self.bot.config.getint('Bot', 'dm_max_flood_attempts', fallback=2)
209+
flood_after = self.bot.config.getint('Bot', 'dm_flood_after', fallback=2)
210+
timeout = 0 # Use suggested timeout from meshcore
211+
212+
self.logger.debug(f"Attempting DM send with {max_attempts} max attempts")
213+
result = await self.bot.meshcore.commands.send_msg_with_retry(
214+
contact,
215+
content,
216+
max_attempts=max_attempts,
217+
max_flood_attempts=max_flood_attempts,
218+
flood_after=flood_after,
219+
timeout=timeout
220+
)
221+
else:
222+
# Fallback to regular send_msg for older meshcore versions
223+
self.logger.debug("send_msg_with_retry not available, using send_msg")
224+
result = await self.bot.meshcore.commands.send_msg(contact, content)
225+
226+
except AttributeError:
227+
# Fallback to regular send_msg for older meshcore versions
228+
self.logger.debug("send_msg_with_retry not available, using send_msg")
229+
result = await self.bot.meshcore.commands.send_msg(contact, content)
205230

206231
# Check if the result indicates success
207232
if result:
208233
if hasattr(result, 'type') and result.type == EventType.ERROR:
209-
self.logger.error(f"Failed to send DM: {result.payload}")
234+
self.logger.error(f"❌ DM failed to {contact_name}: {result.payload}")
210235
return False
211236
elif hasattr(result, 'type') and result.type == EventType.MSG_SENT:
212-
self.logger.info(f"Successfully sent DM to {contact_name}")
237+
# For send_msg_with_retry, check if we got an ACK (result is not None means ACK received)
238+
if hasattr(self.bot.meshcore, 'commands') and hasattr(self.bot.meshcore.commands, 'send_msg_with_retry'):
239+
# We used send_msg_with_retry, so result being returned means ACK was received
240+
self.logger.info(f"✅ DM sent and ACK received from {contact_name}")
241+
else:
242+
# We used regular send_msg, so just log the send
243+
self.logger.info(f"✅ DM sent to {contact_name}")
213244
self.bot.rate_limiter.record_send()
214245
self.bot.bot_tx_rate_limiter.record_tx()
215246
return True
216247
else:
217248
# If result is not None but doesn't have expected attributes, assume success
218-
self.logger.info(f"DM sent to {contact_name} (result: {result})")
249+
self.logger.info(f"DM sent to {contact_name} (result: {result})")
219250
self.bot.rate_limiter.record_send()
220251
self.bot.bot_tx_rate_limiter.record_tx()
221252
return True
222253
else:
223-
self.logger.error(f"Failed to send DM: No result returned")
254+
# This means send_msg_with_retry failed to get an ACK after all retries
255+
if hasattr(self.bot.meshcore, 'commands') and hasattr(self.bot.meshcore.commands, 'send_msg_with_retry'):
256+
self.logger.error(f"❌ DM to {contact_name} failed - no ACK received after retries")
257+
else:
258+
self.logger.error(f"❌ DM to {contact_name} failed - no result returned")
224259
return False
225260

226261
except Exception as e:

modules/core.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ def create_default_config(self):
154154
# Recommended: 100-500ms for busy networks, 0 for quiet networks
155155
tx_delay_ms = 250
156156
157+
# DM retry settings for improved reliability (meshcore-2.1.6+)
158+
# Maximum number of retry attempts for failed DM sends
159+
dm_max_retries = 3
160+
161+
# Maximum flood attempts (when path reset is needed)
162+
dm_max_flood_attempts = 2
163+
164+
# Number of attempts before switching to flood mode
165+
dm_flood_after = 2
166+
157167
# Timezone for bot operations
158168
# Use standard timezone names (e.g., "America/New_York", "Europe/London", "UTC")
159169
# Leave empty to use system timezone

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ geopy>=2.3.0
1111
maidenhead>=1.4.0
1212
pytz>=2023.3
1313
aiohttp>=3.8.0
14+
meshcore>=2.1.6

0 commit comments

Comments
 (0)