From b19cee38da6bcdbaa8cd3a4115c0f24e7dadc9cd Mon Sep 17 00:00:00 2001 From: moderndevslulw Date: Fri, 4 Apr 2025 01:12:56 +0500 Subject: feat: 7TV websocket client --- src/seventv.cpp | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 161 insertions(+), 1 deletion(-) (limited to 'src/seventv.cpp') diff --git a/src/seventv.cpp b/src/seventv.cpp index 1fae55e..51c306c 100644 --- a/src/seventv.cpp +++ b/src/seventv.cpp @@ -1,5 +1,165 @@ #include "emotespp/seventv.hpp" +#include +#include +#include + namespace emotespp { - SevenTVEmoteListener::SevenTVEmoteListener() {} + SevenTVWebsocketClient::SevenTVWebsocketClient() { + this->websocket.setUrl("wss://events.7tv.io/v3"); + this->websocket.enableAutomaticReconnection(); + + this->websocket.setOnMessageCallback( + [this](const ix::WebSocketMessagePtr &msg) { + switch (msg->type) { + case ix::WebSocketMessageType::Message: { + nlohmann::json j = nlohmann::json::parse(msg->str); + + int opcode = j["op"].get(); + + // hello opcode + if (opcode == 1) { + this->is_connected = true; + std::for_each(this->ids.begin(), this->ids.end(), + [this](const std::string &id) { + this->subscribe_emote_set(id); + }); + return; + } else if (opcode != 0) { + return; + } + + nlohmann::json data = j["d"]; + + std::string type = data["type"]; + if (type != "emote_set.update") { + return; + } + + data = data["body"]; + + std::string channel_id = data["id"]; + + nlohmann::json actor = data["actor"]; + std::string actor_id = actor["id"]; + + if (data.contains("pushed") && this->emote_create.has_value()) { + for (const nlohmann::json &d : data["pushed"]) { + nlohmann::json emote = d["value"]; + this->emote_create.value()(channel_id, actor_id, + this->create_emote(emote)); + } + } + + if (data.contains("pulled") && this->emote_delete.has_value()) { + for (const nlohmann::json &d : data["pulled"]) { + nlohmann::json emote = d["old_value"]; + this->emote_delete.value()(channel_id, actor_id, + this->create_emote(emote)); + } + } + + if (data.contains("updated") && this->emote_update.has_value()) { + for (const nlohmann::json &d : data["updated"]) { + nlohmann::json old_emote = d["old_value"]; + nlohmann::json emote = d["value"]; + + std::string id = old_emote["id"]; + std::string code = emote["name"]; + + std::optional original_code = old_emote["name"]; + if (code == original_code) { + original_code = std::nullopt; + } + + Emote emote_data{id, code, original_code}; + + this->emote_update.value()(channel_id, actor_id, emote_data); + } + } + + break; + } + case ix::WebSocketMessageType::Close: + case ix::WebSocketMessageType::Error: { + this->is_connected = false; + break; + } + case ix::WebSocketMessageType::Open: + case ix::WebSocketMessageType::Ping: + case ix::WebSocketMessageType::Pong: + case ix::WebSocketMessageType::Fragment: + break; + } + }); + } + + void SevenTVWebsocketClient::subscribe_emote_set( + const std::string &emote_set_id) { + if (!std::any_of(this->ids.begin(), this->ids.end(), + [&emote_set_id](const std::string &id) { + return id == emote_set_id; + })) { + this->ids.push_back(emote_set_id); + } + + if (this->is_connected) { + nlohmann::json j; + j["op"] = 35; + + nlohmann::json d; + + nlohmann::json c; + c["object_id"] = emote_set_id; + + d["type"] = "emote_set.update"; + d["condition"] = c; + + j["d"] = d; + + this->websocket.sendUtf8Text(j.dump()); + } + } + + void SevenTVWebsocketClient::unsubscribe_emote_set( + const std::string &emote_set_id) { + if (this->is_connected) { + nlohmann::json j; + j["op"] = 36; + + nlohmann::json d; + + nlohmann::json c; + c["object_id"] = emote_set_id; + + d["type"] = "emote_set.update"; + d["condition"] = c; + + j["d"] = d; + + this->websocket.sendUtf8Text(j.dump()); + } + + auto it = std::find_if( + this->ids.begin(), this->ids.end(), + [&emote_set_id](const std::string &x) { return x == emote_set_id; }); + + if (it != this->ids.end()) { + this->ids.erase(it); + } + } + + void SevenTVWebsocketClient::start() { this->websocket.start(); } + + Emote SevenTVWebsocketClient::create_emote(const nlohmann::json &data) { + std::string id = data["id"]; + std::string code = data["name"]; + std::optional original_code = data["data"]["name"]; + + if (code == original_code) { + original_code = std::nullopt; + } + + return {id, code, original_code}; + } } \ No newline at end of file -- cgit v1.2.3