2018-02-05 15:11:50 +01:00
|
|
|
#include "twitchserver.hpp"
|
|
|
|
|
2018-04-27 22:11:19 +02:00
|
|
|
#include "application.hpp"
|
2018-02-05 15:11:50 +01:00
|
|
|
#include "providers/twitch/ircmessagehandler.hpp"
|
|
|
|
#include "providers/twitch/twitchaccount.hpp"
|
2018-03-25 11:37:57 +02:00
|
|
|
#include "providers/twitch/twitchhelpers.hpp"
|
2018-02-05 15:11:50 +01:00
|
|
|
#include "providers/twitch/twitchmessagebuilder.hpp"
|
|
|
|
#include "singletons/accountmanager.hpp"
|
|
|
|
#include "util/posttothread.hpp"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
using namespace Communi;
|
|
|
|
using namespace chatterino::singletons;
|
|
|
|
|
|
|
|
namespace chatterino {
|
|
|
|
namespace providers {
|
|
|
|
namespace twitch {
|
2018-03-25 11:37:57 +02:00
|
|
|
|
2018-02-05 15:11:50 +01:00
|
|
|
TwitchServer::TwitchServer()
|
2018-04-18 09:12:29 +02:00
|
|
|
: whispersChannel(new Channel("/whispers", Channel::TwitchWhispers))
|
|
|
|
, mentionsChannel(new Channel("/mentions", Channel::TwitchMentions))
|
2018-04-20 19:54:45 +02:00
|
|
|
, watchingChannel(Channel::getEmpty(), Channel::TwitchWatching)
|
2018-02-05 15:11:50 +01:00
|
|
|
{
|
2018-04-26 18:10:26 +02:00
|
|
|
qDebug() << "init TwitchServer";
|
2018-02-05 15:11:50 +01:00
|
|
|
}
|
|
|
|
|
2018-04-28 15:20:18 +02:00
|
|
|
void TwitchServer::initialize()
|
2018-02-05 15:11:50 +01:00
|
|
|
{
|
2018-04-28 15:20:18 +02:00
|
|
|
getApp()->accounts->Twitch.userChanged.connect(
|
|
|
|
[this]() { util::postToThread([this] { this->connect(); }); });
|
2018-02-05 15:11:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead, bool isWrite)
|
|
|
|
{
|
2018-04-27 22:11:19 +02:00
|
|
|
std::shared_ptr<TwitchAccount> account = getApp()->accounts->Twitch.getCurrent();
|
2018-02-05 15:11:50 +01:00
|
|
|
|
2018-04-26 18:10:26 +02:00
|
|
|
qDebug() << "logging in as" << account->getUserName();
|
|
|
|
|
2018-02-05 15:11:50 +01:00
|
|
|
QString username = account->getUserName();
|
|
|
|
// QString oauthClient = account->getOAuthClient();
|
|
|
|
QString oauthToken = account->getOAuthToken();
|
|
|
|
|
|
|
|
if (!oauthToken.startsWith("oauth:")) {
|
|
|
|
oauthToken.prepend("oauth:");
|
|
|
|
}
|
|
|
|
|
|
|
|
connection->setUserName(username);
|
|
|
|
connection->setNickName(username);
|
|
|
|
connection->setRealName(username);
|
|
|
|
|
|
|
|
if (!account->isAnon()) {
|
|
|
|
connection->setPassword(oauthToken);
|
|
|
|
|
|
|
|
// fourtf: ignored users
|
|
|
|
// this->refreshIgnoredUsers(username, oauthClient, oauthToken);
|
|
|
|
}
|
|
|
|
|
|
|
|
connection->sendCommand(IrcCommand::createCapability("REQ", "twitch.tv/membership"));
|
|
|
|
connection->sendCommand(IrcCommand::createCapability("REQ", "twitch.tv/commands"));
|
|
|
|
connection->sendCommand(IrcCommand::createCapability("REQ", "twitch.tv/tags"));
|
|
|
|
|
|
|
|
connection->setHost("irc.chat.twitch.tv");
|
|
|
|
connection->setPort(6667);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<Channel> TwitchServer::createChannel(const QString &channelName)
|
|
|
|
{
|
|
|
|
TwitchChannel *channel = new TwitchChannel(channelName, this->getReadConnection());
|
|
|
|
|
|
|
|
channel->sendMessageSignal.connect(
|
|
|
|
[this](auto chan, auto msg) { this->sendMessage(chan, msg); });
|
|
|
|
|
|
|
|
return std::shared_ptr<Channel>(channel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TwitchServer::privateMessageReceived(IrcPrivateMessage *message)
|
|
|
|
{
|
2018-03-25 11:37:57 +02:00
|
|
|
QString channelName;
|
|
|
|
if (!TrimChannelName(message->target(), channelName)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-05 15:11:50 +01:00
|
|
|
this->onPrivateMessage.invoke(message);
|
2018-04-28 15:20:18 +02:00
|
|
|
auto chan = this->getChannelOrEmpty(channelName);
|
2018-02-05 15:11:50 +01:00
|
|
|
|
2018-04-21 00:40:17 +02:00
|
|
|
if (chan->isEmpty()) {
|
2018-02-05 15:11:50 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
messages::MessageParseArgs args;
|
|
|
|
|
|
|
|
TwitchMessageBuilder builder(chan.get(), message, args);
|
|
|
|
|
|
|
|
if (!builder.isIgnored()) {
|
|
|
|
messages::MessagePtr _message = builder.build();
|
|
|
|
if (_message->flags & messages::Message::Highlighted) {
|
2018-04-28 15:20:18 +02:00
|
|
|
this->mentionsChannel->addMessage(_message);
|
2018-02-05 15:11:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
chan->addMessage(_message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TwitchServer::messageReceived(IrcMessage *message)
|
|
|
|
{
|
|
|
|
// this->readConnection
|
|
|
|
if (message->type() == IrcMessage::Type::Private) {
|
|
|
|
// We already have a handler for private messages
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QString &command = message->command();
|
|
|
|
|
|
|
|
if (command == "ROOMSTATE") {
|
|
|
|
IrcMessageHandler::getInstance().handleRoomStateMessage(message);
|
|
|
|
} else if (command == "CLEARCHAT") {
|
|
|
|
IrcMessageHandler::getInstance().handleClearChatMessage(message);
|
|
|
|
} else if (command == "USERSTATE") {
|
|
|
|
IrcMessageHandler::getInstance().handleUserStateMessage(message);
|
|
|
|
} else if (command == "WHISPER") {
|
|
|
|
IrcMessageHandler::getInstance().handleWhisperMessage(message);
|
|
|
|
} else if (command == "USERNOTICE") {
|
|
|
|
IrcMessageHandler::getInstance().handleUserNoticeMessage(message);
|
|
|
|
} else if (command == "MODE") {
|
|
|
|
IrcMessageHandler::getInstance().handleModeMessage(message);
|
|
|
|
} else if (command == "NOTICE") {
|
|
|
|
IrcMessageHandler::getInstance().handleNoticeMessage(
|
|
|
|
static_cast<IrcNoticeMessage *>(message));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TwitchServer::writeConnectionMessageReceived(IrcMessage *message)
|
|
|
|
{
|
|
|
|
switch (message->type()) {
|
|
|
|
case IrcMessage::Type::Notice: {
|
|
|
|
IrcMessageHandler::getInstance().handleWriteConnectionNoticeMessage(
|
|
|
|
static_cast<IrcNoticeMessage *>(message));
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<Channel> TwitchServer::getCustomChannel(const QString &channelName)
|
|
|
|
{
|
|
|
|
if (channelName == "/whispers") {
|
|
|
|
return whispersChannel;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (channelName == "/mentions") {
|
|
|
|
return mentionsChannel;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
2018-02-05 21:20:38 +01:00
|
|
|
|
|
|
|
void TwitchServer::forEachChannelAndSpecialChannels(std::function<void(ChannelPtr)> func)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lock(this->channelMutex);
|
|
|
|
|
|
|
|
for (std::weak_ptr<Channel> &weak : this->channels) {
|
|
|
|
std::shared_ptr<Channel> chan = weak.lock();
|
|
|
|
if (!chan) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
func(chan);
|
|
|
|
}
|
|
|
|
|
|
|
|
func(this->whispersChannel);
|
|
|
|
func(this->mentionsChannel);
|
|
|
|
}
|
2018-03-25 11:37:57 +02:00
|
|
|
|
2018-04-22 15:36:01 +02:00
|
|
|
std::shared_ptr<Channel> TwitchServer::getChannelOrEmptyByID(const QString &channelID)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> lock(this->channelMutex);
|
|
|
|
|
|
|
|
for (const auto &weakChannel : this->channels) {
|
|
|
|
auto channel = weakChannel.lock();
|
|
|
|
if (!channel) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto twitchChannel = std::dynamic_pointer_cast<TwitchChannel>(channel);
|
|
|
|
if (!twitchChannel) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (twitchChannel->roomID == channelID) {
|
|
|
|
return twitchChannel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Channel::getEmpty();
|
|
|
|
}
|
|
|
|
|
2018-04-21 00:40:17 +02:00
|
|
|
QString TwitchServer::cleanChannelName(const QString &dirtyChannelName)
|
2018-04-01 15:10:15 +02:00
|
|
|
{
|
|
|
|
return dirtyChannelName.toLower();
|
|
|
|
}
|
|
|
|
|
2018-02-05 15:11:50 +01:00
|
|
|
} // namespace twitch
|
|
|
|
} // namespace providers
|
|
|
|
} // namespace chatterino
|