1 module diggler.defaultcommands; 2 3 import diggler.attribute; 4 import diggler.bot; 5 import diggler.context; 6 import diggler.command; 7 8 final class DefaultCommands : ICommandSet 9 { 10 Bot bot; 11 Context _context; 12 alias _context this; 13 Command helpCommand; 14 Bot.HelpCommand helpConfig; 15 16 this(Bot bot, Bot.HelpCommand helpConfig) 17 { 18 this.bot = bot; 19 this.helpConfig = helpConfig; 20 this.helpCommand = Command.create!help(&help); 21 } 22 23 @usage("show usage information for commands.") 24 void help(string commandName = null) 25 { 26 import std.array; 27 import std.algorithm : filter, map, joiner, reduce, sort; 28 import std.range : chain; 29 import irc.util : values; 30 import diggler.util : pluralize; 31 32 if(commandName.empty) 33 { 34 if(helpConfig == Bot.HelpCommand.simple) 35 { 36 import std.experimental.allocator : makeArray; 37 import std.experimental.allocator.mallocator : Mallocator; 38 import std.experimental.allocator.showcase : StackFront; 39 StackFront!(2048, Mallocator) alloc; 40 reply("Commands: %s", alloc.makeArray!string(bot.commandSets.map!(set => set.commandNames).joiner).sort().joiner(", ")); 41 } 42 else 43 { 44 auto namedSets = bot.commandSets.filter!(set => set.category); 45 46 foreach(cmdSet; namedSets) 47 { 48 string[] commands = cmdSet.commandNames; 49 if(!commands.empty) 50 { 51 auto commandList = commands.joiner(", "); 52 reply(`%s %s %s: %s`, commands.length, cmdSet.category, pluralize!"command"(commands.length), commandList); 53 } 54 } 55 56 auto miscCommands = bot.commandSets 57 .filter!(set => !set.category) 58 .map!(set => cast(string[])set.commandNames); 59 60 auto numCommands = reduce!((sum, cmds) => sum + cmds.length)(0UL, miscCommands); 61 62 if(numCommands != 0) 63 { 64 auto disambiguation = namedSets.empty? "" : "miscellaneous "; 65 reply("%s %s%s: %s", numCommands, disambiguation, pluralize!"command"(numCommands), miscCommands.joiner().joiner(", ")); 66 } 67 } 68 } 69 else 70 { 71 foreach(cmdSet; bot.commandSets) 72 { 73 if(auto cmd = cmdSet.getCommand(commandName)) 74 { 75 auto names = values(cmd.name) 76 .chain(cmd.aliases) 77 .joiner("|"); 78 79 auto paramSummary = 80 cmd.parameterInfo.map!(param => param.displayName) 81 .joiner(" "); 82 83 immutable description = cmd.usage? cmd.usage : "no description available."; 84 85 string flags; 86 if(cmd.channelOnly && cmd.adminOnly) 87 flags = " [channel, admin]"; 88 else if(cmd.channelOnly) 89 flags = " [channel]"; 90 else if(cmd.adminOnly) 91 flags = " [admin]"; 92 else 93 flags = ""; 94 95 reply(`%s %s: %s%s`, names, paramSummary, description, flags); 96 97 return; // Shouldn't be any duplicates 98 } 99 } 100 101 reply(`The command "%s" does not appear to exist.`, commandName); 102 } 103 } 104 105 override string category() 106 { 107 return null; 108 } 109 110 override ref Context context() 111 { 112 return _context; 113 } 114 115 override void add(ref Command) {} 116 117 override Command* getCommand(in char[] name) 118 { 119 return name == "help"? &helpCommand : null; 120 } 121 122 override string[] commandNames() 123 { 124 return null; 125 } 126 }