mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-08-27 21:10:13 +00:00
Enhance help command to provide a dynamic list of available commands based on usage statistics. Implemented database querying for command usage and improved fallback mechanisms for command listing. Updated CommandManager to utilize the new method for better help text suggestions.
This commit is contained in:
@@ -422,13 +422,22 @@ class CommandManager:
|
||||
return f"Help {command_name}: {help_text}"
|
||||
|
||||
# If still not found, return unknown command message with helpful suggestion
|
||||
available_commands = []
|
||||
for cmd_name, cmd_instance in self.commands.items():
|
||||
available_commands.append(cmd_name)
|
||||
if hasattr(cmd_instance, 'keywords'):
|
||||
available_commands.extend(cmd_instance.keywords)
|
||||
# Use the help command's method to get popular commands (only primary names, no aliases)
|
||||
available_str = ""
|
||||
if 'help' in self.commands:
|
||||
help_command = self.commands['help']
|
||||
if hasattr(help_command, 'get_available_commands_list'):
|
||||
available_str = help_command.get_available_commands_list()
|
||||
|
||||
# Fallback if help command doesn't have the method
|
||||
if not available_str:
|
||||
# Only show primary command names, not keywords
|
||||
primary_names = sorted([
|
||||
cmd.name if hasattr(cmd, 'name') else name
|
||||
for name, cmd in self.commands.items()
|
||||
])
|
||||
available_str = ', '.join(primary_names)
|
||||
|
||||
available_str = ', '.join(sorted(set(available_commands)))
|
||||
if hasattr(self.bot, 'translator'):
|
||||
return self.bot.translator.translate('commands.help.unknown', command=command_name, available=available_str)
|
||||
return f"Unknown: {command_name}. Available: {available_str}. Try 'help' for command list."
|
||||
|
||||
@@ -4,6 +4,8 @@ Help command for the MeshCore Bot
|
||||
Provides help information for commands and general usage
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
from collections import defaultdict
|
||||
from .base_command import BaseCommand
|
||||
from ..models import MeshMessage
|
||||
|
||||
@@ -68,36 +70,100 @@ class HelpCommand(BaseCommand):
|
||||
return help_text
|
||||
|
||||
def get_available_commands_list(self) -> str:
|
||||
"""Get a formatted list of available commands"""
|
||||
commands_list = ""
|
||||
|
||||
# Group commands by category
|
||||
basic_commands = ['test', 'ping', 'help']
|
||||
custom_syntax = ['t_phrase'] # Use the actual command key
|
||||
special_commands = ['advert']
|
||||
|
||||
commands_list += "**Basic Commands:**\n"
|
||||
for cmd in basic_commands:
|
||||
if cmd in self.bot.command_manager.commands:
|
||||
help_text = self.bot.command_manager.commands[cmd].get_help_text()
|
||||
commands_list += f"• `{cmd}` - {help_text}\n"
|
||||
|
||||
commands_list += "\n**Custom Syntax:**\n"
|
||||
for cmd in custom_syntax:
|
||||
if cmd in self.bot.command_manager.commands:
|
||||
help_text = self.bot.command_manager.commands[cmd].get_help_text()
|
||||
# Add user-friendly aliases
|
||||
if cmd == 't_phrase':
|
||||
commands_list += f"• `t phrase` - {help_text}\n"
|
||||
else:
|
||||
commands_list += f"• `{cmd}` - {help_text}\n"
|
||||
|
||||
commands_list += "\n**Special Commands:**\n"
|
||||
for cmd in special_commands:
|
||||
if cmd in self.bot.command_manager.commands:
|
||||
help_text = self.bot.command_manager.commands[cmd].get_help_text()
|
||||
commands_list += f"• `{cmd}` - {help_text}\n"
|
||||
|
||||
return commands_list
|
||||
"""Get a list of most popular commands in descending order, showing only one variant per command"""
|
||||
try:
|
||||
# Use the plugin loader's keyword mappings to map keywords/aliases to primary command names
|
||||
plugin_loader = self.bot.command_manager.plugin_loader
|
||||
keyword_mappings = plugin_loader.keyword_mappings.copy() if hasattr(plugin_loader, 'keyword_mappings') else {}
|
||||
|
||||
# Build a set of all primary command names and ensure they map to themselves
|
||||
primary_names = set()
|
||||
for cmd_name, cmd_instance in self.bot.command_manager.commands.items():
|
||||
primary_name = cmd_instance.name if hasattr(cmd_instance, 'name') else cmd_name
|
||||
primary_names.add(primary_name)
|
||||
# Ensure primary name maps to itself in keyword_mappings
|
||||
keyword_mappings[primary_name.lower()] = primary_name
|
||||
|
||||
# Query the database for command usage statistics
|
||||
command_counts = defaultdict(int)
|
||||
try:
|
||||
with sqlite3.connect(self.bot.db_manager.db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
# Check if command_stats table exists
|
||||
cursor.execute("""
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name='command_stats'
|
||||
""")
|
||||
if cursor.fetchone():
|
||||
# Query command usage
|
||||
cursor.execute("""
|
||||
SELECT command_name, COUNT(*) as count
|
||||
FROM command_stats
|
||||
GROUP BY command_name
|
||||
""")
|
||||
for row in cursor.fetchall():
|
||||
command_name = row[0]
|
||||
count = row[1]
|
||||
|
||||
# Map keyword/alias to primary command name
|
||||
# First try the plugin_loader's keyword_mappings
|
||||
primary_name = keyword_mappings.get(command_name.lower())
|
||||
|
||||
# If not found in mappings, check if it's already a primary name
|
||||
if primary_name is None:
|
||||
if command_name in primary_names:
|
||||
primary_name = command_name
|
||||
else:
|
||||
# Try to find which command this belongs to by checking all commands
|
||||
for cmd_name, cmd_instance in self.bot.command_manager.commands.items():
|
||||
# Check if command_name matches the command's name
|
||||
cmd_primary = cmd_instance.name if hasattr(cmd_instance, 'name') else cmd_name
|
||||
if cmd_primary == command_name:
|
||||
primary_name = cmd_primary
|
||||
break
|
||||
# Check if it's a keyword of this command
|
||||
if hasattr(cmd_instance, 'keywords'):
|
||||
if command_name.lower() in [k.lower() for k in cmd_instance.keywords]:
|
||||
primary_name = cmd_primary
|
||||
break
|
||||
# If still not found, use the command_name as-is
|
||||
if primary_name is None:
|
||||
primary_name = command_name
|
||||
|
||||
command_counts[primary_name] += count
|
||||
except Exception as e:
|
||||
self.logger.debug(f"Error querying command stats: {e}")
|
||||
# If stats table doesn't exist or query fails, fall back to all commands
|
||||
for cmd_name in self.bot.command_manager.commands.keys():
|
||||
primary_name = self.bot.command_manager.commands[cmd_name].name if hasattr(self.bot.command_manager.commands[cmd_name], 'name') else cmd_name
|
||||
command_counts[primary_name] = 0
|
||||
|
||||
# If we have stats, sort by count descending, otherwise use all commands
|
||||
if command_counts:
|
||||
# Sort by count descending, then by name for consistency
|
||||
sorted_commands = sorted(
|
||||
command_counts.items(),
|
||||
key=lambda x: (-x[1], x[0])
|
||||
)
|
||||
# Extract just the command names (only primary names, no aliases)
|
||||
command_names = [name for name, _ in sorted_commands]
|
||||
else:
|
||||
# Fallback: use all primary command names
|
||||
command_names = sorted([
|
||||
cmd.name if hasattr(cmd, 'name') else name
|
||||
for name, cmd in self.bot.command_manager.commands.items()
|
||||
])
|
||||
|
||||
# Return comma-separated list
|
||||
return ', '.join(command_names)
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error getting available commands list: {e}")
|
||||
# Fallback to simple list of all command names
|
||||
command_names = sorted([
|
||||
cmd.name if hasattr(cmd, 'name') else name
|
||||
for name, cmd in self.bot.command_manager.commands.items()
|
||||
])
|
||||
return ', '.join(command_names)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user