UI: Add ability to send messages to YouTube chat
parent
49dfc113c1
commit
3513c78be2
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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."
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue