From 31be24eb7fe50c02d797ef9d056405734a4be1cb Mon Sep 17 00:00:00 2001 From: Tomatix Date: Fri, 9 Jul 2021 23:42:58 +0200 Subject: [PATCH] #102 Added a simple sandbox-implementation of "IRCClient" - For testing stuff. --- IRCClientSandbox/CMakeLists.txt | 4 + IRCClientSandbox/main.cpp | 277 ++++++++++++++++++++++++++++++++ 2 files changed, 281 insertions(+) create mode 100644 IRCClientSandbox/CMakeLists.txt create mode 100644 IRCClientSandbox/main.cpp diff --git a/IRCClientSandbox/CMakeLists.txt b/IRCClientSandbox/CMakeLists.txt new file mode 100644 index 0000000..fd739d2 --- /dev/null +++ b/IRCClientSandbox/CMakeLists.txt @@ -0,0 +1,4 @@ +project(IRCClientSandbox) + +add_executable(${PROJECT_NAME} main.cpp) +target_link_libraries(${PROJECT_NAME} IRCClient) diff --git a/IRCClientSandbox/main.cpp b/IRCClientSandbox/main.cpp new file mode 100644 index 0000000..eecd956 --- /dev/null +++ b/IRCClientSandbox/main.cpp @@ -0,0 +1,277 @@ +#include "IRCClient/IRCBase.h" +#include + +//#define ENABLE_MESSAGES + + +#ifdef ENABLE_MESSAGES +template +void print(const std::string& msg, Ts ... arg) +{ + fmt::print(msg, arg...); +} + +void print(const std::string& msg) +{ + fmt::print(msg); +} +#else +void print(const std::string&) +{} +template +void print(const std::string&, Ts ...) +{} +#endif + +class IRCClient : public IRCBase +{ + void onConnected() override + { + print("Connected to {}:{} (ssl={})", getHostname(), getPort(), isSSL()); + } + + void onConnectedWithSSLExceptions(const std::vector& codes) override + { + print("Connected (with ssl exceptions) to {}:{} (ssl={})", getHostname(), getPort(), isSSL()); + for (const auto& code : codes) + print("SSL exception: {}", IRCErrorToString(code)); + } + + void onDisconnected() override + { + print("Disconnected from {}:{} (ssl={})", getHostname(), getPort(), isSSL()); + m_running = false; + } + + void onRegistered() override + { + print("Successfully registered with the server"); + } + + void onConnectionError(IRCError e) override + { + print("Connection error: ", IRCErrorToString(e)); + } + + void onMsgNick(const IRCPrefix& sender, const std::string& newNickname, const std::vector& channelsAffected) override + { + print("{} is now known as {}", sender.nickname(), newNickname); + } + + void onMsgMode(const IRCPrefix& sender, const std::string& target, const std::string& modes, const std::vector& args) override + { + std::string everything = modes; + for (const auto& arg : args) + everything.append(fmt::format(" {}", arg)); + + if (target == getNickname()) + print("Own usermode changed: {}", everything); + else + print("[{}] Mode set: {}", target, everything); + } + + void onMsgQuit(const IRCPrefix& sender, const std::string& message, const std::vector& channelsAffected) override + { + print("Quit: {} ({}@{}) ({})", sender.nickname(), sender.user(), sender.host(), message); + } + + void onMsgJoin(const IRCPrefix& sender, const std::string& target) override + { + print("[{}] Join: {} ({}@{})", target, sender.nickname(), sender.user(), sender.host()); + } + + void onMsgPart(const IRCPrefix& sender, const std::string& target, const std::string& message) override + { + if (message.empty()) + print("[{}] Part: {} ({}@{})", target, sender.nickname(), sender.user(), sender.host()); + else + print("[{}] Part: {} ({}@{}) ({})", target, sender.nickname(), sender.user(), sender.host(), message); + } + + void onMsgTopic(const IRCPrefix& sender, const std::string& target, const std::string& topic) override + { + if (topic.empty()) + print("[{}] {} cleared the topic", target, sender.nickname()); + else + print("[{}] {} set new topic: {}", target, sender.nickname(), topic); + } + + void onMsgInvite(const IRCPrefix& sender, const std::string& target) override + { + print("{} invited you to join {}", sender.nickname(), target); + } + + void onMsgKick(const IRCPrefix& sender, const std::string& target, const std::string& who, const std::string& reason) override + { + if (who == getNickname()) + print("[{}] You were kicked by {} ({})", target, sender.nickname(), reason); + else + print("[{}] {} kicked {} ({})", target, sender.nickname(), who, reason); + } + + void onMsgPrivmsg(const IRCPrefix& sender, const std::string& target, const std::string& message) override + { + print("[{}] <{}> {}", target, sender.nickname(), message); + } + + void onMsgNotice(const IRCPrefix& sender, const std::string& target, const std::string& message) override + { + if (target == getNickname()) + print("-{}- {}", sender.nickname(), message); + else + print("[{}] -{}- {}", target, sender.nickname(), message); + } + + void onMsgKill(const IRCPrefix& sender, const std::string& reason) override + { + print("You were killed by {} ({})", sender.nickname(), reason); + } + + void onMsgPing(const std::string& message) override + { + + } + + void onMsgPong(const std::string& message) override + { + + } + + void onMsgError(const std::string& message) override + { + print("Server error: {}", message); + } + + void onMsgWallops(const IRCPrefix& sender, const std::string& message) override + { + print("!{}! {}", sender.nickname(), message); + } + + void onMsgNumeric(const IRCPrefix& sender, const std::string& num, const std::vector& args, const std::string& message) override + { + std::string everything; + + for (const auto& arg : args) + everything.append(fmt::format("{} ", arg)); + + if (!everything.empty()) + everything.append(": "); + + everything.append(message); + print(everything); + } + + void onMsgCTCPRequest(const IRCPrefix& sender, const std::string& target, const std::string& command, const std::string& message) override + { + std::string printmsg; + if (message.empty()) + printmsg = fmt::format("[CTCP {} from {}]", command, sender.nickname()); + else + printmsg = fmt::format("[CTCP {} from {}] {}", command, sender.nickname(), message); + + if (target != getNickname()) + printmsg = fmt::format("[{}] {}", target, printmsg); + + print(printmsg); + } + + void onMsgCTCPResponse(const IRCPrefix& sender, const std::string& target, const std::string& command, const std::string& message) override + { + std::string printmsg; + if (message.empty()) + printmsg = fmt::format("[CTCP REPLY {} from {}]", command, sender.nickname()); + else + printmsg = fmt::format("[CTCP REPLY {} from {}] {}", command, sender.nickname(), message); + + if (target != getNickname()) + printmsg = fmt::format("[{}] {}", target, printmsg); + + print(printmsg); + } + + void onMsgDCCRequest(std::shared_ptr dcc, const IRCPrefix& sender, const std::string& target, const std::string& type, const std::string& message) override + { + + } + + void v3onMsgAway(const IRCPrefix& sender, const std::string& message, const std::vector& channelsAffected) override + { + if (message.empty()) + print("{} is no longer away", sender.nickname()); + else + print("{} is away: {}", sender.nickname(), message); + } + + void v3onMsgAccountLogin(const IRCPrefix& sender, const std::string& useraccount) override + { + print("{} is now logged in as {}", sender.nickname(), useraccount); + } + + void v3onMsgAccountLogout(const IRCPrefix& sender) override + { + print("{} logged out from their account", sender.nickname()); + } + + /* + * Required IRCv3 extensions to implement. + */ + void v3onMsgJoin(const IRCPrefix& sender, const std::string& channel, const std::string& useraccount, const std::string& realname) override + { + print("[{}] Join: {} (Account: {}) ({}@{})", channel, sender.nickname(), useraccount, sender.user(), sender.host()); + } + + /* + * Catch-all handler. If the message parser cannot match for any of the commands, it will turn up here. + * Optional to implement. + */ + void onMsgUnhandled(const IRCPrefix& sender, const std::string& command, const std::vector& args, const std::string& message) override + { + std::string everything = command; + + for (const auto& arg : args) + everything.append(fmt::format(" {}", arg)); + + if (!message.empty()) + everything.append(fmt::format(" {}", message)); + + print("Unhandled command from {}: {}", sender.nickname(), everything); + } + + + bool m_running{ true }; + +public: + [[nodiscard]] bool isRunning() const { return m_running; } +}; + +int main() +{ + IRCClient client; + + /* + * WARNING + * Do not commit any connection details to the source repository! + */ + client.setHostname(""); + client.setPort(""); + client.setNickname(""); + client.setIdent(""); + client.setRealname(""); + + auto connectionStatus = client.tryConnect(); + + print("Entering event loop"); + + while (true) { + if (connectionStatus != IRCError::NoError || !client.isRunning()) + break; + + client.poll(); + + connectionStatus = client.lastErrorCode(); + } + + print("Leaving event loop"); + + return 0; +}