diff --git a/Bot/Bot.vcxproj b/Bot/Bot.vcxproj index 5d7b0e5..29a4484 100644 --- a/Bot/Bot.vcxproj +++ b/Bot/Bot.vcxproj @@ -88,6 +88,7 @@ + @@ -95,6 +96,7 @@ + diff --git a/Bot/Bot.vcxproj.filters b/Bot/Bot.vcxproj.filters index e11e6f6..9478b74 100644 --- a/Bot/Bot.vcxproj.filters +++ b/Bot/Bot.vcxproj.filters @@ -30,6 +30,9 @@ Source Files + + Source Files + @@ -47,6 +50,9 @@ Header Files + + Header Files + diff --git a/Bot/Console_Command.h b/Bot/Console_Command.h index 94a5b00..e7955ae 100644 --- a/Bot/Console_Command.h +++ b/Bot/Console_Command.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2013-2014 Justin James. + * Copyright (C) 2013-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any @@ -23,21 +23,13 @@ * @brief Provides an extendable command system specialized for console-based commands. */ -#include "Jupiter_Bot.h" #include "Jupiter/Command.h" #include "Jupiter/ArrayList.h" +#include "Jupiter_Bot.h" +#include "Generic_Command.h" -class Command; class ConsoleCommand; -/* -* Initial access level is always 0. Change this using setAccessLevel() -* There are no default triggers. Add triggers using addTrigger(trigger) -* When your command is triggered, trigger(parameters) will be called. -* You must provide command-specific help for your command, through getHelp(). -* The first trigger added is the trigger which is displayed to the user in the help command. -*/ - /** DLL Linkage Nagging */ #if defined _MSC_VER #pragma warning(push) @@ -49,7 +41,10 @@ JUPITER_BOT_API extern Jupiter::ArrayList *consoleCommands; /** * @brief Provides the basis for console commands. -* Note: This will likely be moved to a separate file in the future. +* There are no default triggers. Add triggers using addTrigger(trigger) +* When your command is triggered, trigger(parameters) will be called. +* You must provide command-specific help for your command, through getHelp(). +* The first trigger added is the trigger which is displayed to the user in "help" commands. */ class JUPITER_BOT_API ConsoleCommand : public Jupiter::Command { @@ -99,6 +94,28 @@ class CLASS : public ConsoleCommand { \ #define CONSOLE_COMMAND_INIT(CLASS) \ CLASS CLASS ## _instance; +/** Generates a console command implementation from a generic command. */ +#define GENERIC_COMMAND_AS_CONSOLE_COMMAND_IMPL(CLASS) \ + CLASS ## _AS_CONSOLE_COMMAND :: CLASS ## _AS_CONSOLE_COMMAND() { \ + size_t index = 0; \ + while (index != CLASS ## _instance.getTriggerCount()) this->addTrigger(CLASS ## _instance.getTrigger(index++)); } \ + void CLASS ## _AS_CONSOLE_COMMAND :: trigger(const Jupiter::ReadableString ¶meters) { \ + GenericCommand::ResponseLine *del; \ + GenericCommand::ResponseLine *ret = CLASS ## _instance.trigger(parameters); \ + while (ret != nullptr) { \ + ret->response.println(ret->type == GenericCommand::DisplayType::PublicError || ret->type == GenericCommand::DisplayType::PrivateError ? stderr : stdout); \ + del = ret; ret = ret->next; delete del; } } \ + const Jupiter::ReadableString & CLASS ## _AS_CONSOLE_COMMAND :: getHelp(const Jupiter::ReadableString ¶meters) { \ + return CLASS ## _instance.getHelp(parameters); } \ + CONSOLE_COMMAND_INIT(CLASS ## _AS_CONSOLE_COMMAND) + +/** Generates a console command from a generic command. */ +#define GENERIC_COMMAND_AS_CONSOLE_COMMAND(CLASS) \ + GENERIC_CONSOLE_COMMAND(CLASS ## _AS_CONSOLE_COMMAND) \ + GENERIC_COMMAND_AS_CONSOLE_COMMAND_IMPL(CLASS); + + + /** Re-enable warnings */ #if defined _MSC_VER #pragma warning(pop) diff --git a/Bot/Generic_Command.cpp b/Bot/Generic_Command.cpp new file mode 100644 index 0000000..64b526b --- /dev/null +++ b/Bot/Generic_Command.cpp @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2015 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "Generic_Command.h" + +Jupiter::ArrayList _genericCommands; +Jupiter::ArrayList *genericCommands = &_genericCommands; + +GenericCommand::GenericCommand() +{ + _genericCommands.add(this); +} + +GenericCommand::~GenericCommand() +{ + size_t count = _genericCommands.size(); + while (count != 0) + if (_genericCommands.get(--count) == this) + { + _genericCommands.remove(count); + break; + } +} + +GenericCommand *getGenericCommand(const Jupiter::ReadableString &trigger) +{ + size_t count = _genericCommands.size(); + while (count != 0) + { + GenericCommand *cmd = _genericCommands.get(--count); + if (cmd->matches(trigger)) + return cmd; + } + return nullptr; +} + +GenericCommand::ResponseLine::ResponseLine(const Jupiter::ReadableString &response_, GenericCommand::DisplayType type_) +{ + GenericCommand::ResponseLine::response = response_; + GenericCommand::ResponseLine::type = type_; +} + +GenericCommand::ResponseLine *GenericCommand::ResponseLine::set(const Jupiter::ReadableString &response_, GenericCommand::DisplayType type_) +{ + GenericCommand::ResponseLine::response = response_; + GenericCommand::ResponseLine::type = type_; + return this; +} \ No newline at end of file diff --git a/Bot/Generic_Command.h b/Bot/Generic_Command.h new file mode 100644 index 0000000..824f6bf --- /dev/null +++ b/Bot/Generic_Command.h @@ -0,0 +1,125 @@ +/** + * Copyright (C) 2015 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _GENERIC_COMMAND_H_HEADER +#define _GENERIC_COMMAND_H_HEADER + +/** +* @file Generic_Command.h +* @brief Provides an extendable command system. +*/ + +#include "Jupiter/Command.h" +#include "Jupiter/String.h" +#include "Jupiter_Bot.h" + +class GenericCommand; + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +/** Generic command list */ +JUPITER_BOT_API extern Jupiter::ArrayList *genericCommands; + +/** +* @brief Provides the base for generic commands. +*/ +class JUPITER_BOT_API GenericCommand : public Jupiter::Command +{ +public: + /** Enumerated class to guide output in generic command interpreters */ + enum class DisplayType + { + PublicSuccess, + PrivateSuccess, + PublicError, + PrivateError, + }; + + /** Data entry returned by trigger() */ + struct JUPITER_BOT_API ResponseLine + { + Jupiter::StringS response; + GenericCommand::DisplayType type; + ResponseLine *next = nullptr; + + /** + * @brief Sets the response and type of the ResponseLine. + * + * @param in_response Value to set response to. + * @param in_type Value to set type to. + * @return This. + */ + ResponseLine *set(const Jupiter::ReadableString &response, GenericCommand::DisplayType type); + ResponseLine() = default; + ResponseLine(const Jupiter::ReadableString &response, GenericCommand::DisplayType type); + }; + + /** + * @brief Called when the command is to be executed. + * + * @param input Parameters passed to the command by the user. + */ + virtual ResponseLine *trigger(const Jupiter::ReadableString &input) = 0; + + /** + * @brief Default constructor for the generic command class. + */ + GenericCommand(); + + /** + * @brief Destructor for the generic command class. + */ + ~GenericCommand(); +}; + +/** +* @brief Fetches a generic command based on its trigger. +* +* @param trigger Trigger of the command to fetch. +* @return A generic command if it exists, nullptr otherwise. +*/ +JUPITER_BOT_API extern GenericCommand *getGenericCommand(const Jupiter::ReadableString &trigger); + +/** Generic Command Macros */ + +/** Defines the core of a generic command's declaration. This should be included in every generic command. */ +#define BASE_GENERIC_COMMAND(CLASS) \ + public: \ + CLASS(); \ + GenericCommand::ResponseLine *trigger(const Jupiter::ReadableString ¶meters); \ + const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters); + +/** Expands to become the entire declaration for a generic command. In most cases, this will be sufficient. */ +#define GENERIC_GENERIC_COMMAND(CLASS) \ +class CLASS : public GenericCommand { \ + BASE_GENERIC_COMMAND(CLASS) \ +}; + +/** Instantiates a generic command. */ +#define GENERIC_COMMAND_INIT(CLASS) \ + CLASS CLASS ## _instance; + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _GENERIC_COMMAND_H_HEADER \ No newline at end of file diff --git a/Bot/IRC_Command.h b/Bot/IRC_Command.h index 209d1af..7540829 100644 --- a/Bot/IRC_Command.h +++ b/Bot/IRC_Command.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2013-2014 Justin James. + * Copyright (C) 2013-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any @@ -27,20 +27,12 @@ #include "Jupiter/IRC_Client.h" #include "Jupiter/ArrayList.h" #include "Jupiter/String.h" -#include "ServerManager.h" #include "Jupiter_Bot.h" +#include "ServerManager.h" +#include "IRC_Bot.h" -class IRC_Bot; class IRCCommand; -/* -* Initial access level is always 0. Change this using setAccessLevel() -* There are no default triggers. Add triggers using addTrigger(trigger) -* When your command is triggered, trigger(channel, nick, parameters) will be called. -* You must provide command-specific help for your command, through getHelp(). -* The first trigger added is the trigger which is displayed to the user in the help command. -*/ - /** DLL Linkage Nagging */ #if defined _MSC_VER #pragma warning(push) @@ -52,7 +44,11 @@ JUPITER_BOT_API extern Jupiter::ArrayList *IRCMasterCommandList; /** * @brief Provides the basis for IRC commands. -* Note: This will likely be moved to a separate file in the future. +* Initial access level is always 0. Change this using setAccessLevel() +* There are no default triggers. Add triggers using addTrigger(trigger) +* When your command is triggered, trigger(channel, nick, parameters) will be called. +* You must provide command-specific help for your command, through getHelp(). +* The first trigger added is the trigger which is displayed to the user in the help command. */ class JUPITER_BOT_API IRCCommand : public Jupiter::Command { @@ -189,6 +185,55 @@ class CLASS : public IRCCommand { \ CLASS CLASS ## _instance; \ CLASS *CLASS::copy() { return new CLASS(*this); } +/** Generates a base IRC command implementation from a generic command. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_BASE(CLASS) \ + void CLASS ## _AS_IRC_COMMAND :: trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { \ + GenericCommand::ResponseLine *del; \ + GenericCommand::ResponseLine *ret = CLASS ## _instance.trigger(parameters); \ + while (ret != nullptr) { \ + switch(ret->type) { \ + case GenericCommand::DisplayType::PublicSuccess: \ + case GenericCommand::DisplayType::PublicError: \ + source->sendMessage(channel, ret->response); \ + break; \ + case GenericCommand::DisplayType::PrivateSuccess: \ + case GenericCommand::DisplayType::PrivateError: \ + source->sendNotice(nick, ret->response); \ + break; \ + default: \ + source->sendMessage(nick, ret->response); \ + break; \ + } \ + del = ret; ret = ret->next; delete del; } } \ + const Jupiter::ReadableString & CLASS ## _AS_IRC_COMMAND :: getHelp(const Jupiter::ReadableString ¶meters) { \ + return CLASS ##_instance.getHelp(parameters); } \ + IRC_COMMAND_INIT(CLASS ## _AS_IRC_COMMAND) + +/** Generates an IRC command implementation from a generic command. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND_IMPL(CLASS) \ + void CLASS ## _AS_IRC_COMMAND :: create() { \ + size_t index = 0; \ + while (index != CLASS ## _instance.getTriggerCount()) this->addTrigger(CLASS ## _instance.getTrigger(index++)); } \ + GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_BASE(CLASS) + +/** Generates an IRC command implementation from a generic command. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_2(CLASS, ACCESS_LEVEL) \ + void CLASS ## _AS_IRC_COMMAND :: create() { \ + size_t index = 0; \ + while (index != CLASS ## _instance.getTriggerCount()) this->addTrigger(CLASS ## _instance.getTrigger(index++)); \ + this->setAccessLevel(ACCESS_LEVEL); } \ + GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_BASE(CLASS) + +/** Generates an IRC command from a generic command. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND(CLASS) \ + GENERIC_IRC_COMMAND(CLASS ## _AS_IRC_COMMAND) \ + GENERIC_COMMAND_AS_IRC_COMMAND_IMPL(CLASS); + +/** Generates an IRC command from a generic command. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND_2(CLASS, ACCESS_LEVEL) \ + GENERIC_IRC_COMMAND(CLASS ## _AS_IRC_COMMAND) \ + GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_2(CLASS, ACCESS_LEVEL); + /** Re-enable warnings */ #if defined _MSC_VER #pragma warning(pop) diff --git a/Jupiter Bot.sln b/Jupiter Bot.sln index 88da219..50e2b32 100644 --- a/Jupiter Bot.sln +++ b/Jupiter Bot.sln @@ -158,6 +158,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.Listen", "RenX.Listen\ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChannelRelay", "ChannelRelay\ChannelRelay.vcxproj", "{ADAD973E-EAA8-446D-BCD3-83B53DBC3A3F}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Release/Bot.lib b/Release/Bot.lib index bf5a487..9336cfe 100644 Binary files a/Release/Bot.lib and b/Release/Bot.lib differ diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index e2bf5ba..f04168f 100644 Binary files a/Release/Plugins/RenX.Core.lib and b/Release/Plugins/RenX.Core.lib differ