Skip to main content
Switch to FetchContent; will need to deal with the version bump after I actually do stuff
Source Link

Theoretically Windows, MacOS, and Linux, but I've only verified that it works on Linux. MayShould also work on any other platforms able to compile C++20 and the dependencies - please open an issue if it doesn't.

The recommended integration approach is with submodules (git submodule add https://github.com/LunarWatcher/stackchat.cpp). Alternatively, FetchContent can be used, but this is left as an exercise to the reader for no reason in particular :)

With submodules, integration is done with two lines of code:

add_subdirectoryinclude (FetchContent)
FetchContent_Declare(stackchat
    GIT_REPOSITORY https://github.com/LunarWatcher/stackchat.cpp)
FetchContent_MakeAvailable(stackchat)
# ...
 
target_link_libraries(never-gonna-bot stackchat)

Theoretically Windows, MacOS, and Linux, but I've only verified that it works on Linux. May also work on any other platforms able to compile C++20 and the dependencies.

The recommended integration approach is with submodules (git submodule add https://github.com/LunarWatcher/stackchat.cpp). Alternatively, FetchContent can be used, but this is left as an exercise to the reader for no reason in particular :)

With submodules, integration is done with two lines of code:

add_subdirectory(stackchat.cpp)

# ...
 
target_link_libraries(never-gonna-bot stackchat)

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.

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)
Commands have been refactored into classes
Source Link
#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", [](stackchatstd::Room&make_shared<InterjectCommand>());

 r, const stackchat::ChatEvent& ev,// constThere std::string&)are {
many ways to deal with chat joining, as r.sendMessage("I'dwell likeas toannouncements interjectand forconfig, abut moment.this Whatis you'releft referringas toan asexercise chatto loginthe isreader, inbecause factthere
    // are very, anvery eternalmany sourceways ofto painimplement andit, suffering.");
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();
}

Screenshot of chat; transcription follows.Screenshot of chat; transcription follows.

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.

#include "stackchat/StackChat.hpp"
#include "stackchat/chat/ChatEvent.hpp"

#include <iostream>
#include <string>

int main() {
    std::string email = std::getenv("STACK_EMAIL"), password = std::getenv("STACK_PASSWORD");
    if (email == "" || password == "") {
        throw std::runtime_error("Please provide credentials to run the demo.");
    }

    stackchat::StackChat chat({
        .email = email,
        .password = password,
        .prefix = "~",
        .userAgent = "StackChatCppDemos/git (+https://github.com/LunarWatcher/stackchat.cpp)",
    });

    chat.registerCommand("interject", [](stackchat::Room& r, const stackchat::ChatEvent& ev, const std::string&) {
        r.sendMessage("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.");
    });

    chat.join(stackchat::StackSite::STACKOVERFLOW, 1);
    chat.sendTo(stackchat::StackSite::STACKOVERFLOW, 1, "Chat login is horrible. *angry fox noises*");

    chat.block();
}

Screenshot of chat; transcription follows.

Gemmy [bot]: Chat login is horrible. angry fox noises
Zoe [me]: ~interject
Gemmy [bot]: 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.

#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();
}

Screenshot of chat; transcription follows.

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.

added 196 characters in body
Source Link
Source Link
Loading