Add option to set Twitch stream tags

This commit is contained in:
WarmUpTill 2025-08-11 19:11:08 +02:00 committed by WarmUpTill
parent ea4a951554
commit 058e941a46
14 changed files with 384 additions and 50 deletions

View File

@ -1201,6 +1201,7 @@ AdvSceneSwitcher.action.sceneLock.entry="On{{scenes}}{{actions}}{{sources}}"
AdvSceneSwitcher.action.twitch="Twitch"
AdvSceneSwitcher.action.twitch.type.channel.info.title.set="Set stream title"
AdvSceneSwitcher.action.twitch.type.channel.info.category.set="Set stream category"
AdvSceneSwitcher.action.twitch.type.channel.info.tags.set="Set stream tags"
AdvSceneSwitcher.action.twitch.type.raid.start="Start raid"
AdvSceneSwitcher.action.twitch.type.commercial.start="Start commercial"
AdvSceneSwitcher.action.twitch.type.marker.create="Create stream marker"
@ -1228,6 +1229,14 @@ AdvSceneSwitcher.action.twitch.announcement.orange="Orange"
AdvSceneSwitcher.action.twitch.announcement.purple="Purple"
AdvSceneSwitcher.action.twitch.user.getInfo.queryType.id="User Id"
AdvSceneSwitcher.action.twitch.user.getInfo.queryType.login="User login"
AdvSceneSwitcher.action.twitch.tags.add="Add Channel Tag"
AdvSceneSwitcher.action.twitch.tags.getCurrent="Get current channel tags"
AdvSceneSwitcher.action.twitch.tags.invalid="Invalid Tag"
AdvSceneSwitcher.action.twitch.tags.invalid.info="Tags must be 1%1 characters long, contain only letters or numbers, and have no spaces or special characters."
AdvSceneSwitcher.action.twitch.tags.duplicate="Duplicate Tag"
AdvSceneSwitcher.action.twitch.tags.duplicate.info="This tag is already in the list."
AdvSceneSwitcher.action.twitch.tags.limit="Tag Limit Reached"
AdvSceneSwitcher.action.twitch.tags.limit.info="You can only have up to %1 tags."
AdvSceneSwitcher.action.clipboard="Clipboard"
AdvSceneSwitcher.action.clipboard.type.copy.text="Copy text"
AdvSceneSwitcher.action.clipboard.type.copy.image="Copy image"

View File

@ -12,6 +12,7 @@ class ADVSS_EXPORT ListEditor : public QWidget {
public:
ListEditor(QWidget *parent = nullptr, bool reorder = true);
int count() const { return _list->count(); };
protected:
void showEvent(QShowEvent *);

View File

@ -46,14 +46,17 @@ void StringList::ResolveVariables()
}
}
StringListEdit::StringListEdit(QWidget *parent, const QString &addString,
const QString &addStringDescription,
int maxStringSize, bool allowEmtpy)
StringListEdit::StringListEdit(
QWidget *parent, const QString &addString,
const QString &addStringDescription, int maxStringSize,
const std::function<bool(const std::string &)> &filter,
const std::function<void(std::string &input)> &preprocess)
: ListEditor(parent),
_addString(addString),
_addStringDescription(addStringDescription),
_maxStringSize(maxStringSize),
_allowEmpty(allowEmtpy)
_filterCallback(filter),
_preprocessCallback(preprocess)
{
}
@ -77,15 +80,19 @@ void StringListEdit::SetMaxStringSize(int size)
void StringListEdit::Add()
{
std::string name;
std::string entry;
bool accepted = NameDialog::AskForName(this, _addString,
_addStringDescription, name, "",
_addStringDescription, entry, "",
_maxStringSize, false);
if (!accepted || (!_allowEmpty && name.empty())) {
if (!accepted) {
return;
}
StringVariable string = name;
_preprocessCallback(entry);
if (_filterCallback(entry)) {
return;
}
StringVariable string = entry;
QVariant v = QVariant::fromValue(string);
QListWidgetItem *item = new QListWidgetItem(
QString::fromStdString(string.UnresolvedValue()), _list);
@ -145,17 +152,21 @@ void StringListEdit::Down()
void StringListEdit::Clicked(QListWidgetItem *item)
{
std::string name;
std::string entry;
bool accepted = NameDialog::AskForName(this, _addString,
_addStringDescription, name,
_addStringDescription, entry,
item->text(), _maxStringSize,
false);
if (!accepted || (!_allowEmpty && name.empty())) {
if (!accepted) {
return;
}
StringVariable string = name;
_preprocessCallback(entry);
if (_filterCallback(entry)) {
return;
}
StringVariable string = entry;
QVariant v = QVariant::fromValue(string);
item->setText(QString::fromStdString(string.UnresolvedValue()));
item->setData(Qt::UserRole, string);

View File

@ -19,14 +19,20 @@ public:
friend class StringListEdit;
};
class ADVSS_EXPORT StringListEdit final : public ListEditor {
class ADVSS_EXPORT StringListEdit : public ListEditor {
Q_OBJECT
public:
StringListEdit(QWidget *parent, const QString &addString = "",
const QString &addStringDescription = "",
int maxStringSize = 170, bool allowEmtpy = false);
StringListEdit(
QWidget *parent, const QString &addString = "",
const QString &addStringDescription = "",
int maxStringSize = 170,
const std::function<bool(const std::string &)> &filter =
[](const std::string &) { return false; },
const std::function<void(std::string &input)> &preprocess =
[](std::string &) {});
void SetStringList(const StringList &);
StringList GetStringList() const { return _stringList; }
void SetMaxStringSize(int);
private slots:
@ -44,7 +50,8 @@ private:
QString _addString;
QString _addStringDescription;
int _maxStringSize = 170;
bool _allowEmpty = false;
std::function<bool(const std::string &)> _filterCallback;
std::function<void(std::string &)> _preprocessCallback;
};
} // namespace advss

View File

@ -169,7 +169,8 @@ MacroActionHttpEdit::MacroActionHttpEdit(
_headerListLayout(new QVBoxLayout()),
_headerList(new StringListEdit(
this, obs_module_text("AdvSceneSwitcher.action.http.headers"),
obs_module_text("AdvSceneSwitcher.action.http.addHeader"))),
obs_module_text("AdvSceneSwitcher.action.http.addHeader"),
170, [](const std::string &input) { return input.empty(); })),
_timeout(new DurationSelection(this, false))
{
populateMethodSelection(_methods);

View File

@ -132,7 +132,7 @@ ProcessConfigEdit::ProcessConfigEdit(QWidget *parent)
this, obs_module_text("AdvSceneSwitcher.process.addArgument"),
obs_module_text(
"AdvSceneSwitcher.process.addArgumentDescription"),
4096, true)),
4096)),
_workingDirectory(new FileSelection(FileSelection::Type::FOLDER))
{
_advancedSettingsLayout->setContentsMargins(0, 0, 0, 0);

View File

@ -94,6 +94,8 @@ target_sources(
macro-condition-twitch.hpp
points-reward-selection.cpp
points-reward-selection.hpp
tag-selection.cpp
tag-selection.hpp
token.cpp
token.hpp
twitch-helpers.cpp

View File

@ -48,6 +48,7 @@ struct ChannelInfo {
struct TwitchChannel {
void Load(obs_data_t *obj);
void Save(obs_data_t *obj) const;
void SetName(const StringVariable &name) { _name = name; }
StringVariable GetName() const { return _name; }
std::string GetUserID(const TwitchToken &token) const;
bool IsValid(const std::string &id) const;

View File

@ -17,6 +17,7 @@ bool MacroActionTwitch::_registered = MacroActionFactory::Register(
void MacroActionTwitch::ResolveVariablesToFixedValues()
{
_streamTitle.ResolveVariables();
_tags.ResolveVariables();
_markerDescription.ResolveVariables();
_duration.ResolveVariables();
_announcementMessage.ResolveVariables();
@ -56,6 +57,8 @@ const static std::map<MacroActionTwitch::Action, std::string> actionTypes = {
"AdvSceneSwitcher.action.twitch.type.channel.info.title.set"},
{MacroActionTwitch::Action::CHANNEL_INFO_CATEGORY_SET,
"AdvSceneSwitcher.action.twitch.type.channel.info.category.set"},
{MacroActionTwitch::Action::CHANNEL_INFO_TAGS_SET,
"AdvSceneSwitcher.action.twitch.type.channel.info.tags.set"},
{MacroActionTwitch::Action::RAID_START,
"AdvSceneSwitcher.action.twitch.type.raid.start"},
{MacroActionTwitch::Action::COMMERCIAL_START,
@ -517,6 +520,9 @@ bool MacroActionTwitch::PerformAction()
case Action::CHANNEL_INFO_CATEGORY_SET:
SetStreamCategory(token);
break;
case Action::CHANNEL_INFO_TAGS_SET:
_tags.SetStreamTags(*token);
break;
case Action::RAID_START:
StartRaid(token);
break;
@ -576,6 +582,7 @@ bool MacroActionTwitch::Save(obs_data_t *obj) const
GetWeakTwitchTokenName(_token).c_str());
_streamTitle.Save(obj, "streamTitle");
_category.Save(obj);
_tags.Save(obj);
_markerDescription.Save(obj, "markerDescription");
obs_data_set_bool(obj, "clipHasDelay", _clipHasDelay);
_duration.Save(obj);
@ -604,6 +611,7 @@ bool MacroActionTwitch::Load(obs_data_t *obj)
_token = GetWeakTwitchTokenByName(obs_data_get_string(obj, "token"));
_streamTitle.Load(obj, "streamTitle");
_category.Load(obj);
_tags.Load(obj);
_markerDescription.Load(obj, "markerDescription");
_clipHasDelay = obs_data_get_bool(obj, "clipHasDelay");
_duration.Load(obj);
@ -642,6 +650,8 @@ bool MacroActionTwitch::ActionIsSupportedByToken()
{{"channel:manage:broadcast"}}},
{Action::CHANNEL_INFO_CATEGORY_SET,
{{"channel:manage:broadcast"}}},
{Action::CHANNEL_INFO_TAGS_SET,
{{"channel:manage:broadcast"}}},
{Action::CHANNEL_INFO_LANGUAGE_SET,
{{"channel:manage:broadcast"}}},
{Action::CHANNEL_INFO_DELAY_SET,
@ -815,6 +825,7 @@ MacroActionTwitchEdit::MacroActionTwitchEdit(
_tokenWarning(new QLabel()),
_streamTitle(new VariableLineEdit(this)),
_category(new TwitchCategoryWidget(this)),
_tags(new TagListWidget(this)),
_markerDescription(new VariableLineEdit(this)),
_clipHasDelay(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.action.twitch.clip.hasDelay"))),
@ -840,6 +851,7 @@ MacroActionTwitchEdit::MacroActionTwitchEdit(
mainLayout->addLayout(_layout);
mainLayout->addWidget(_announcementMessage);
mainLayout->addWidget(_chatMessage);
mainLayout->addWidget(_tags);
mainLayout->addWidget(_tokenWarning);
setLayout(mainLayout);
@ -876,6 +888,7 @@ void MacroActionTwitchEdit::TwitchTokenChanged(const QString &token)
_category->SetToken(_entryData->_token);
_channel->SetToken(_entryData->_token);
_pointsReward->SetToken(_entryData->_token);
_tags->SetToken(_entryData->_token);
_entryData->ResetChatConnection();
SetWidgetVisibility();
@ -930,6 +943,12 @@ void MacroActionTwitchEdit::CategoryChanged(const TwitchCategory &category)
_entryData->_category = category;
}
void MacroActionTwitchEdit::TagsChanged(const TwitchTagList &tags)
{
GUARD_LOADING_AND_LOCK();
_entryData->_tags = tags;
}
void MacroActionTwitchEdit::MarkerDescriptionChanged()
{
GUARD_LOADING_AND_LOCK();
@ -1010,6 +1029,8 @@ void MacroActionTwitchEdit::SetWidgetSignalConnections()
QWidget::connect(_category,
SIGNAL(CategoryChanged(const TwitchCategory &)), this,
SLOT(CategoryChanged(const TwitchCategory &)));
QWidget::connect(_tags, SIGNAL(TagListChanged(const TwitchTagList &)),
this, SLOT(TagsChanged(const TwitchTagList &)));
QWidget::connect(_markerDescription, SIGNAL(editingFinished()), this,
SLOT(MarkerDescriptionChanged()));
QObject::connect(_clipHasDelay, SIGNAL(stateChanged(int)), this,
@ -1052,6 +1073,8 @@ void MacroActionTwitchEdit::SetWidgetVisibility()
_category->setVisible(
_entryData->GetAction() ==
MacroActionTwitch::Action::CHANNEL_INFO_CATEGORY_SET);
_tags->setVisible(_entryData->GetAction() ==
MacroActionTwitch::Action::CHANNEL_INFO_TAGS_SET);
_channel->setVisible(
_entryData->GetAction() ==
MacroActionTwitch::Action::RAID_START ||
@ -1247,6 +1270,8 @@ void MacroActionTwitchEdit::UpdateEntryData()
_streamTitle->setText(_entryData->_streamTitle);
_category->SetToken(_entryData->_token);
_category->SetCategory(_entryData->_category);
_tags->SetTags(_entryData->_tags);
_tags->SetToken(_entryData->_token);
_markerDescription->setText(_entryData->_markerDescription);
_clipHasDelay->setChecked(_entryData->_clipHasDelay);
_duration->SetDuration(_entryData->_duration);

View File

@ -5,6 +5,7 @@
#include "channel-selection.hpp"
#include "chat-connection.hpp"
#include "points-reward-selection.hpp"
#include "tag-selection.hpp"
#include <variable-line-edit.hpp>
#include <variable-text-edit.hpp>
@ -27,7 +28,7 @@ public:
CHANNEL_INFO_CATEGORY_SET = 20,
CHANNEL_INFO_LANGUAGE_SET = 30,
CHANNEL_INFO_DELAY_SET = 40,
CHANNEL_INFO_TAGS_SET = 50, // TODO
CHANNEL_INFO_TAGS_SET = 50,
CHANNEL_INFO_CONTENT_LABELS_SET = 60, // TODO
CHANNEL_INFO_BRANDED_CONTENT_ENABLE = 70,
CHANNEL_INFO_BRANDED_CONTENT_DISABLE = 71,
@ -168,6 +169,7 @@ public:
StringVariable _streamTitle =
obs_module_text("AdvSceneSwitcher.action.twitch.title.title");
TwitchCategory _category;
TwitchTagList _tags;
StringVariable _markerDescription = obs_module_text(
"AdvSceneSwitcher.action.twitch.marker.description");
bool _clipHasDelay = false;
@ -235,6 +237,7 @@ private slots:
void CheckToken();
void StreamTitleChanged();
void CategoryChanged(const TwitchCategory &);
void TagsChanged(const TwitchTagList &tags);
void MarkerDescriptionChanged();
void ClipHasDelayChanged(int state);
void DurationChanged(const Duration &);
@ -269,6 +272,7 @@ private:
QTimer _tokenCheckTimer;
VariableLineEdit *_streamTitle;
TwitchCategoryWidget *_category;
TagListWidget *_tags;
VariableLineEdit *_markerDescription;
QCheckBox *_clipHasDelay;
DurationSelection *_duration;

View File

@ -0,0 +1,192 @@
#include "tag-selection.hpp"
#include "channel-selection.hpp"
#include "log-helper.hpp"
#include "obs-module-helper.hpp"
#include "twitch-helpers.hpp"
#include <nlohmann/json.hpp>
#include <QHBoxLayout>
#include <QListWidget>
#include <QMessageBox>
#include <QPushButton>
#include <QRegularExpression>
#include <QVBoxLayout>
namespace advss {
void TwitchTagList::Load(obs_data_t *obj)
{
StringList::Load(obj, "tags", "tag");
}
void TwitchTagList::Save(obs_data_t *obj) const
{
StringList::Save(obj, "tags", "tag");
}
void TwitchTagList::SetStreamTags(const TwitchToken &token) const
{
nlohmann::json j;
j["tags"] = toVector();
// Although the Twitch API doesn't mention it, a request only containing
// an empty tags array will be denied.
// So, we just set the title, too, to work around this limitation.
if (isEmpty()) {
TwitchChannel channel;
channel.SetName(token.Name());
const auto channelInfo = channel.GetInfo(token);
if (!channelInfo) {
return;
}
if (channelInfo->title.empty()) {
return;
}
j["title"] = channelInfo->title;
}
auto result = SendPatchRequest(token, "https://api.twitch.tv",
"/helix/channels",
{{"broadcaster_id", token.GetUserID()}},
j.dump());
if (result.status != 204) {
blog(LOG_INFO, "Failed to set stream tags! (%d)",
result.status);
}
}
TagListWidget::TagListWidget(QWidget *parent)
: StringListEdit(
parent,
obs_module_text("AdvSceneSwitcher.action.twitch.tags.add"),
obs_module_text("AdvSceneSwitcher.action.twitch.tags.add"),
_maxTagLength,
[this](const std::string &input) { return Filter(input); },
[](std::string &input) {
input = QString::fromStdString(input)
.trimmed()
.toStdString();
})
{
connect(this, SIGNAL(StringListChanged(const StringList &)), this,
SLOT(StringListChangedWrapper(const StringList &)));
auto getCurrent = new QPushButton(obs_module_text(
"AdvSceneSwitcher.action.twitch.tags.getCurrent"));
connect(getCurrent, &QPushButton::clicked, this,
&TagListWidget::GetCurrentClicked);
_mainLayout->addWidget(getCurrent);
// TODO:
// Figure out why the Twitch API always returns an empty tag list
// Hide for now
getCurrent->hide();
}
void TagListWidget::SetTags(const TwitchTagList &tags)
{
SetStringList(tags);
}
void TagListWidget::SetToken(const std::weak_ptr<TwitchToken> &t)
{
_token = t;
}
void TagListWidget::GetCurrentClicked()
{
auto token = _token.lock();
if (!token) {
return;
}
TwitchChannel channel;
channel.SetName(token->Name());
const auto channelInfo = channel.GetInfo(*token);
if (!channelInfo) {
return;
}
TwitchTagList tags;
for (const auto &tag : channelInfo->tags) {
tags << tag;
}
SetTags(tags);
}
void TagListWidget::StringListChangedWrapper(const StringList &list)
{
emit TagListChanged(TwitchTagList{list});
}
bool TagListWidget::Filter(const std::string &input)
{
const auto tag = QString::fromStdString(input);
if (!IsValidTag(tag)) {
QMessageBox::warning(
this,
obs_module_text(
"AdvSceneSwitcher.action.twitch.tags.invalid"),
QString(obs_module_text(
"AdvSceneSwitcher.action.twitch.tags.invalid.info"))
.arg(_maxTagLength));
return true;
}
if (ContainsTag(tag)) {
QMessageBox::information(
this,
obs_module_text(
"AdvSceneSwitcher.action.twitch.tags.duplicate"),
obs_module_text(
"AdvSceneSwitcher.action.twitch.tags.duplicate.info"));
return true;
}
if (count() >= _maxTags) {
QMessageBox::warning(
this,
obs_module_text(
"AdvSceneSwitcher.action.twitch.tags.limit"),
QString(obs_module_text(
"AdvSceneSwitcher.action.twitch.tags.limit.info"))
.arg(_maxTags));
return true;
}
return false;
}
bool TagListWidget::IsValidTag(const QString &tag)
{
if (tag.isEmpty() || tag.length() > _maxTagLength) {
return false;
}
// If string contains variables don't filter
const StringVariable tmp = tag.toStdString();
if (tmp.UnresolvedValue() != std::string(tmp)) {
return true;
}
QRegularExpression regex("^[A-Za-z0-9]+$"); // Only letters and digits
return regex.match(tag).hasMatch();
}
bool TagListWidget::ContainsTag(const QString &tag) const
{
const auto lowerTag = tag.toLower();
const auto tags = GetStringList();
for (const auto &tag : tags) {
if (QString::fromStdString(tag.UnresolvedValue()).toLower() ==
lowerTag) {
return true;
}
}
return false;
}
} // namespace advss

View File

@ -0,0 +1,47 @@
#pragma once
#include "variable-line-edit.hpp"
#include "string-list.hpp"
#include "token.hpp"
#include <QWidget>
#include <string>
#include <vector>
class QListWidget;
class QPushButton;
class TwitchToken;
namespace advss {
struct TwitchTagList : public StringList {
void Load(obs_data_t *obj);
void Save(obs_data_t *obj) const;
void SetStreamTags(const TwitchToken &token) const;
};
class TagListWidget final : public StringListEdit {
Q_OBJECT
public:
explicit TagListWidget(QWidget *parent = nullptr);
void SetTags(const TwitchTagList &tags);
void SetToken(const std::weak_ptr<TwitchToken> &token);
private slots:
void StringListChangedWrapper(const StringList &);
void GetCurrentClicked();
signals:
void TagListChanged(const TwitchTagList &);
private:
bool Filter(const std::string &input);
static bool IsValidTag(const QString &tag);
bool ContainsTag(const QString &tag) const;
std::weak_ptr<TwitchToken> _token;
static constexpr int _maxTags = 10;
static constexpr int _maxTagLength = 25;
};
} // namespace advss

View File

@ -6,17 +6,11 @@
#include <nlohmann/json.hpp>
#include <string>
namespace advss {
namespace {
static constexpr std::string_view clientID = "ds5tt4ogliifsqc04mz3d3etnck3e5";
static const int cacheTimeoutSeconds = 10;
static std::atomic_bool apiIsThrottling = {false};
const char *GetClientID()
{
return clientID.data();
}
class Args {
public:
Args(const std::string &uri, const std::string &path,
@ -54,10 +48,10 @@ private:
httplib::Headers _headers;
};
}; // namespace advss
}; // namespace
template<> struct std::hash<advss::Args> {
inline std::size_t operator()(const advss::Args &args) const
template<> struct std::hash<Args> {
inline std::size_t operator()(const Args &args) const
{
static constexpr auto hash_combine = [](std::size_t &seed,
std::size_t hashValue) {
@ -85,6 +79,13 @@ template<> struct std::hash<advss::Args> {
namespace advss {
static constexpr std::string_view clientID = "ds5tt4ogliifsqc04mz3d3etnck3e5";
const char *GetClientID()
{
return clientID.data();
}
struct CacheEntry {
RequestResult result;
std::chrono::system_clock::time_point cacheTime =
@ -255,7 +256,7 @@ static RequestResult sendPostRequest(const TwitchToken &token,
const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data)
const std::string &data)
{
if (apiIsThrottling) {
return {};
@ -273,9 +274,8 @@ static RequestResult sendPostRequest(const TwitchToken &token,
vblog(LOG_INFO, "Twitch POST request to %s began", url.c_str());
auto headers = getTokenRequestHeaders(*tokenStr);
auto body = getRequestBody(data);
auto response =
cli.Post(pathWithParams, headers, body, "application/json");
cli.Post(pathWithParams, headers, data, "application/json");
return processResult(response, __func__);
}
@ -284,6 +284,15 @@ RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data, bool useCache)
{
auto body = getRequestBody(data);
return SendPostRequest(token, uri, path, params, body, useCache);
}
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const std::string &data, bool useCache)
{
if (apiIsThrottling) {
return {};
@ -303,8 +312,7 @@ RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
}
auto headers = getTokenRequestHeaders(*tokenStr);
auto body = getRequestBody(data);
Args args(uri, path, body, params, headers);
Args args(uri, path, data, params, headers);
if (!useCache) {
return sendPostRequest(token, uri, path, params, data);
@ -326,7 +334,7 @@ static RequestResult sendPutRequest(const TwitchToken &token,
const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data)
const std::string &data)
{
if (apiIsThrottling) {
return {};
@ -344,9 +352,8 @@ static RequestResult sendPutRequest(const TwitchToken &token,
vblog(LOG_INFO, "Twitch PUT request to %s began", url.c_str());
auto headers = getTokenRequestHeaders(*tokenStr);
auto body = getRequestBody(data);
auto response =
cli.Put(pathWithParams, headers, body, "application/json");
cli.Put(pathWithParams, headers, data, "application/json");
return processResult(response, __func__);
}
@ -355,6 +362,15 @@ RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params, const OBSData &data,
bool useCache)
{
auto body = getRequestBody(data);
return SendPutRequest(token, uri, path, params, body, useCache);
}
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const std::string &data, bool useCache)
{
if (apiIsThrottling) {
return {};
@ -374,8 +390,7 @@ RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
}
auto headers = getTokenRequestHeaders(*tokenStr);
auto body = getRequestBody(data);
Args args(uri, path, body, params, headers);
Args args(uri, path, data, params, headers);
if (!useCache) {
return sendPutRequest(token, uri, path, params, data);
@ -397,7 +412,7 @@ static RequestResult sendPatchRequest(const TwitchToken &token,
const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data)
const std::string &data)
{
if (apiIsThrottling) {
return {};
@ -415,9 +430,8 @@ static RequestResult sendPatchRequest(const TwitchToken &token,
vblog(LOG_INFO, "Twitch PATCH request to %s began", url.c_str());
auto headers = getTokenRequestHeaders(*tokenStr);
auto body = getRequestBody(data);
auto response =
cli.Patch(pathWithParams, headers, body, "application/json");
cli.Patch(pathWithParams, headers, data, "application/json");
return processResult(response, __func__);
}
@ -426,6 +440,15 @@ RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data, bool useCache)
{
auto body = getRequestBody(data);
return SendPatchRequest(token, uri, path, params, body, useCache);
}
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const std::string &data, bool useCache)
{
if (apiIsThrottling) {
return {};
@ -445,8 +468,7 @@ RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
}
auto headers = getTokenRequestHeaders(*tokenStr);
auto body = getRequestBody(data);
Args args(uri, path, body, params, headers);
Args args(uri, path, data, params, headers);
if (!useCache) {
return sendPatchRequest(token, uri, path, params, data);

View File

@ -21,20 +21,32 @@ RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params = {},
bool useCache = false);
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data, bool useCache = false);
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params = {},
const OBSData &data = nullptr,
const std::string &data = "",
bool useCache = false);
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params, const OBSData &data,
bool useCache = false);
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params = {},
const OBSData &data = nullptr,
const std::string &data = "",
bool useCache = false);
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params,
const OBSData &data, bool useCache = false);
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
const std::string &path,
const httplib::Params &params = {},
const OBSData &data = nullptr,
const std::string &data = "",
bool useCache = false);
// Helper functions to set temp var values