feat: Send messages using Helix API (#5200)

This commit is contained in:
nerix
2024-02-25 14:45:55 +01:00
committed by GitHub
parent 1e2c943ae9
commit 0cfd25ce8e
8 changed files with 306 additions and 20 deletions
+127 -15
View File
@@ -31,9 +31,94 @@ using namespace std::chrono_literals;
namespace {
using namespace chatterino;
const QString BTTV_LIVE_UPDATES_URL = "wss://sockets.betterttv.net/ws";
const QString SEVENTV_EVENTAPI_URL = "wss://events.7tv.io/v3";
void sendHelixMessage(const std::shared_ptr<TwitchChannel> &channel,
const QString &message, const QString &replyParentId = {})
{
getHelix()->sendChatMessage(
{
.broadcasterID = channel->roomId(),
.senderID =
getIApp()->getAccounts()->twitch.getCurrent()->getUserId(),
.message = message,
.replyParentMessageID = replyParentId,
},
[weak = std::weak_ptr(channel)](const auto &res) {
auto chan = weak.lock();
if (!chan)
{
return;
}
if (res.isSent)
{
return;
}
auto errorMessage = [&] {
if (res.dropReason)
{
return makeSystemMessage(res.dropReason->message);
}
return makeSystemMessage("Your message was not sent.");
}();
chan->addMessage(errorMessage);
},
[weak = std::weak_ptr(channel)](auto error, const auto &message) {
auto chan = weak.lock();
if (!chan)
{
return;
}
using Error = decltype(error);
auto errorMessage = [&]() -> QString {
switch (error)
{
case Error::MissingText:
return "You can't send an empty message.";
case Error::BadRequest:
return "Failed to send message: " + message;
case Error::Forbidden:
return "You are not allowed to send messages in this "
"channel.";
case Error::MessageTooLarge:
return "Your message was too long.";
case Error::UserMissingScope:
return "Missing required scope. Re-login with your "
"account and try again.";
case Error::Forwarded:
return message;
case Error::Unknown:
default:
return "Unknown error: " + message;
}
}();
chan->addMessage(makeSystemMessage(errorMessage));
});
}
/// Returns true if chat messages should be sent over Helix
bool shouldSendHelixChat()
{
switch (getSettings()->chatSendProtocol)
{
case ChatSendProtocol::Helix:
return true;
case ChatSendProtocol::Default:
case ChatSendProtocol::IRC:
return false;
default:
assert(false && "Invalid chat protocol value");
return false;
}
}
} // namespace
namespace chatterino {
@@ -139,13 +224,24 @@ std::shared_ptr<Channel> TwitchIrcServer::createChannel(
// no Channel's should live
// NOTE: CHANNEL_LIFETIME
std::ignore = channel->sendMessageSignal.connect(
[this, channel = channel.get()](auto &chan, auto &msg, bool &sent) {
this->onMessageSendRequested(channel, msg, sent);
[this, channel = std::weak_ptr(channel)](auto &chan, auto &msg,
bool &sent) {
auto c = channel.lock();
if (!c)
{
return;
}
this->onMessageSendRequested(c, msg, sent);
});
std::ignore = channel->sendReplySignal.connect(
[this, channel = channel.get()](auto &chan, auto &msg, auto &replyId,
bool &sent) {
this->onReplySendRequested(channel, msg, replyId, sent);
[this, channel = std::weak_ptr(channel)](auto &chan, auto &msg,
auto &replyId, bool &sent) {
auto c = channel.lock();
if (!c)
{
return;
}
this->onReplySendRequested(c, msg, replyId, sent);
});
return channel;
@@ -436,7 +532,8 @@ bool TwitchIrcServer::hasSeparateWriteConnection() const
// return getSettings()->twitchSeperateWriteConnection;
}
bool TwitchIrcServer::prepareToSend(TwitchChannel *channel)
bool TwitchIrcServer::prepareToSend(
const std::shared_ptr<TwitchChannel> &channel)
{
std::lock_guard<std::mutex> guard(this->lastMessageMutex_);
@@ -487,8 +584,9 @@ bool TwitchIrcServer::prepareToSend(TwitchChannel *channel)
return true;
}
void TwitchIrcServer::onMessageSendRequested(TwitchChannel *channel,
const QString &message, bool &sent)
void TwitchIrcServer::onMessageSendRequested(
const std::shared_ptr<TwitchChannel> &channel, const QString &message,
bool &sent)
{
sent = false;
@@ -498,13 +596,21 @@ void TwitchIrcServer::onMessageSendRequested(TwitchChannel *channel,
return;
}
this->sendMessage(channel->getName(), message);
if (shouldSendHelixChat())
{
sendHelixMessage(channel, message);
}
else
{
this->sendMessage(channel->getName(), message);
}
sent = true;
}
void TwitchIrcServer::onReplySendRequested(TwitchChannel *channel,
const QString &message,
const QString &replyId, bool &sent)
void TwitchIrcServer::onReplySendRequested(
const std::shared_ptr<TwitchChannel> &channel, const QString &message,
const QString &replyId, bool &sent)
{
sent = false;
@@ -514,9 +620,15 @@ void TwitchIrcServer::onReplySendRequested(TwitchChannel *channel,
return;
}
this->sendRawMessage("@reply-parent-msg-id=" + replyId + " PRIVMSG #" +
channel->getName() + " :" + message);
if (shouldSendHelixChat())
{
sendHelixMessage(channel, message, replyId);
}
else
{
this->sendRawMessage("@reply-parent-msg-id=" + replyId + " PRIVMSG #" +
channel->getName() + " :" + message);
}
sent = true;
}