Code snippet
#include "stackchat/StackChat.hpp"
#include "stackchat/chat/ChatEvent.hpp"
#include "stackchat/chat/Command.hpp"
#include <iostream>
#include <string>
// This is not the only way to define a command, for the record. Utility classes exist (or will be added when necessary),
// but the goal is to be as flexible as possible.
//
// The system does take a heavy OOP approach, largely to allow for context-based commands. I also like OOP, so that's part of it.
// Plus, it comes with the advantage of allowing stuff like MultiLevelCommand, used in a different demo.
class InterjectCommand : public stackchat::Command {
public:
void onMessage(stackchat::Room& r, const stackchat::ChatEvent& ev, const std::vector<std::string>&) {
r.reply(ev, "I'd like to interject for a moment. What you're referring to as chat login is, in fact, an eternal source of pain and suffering.");
}
};
int main() {
// This isn't a fantastic way to get the credentials, but it is an option. There are other options as well,
// this is just the laziest approach I can think of.
std::string email = std::getenv("STACK_EMAIL"), password = std::getenv("STACK_PASSWORD");
if (email == "" || password == "") {
// This is deceptively useless; missing credentials actually results in an initialisation exception (something something null string)
throw std::runtime_error("Please provide credentials to run the demo.");
}
stackchat::StackChat chat({
.email = email,
.password = password,
.prefix = "~", // Required for command functionality. Defaults to nothing, which will disable commands
.userAgent = "StackChatCppDemos/git (+https://github.com/LunarWatcher/stackchat.cpp)",
});
chat.registerCommand("interject", std::make_shared<InterjectCommand>());
// There are many ways to deal with chat joining, as well as announcements and config, but this is left as an exercise to the reader, because there
// are very, very many ways to implement it, depending on what the bot is used for.
chat.join(stackchat::StackSite::STACKOVERFLOW, 1);
// As an aside, this isn't really the only way to do join announcements.
// It would be possible to hook up a join listener, and check if the bot triggered the event.
chat.sendTo(stackchat::StackSite::STACKOVERFLOW, 1, "Chat login is horrible. *angry fox noises*");
// Only required for chatbot-first applications.
// The main thread can, after this, be used for something completely different, such as API access.
// You can also make your own sleep system. This function is just provided as a convenience
chat.block();
}
Example run:
Gemmy [bot]: Chat login is horrible. angry fox noises
Zoe [me]: ~interject
Gemmy [bot]: [:reply] I'd like to interject for a moment. What you're referring to as chat login is, in fact, an eternal source of pain and suffering.
Additional demos can be found on GitHub
About
In the same chain as the C++20 API library, I need a chat library for Stuff™. Unlike the API library (where a Boost-based library is available), there are no C++ chat libraries available, at least that I'm aware of or can find here on Stackapps.
The library uses cpr for web requests, nlohmann/json for JSON parsing and deserialisation, spdlog for logging (libfmt is explicitly downloaded as well), and IXWebSocket for (shock) websockets. A general use support library I've previously made is also used. All dependencies are automagically handled thanks to FetchContent.
Note that the library is currently a work in progress, and heavily lacking in documentation, but does function. I also expect to do several revisions of the library interface, particularly as feature requirements and error handling starts being developed, so the library interface is currently considered unstable. This paragraph will be replaced with links to the documentation when stuff is fully ready.
License
MIT. See LICENSE
Source
Platform
Theoretically Windows, MacOS, and Linux, but I've only verified that it works on Linux. Should also work on any other platforms able to compile C++20 and the dependencies - please open an issue if it doesn't.
Contact
Use GitHub to report any issues. General questions can be posted on GitHub Discussions.
Integration
The recommended integration approach is with FetchContent:
include (FetchContent)
FetchContent_Declare(stackchat
GIT_REPOSITORY https://github.com/LunarWatcher/stackchat.cpp)
FetchContent_MakeAvailable(stackchat)
...
target_link_libraries(never-gonna-bot stackchat)