obs-studio/UI/auth-restream.cpp
jp9000 f53df7da64 clang-format: Apply formatting
Code submissions have continually suffered from formatting
inconsistencies that constantly have to be addressed.  Using
clang-format simplifies this by making code formatting more consistent,
and allows automation of the code formatting so that maintainers can
focus more on the code itself instead of code formatting.
2019-06-23 23:49:10 -07:00

263 lines
6.5 KiB
C++

#include "auth-restream.hpp"
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <qt-wrappers.hpp>
#include <json11.hpp>
#include <ctime>
#include <sstream>
#include <obs-app.hpp>
#include "window-basic-main.hpp"
#include "remote-text.hpp"
#include "ui-config.h"
#include "obf.h"
#include <browser-panel.hpp>
using namespace json11;
extern QCef *cef;
extern QCefCookieManager *panel_cookies;
/* ------------------------------------------------------------------------- */
#define RESTREAM_AUTH_URL \
"https://obsproject.com/app-auth/restream?action=redirect"
#define RESTREAM_TOKEN_URL "https://obsproject.com/app-auth/restream-token"
#define RESTREAM_STREAMKEY_URL "https://api.restream.io/v2/user/streamKey"
#define RESTREAM_SCOPE_VERSION 1
static Auth::Def restreamDef = {"Restream", Auth::Type::OAuth_StreamKey};
/* ------------------------------------------------------------------------- */
RestreamAuth::RestreamAuth(const Def &d) : OAuthStreamKey(d) {}
bool RestreamAuth::GetChannelInfo()
try {
std::string client_id = RESTREAM_CLIENTID;
deobfuscate_str(&client_id[0], RESTREAM_HASH);
if (!GetToken(RESTREAM_TOKEN_URL, client_id, RESTREAM_SCOPE_VERSION))
return false;
if (token.empty())
return false;
if (!key_.empty())
return true;
std::string auth;
auth += "Authorization: Bearer ";
auth += token;
std::vector<std::string> headers;
headers.push_back(std::string("Client-ID: ") + client_id);
headers.push_back(std::move(auth));
std::string output;
std::string error;
Json json;
bool success;
auto func = [&]() {
success = GetRemoteFile(RESTREAM_STREAMKEY_URL, output, error,
nullptr, "application/json", nullptr,
headers, nullptr, 5);
};
ExecThreadedWithoutBlocking(
func, QTStr("Auth.LoadingChannel.Title"),
QTStr("Auth.LoadingChannel.Text").arg(service()));
if (!success || output.empty())
throw ErrorInfo("Failed to get stream key from remote", error);
json = Json::parse(output, error);
if (!error.empty())
throw ErrorInfo("Failed to parse json", error);
error = json["error"].string_value();
if (!error.empty())
throw ErrorInfo(error,
json["error_description"].string_value());
key_ = json["streamKey"].string_value();
return true;
} catch (ErrorInfo info) {
QString title = QTStr("Auth.ChannelFailure.Title");
QString text = QTStr("Auth.ChannelFailure.Text")
.arg(service(), info.message.c_str(),
info.error.c_str());
QMessageBox::warning(OBSBasic::Get(), title, text);
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(),
info.error.c_str());
return false;
}
void RestreamAuth::SaveInternal()
{
OBSBasic *main = OBSBasic::Get();
config_set_string(main->Config(), service(), "DockState",
main->saveState().toBase64().constData());
OAuthStreamKey::SaveInternal();
}
static inline std::string get_config_str(OBSBasic *main, const char *section,
const char *name)
{
const char *val = config_get_string(main->Config(), section, name);
return val ? val : "";
}
bool RestreamAuth::LoadInternal()
{
firstLoad = false;
return OAuthStreamKey::LoadInternal();
}
class RestreamWidget : public QDockWidget {
public:
inline RestreamWidget() : QDockWidget() {}
QScopedPointer<QCefWidget> widget;
};
void RestreamAuth::LoadUI()
{
if (uiLoaded)
return;
if (!GetChannelInfo())
return;
OBSBasic::InitBrowserPanelSafeBlock();
OBSBasic *main = OBSBasic::Get();
QCefWidget *browser;
std::string url;
std::string script;
/* ----------------------------------- */
url = "https://restream.io/chat-application";
QSize size = main->frameSize();
QPoint pos = main->pos();
chat.reset(new RestreamWidget());
chat->setObjectName("restreamChat");
chat->resize(420, 600);
chat->setMinimumSize(200, 300);
chat->setWindowTitle(QTStr("Auth.Chat"));
chat->setAllowedAreas(Qt::AllDockWidgetAreas);
browser = cef->create_widget(nullptr, url, panel_cookies);
chat->setWidget(browser);
main->addDockWidget(Qt::RightDockWidgetArea, chat.data());
chatMenu.reset(main->AddDockWidget(chat.data()));
/* ----------------------------------- */
url = "https://restream.io/titles/embed";
info.reset(new RestreamWidget());
info->setObjectName("restreamInfo");
info->resize(410, 600);
info->setMinimumSize(200, 150);
info->setWindowTitle(QTStr("Auth.StreamInfo"));
info->setAllowedAreas(Qt::AllDockWidgetAreas);
browser = cef->create_widget(nullptr, url, panel_cookies);
info->setWidget(browser);
main->addDockWidget(Qt::RightDockWidgetArea, info.data());
infoMenu.reset(main->AddDockWidget(info.data()));
/* ----------------------------------- */
chat->setFloating(true);
info->setFloating(true);
chat->move(pos.x() + size.width() - chat->width() - 50, pos.y() + 50);
info->move(pos.x() + 40, pos.y() + 50);
if (firstLoad) {
chat->setVisible(true);
info->setVisible(true);
} else {
const char *dockStateStr = config_get_string(
main->Config(), service(), "DockState");
QByteArray dockState =
QByteArray::fromBase64(QByteArray(dockStateStr));
main->restoreState(dockState);
}
uiLoaded = true;
}
bool RestreamAuth::RetryLogin()
{
OAuthLogin login(OBSBasic::Get(), RESTREAM_AUTH_URL, false);
cef->add_popup_whitelist_url("about:blank", &login);
if (login.exec() == QDialog::Rejected) {
return false;
}
std::shared_ptr<RestreamAuth> auth =
std::make_shared<RestreamAuth>(restreamDef);
std::string client_id = RESTREAM_CLIENTID;
deobfuscate_str(&client_id[0], RESTREAM_HASH);
return GetToken(RESTREAM_TOKEN_URL, client_id, RESTREAM_SCOPE_VERSION,
QT_TO_UTF8(login.GetCode()), true);
}
std::shared_ptr<Auth> RestreamAuth::Login(QWidget *parent)
{
OAuthLogin login(parent, RESTREAM_AUTH_URL, false);
cef->add_popup_whitelist_url("about:blank", &login);
if (login.exec() == QDialog::Rejected) {
return nullptr;
}
std::shared_ptr<RestreamAuth> auth =
std::make_shared<RestreamAuth>(restreamDef);
std::string client_id = RESTREAM_CLIENTID;
deobfuscate_str(&client_id[0], RESTREAM_HASH);
if (!auth->GetToken(RESTREAM_TOKEN_URL, client_id,
RESTREAM_SCOPE_VERSION,
QT_TO_UTF8(login.GetCode()))) {
return nullptr;
}
std::string error;
if (auth->GetChannelInfo()) {
return auth;
}
return nullptr;
}
static std::shared_ptr<Auth> CreateRestreamAuth()
{
return std::make_shared<RestreamAuth>(restreamDef);
}
static void DeleteCookies()
{
if (panel_cookies) {
panel_cookies->DeleteCookies("restream.io", std::string());
}
}
void RegisterRestreamAuth()
{
OAuth::RegisterOAuth(restreamDef, CreateRestreamAuth,
RestreamAuth::Login, DeleteCookies);
}