summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorilotterytea <iltsu@alright.party>2025-04-18 16:25:28 +0500
committerilotterytea <iltsu@alright.party>2025-04-18 16:25:28 +0500
commit9b1a11e8fee33abb933aa3836faf60cc14deb68d (patch)
treeb94a90a53f89e62e4aac770d97ead73a97072d76
parent4827c87c986d217a940ce87cc31245440d6b1ab6 (diff)
feat: betterttv clients (experimental)
-rw-r--r--bot/CMakeLists.txt7
-rw-r--r--bot/src/emotes.cpp155
-rw-r--r--bot/src/emotes.hpp4
-rw-r--r--bot/src/main.cpp54
-rw-r--r--bot/src/schemas/stream.cpp24
-rw-r--r--bot/src/schemas/stream.hpp9
6 files changed, 196 insertions, 57 deletions
diff --git a/bot/CMakeLists.txt b/bot/CMakeLists.txt
index 51a14fc..abcf8ed 100644
--- a/bot/CMakeLists.txt
+++ b/bot/CMakeLists.txt
@@ -28,6 +28,13 @@ set_target_properties(
OUTPUT_NAME "${PROJECT_NAME}-bot"
)
+# BetterTTV Emote support
+set(BUILD_BETTERTTV OFF BOOL "Enable BetterTTV emotes")
+if (BUILD_BETTERTTV)
+ message("-- Bulding BetterTTV parts")
+ target_compile_definitions(Bot PRIVATE BUILD_BETTERTTV=1)
+endif()
+
# TLS for websocket connections
set(USE_TLS ON CACHE BOOL "Enable TLS support")
diff --git a/bot/src/emotes.cpp b/bot/src/emotes.cpp
index c19c65b..dbae407 100644
--- a/bot/src/emotes.cpp
+++ b/bot/src/emotes.cpp
@@ -3,6 +3,7 @@
#include <algorithm>
#include <chrono>
#include <exception>
+#include <map>
#include <optional>
#include <pqxx/pqxx>
#include <string>
@@ -32,7 +33,12 @@ namespace bot::emotes {
}
bool is_stv = event_type >= schemas::EventType::STV_EMOTE_CREATE &&
- schemas::EventType::STV_EMOTE_UPDATE >= event_type;
+ event_type <= schemas::EventType::STV_EMOTE_UPDATE;
+
+#ifdef BUILD_BETTERTTV
+ bool is_bttv = event_type >= schemas::EventType::BTTV_EMOTE_CREATE &&
+ event_type <= schemas::EventType::BTTV_EMOTE_UPDATE;
+#endif
if (is_stv) {
std::optional<emotespp::EmoteSet> emote_set =
@@ -44,6 +50,12 @@ namespace bot::emotes {
c_name = emote_set->owner.alias_id;
prefix = "(7TV)";
}
+#ifdef BUILD_BETTERTTV
+ else if (is_bttv) {
+ c_name = channel_name.substr(7);
+ prefix = "(BTTV)";
+ }
+#endif
if (c_name.empty()) {
return;
@@ -122,65 +134,108 @@ namespace bot::emotes {
conn.close();
}
- void create_emote_thread(const EmoteEventBundle *bundle) {
- log::info("emotes/thread", "Started emote thread.");
+ void check_seventv_emotesets(const EmoteEventBundle *bundle,
+ pqxx::work &work) {
+ pqxx::result events = work.exec(
+ "SELECT name FROM events WHERE event_type >= 10 AND event_type <= "
+ "12 GROUP BY name");
- while (true) {
- pqxx::connection conn(GET_DATABASE_CONNECTION_URL(bundle->configuration));
- pqxx::work work(conn);
+ auto &ids = bundle->stv_ws_client.get_ids();
- try {
- pqxx::result events = work.exec(
- "SELECT name FROM events WHERE event_type >= 10 AND event_type <= "
- "12 GROUP BY name");
+ std::vector<std::string> names;
+ std::for_each(events.begin(), events.end(), [&names](const pqxx::row &r) {
+ names.push_back(r[0].as<std::string>());
+ });
- auto &ids = bundle->stv_ws_client.get_ids();
+ // adding new emote sets
+ for (const std::string &name : names) {
+ std::optional<emotespp::User> stv_user =
+ bundle->stv_api_client.get_user_by_twitch_id(std::stoi(name));
- std::vector<std::string> names;
- std::for_each(events.begin(), events.end(),
- [&names](const pqxx::row &r) {
- names.push_back(r[0].as<std::string>());
- });
+ if (!stv_user.has_value()) {
+ continue;
+ }
+
+ if (!std::any_of(ids.begin(), ids.end(),
+ [&stv_user](const std::string &id) {
+ return id == stv_user->emote_set_id;
+ })) {
+ bundle->stv_ws_client.subscribe_emote_set(stv_user->emote_set_id);
+ log::info(
+ "emotes/thread/7tv",
+ "Subscribing to " + stv_user->emote_set_id + " (" + name + ")");
+ }
+ }
- // adding new emote sets
- for (const std::string &name : names) {
- std::optional<emotespp::User> stv_user =
- bundle->stv_api_client.get_user_by_twitch_id(std::stoi(name));
+ // removing old emote sets
+ std::for_each(
+ ids.begin(), ids.end(), [&names, &bundle](const std::string &id) {
+ std::optional<emotespp::EmoteSet> stv_set =
+ bundle->stv_api_client.get_emote_set(id);
- if (!stv_user.has_value()) {
- continue;
+ if (!stv_set.has_value()) {
+ return;
}
- if (!std::any_of(ids.begin(), ids.end(),
- [&stv_user](const std::string &id) {
- return id == stv_user->emote_set_id;
+ if (!std::any_of(names.begin(), names.end(),
+ [&stv_set](const std::string &id) {
+ return id == stv_set->owner.alias_id;
})) {
- bundle->stv_ws_client.subscribe_emote_set(stv_user->emote_set_id);
- log::info(
- "emotes/thread",
- "Subscribing to " + stv_user->emote_set_id + " (" + name + ")");
- }
- }
-
- // removing old emote sets
- std::for_each(
- ids.begin(), ids.end(), [&names, &bundle](const std::string &id) {
- std::optional<emotespp::EmoteSet> stv_set =
- bundle->stv_api_client.get_emote_set(id);
-
- if (!stv_set.has_value()) {
- return;
- }
-
- if (!std::any_of(names.begin(), names.end(),
- [&stv_set](const std::string &id) {
- return id == stv_set->owner.alias_id;
- })) {
- bundle->stv_ws_client.unsubscribe_emote_set(id);
- log::info("emotes/thread", "Unsubscribing from " + id + " (" +
+ bundle->stv_ws_client.unsubscribe_emote_set(id);
+ log::info("emotes/thread/7tv", "Unsubscribing from " + id + " (" +
stv_set->owner.alias_id + ")");
- }
- });
+ }
+ });
+ }
+
+#ifdef BUILD_BETTERTTV
+ void check_betterttv_users(const EmoteEventBundle *bundle, pqxx::work &work) {
+ pqxx::result events = work.exec(
+ "SELECT name FROM events WHERE event_type >= 13 AND event_type <= "
+ "15 GROUP BY name");
+
+ const std::map<std::string, std::vector<emotespp::Emote>> &ids =
+ bundle->bttv_ws_client.get_ids();
+
+ std::vector<std::string> names;
+ std::for_each(events.begin(), events.end(), [&names](const pqxx::row &r) {
+ names.push_back("twitch:" + r[0].as<std::string>());
+ });
+
+ // adding new users
+ for (const std::string &name : names) {
+ if (!std::any_of(ids.begin(), ids.end(), [&name](const auto &pair) {
+ return pair.first == name;
+ })) {
+ bundle->bttv_ws_client.subscribe_emote_set(name);
+ log::info("emotes/thread/bttv", "Subscribing to " + name);
+ }
+ }
+
+ // removing old users
+ std::for_each(ids.begin(), ids.end(), [&names, &bundle](const auto &pair) {
+ if (!std::any_of(
+ names.begin(), names.end(),
+ [&pair](const std::string &id) { return id == pair.first; })) {
+ bundle->bttv_ws_client.unsubscribe_emote_set(pair.first);
+ log::info("emotes/thread/bttv", "Unsubscribing from " + pair.first);
+ }
+ });
+ }
+#endif
+
+ void create_emote_thread(const EmoteEventBundle *bundle) {
+ log::info("emotes/thread", "Started emote thread.");
+
+ while (true) {
+ pqxx::connection conn(GET_DATABASE_CONNECTION_URL(bundle->configuration));
+ pqxx::work work(conn);
+
+ try {
+ check_seventv_emotesets(bundle, work);
+#ifdef BUILD_BETTERTTV
+ check_betterttv_users(bundle, work);
+#endif
} catch (std::exception ex) {
log::error("emotes/thread",
"Error occurred in emote thread: " + std::string(ex.what()));
diff --git a/bot/src/emotes.hpp b/bot/src/emotes.hpp
index 7493edf..3e6d9f8 100644
--- a/bot/src/emotes.hpp
+++ b/bot/src/emotes.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include <emotespp/betterttv.hpp>
#include <emotespp/seventv.hpp>
#include <optional>
#include <string>
@@ -13,6 +14,9 @@ namespace bot::emotes {
struct EmoteEventBundle {
irc::Client &irc_client;
const api::twitch::HelixClient &helix_client;
+#ifdef BUILD_BETTERTTV
+ emotespp::BetterTTVWebsocketClient &bttv_ws_client;
+#endif
emotespp::SevenTVWebsocketClient &stv_ws_client;
const emotespp::SevenTVAPIClient &stv_api_client;
const Configuration &configuration;
diff --git a/bot/src/main.cpp b/bot/src/main.cpp
index 733c0eb..c98841b 100644
--- a/bot/src/main.cpp
+++ b/bot/src/main.cpp
@@ -62,6 +62,9 @@ int main(int argc, char *argv[]) {
bot::api::twitch::HelixClient helix_client(cfg.twitch_credentials.token,
cfg.twitch_credentials.client_id);
+#ifdef BUILD_BETTERTTV
+ emotespp::BetterTTVWebsocketClient bttv_ws_client;
+#endif
emotespp::SevenTVWebsocketClient seventv_emote_listener;
emotespp::SevenTVAPIClient seventv_api_client;
@@ -115,9 +118,18 @@ int main(int argc, char *argv[]) {
bot::GithubListener github_listener(cfg, client, helix_client);
- bot::emotes::EmoteEventBundle emote_bundle{
- client, helix_client, seventv_emote_listener, seventv_api_client, cfg};
-
+ bot::emotes::EmoteEventBundle emote_bundle{client,
+ helix_client,
+#ifdef BUILD_BETTERTTV
+ bttv_ws_client,
+#endif
+ seventv_emote_listener,
+ seventv_api_client,
+ cfg};
+
+ // ---------------
+ // 7TV !!!
+ // ---------------
seventv_emote_listener.on_emote_create(
[&emote_bundle](const std::string &channel_name,
const std::optional<std::string> &author_id,
@@ -147,6 +159,42 @@ int main(int argc, char *argv[]) {
seventv_emote_listener.start();
+#ifdef BUILD_BETTERTTV
+ // ----------------
+ // BETTERTTV
+ // ----------------
+
+ bttv_ws_client.on_emote_create(
+ [&emote_bundle](const std::string &channel_name,
+ const std::optional<std::string> &author_id,
+ const emotespp::Emote &emote) {
+ bot::emotes::handle_emote_event(emote_bundle,
+ bot::schemas::BTTV_EMOTE_CREATE,
+ channel_name, author_id, emote);
+ });
+
+ bttv_ws_client.on_emote_delete(
+ [&emote_bundle](const std::string &channel_name,
+ const std::optional<std::string> &author_id,
+ const emotespp::Emote &emote) {
+ bot::emotes::handle_emote_event(emote_bundle,
+ bot::schemas::BTTV_EMOTE_DELETE,
+ channel_name, author_id, emote);
+ });
+
+ bttv_ws_client.on_emote_update(
+ [&emote_bundle](const std::string &channel_name,
+ const std::optional<std::string> &author_id,
+ const emotespp::Emote &emote) {
+ bot::emotes::handle_emote_event(emote_bundle,
+ bot::schemas::BTTV_EMOTE_UPDATE,
+ channel_name, author_id, emote);
+ });
+
+ bttv_ws_client.start();
+
+#endif
+
client.on<bot::irc::MessageType::Privmsg>(
[&client, &command_loader, &localization, &cfg, &helix_client](
const bot::irc::Message<bot::irc::MessageType::Privmsg> &message) {
diff --git a/bot/src/schemas/stream.cpp b/bot/src/schemas/stream.cpp
index d4f769b..f6df3f4 100644
--- a/bot/src/schemas/stream.cpp
+++ b/bot/src/schemas/stream.cpp
@@ -18,7 +18,17 @@ namespace bot::schemas {
return EventType::STV_EMOTE_DELETE;
} else if (type == "7tv_emote_update") {
return EventType::STV_EMOTE_UPDATE;
- } else {
+ }
+#ifdef BUILD_BETTERTTV
+ else if (type == "bttv_emote_add") {
+ return EventType::BTTV_EMOTE_CREATE;
+ } else if (type == "bttv_emote_delete") {
+ return EventType::BTTV_EMOTE_DELETE;
+ } else if (type == "bttv_emote_update") {
+ return EventType::BTTV_EMOTE_UPDATE;
+ }
+#endif
+ else {
return EventType::CUSTOM;
}
}
@@ -40,7 +50,17 @@ namespace bot::schemas {
return "7tv_emote_delete";
} else if (type == STV_EMOTE_UPDATE) {
return "7tv_emote_update";
- } else {
+ }
+#ifdef BUILD_BETTERTTV
+ else if (type == BTTV_EMOTE_CREATE) {
+ return "bttv_emote_add";
+ } else if (type == BTTV_EMOTE_DELETE) {
+ return "bttv_emote_delete";
+ } else if (type == BTTV_EMOTE_UPDATE) {
+ return "bttv_emote_update";
+ }
+#endif
+ else {
return "custom";
}
}
diff --git a/bot/src/schemas/stream.hpp b/bot/src/schemas/stream.hpp
index 357d476..348eccb 100644
--- a/bot/src/schemas/stream.hpp
+++ b/bot/src/schemas/stream.hpp
@@ -10,8 +10,13 @@ namespace bot::schemas {
TITLE,
GAME,
STV_EMOTE_CREATE = 10,
- STV_EMOTE_DELETE = 11,
- STV_EMOTE_UPDATE = 12,
+ STV_EMOTE_DELETE,
+ STV_EMOTE_UPDATE,
+#ifdef BUILD_BETTERTTV
+ BTTV_EMOTE_CREATE,
+ BTTV_EMOTE_DELETE,
+ BTTV_EMOTE_UPDATE,
+#endif
GITHUB = 40,
CUSTOM = 99
};