UI: Add ability to send messages to YouTube chat

master
gxalpha 2022-05-08 16:50:36 +02:00 committed by Ryan Foster
parent 49dfc113c1
commit 3513c78be2
4 changed files with 125 additions and 10 deletions

View File

@ -141,7 +141,7 @@ void YoutubeAuth::LoadUI()
QSize size = main->frameSize(); QSize size = main->frameSize();
QPoint pos = main->pos(); QPoint pos = main->pos();
chat.reset(new BrowserDock()); chat.reset(new YoutubeChatDock());
chat->setObjectName("ytChat"); chat->setObjectName("ytChat");
chat->resize(300, 600); chat->resize(300, 600);
chat->setMinimumSize(200, 300); chat->setMinimumSize(200, 300);
@ -173,16 +173,18 @@ void YoutubeAuth::LoadUI()
uiLoaded = true; uiLoaded = true;
} }
void YoutubeAuth::SetChatId(QString &chat_id) void YoutubeAuth::SetChatId(const QString &chat_id,
const std::string &api_chat_id)
{ {
#ifdef BROWSER_AVAILABLE #ifdef BROWSER_AVAILABLE
QString chat_url = QString(YOUTUBE_CHAT_POPOUT_URL).arg(chat_id); QString chat_url = QString(YOUTUBE_CHAT_POPOUT_URL).arg(chat_id);
if (chat && chat->cefWidget) { if (chat && chat->cefWidget) {
chat->cefWidget->setURL(chat_url.toStdString()); chat->cefWidget->setURL(chat_url.toStdString());
chat->SetApiChatId(api_chat_id);
} }
#else #else
UNUSED_PARAMETER(chat_id); UNUSED_PARAMETER(chat_id, api_chat_id);
#endif #endif
} }
@ -322,3 +324,83 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner,
config_save_safe(config, "tmp", nullptr); config_save_safe(config, "tmp", nullptr);
return auth; return auth;
} }
#ifdef BROWSER_AVAILABLE
void YoutubeChatDock::SetWidget(QCefWidget *widget_)
{
lineEdit = new LineEditAutoResize();
lineEdit->setVisible(false);
lineEdit->setMaxLength(200);
lineEdit->setPlaceholderText(QTStr("YouTube.Chat.Input.Placeholder"));
sendButton = new QPushButton(QTStr("YouTube.Chat.Input.Send"));
sendButton->setVisible(false);
chatLayout = new QHBoxLayout();
chatLayout->setMargin(0);
chatLayout->addWidget(lineEdit, 1);
chatLayout->addWidget(sendButton);
QVBoxLayout *layout = new QVBoxLayout();
layout->setMargin(0);
layout->addWidget(widget_, 1);
layout->addLayout(chatLayout);
QWidget *widget = new QWidget();
widget->setLayout(layout);
setWidget(widget);
QWidget::connect(lineEdit, SIGNAL(returnPressed()), this,
SLOT(SendChatMessage()));
QWidget::connect(sendButton, SIGNAL(pressed()), this,
SLOT(SendChatMessage()));
cefWidget.reset(widget_);
}
void YoutubeChatDock::SetApiChatId(const std::string &id)
{
this->apiChatId = id;
QMetaObject::invokeMethod(this, "EnableChatInput",
Qt::QueuedConnection);
}
void YoutubeChatDock::SendChatMessage()
{
const QString message = lineEdit->text();
if (message == "")
return;
OBSBasic *main = OBSBasic::Get();
YoutubeApiWrappers *apiYouTube(
dynamic_cast<YoutubeApiWrappers *>(main->GetAuth()));
ExecuteFuncSafeBlock([&]() {
lineEdit->setText("");
lineEdit->setPlaceholderText(
QTStr("YouTube.Chat.Input.Sending"));
if (apiYouTube->SendChatMessage(apiChatId, message)) {
os_sleep_ms(3000);
} else {
QString error = apiYouTube->GetLastError();
apiYouTube->GetTranslatedError(error);
QMetaObject::invokeMethod(
this, "ShowErrorMessage", Qt::QueuedConnection,
Q_ARG(const QString &, error));
}
lineEdit->setPlaceholderText(
QTStr("YouTube.Chat.Input.Placeholder"));
});
}
void YoutubeChatDock::ShowErrorMessage(const QString &error)
{
QMessageBox::warning(this, QTStr("YouTube.Chat.Error.Title"),
QTStr("YouTube.Chat.Error.Text").arg(error));
}
void YoutubeChatDock::EnableChatInput()
{
lineEdit->setVisible(true);
sendButton->setVisible(true);
}
#endif

View File

@ -8,7 +8,27 @@
#include "auth-oauth.hpp" #include "auth-oauth.hpp"
#ifdef BROWSER_AVAILABLE #ifdef BROWSER_AVAILABLE
class BrowserDock; #include "window-dock-browser.hpp"
#include "lineedit-autoresize.hpp"
#include <QHBoxLayout>
class YoutubeChatDock : public BrowserDock {
Q_OBJECT
private:
std::string apiChatId;
LineEditAutoResize *lineEdit;
QPushButton *sendButton;
QHBoxLayout *chatLayout;
public:
void SetWidget(QCefWidget *widget_);
void SetApiChatId(const std::string &id);
private slots:
void SendChatMessage();
void ShowErrorMessage(const QString &error);
void EnableChatInput();
};
#endif #endif
inline const std::vector<Auth::Def> youtubeServices = { inline const std::vector<Auth::Def> youtubeServices = {
@ -24,7 +44,7 @@ class YoutubeAuth : public OAuthStreamKey {
std::string section; std::string section;
#ifdef BROWSER_AVAILABLE #ifdef BROWSER_AVAILABLE
QSharedPointer<BrowserDock> chat; QSharedPointer<YoutubeChatDock> chat;
QSharedPointer<QAction> chatMenu; QSharedPointer<QAction> chatMenu;
#endif #endif
@ -38,7 +58,7 @@ class YoutubeAuth : public OAuthStreamKey {
public: public:
YoutubeAuth(const Def &d); YoutubeAuth(const Def &d);
void SetChatId(QString &chat_id); void SetChatId(const QString &chat_id, const std::string &api_chat_id);
void ResetChat(); void ResetChat();
static std::shared_ptr<Auth> Login(QWidget *parent, static std::shared_ptr<Auth> Login(QWidget *parent,

View File

@ -1320,6 +1320,12 @@ YouTube.Actions.AutoStartStreamingWarning.Title="Manual start required"
YouTube.Actions.AutoStartStreamingWarning="Auto-start is disabled for this event, click \"Go Live\" to start your broadcast." YouTube.Actions.AutoStartStreamingWarning="Auto-start is disabled for this event, click \"Go Live\" to start your broadcast."
YouTube.Actions.AutoStopStreamingWarning="You will not be able to reconnect.<br>Your stream will stop and you will no longer be live." YouTube.Actions.AutoStopStreamingWarning="You will not be able to reconnect.<br>Your stream will stop and you will no longer be live."
YouTube.Chat.Input.Send="Send"
YouTube.Chat.Input.Placeholder="Enter message here..."
YouTube.Chat.Input.Sending="Sending..."
YouTube.Chat.Error.Title="Error while sending message"
YouTube.Chat.Error.Text="The message couldn't be sent: %1"
# YouTube API errors in format "YouTube.Errors.<error reason>" # YouTube API errors in format "YouTube.Errors.<error reason>"
YouTube.Errors.liveStreamingNotEnabled="Live streaming is not enabled on the selected YouTube channel.<br/><br/>See <a href='https://www.youtube.com/features'>youtube.com/features</a> for more information." YouTube.Errors.liveStreamingNotEnabled="Live streaming is not enabled on the selected YouTube channel.<br/><br/>See <a href='https://www.youtube.com/features'>youtube.com/features</a> for more information."
YouTube.Errors.livePermissionBlocked="Live streaming is unavailable on the selected YouTube Channel.<br/>Please note that it may take up to 24 hours for live streaming to become available after enabling it in your channel settings.<br/><br/>See <a href='https://www.youtube.com/features'>youtube.com/features</a> for details." YouTube.Errors.livePermissionBlocked="Live streaming is unavailable on the selected YouTube Channel.<br/>Please note that it may take up to 24 hours for live streaming to become available after enabling it in your channel settings.<br/><br/>See <a href='https://www.youtube.com/features'>youtube.com/features</a> for details."

View File

@ -503,10 +503,13 @@ bool OBSYoutubeActions::CreateEventAction(YoutubeApiWrappers *api,
return false; return false;
} }
if (broadcast.privacy != "private") if (broadcast.privacy != "private") {
apiYouTube->SetChatId(broadcast.id); const std::string apiLiveChatId =
else json["snippet"]["liveChatId"].string_value();
apiYouTube->SetChatId(broadcast.id, apiLiveChatId);
} else {
apiYouTube->ResetChat(); apiYouTube->ResetChat();
}
} }
return true; return true;
@ -531,6 +534,10 @@ bool OBSYoutubeActions::ChooseAnEventAction(YoutubeApiWrappers *api,
json["items"] json["items"]
.array_items()[0]["status"]["privacyStatus"] .array_items()[0]["status"]["privacyStatus"]
.string_value(); .string_value();
std::string apiLiveChatId =
json["items"]
.array_items()[0]["snippet"]["liveChatId"]
.string_value();
stream.id = boundStreamId.c_str(); stream.id = boundStreamId.c_str();
if (!stream.id.isEmpty() && apiYouTube->FindStream(stream.id, json)) { if (!stream.id.isEmpty() && apiYouTube->FindStream(stream.id, json)) {
@ -556,7 +563,7 @@ bool OBSYoutubeActions::ChooseAnEventAction(YoutubeApiWrappers *api,
} }
if (broadcastPrivacy != "private") if (broadcastPrivacy != "private")
apiYouTube->SetChatId(selectedBroadcast); apiYouTube->SetChatId(selectedBroadcast, apiLiveChatId);
else else
apiYouTube->ResetChat(); apiYouTube->ResetChat();