categorized emtotepopup

This commit is contained in:
fourtf
2018-08-11 14:20:53 +02:00
parent 09b8a9d821
commit c719bb6b74
55 changed files with 420 additions and 604 deletions
+44 -71
View File
@@ -10,9 +10,7 @@
#include <QThread>
namespace chatterino {
namespace {
Url getEmoteLink(QString urlTemplate, const EmoteId &id,
const QString &emoteScale)
{
@@ -21,72 +19,14 @@ Url getEmoteLink(QString urlTemplate, const EmoteId &id,
return {urlTemplate.replace("{{id}}", id.string)
.replace("{{image}}", emoteScale)};
}
} // namespace
AccessGuard<const EmoteMap> BttvEmotes::accessGlobalEmotes() const
{
return this->globalEmotes_.accessConst();
}
boost::optional<EmotePtr> BttvEmotes::getGlobalEmote(const EmoteName &name)
{
auto emotes = this->globalEmotes_.access();
auto it = emotes->find(name);
if (it == emotes->end()) return boost::none;
return it->second;
}
// FOURTF: never returns anything
// boost::optional<EmotePtr> BttvEmotes::getEmote(const EmoteId &id)
//{
// auto cache = this->channelEmoteCache_.access();
// auto it = cache->find(id);
//
// if (it != cache->end()) {
// auto shared = it->second.lock();
// if (shared) {
// return shared;
// }
// }
//
// return boost::none;
//}
void BttvEmotes::loadGlobalEmotes()
{
auto request = NetworkRequest(QString(globalEmoteApiUrl));
request.setCaller(QThread::currentThread());
request.setTimeout(30000);
request.onSuccess([this](auto result) -> Outcome {
// if (auto shared = weak.lock()) {
auto currentEmotes = this->globalEmotes_.access();
auto pair = this->parseGlobalEmotes(result.parseJson(), *currentEmotes);
if (pair.first) {
*currentEmotes = std::move(pair.second);
}
return pair.first;
// }
return Failure;
});
request.execute();
}
std::pair<Outcome, EmoteMap> BttvEmotes::parseGlobalEmotes(
const QJsonObject &jsonRoot, const EmoteMap &currentEmotes)
std::pair<Outcome, EmoteMap> parseGlobalEmotes(const QJsonObject &jsonRoot,
const EmoteMap &currentEmotes)
{
auto emotes = EmoteMap();
auto jsonEmotes = jsonRoot.value("emotes").toArray();
auto urlTemplate =
QString("https:" + jsonRoot.value("urlTemplate").toString());
auto urlTemplate = qS("https:") + jsonRoot.value("urlTemplate").toString();
for (const QJsonValue &jsonEmote : jsonEmotes) {
for (auto jsonEmote : jsonEmotes) {
auto id = EmoteId{jsonEmote.toObject().value("id").toString()};
auto name = EmoteName{jsonEmote.toObject().value("code").toString()};
@@ -99,16 +39,49 @@ std::pair<Outcome, EmoteMap> BttvEmotes::parseGlobalEmotes(
Tooltip{name.string + "<br />Global Bttv Emote"},
Url{"https://manage.betterttv.net/emotes/" + id.string}});
auto it = currentEmotes.find(name);
if (it != currentEmotes.end() && *it->second == emote) {
// reuse old shared_ptr if nothing changed
emotes[name] = it->second;
} else {
emotes[name] = std::make_shared<Emote>(std::move(emote));
}
emotes[name] = cachedOrMakeEmotePtr(std::move(emote), currentEmotes);
}
return {Success, std::move(emotes)};
}
} // namespace
BttvEmotes::BttvEmotes()
: global_(std::make_shared<EmoteMap>())
{
}
std::shared_ptr<const EmoteMap> BttvEmotes::global() const
{
return this->global_.get();
}
boost::optional<EmotePtr> BttvEmotes::global(const EmoteName &name) const
{
auto emotes = this->global_.get();
auto it = emotes->find(name);
if (it == emotes->end()) return boost::none;
return it->second;
}
void BttvEmotes::loadGlobal()
{
auto request = NetworkRequest(QString(globalEmoteApiUrl));
request.setCaller(QThread::currentThread());
request.setTimeout(30000);
request.onSuccess([this](auto result) -> Outcome {
auto emotes = this->global_.get();
auto pair = parseGlobalEmotes(result.parseJson(), *emotes);
if (pair.first)
this->global_.set(
std::make_shared<EmoteMap>(std::move(pair.second)));
return pair.first;
});
request.execute();
}
} // namespace chatterino
+7 -15
View File
@@ -1,33 +1,25 @@
#pragma once
#include <memory>
#include "common/UniqueAccess.hpp"
#include "common/Atomic.hpp"
#include "messages/Emote.hpp"
#include "messages/EmoteCache.hpp"
namespace chatterino {
class BttvEmotes final : std::enable_shared_from_this<BttvEmotes>
class BttvEmotes final
{
static constexpr const char *globalEmoteApiUrl =
"https://api.betterttv.net/2/emotes";
public:
// BttvEmotes();
BttvEmotes();
AccessGuard<const EmoteMap> accessGlobalEmotes() const;
boost::optional<EmotePtr> getGlobalEmote(const EmoteName &name);
boost::optional<EmotePtr> getEmote(const EmoteId &id);
void loadGlobalEmotes();
std::shared_ptr<const EmoteMap> global() const;
boost::optional<EmotePtr> global(const EmoteName &name) const;
void loadGlobal();
private:
std::pair<Outcome, EmoteMap> parseGlobalEmotes(
const QJsonObject &jsonRoot, const EmoteMap &currentEmotes);
UniqueAccess<EmoteMap> globalEmotes_;
// UniqueAccess<WeakEmoteIdMap> channelEmoteCache_;
Atomic<std::shared_ptr<const EmoteMap>> global_;
};
} // namespace chatterino
+3 -3
View File
@@ -118,7 +118,7 @@ void Emojis::loadEmojis()
rapidjson::ParseResult result = root.Parse(data.toUtf8(), data.length());
if (result.Code() != rapidjson::kParseErrorNone) {
Log("JSON parse error: {} ({})",
log("JSON parse error: {} ({})",
rapidjson::GetParseError_En(result.Code()), result.Offset());
return;
}
@@ -146,7 +146,7 @@ void Emojis::loadEmojis()
auto toneNameIt = toneNames.find(tone);
if (toneNameIt == toneNames.end()) {
Log("Tone with key {} does not exist in tone names map",
log("Tone with key {} does not exist in tone names map",
tone);
continue;
}
@@ -219,7 +219,7 @@ void Emojis::loadEmojiSet()
auto app = getApp();
app->settings->emojiSet.connect([=](const auto &emojiSet, auto) {
Log("Using emoji set {}", emojiSet);
log("Using emoji set {}", emojiSet);
this->emojis.each([=](const auto &name,
std::shared_ptr<EmojiData> &emoji) {
QString emojiSetToUse = emojiSet;
-1
View File
@@ -1,6 +1,5 @@
#pragma once
#include "common/SimpleSignalVector.hpp"
#include "messages/Emote.hpp"
#include "util/ConcurrentMap.hpp"
+47 -49
View File
@@ -19,7 +19,6 @@ Url getEmoteLink(const QJsonObject &urls, const QString &emoteScale)
return {"https:" + emote.toString()};
}
void fillInEmoteData(const QJsonObject &urls, const EmoteName &name,
const QString &tooltip, Emote &emoteData)
{
@@ -34,52 +33,11 @@ void fillInEmoteData(const QJsonObject &urls, const EmoteName &name,
Image::fromUrl(url3x, 0.25)};
emoteData.tooltip = {tooltip};
}
} // namespace
AccessGuard<const EmoteCache<EmoteName>> FfzEmotes::accessGlobalEmotes() const
{
return this->globalEmotes_.accessConst();
}
boost::optional<EmotePtr> FfzEmotes::getEmote(const EmoteId &id)
{
auto cache = this->channelEmoteCache_.access();
auto it = cache->find(id);
if (it != cache->end()) {
auto shared = it->second.lock();
if (shared) {
return shared;
}
}
return boost::none;
}
boost::optional<EmotePtr> FfzEmotes::getGlobalEmote(const EmoteName &name)
{
return this->globalEmotes_.access()->get(name);
}
void FfzEmotes::loadGlobalEmotes()
{
QString url("https://api.frankerfacez.com/v1/set/global");
NetworkRequest request(url);
request.setCaller(QThread::currentThread());
request.setTimeout(30000);
request.onSuccess([this](auto result) -> Outcome {
return this->parseGlobalEmotes(result.parseJson());
});
request.execute();
}
Outcome FfzEmotes::parseGlobalEmotes(const QJsonObject &jsonRoot)
std::pair<Outcome, EmoteMap> parseGlobalEmotes(const QJsonObject &jsonRoot,
const EmoteMap &currentEmotes)
{
auto jsonSets = jsonRoot.value("sets").toObject();
auto emotes = this->globalEmotes_.access();
auto replacement = emotes->makeReplacment();
auto emotes = EmoteMap();
for (auto jsonSet : jsonSets) {
auto jsonEmotes = jsonSet.toObject().value("emoticons").toArray();
@@ -99,15 +57,55 @@ Outcome FfzEmotes::parseGlobalEmotes(const QJsonObject &jsonRoot)
.arg(id.string)
.arg(name.string)};
replacement.add(name, emote);
emotes[name] =
cachedOrMakeEmotePtr(std::move(emote), currentEmotes);
}
}
return Success;
return {Success, std::move(emotes)};
}
} // namespace
FfzEmotes::FfzEmotes()
: global_(std::make_shared<EmoteMap>())
{
}
void FfzEmotes::loadChannelEmotes(const QString &channelName,
std::function<void(EmoteMap &&)> callback)
std::shared_ptr<const EmoteMap> FfzEmotes::global() const
{
return this->global_.get();
}
boost::optional<EmotePtr> FfzEmotes::global(const EmoteName &name) const
{
auto emotes = this->global_.get();
auto it = emotes->find(name);
if (it != emotes->end()) return it->second;
return boost::none;
}
void FfzEmotes::loadGlobal()
{
QString url("https://api.frankerfacez.com/v1/set/global");
NetworkRequest request(url);
request.setCaller(QThread::currentThread());
request.setTimeout(30000);
request.onSuccess([this](auto result) -> Outcome {
auto emotes = this->global();
auto pair = parseGlobalEmotes(result.parseJson(), *emotes);
if (pair.first)
this->global_.set(
std::make_shared<EmoteMap>(std::move(pair.second)));
return pair.first;
});
request.execute();
}
void FfzEmotes::loadChannel(const QString &channelName,
std::function<void(EmoteMap &&)> callback)
{
// printf("[FFZEmotes] Reload FFZ Channel Emotes for channel %s\n",
// qPrintable(channelName));
+9 -16
View File
@@ -2,7 +2,7 @@
#include <memory>
#include "common/UniqueAccess.hpp"
#include "common/Atomic.hpp"
#include "messages/Emote.hpp"
#include "messages/EmoteCache.hpp"
@@ -16,24 +16,17 @@ class FfzEmotes final : std::enable_shared_from_this<FfzEmotes>
"https://api.betterttv.net/2/channels/";
public:
// FfzEmotes();
FfzEmotes();
static std::shared_ptr<FfzEmotes> create();
std::shared_ptr<const EmoteMap> global() const;
boost::optional<EmotePtr> global(const EmoteName &name) const;
AccessGuard<const EmoteCache<EmoteName>> accessGlobalEmotes() const;
boost::optional<EmotePtr> getGlobalEmote(const EmoteName &name);
boost::optional<EmotePtr> getEmote(const EmoteId &id);
void loadGlobal();
void loadChannel(const QString &channelName,
std::function<void(EmoteMap &&)> callback);
void loadGlobalEmotes();
void loadChannelEmotes(const QString &channelName,
std::function<void(EmoteMap &&)> callback);
protected:
Outcome parseGlobalEmotes(const QJsonObject &jsonRoot);
Outcome parseChannelEmotes(const QJsonObject &jsonRoot);
UniqueAccess<EmoteCache<EmoteName>> globalEmotes_;
UniqueAccess<WeakEmoteIdMap> channelEmoteCache_;
private:
Atomic<std::shared_ptr<const EmoteMap>> global_;
};
} // namespace chatterino
+1 -1
View File
@@ -131,7 +131,7 @@ std::shared_ptr<Channel> AbstractIrcServer::getOrAddChannel(
chan->destroyed.connect([this, clojuresInCppAreShit] {
// fourtf: issues when the server itself is destroyed
Log("[AbstractIrcServer::addChannel] {} was destroyed",
log("[AbstractIrcServer::addChannel] {} was destroyed",
clojuresInCppAreShit);
this->channels.remove(clojuresInCppAreShit);
+4 -4
View File
@@ -145,7 +145,7 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
auto chan = app->twitch.server->getChannelOrEmpty(chanName);
if (chan->isEmpty()) {
Log("[IrcMessageHandler:handleClearChatMessage] Twitch channel {} not "
log("[IrcMessageHandler:handleClearChatMessage] Twitch channel {} not "
"found",
chanName);
return;
@@ -209,7 +209,7 @@ void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message)
void IrcMessageHandler::handleWhisperMessage(Communi::IrcMessage *message)
{
auto app = getApp();
Log("Received whisper!");
log("Received whisper!");
MessageParseArgs args;
args.isReceivedWhisper = true;
@@ -326,7 +326,7 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message)
auto channel = app->twitch.server->getChannelOrEmpty(channelName);
if (channel->isEmpty()) {
Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel "
log("[IrcManager:handleNoticeMessage] Channel {} not found in channel "
"manager ",
channelName);
return;
@@ -366,7 +366,7 @@ void IrcMessageHandler::handleWriteConnectionNoticeMessage(
return;
}
Log("Showing notice message from write connection with message id '{}'",
log("Showing notice message from write connection with message id '{}'",
msgID);
}
+4 -4
View File
@@ -42,23 +42,23 @@ void PartialTwitchUser::getId(std::function<void(QString)> successCallback,
request.onSuccess([successCallback](auto result) -> Outcome {
auto root = result.parseJson();
if (!root.value("users").isArray()) {
Log("API Error while getting user id, users is not an array");
log("API Error while getting user id, users is not an array");
return Failure;
}
auto users = root.value("users").toArray();
if (users.size() != 1) {
Log("API Error while getting user id, users array size is not 1");
log("API Error while getting user id, users array size is not 1");
return Failure;
}
if (!users[0].isObject()) {
Log("API Error while getting user id, first user is not an object");
log("API Error while getting user id, first user is not an object");
return Failure;
}
auto firstUser = users[0].toObject();
auto id = firstUser.value("_id");
if (!id.isString()) {
Log("API Error: while getting user id, first user object `_id` key "
log("API Error: while getting user id, first user object `_id` key "
"is not a "
"string");
return Failure;
+40 -40
View File
@@ -109,7 +109,7 @@ void PubSubClient::handlePong()
{
assert(this->awaitingPong_);
Log("Got pong!");
log("Got pong!");
this->awaitingPong_ = false;
}
@@ -144,7 +144,7 @@ void PubSubClient::ping()
}
if (self->awaitingPong_) {
Log("No pong respnose, disconnect!");
log("No pong respnose, disconnect!");
// TODO(pajlada): Label this connection as "disconnect me"
}
});
@@ -166,7 +166,7 @@ bool PubSubClient::send(const char *payload)
websocketpp::frame::opcode::text, ec);
if (ec) {
Log("Error sending message {}: {}", payload, ec.message());
log("Error sending message {}: {}", payload, ec.message());
// TODO(pajlada): Check which error code happened and maybe gracefully
// handle it
@@ -207,26 +207,26 @@ PubSub::PubSub()
action.state = ModeChangedAction::State::On;
if (!data.HasMember("args")) {
Log("Missing required args member");
log("Missing required args member");
return;
}
const auto &args = data["args"];
if (!args.IsArray()) {
Log("args member must be an array");
log("args member must be an array");
return;
}
if (args.Size() == 0) {
Log("Missing duration argument in slowmode on");
log("Missing duration argument in slowmode on");
return;
}
const auto &durationArg = args[0];
if (!durationArg.IsString()) {
Log("Duration arg must be a string");
log("Duration arg must be a string");
return;
}
@@ -314,7 +314,7 @@ PubSub::PubSub()
return;
}
} catch (const std::runtime_error &ex) {
Log("Error parsing moderation action: {}", ex.what());
log("Error parsing moderation action: {}", ex.what());
}
action.modded = false;
@@ -339,7 +339,7 @@ PubSub::PubSub()
return;
}
} catch (const std::runtime_error &ex) {
Log("Error parsing moderation action: {}", ex.what());
log("Error parsing moderation action: {}", ex.what());
}
action.modded = true;
@@ -380,7 +380,7 @@ PubSub::PubSub()
this->signals_.moderation.userBanned.invoke(action);
} catch (const std::runtime_error &ex) {
Log("Error parsing moderation action: {}", ex.what());
log("Error parsing moderation action: {}", ex.what());
}
};
@@ -410,7 +410,7 @@ PubSub::PubSub()
this->signals_.moderation.userBanned.invoke(action);
} catch (const std::runtime_error &ex) {
Log("Error parsing moderation action: {}", ex.what());
log("Error parsing moderation action: {}", ex.what());
}
};
@@ -436,7 +436,7 @@ PubSub::PubSub()
this->signals_.moderation.userUnbanned.invoke(action);
} catch (const std::runtime_error &ex) {
Log("Error parsing moderation action: {}", ex.what());
log("Error parsing moderation action: {}", ex.what());
}
};
@@ -462,7 +462,7 @@ PubSub::PubSub()
this->signals_.moderation.userUnbanned.invoke(action);
} catch (const std::runtime_error &ex) {
Log("Error parsing moderation action: {}", ex.what());
log("Error parsing moderation action: {}", ex.what());
}
};
@@ -493,7 +493,7 @@ void PubSub::addClient()
auto con = this->websocketClient.get_connection(TWITCH_PUBSUB_URL, ec);
if (ec) {
Log("Unable to establish connection: {}", ec.message());
log("Unable to establish connection: {}", ec.message());
return;
}
@@ -512,7 +512,7 @@ void PubSub::listenToWhispers(std::shared_ptr<TwitchAccount> account)
std::string userID = account->getUserId().toStdString();
Log("Connection open!");
log("Connection open!");
websocketpp::lib::error_code ec;
std::vector<std::string> topics({"whispers." + userID});
@@ -520,7 +520,7 @@ void PubSub::listenToWhispers(std::shared_ptr<TwitchAccount> account)
this->listen(createListenMessage(topics, account));
if (ec) {
Log("Unable to send message to websocket server: {}", ec.message());
log("Unable to send message to websocket server: {}", ec.message());
return;
}
}
@@ -544,11 +544,11 @@ void PubSub::listenToChannelModerationActions(
std::string topic(fS("chat_moderator_actions.{}.{}", userID, channelID));
if (this->isListeningToTopic(topic)) {
Log("We are already listening to topic {}", topic);
log("We are already listening to topic {}", topic);
return;
}
Log("Listen to topic {}", topic);
log("Listen to topic {}", topic);
this->listenToTopic(topic, account);
}
@@ -564,18 +564,18 @@ void PubSub::listenToTopic(const std::string &topic,
void PubSub::listen(rapidjson::Document &&msg)
{
if (this->tryListen(msg)) {
Log("Successfully listened!");
log("Successfully listened!");
return;
}
Log("Added to the back of the queue");
log("Added to the back of the queue");
this->requests.emplace_back(
std::make_unique<rapidjson::Document>(std::move(msg)));
}
bool PubSub::tryListen(rapidjson::Document &msg)
{
Log("tryListen with {} clients", this->clients.size());
log("tryListen with {} clients", this->clients.size());
for (const auto &p : this->clients) {
const auto &client = p.second;
if (client->listen(msg)) {
@@ -608,13 +608,13 @@ void PubSub::onMessage(websocketpp::connection_hdl hdl,
rapidjson::ParseResult res = msg.Parse(payload.c_str());
if (!res) {
Log("Error parsing message '{}' from PubSub: {}", payload,
log("Error parsing message '{}' from PubSub: {}", payload,
rapidjson::GetParseError_En(res.Code()));
return;
}
if (!msg.IsObject()) {
Log("Error parsing message '{}' from PubSub. Root object is not an "
log("Error parsing message '{}' from PubSub. Root object is not an "
"object",
payload);
return;
@@ -623,7 +623,7 @@ void PubSub::onMessage(websocketpp::connection_hdl hdl,
std::string type;
if (!rj::getSafe(msg, "type", type)) {
Log("Missing required string member `type` in message root");
log("Missing required string member `type` in message root");
return;
}
@@ -631,14 +631,14 @@ void PubSub::onMessage(websocketpp::connection_hdl hdl,
this->handleListenResponse(msg);
} else if (type == "MESSAGE") {
if (!msg.HasMember("data")) {
Log("Missing required object member `data` in message root");
log("Missing required object member `data` in message root");
return;
}
const auto &data = msg["data"];
if (!data.IsObject()) {
Log("Member `data` must be an object");
log("Member `data` must be an object");
return;
}
@@ -654,7 +654,7 @@ void PubSub::onMessage(websocketpp::connection_hdl hdl,
client.second->handlePong();
} else {
Log("Unknown message type: {}", type);
log("Unknown message type: {}", type);
}
}
@@ -699,7 +699,7 @@ PubSub::WebsocketContextPtr PubSub::onTLSInit(websocketpp::connection_hdl hdl)
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::single_dh_use);
} catch (const std::exception &e) {
Log("Exception caught in OnTLSInit: {}", e.what());
log("Exception caught in OnTLSInit: {}", e.what());
}
return ctx;
@@ -714,12 +714,12 @@ void PubSub::handleListenResponse(const rapidjson::Document &msg)
rj::getSafe(msg, "nonce", nonce);
if (error.empty()) {
Log("Successfully listened to nonce {}", nonce);
log("Successfully listened to nonce {}", nonce);
// Nothing went wrong
return;
}
Log("PubSub error: {} on nonce {}", error, nonce);
log("PubSub error: {} on nonce {}", error, nonce);
return;
}
}
@@ -729,14 +729,14 @@ void PubSub::handleMessageResponse(const rapidjson::Value &outerData)
QString topic;
if (!rj::getSafe(outerData, "topic", topic)) {
Log("Missing required string member `topic` in outerData");
log("Missing required string member `topic` in outerData");
return;
}
std::string payload;
if (!rj::getSafe(outerData, "message", payload)) {
Log("Expected string message in outerData");
log("Expected string message in outerData");
return;
}
@@ -745,7 +745,7 @@ void PubSub::handleMessageResponse(const rapidjson::Value &outerData)
rapidjson::ParseResult res = msg.Parse(payload.c_str());
if (!res) {
Log("Error parsing message '{}' from PubSub: {}", payload,
log("Error parsing message '{}' from PubSub: {}", payload,
rapidjson::GetParseError_En(res.Code()));
return;
}
@@ -754,7 +754,7 @@ void PubSub::handleMessageResponse(const rapidjson::Value &outerData)
std::string whisperType;
if (!rj::getSafe(msg, "type", whisperType)) {
Log("Bad whisper data");
log("Bad whisper data");
return;
}
@@ -765,7 +765,7 @@ void PubSub::handleMessageResponse(const rapidjson::Value &outerData)
} else if (whisperType == "thread") {
// Handle thread?
} else {
Log("Invalid whisper type: {}", whisperType);
log("Invalid whisper type: {}", whisperType);
assert(false);
return;
}
@@ -777,30 +777,30 @@ void PubSub::handleMessageResponse(const rapidjson::Value &outerData)
std::string moderationAction;
if (!rj::getSafe(data, "moderation_action", moderationAction)) {
Log("Missing moderation action in data: {}", rj::stringify(data));
log("Missing moderation action in data: {}", rj::stringify(data));
return;
}
auto handlerIt = this->moderationActionHandlers.find(moderationAction);
if (handlerIt == this->moderationActionHandlers.end()) {
Log("No handler found for moderation action {}", moderationAction);
log("No handler found for moderation action {}", moderationAction);
return;
}
// Invoke handler function
handlerIt->second(data, topicParts[2]);
} else {
Log("Unknown topic: {}", topic);
log("Unknown topic: {}", topic);
return;
}
}
void PubSub::runThread()
{
Log("Start pubsub manager thread");
log("Start pubsub manager thread");
this->websocketClient.run();
Log("Done with pubsub manager thread");
log("Done with pubsub manager thread");
}
} // namespace chatterino
+2 -2
View File
@@ -35,7 +35,7 @@ void runAfter(boost::asio::io_service &ioService, Duration duration,
timer->async_wait([timer, cb](const boost::system::error_code &ec) {
if (ec) {
Log("Error in runAfter: {}", ec.message());
log("Error in runAfter: {}", ec.message());
return;
}
@@ -52,7 +52,7 @@ void runAfter(std::shared_ptr<boost::asio::steady_timer> timer,
timer->async_wait([timer, cb](const boost::system::error_code &ec) {
if (ec) {
Log("Error in runAfter: {}", ec.message());
log("Error in runAfter: {}", ec.message());
return;
}
+17 -18
View File
@@ -143,7 +143,7 @@ void TwitchAccount::loadIgnores()
}
TwitchUser ignoredUser;
if (!rj::getSafe(userIt->value, ignoredUser)) {
Log("Error parsing twitch user JSON {}",
log("Error parsing twitch user JSON {}",
rj::stringify(userIt->value));
continue;
}
@@ -368,13 +368,13 @@ std::set<TwitchUser> TwitchAccount::getIgnores() const
void TwitchAccount::loadEmotes()
{
Log("Loading Twitch emotes for user {}", this->getUserName());
log("Loading Twitch emotes for user {}", this->getUserName());
const auto &clientID = this->getOAuthClient();
const auto &oauthToken = this->getOAuthToken();
if (clientID.isEmpty() || oauthToken.isEmpty()) {
Log("Missing Client ID or OAuth token");
log("Missing Client ID or OAuth token");
return;
}
@@ -386,7 +386,7 @@ void TwitchAccount::loadEmotes()
req.makeAuthorizedV5(this->getOAuthClient(), this->getOAuthToken());
req.onError([=](int errorCode) {
Log("[TwitchAccount::loadEmotes] Error {}", errorCode);
log("[TwitchAccount::loadEmotes] Error {}", errorCode);
if (errorCode == 203) {
// onFinished(FollowResult_NotFollowing);
} else {
@@ -420,7 +420,7 @@ void TwitchAccount::parseEmotes(const rapidjson::Document &root)
auto emoticonSets = root.FindMember("emoticon_sets");
if (emoticonSets == root.MemberEnd() || !emoticonSets->value.IsObject()) {
Log("No emoticon_sets in load emotes response");
log("No emoticon_sets in load emotes response");
return;
}
@@ -434,19 +434,19 @@ void TwitchAccount::parseEmotes(const rapidjson::Document &root)
for (const rapidjson::Value &emoteJSON :
emoteSetJSON.value.GetArray()) {
if (!emoteJSON.IsObject()) {
Log("Emote value was invalid");
log("Emote value was invalid");
return;
}
uint64_t idNumber;
if (!rj::getSafe(emoteJSON, "id", idNumber)) {
Log("No ID key found in Emote value");
log("No ID key found in Emote value");
return;
}
QString _code;
if (!rj::getSafe(emoteJSON, "code", _code)) {
Log("No code key found in Emote value");
log("No code key found in Emote value");
return;
}
@@ -468,7 +468,7 @@ void TwitchAccount::parseEmotes(const rapidjson::Document &root)
void TwitchAccount::loadEmoteSetData(std::shared_ptr<EmoteSet> emoteSet)
{
if (!emoteSet) {
Log("null emote set sent");
log("null emote set sent");
return;
}
@@ -486,7 +486,7 @@ void TwitchAccount::loadEmoteSetData(std::shared_ptr<EmoteSet> emoteSet)
req.setUseQuickLoadCache(true);
req.onError([](int errorCode) -> bool {
Log("Error code {} while loading emote set data", errorCode);
log("Error code {} while loading emote set data", errorCode);
return true;
});
@@ -507,16 +507,15 @@ void TwitchAccount::loadEmoteSetData(std::shared_ptr<EmoteSet> emoteSet)
return Failure;
}
Log("Loaded twitch emote set data for {}!", emoteSet->key);
log("Loaded twitch emote set data for {}!", emoteSet->key);
if (type == "sub") {
emoteSet->text =
QString("Twitch Subscriber Emote (%1)").arg(channelName);
} else {
emoteSet->text =
QString("Twitch Account Emote (%1)").arg(channelName);
}
auto name = channelName;
name.detach();
name[0] = name[0].toUpper();
emoteSet->text = name;
emoteSet->type = type;
emoteSet->channelName = channelName;
return Success;
+1
View File
@@ -44,6 +44,7 @@ public:
QString key;
QString channelName;
QString text;
QString type;
std::vector<TwitchEmote> emotes;
};
@@ -93,20 +93,20 @@ void TwitchAccountManager::reloadUsers()
switch (this->addUser(userData)) {
case AddUserResponse::UserAlreadyExists: {
Log("User {} already exists", userData.username);
log("User {} already exists", userData.username);
// Do nothing
} break;
case AddUserResponse::UserValuesUpdated: {
Log("User {} already exists, and values updated!",
log("User {} already exists, and values updated!",
userData.username);
if (userData.username == this->getCurrent()->getUserName()) {
Log("It was the current user, so we need to reconnect "
log("It was the current user, so we need to reconnect "
"stuff!");
this->currentUserChanged.invoke();
}
} break;
case AddUserResponse::UserAdded: {
Log("Added user {}", userData.username);
log("Added user {}", userData.username);
listUpdated = true;
} break;
}
@@ -125,12 +125,12 @@ void TwitchAccountManager::load()
QString newUsername(QString::fromStdString(newValue));
auto user = this->findUserByUsername(newUsername);
if (user) {
Log("[AccountManager:currentUsernameChanged] User successfully "
log("[AccountManager:currentUsernameChanged] User successfully "
"updated to {}",
newUsername);
this->currentUser_ = user;
} else {
Log("[AccountManager:currentUsernameChanged] User successfully "
log("[AccountManager:currentUsernameChanged] User successfully "
"updated to anonymous");
this->currentUser_ = this->anonymousUser_;
}
+4 -4
View File
@@ -20,25 +20,25 @@ void TwitchApi::findUserId(const QString user,
request.onSuccess([successCallback](auto result) mutable -> Outcome {
auto root = result.parseJson();
if (!root.value("users").isArray()) {
Log("API Error while getting user id, users is not an array");
log("API Error while getting user id, users is not an array");
successCallback("");
return Failure;
}
auto users = root.value("users").toArray();
if (users.size() != 1) {
Log("API Error while getting user id, users array size is not 1");
log("API Error while getting user id, users array size is not 1");
successCallback("");
return Failure;
}
if (!users[0].isObject()) {
Log("API Error while getting user id, first user is not an object");
log("API Error while getting user id, first user is not an object");
successCallback("");
return Failure;
}
auto firstUser = users[0].toObject();
auto id = firstUser.value("_id");
if (!id.isString()) {
Log("API Error: while getting user id, first user object `_id` key "
log("API Error: while getting user id, first user object `_id` key "
"is not a "
"string");
successCallback("");
+9 -9
View File
@@ -56,7 +56,7 @@ TwitchChannel::TwitchChannel(const QString &name)
, popoutPlayerUrl_("https://player.twitch.tv/?channel=" + name)
, mod_(false)
{
Log("[TwitchChannel:{}] Opened", name);
log("[TwitchChannel:{}] Opened", name);
// this->refreshChannelEmotes();
// this->refreshViewerList();
@@ -116,7 +116,7 @@ void TwitchChannel::refreshChannelEmotes()
if (auto shared = weak.lock()) //
*this->bttvEmotes_.access() = emoteMap;
});
getApp()->emotes->ffz.loadChannelEmotes(
getApp()->emotes->ffz.loadChannel(
this->getName(), [this, weak = weakOf<Channel>(this)](auto &&emoteMap) {
if (auto shared = weak.lock())
*this->ffzEmotes_.access() = emoteMap;
@@ -136,7 +136,7 @@ void TwitchChannel::sendMessage(const QString &message)
return;
}
Log("[TwitchChannel:{}] Send message: {}", this->getName(), message);
log("[TwitchChannel:{}] Send message: {}", this->getName(), message);
// Do last message processing
QString parsedMessage = app->emotes->emojis.replaceShortCodes(message);
@@ -350,13 +350,13 @@ void TwitchChannel::refreshLiveStatus()
auto roomID = this->getRoomId();
if (roomID.isEmpty()) {
Log("[TwitchChannel:{}] Refreshing live status (Missing ID)",
log("[TwitchChannel:{}] Refreshing live status (Missing ID)",
this->getName());
this->setLive(false);
return;
}
Log("[TwitchChannel:{}] Refreshing live status", this->getName());
log("[TwitchChannel:{}] Refreshing live status", this->getName());
QString url("https://api.twitch.tv/kraken/streams/" + roomID);
@@ -381,12 +381,12 @@ void TwitchChannel::refreshLiveStatus()
Outcome TwitchChannel::parseLiveStatus(const rapidjson::Document &document)
{
if (!document.IsObject()) {
Log("[TwitchChannel:refreshLiveStatus] root is not an object");
log("[TwitchChannel:refreshLiveStatus] root is not an object");
return Failure;
}
if (!document.HasMember("stream")) {
Log("[TwitchChannel:refreshLiveStatus] Missing stream in root");
log("[TwitchChannel:refreshLiveStatus] Missing stream in root");
return Failure;
}
@@ -400,7 +400,7 @@ Outcome TwitchChannel::parseLiveStatus(const rapidjson::Document &document)
if (!stream.HasMember("viewers") || !stream.HasMember("game") ||
!stream.HasMember("channel") || !stream.HasMember("created_at")) {
Log("[TwitchChannel:refreshLiveStatus] Missing members in stream");
log("[TwitchChannel:refreshLiveStatus] Missing members in stream");
this->setLive(false);
return Failure;
}
@@ -408,7 +408,7 @@ Outcome TwitchChannel::parseLiveStatus(const rapidjson::Document &document)
const rapidjson::Value &streamChannel = stream["channel"];
if (!streamChannel.IsObject() || !streamChannel.HasMember("status")) {
Log("[TwitchChannel:refreshLiveStatus] Missing member \"status\" in "
log("[TwitchChannel:refreshLiveStatus] Missing member \"status\" in "
"channel");
return Failure;
}
+1 -1
View File
@@ -4,7 +4,7 @@
#include "common/Channel.hpp"
#include "common/Common.hpp"
#include "common/MutexValue.hpp"
#include "common/Atomic.hpp"
#include "common/UniqueAccess.hpp"
#include "messages/Emote.hpp"
#include "singletons/Emotes.hpp"
+1 -1
View File
@@ -6,7 +6,7 @@ namespace chatterino {
bool trimChannelName(const QString &channelName, QString &outChannelName)
{
if (channelName.length() < 3) {
Log("channel name length below 3");
log("channel name length below 3");
return false;
}
@@ -55,7 +55,7 @@ bool TwitchMessageBuilder::isIgnored() const
// TODO(pajlada): Do we need to check if the phrase is valid first?
for (const auto &phrase : app->ignores->phrases.getVector()) {
if (phrase.isMatch(this->originalMessage_)) {
Log("Blocking message because it contains ignored phrase {}",
log("Blocking message because it contains ignored phrase {}",
phrase.getPattern());
return true;
}
@@ -68,7 +68,7 @@ bool TwitchMessageBuilder::isIgnored() const
for (const auto &user :
app->accounts->twitch.getCurrent()->getIgnores()) {
if (sourceUserID == user.id) {
Log("Blocking message because it's from blocked user {}",
log("Blocking message because it's from blocked user {}",
user.name);
return true;
}
@@ -533,7 +533,7 @@ void TwitchMessageBuilder::parseHighlights(bool isPastMsg)
if (!app->highlights->blacklistContains(this->ircMessage->nick())) {
for (const HighlightPhrase &highlight : activeHighlights) {
if (highlight.isMatch(this->originalMessage_)) {
Log("Highlight because {} matches {}", this->originalMessage_,
log("Highlight because {} matches {}", this->originalMessage_,
highlight.getPattern());
doHighlight = true;
@@ -555,7 +555,7 @@ void TwitchMessageBuilder::parseHighlights(bool isPastMsg)
}
for (const HighlightPhrase &userHighlight : userHighlights) {
if (userHighlight.isMatch(this->ircMessage->nick())) {
Log("Highlight because user {} sent a message",
log("Highlight because user {} sent a message",
this->ircMessage->nick());
doHighlight = true;
@@ -638,12 +638,12 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name)
auto flags = MessageElementFlags();
auto emote = boost::optional<EmotePtr>{};
if ((emote = getApp()->emotes->bttv.getGlobalEmote(name))) {
if ((emote = getApp()->emotes->bttv.global(name))) {
flags = MessageElementFlag::BttvEmote;
} else if (twitchChannel &&
(emote = this->twitchChannel->getBttvEmote(name))) {
flags = MessageElementFlag::BttvEmote;
} else if ((emote = getApp()->emotes->ffz.getGlobalEmote(name))) {
} else if ((emote = getApp()->emotes->ffz.global(name))) {
flags = MessageElementFlag::FfzEmote;
} else if (twitchChannel &&
(emote = this->twitchChannel->getFfzEmote(name))) {
@@ -1,7 +1,6 @@
#pragma once
#include "messages/MessageBuilder.hpp"
#include "messages/MessageParseArgs.hpp"
#include "singletons/Emotes.hpp"
#include <IrcMessage>
+2 -2
View File
@@ -1,6 +1,6 @@
#pragma once
#include "common/MutexValue.hpp"
#include "common/Atomic.hpp"
#include "common/Singleton.hpp"
#include "providers/irc/AbstractIrcServer.hpp"
#include "providers/twitch/TwitchAccount.hpp"
@@ -29,7 +29,7 @@ public:
std::shared_ptr<Channel> getChannelOrEmptyByID(const QString &channelID);
MutexValue<QString> lastUserThatWhisperedMe;
Atomic<QString> lastUserThatWhisperedMe;
const ChannelPtr whispersChannel;
const ChannelPtr mentionsChannel;