mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-04-03 22:15:40 +00:00
BUG-025: send_channel_message retry logic on no_event_received BUG-026: split_text_into_chunks and chunked dispatch in message_handler BUG-027: test_weekly_on_wrong_day_does_not_run patch uses fake_now BUG-028: byte_data = b"" initialised before try in decode_meshcore_packet BUG-029: app.py db_path via self._config_base; realtime.html socket race fixed; base.html forceNew removed; ping_timeout 5 to 20s Additional: ruff and mypy refinements across all modules; discord bridge, telegram bridge, rate limiter, and service plugin updates
111 lines
3.9 KiB
Python
111 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Schedule command for the MeshCore Bot
|
|
Lists upcoming scheduled messages and interval advertising settings.
|
|
"""
|
|
|
|
from typing import Any, Optional
|
|
|
|
from ..models import MeshMessage
|
|
from .base_command import BaseCommand
|
|
|
|
|
|
class ScheduleCommand(BaseCommand):
|
|
"""Show scheduled messages and advertising interval configured for the bot.
|
|
|
|
Responds to ``schedule`` or ``schedule list``. The output is kept compact
|
|
so it fits within typical MeshCore message limits (~200 chars).
|
|
|
|
Config section ``[Schedule_Command]``:
|
|
enabled = true # enable/disable this command
|
|
dm_only = true # restrict to DMs (default true — exposes config)
|
|
"""
|
|
|
|
name = "schedule"
|
|
keywords = ["schedule"]
|
|
description = "List upcoming scheduled messages and advertising interval."
|
|
category = "admin"
|
|
|
|
short_description = "Show scheduled messages and advertising interval"
|
|
usage = "schedule [list]"
|
|
examples = ["schedule", "schedule list"]
|
|
|
|
def __init__(self, bot: Any) -> None:
|
|
super().__init__(bot)
|
|
self._enabled = self.get_config_value(
|
|
"Schedule_Command", "enabled", fallback=True, value_type="bool"
|
|
)
|
|
self._dm_only = self.get_config_value(
|
|
"Schedule_Command", "dm_only", fallback=True, value_type="bool"
|
|
)
|
|
|
|
# ------------------------------------------------------------------
|
|
# BaseCommand interface
|
|
# ------------------------------------------------------------------
|
|
|
|
def can_execute(self, message: MeshMessage, skip_channel_check: bool = False) -> bool:
|
|
if not self._enabled:
|
|
return False
|
|
if self._dm_only and not message.is_dm:
|
|
return False
|
|
return super().can_execute(message)
|
|
|
|
def get_help_text(self) -> str:
|
|
return "schedule [list] — show scheduled messages and advert interval"
|
|
|
|
async def execute(self, message: MeshMessage) -> bool:
|
|
response = self._build_response()
|
|
return await self.send_response(message, response)
|
|
|
|
# ------------------------------------------------------------------
|
|
# Internal helpers
|
|
# ------------------------------------------------------------------
|
|
|
|
def _build_response(self) -> str:
|
|
lines: list[str] = []
|
|
|
|
# --- Scheduled messages ---
|
|
scheduled = self._get_scheduled_messages()
|
|
if scheduled:
|
|
lines.append(f"Scheduled ({len(scheduled)}):")
|
|
for time_str, channel, preview in scheduled:
|
|
# Format HHMM → HH:MM
|
|
hhmm = f"{time_str[:2]}:{time_str[2:]}"
|
|
lines.append(f" {hhmm} #{channel}: {preview}")
|
|
else:
|
|
lines.append("No scheduled messages configured.")
|
|
|
|
# --- Interval advertising ---
|
|
advert_info = self._get_advert_info()
|
|
if advert_info:
|
|
lines.append(advert_info)
|
|
|
|
return "\n".join(lines)
|
|
|
|
def _get_scheduled_messages(self) -> list[tuple]:
|
|
"""Return sorted list of (time_str, channel, preview) tuples."""
|
|
scheduler = getattr(self.bot, "scheduler", None)
|
|
if scheduler is None:
|
|
return []
|
|
|
|
scheduled = getattr(scheduler, "scheduled_messages", {})
|
|
results = []
|
|
for time_str, payload in sorted(scheduled.items()):
|
|
channel, message = payload
|
|
# Truncate long messages so response stays compact
|
|
preview = message if len(message) <= 40 else message[:37] + "..."
|
|
results.append((time_str, channel, preview))
|
|
return results
|
|
|
|
def _get_advert_info(self) -> Optional[str]:
|
|
"""Return a one-line advert interval summary, or None if disabled."""
|
|
try:
|
|
interval_hours = self.bot.config.getint(
|
|
"Bot", "advert_interval_hours", fallback=0
|
|
)
|
|
if interval_hours > 0:
|
|
return f"Advert interval: every {interval_hours}h"
|
|
except Exception:
|
|
pass
|
|
return None
|