Switch to v2 of RAnders00's recent-messages API, so we support showing

old sub messages and stuff
This commit is contained in:
Rasmus Karlsson 2019-04-13 19:14:58 +02:00
parent a4cba22bcb
commit 8b3867fa7d
4 changed files with 183 additions and 39 deletions

View file

@ -44,6 +44,46 @@ IrcMessageHandler &IrcMessageHandler::getInstance()
return instance; return instance;
} }
std::vector<MessagePtr> IrcMessageHandler::parseMessage(
Channel *channel, Communi::IrcMessage *message)
{
std::vector<MessagePtr> builtMessages;
auto command = message->command();
if (command == "PRIVMSG")
{
return this->parsePrivMessage(
channel, static_cast<Communi::IrcPrivateMessage *>(message));
}
else if (command == "USERNOTICE")
{
return this->parseUserNoticeMessage(channel, message);
}
else if (command == "NOTICE")
{
return this->parseNoticeMessage(
static_cast<Communi::IrcNoticeMessage *>(message));
}
return builtMessages;
}
std::vector<MessagePtr> IrcMessageHandler::parsePrivMessage(
Channel *channel, Communi::IrcPrivateMessage *message)
{
log("Parse priv msg");
std::vector<MessagePtr> builtMessages;
MessageParseArgs args;
TwitchMessageBuilder builder(channel, message, args, message->content(),
message->isAction());
if (!builder.isIgnored())
{
builtMessages.emplace_back(builder.build());
}
return builtMessages;
}
void IrcMessageHandler::handlePrivMessage(Communi::IrcPrivateMessage *message, void IrcMessageHandler::handlePrivMessage(Communi::IrcPrivateMessage *message,
TwitchServer &server) TwitchServer &server)
{ {
@ -302,6 +342,56 @@ void IrcMessageHandler::handleWhisperMessage(Communi::IrcMessage *message)
} }
} }
std::vector<MessagePtr> IrcMessageHandler::parseUserNoticeMessage(
Channel *channel, Communi::IrcMessage *message)
{
std::vector<MessagePtr> builtMessages;
auto data = message->toData();
auto tags = message->tags();
auto parameters = message->parameters();
auto target = parameters[0];
QString msgType = tags.value("msg-id", "").toString();
QString content;
if (parameters.size() >= 2)
{
content = parameters[1];
}
if (msgType == "sub" || msgType == "resub" || msgType == "subgift")
{
// Sub-specific message. I think it's only allowed for "resub" messages
// atm
if (!content.isEmpty())
{
MessageParseArgs args;
args.trimSubscriberUsername = true;
TwitchMessageBuilder builder(channel, message, args, content,
false);
builder->flags.set(MessageFlag::Subscription);
builder->flags.unset(MessageFlag::Highlighted);
builtMessages.emplace_back(builder.build());
}
}
auto it = tags.find("system-msg");
if (it != tags.end())
{
auto b = MessageBuilder(systemMessage,
parseTagString(it.value().toString()));
b->flags.set(MessageFlag::Subscription);
auto newMessage = b.release();
builtMessages.emplace_back(newMessage);
}
return builtMessages;
}
void IrcMessageHandler::handleUserNoticeMessage(Communi::IrcMessage *message, void IrcMessageHandler::handleUserNoticeMessage(Communi::IrcMessage *message,
TwitchServer &server) TwitchServer &server)
{ {
@ -381,11 +471,23 @@ void IrcMessageHandler::handleModeMessage(Communi::IrcMessage *message)
} }
} }
std::vector<MessagePtr> IrcMessageHandler::parseNoticeMessage(
Communi::IrcNoticeMessage *message)
{
std::vector<MessagePtr> builtMessages;
builtMessages.emplace_back(makeSystemMessage(message->content()));
return builtMessages;
}
void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message) void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message)
{ {
auto app = getApp(); auto app = getApp();
MessagePtr msg = makeSystemMessage(message->content()); auto builtMessages = this->parseNoticeMessage(message);
for (auto msg : builtMessages)
{
QString channelName; QString channelName;
if (!trimChannelName(message->target(), channelName)) if (!trimChannelName(message->target(), channelName))
{ {
@ -403,7 +505,8 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message)
if (channel->isEmpty()) if (channel->isEmpty())
{ {
log("[IrcManager:handleNoticeMessage] Channel {} not found in channel " log("[IrcManager:handleNoticeMessage] Channel {} not found in "
"channel "
"manager ", "manager ",
channelName); channelName);
return; return;
@ -411,6 +514,7 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message)
channel->addMessage(msg); channel->addMessage(msg);
} }
}
void IrcMessageHandler::handleWriteConnectionNoticeMessage( void IrcMessageHandler::handleWriteConnectionNoticeMessage(
Communi::IrcNoticeMessage *message) Communi::IrcNoticeMessage *message)

View file

@ -1,10 +1,12 @@
#pragma once #pragma once
#include <IrcMessage> #include <IrcMessage>
#include "messages/Message.hpp"
namespace chatterino { namespace chatterino {
class TwitchServer; class TwitchServer;
class Channel;
class IrcMessageHandler class IrcMessageHandler
{ {
@ -13,6 +15,13 @@ class IrcMessageHandler
public: public:
static IrcMessageHandler &getInstance(); static IrcMessageHandler &getInstance();
// parseMessage parses a single IRC message into 0+ Chatterino messages
std::vector<MessagePtr> parseMessage(Channel *channel,
Communi::IrcMessage *message);
// parsePrivMessage arses a single IRC PRIVMSG into 0-1 Chatterino messages
std::vector<MessagePtr> parsePrivMessage(
Channel *channel, Communi::IrcPrivateMessage *message);
void handlePrivMessage(Communi::IrcPrivateMessage *message, void handlePrivMessage(Communi::IrcPrivateMessage *message,
TwitchServer &server); TwitchServer &server);
@ -20,10 +29,22 @@ public:
void handleClearChatMessage(Communi::IrcMessage *message); void handleClearChatMessage(Communi::IrcMessage *message);
void handleUserStateMessage(Communi::IrcMessage *message); void handleUserStateMessage(Communi::IrcMessage *message);
void handleWhisperMessage(Communi::IrcMessage *message); void handleWhisperMessage(Communi::IrcMessage *message);
// parseUserNoticeMessage parses a single IRC USERNOTICE message into 0+
// chatterino messages
std::vector<MessagePtr> parseUserNoticeMessage(
Channel *channel, Communi::IrcMessage *message);
void handleUserNoticeMessage(Communi::IrcMessage *message, void handleUserNoticeMessage(Communi::IrcMessage *message,
TwitchServer &server); TwitchServer &server);
void handleModeMessage(Communi::IrcMessage *message); void handleModeMessage(Communi::IrcMessage *message);
// parseNoticeMessage parses a single IRC NOTICE message into 0+ chatterino
// messages
std::vector<MessagePtr> parseNoticeMessage(
Communi::IrcNoticeMessage *message);
void handleNoticeMessage(Communi::IrcNoticeMessage *message); void handleNoticeMessage(Communi::IrcNoticeMessage *message);
void handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message); void handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message);
void handleJoinMessage(Communi::IrcMessage *message); void handleJoinMessage(Communi::IrcMessage *message);

View file

@ -9,6 +9,7 @@
#include "messages/Message.hpp" #include "messages/Message.hpp"
#include "providers/bttv/BttvEmotes.hpp" #include "providers/bttv/BttvEmotes.hpp"
#include "providers/bttv/LoadBttvChannelEmote.hpp" #include "providers/bttv/LoadBttvChannelEmote.hpp"
#include "providers/twitch/IrcMessageHandler.hpp"
#include "providers/twitch/PubsubClient.hpp" #include "providers/twitch/PubsubClient.hpp"
#include "providers/twitch/TwitchCommon.hpp" #include "providers/twitch/TwitchCommon.hpp"
#include "providers/twitch/TwitchMessageBuilder.hpp" #include "providers/twitch/TwitchMessageBuilder.hpp"
@ -29,10 +30,12 @@
namespace chatterino { namespace chatterino {
namespace { namespace {
// parseRecentMessages takes a json object and returns a vector of
// Communi IrcMessages
auto parseRecentMessages(const QJsonObject &jsonRoot, ChannelPtr channel) auto parseRecentMessages(const QJsonObject &jsonRoot, ChannelPtr channel)
{ {
QJsonArray jsonMessages = jsonRoot.value("messages").toArray(); QJsonArray jsonMessages = jsonRoot.value("messages").toArray();
std::vector<MessagePtr> messages; std::vector<Communi::IrcMessage *> messages;
if (jsonMessages.empty()) if (jsonMessages.empty())
return messages; return messages;
@ -40,18 +43,8 @@ namespace {
for (const auto jsonMessage : jsonMessages) for (const auto jsonMessage : jsonMessages)
{ {
auto content = jsonMessage.toString().toUtf8(); auto content = jsonMessage.toString().toUtf8();
// passing nullptr as the channel makes the message invalid but we messages.emplace_back(
// don't check for that anyways Communi::IrcMessage::fromData(content, nullptr));
auto message = Communi::IrcMessage::fromData(content, nullptr);
auto privMsg = dynamic_cast<Communi::IrcPrivateMessage *>(message);
assert(privMsg);
MessageParseArgs args;
TwitchMessageBuilder builder(channel.get(), privMsg, args);
builder.message().flags.set(MessageFlag::RecentMessage);
if (!builder.isIgnored())
messages.push_back(builder.build());
} }
return messages; return messages;
@ -611,8 +604,8 @@ Outcome TwitchChannel::parseLiveStatus(const rapidjson::Document &document)
void TwitchChannel::loadRecentMessages() void TwitchChannel::loadRecentMessages()
{ {
static QString genericURL = static QString genericURL = "https://recent-messages.robotty.de/api/v2/"
"https://recent-messages.robotty.de/v1/recent-messages/%1"; "recent-messages/%1?clearchatToNotice=true";
NetworkRequest request(genericURL.arg(this->getName())); NetworkRequest request(genericURL.arg(this->getName()));
request.setCaller(QThread::currentThread()); request.setCaller(QThread::currentThread());
@ -626,7 +619,21 @@ void TwitchChannel::loadRecentMessages()
auto messages = parseRecentMessages(result.parseJson(), shared); auto messages = parseRecentMessages(result.parseJson(), shared);
shared->addMessagesAtStart(messages); auto &handler = IrcMessageHandler::getInstance();
std::vector<MessagePtr> allBuiltMessages;
for (auto message : messages)
{
for (auto builtMessage :
handler.parseMessage(shared.get(), message))
{
builtMessage->flags.set(MessageFlag::RecentMessage);
allBuiltMessages.emplace_back(builtMessage);
}
}
shared->addMessagesAtStart(allBuiltMessages);
return Success; return Success;
}); });

View file

@ -109,12 +109,24 @@ MessagePtr TwitchMessageBuilder::build()
this->appendChannelName(); this->appendChannelName();
if (this->tags.contains("rm-deleted"))
{
this->message().flags.set(MessageFlag::Disabled);
}
// timestamp // timestamp
bool isPastMsg = this->tags.contains("historical"); bool isPastMsg = this->tags.contains("historical");
if (isPastMsg) if (isPastMsg)
{ {
// This may be architecture dependent(datatype) // This may be architecture dependent(datatype)
qint64 ts = this->tags.value("tmi-sent-ts").toLongLong(); bool customReceived = false;
qint64 ts =
this->tags.value("rm-received-ts").toLongLong(&customReceived);
if (!customReceived)
{
ts = this->tags.value("tmi-sent-ts").toLongLong();
}
QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(ts); QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(ts);
this->emplace<TimestampElement>(dateTime.time()); this->emplace<TimestampElement>(dateTime.time());
} }