mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Validate that user id matches token
This commit is contained in:
parent
bf216e0917
commit
bf18d8e106
|
|
@ -68,10 +68,15 @@ void ContentClassification::SetContentClassification(
|
|||
data = obs_data_create();
|
||||
obs_data_set_array(data, "content_classification_labels", ccls);
|
||||
|
||||
const auto id = token.GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
auto result = SendPatchRequest(token, "https://api.twitch.tv",
|
||||
"/helix/channels",
|
||||
{{"broadcaster_id", token.GetUserID()}},
|
||||
data.Get());
|
||||
{{"broadcaster_id", *id}}, data.Get());
|
||||
|
||||
if (result.status != 204) {
|
||||
blog(LOG_INFO,
|
||||
|
|
|
|||
|
|
@ -189,12 +189,17 @@ void LanguageSelection::Save(obs_data_t *obj) const
|
|||
|
||||
void LanguageSelection::SetStreamLanguage(const TwitchToken &token) const
|
||||
{
|
||||
const auto id = token.GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "broadcaster_language", _language.c_str());
|
||||
auto result = SendPatchRequest(token, "https://api.twitch.tv",
|
||||
"/helix/channels",
|
||||
{{"broadcaster_id", token.GetUserID()}},
|
||||
data.Get());
|
||||
{{"broadcaster_id", *id}}, data.Get());
|
||||
|
||||
if (result.status != 204) {
|
||||
blog(LOG_INFO, "Failed to set stream language! (%d)",
|
||||
|
|
|
|||
|
|
@ -123,12 +123,17 @@ void MacroActionTwitch::SetStreamTitle(
|
|||
return;
|
||||
}
|
||||
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "title", _streamTitle.c_str());
|
||||
auto result = SendPatchRequest(*token, "https://api.twitch.tv",
|
||||
"/helix/channels",
|
||||
{{"broadcaster_id", token->GetUserID()}},
|
||||
data.Get());
|
||||
{{"broadcaster_id", *id}}, data.Get());
|
||||
|
||||
if (result.status != 204) {
|
||||
blog(LOG_INFO, "Failed to set stream title! (%d)",
|
||||
|
|
@ -143,13 +148,18 @@ void MacroActionTwitch::SetStreamCategory(
|
|||
return;
|
||||
}
|
||||
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "game_id",
|
||||
std::to_string(_category.id).c_str());
|
||||
auto result = SendPatchRequest(*token, "https://api.twitch.tv",
|
||||
"/helix/channels",
|
||||
{{"broadcaster_id", token->GetUserID()}},
|
||||
data.Get());
|
||||
{{"broadcaster_id", *id}}, data.Get());
|
||||
|
||||
if (result.status != 204) {
|
||||
blog(LOG_INFO, "Failed to set stream category! (%d)",
|
||||
|
|
@ -160,8 +170,14 @@ void MacroActionTwitch::SetStreamCategory(
|
|||
void MacroActionTwitch::CreateStreamMarker(
|
||||
const std::shared_ptr<TwitchToken> &token) const
|
||||
{
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "user_id", token->GetUserID().c_str());
|
||||
obs_data_set_string(data, "user_id", id->c_str());
|
||||
|
||||
if (!std::string(_markerDescription).empty()) {
|
||||
obs_data_set_string(data, "description",
|
||||
|
|
@ -179,12 +195,17 @@ void MacroActionTwitch::CreateStreamMarker(
|
|||
void MacroActionTwitch::CreateStreamClip(
|
||||
const std::shared_ptr<TwitchToken> &token) const
|
||||
{
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
auto hasDelay = _clipHasDelay ? "true" : "false";
|
||||
|
||||
auto result = SendPostRequest(*token, "https://api.twitch.tv",
|
||||
"/helix/clips",
|
||||
{{"broadcaster_id", token->GetUserID()},
|
||||
{"has_delay", hasDelay}});
|
||||
auto result = SendPostRequest(
|
||||
*token, "https://api.twitch.tv", "/helix/clips",
|
||||
{{"broadcaster_id", *id}, {"has_delay", hasDelay}});
|
||||
|
||||
if (result.status != 202) {
|
||||
blog(LOG_INFO, "Failed to create clip! (%d)", result.status);
|
||||
|
|
@ -194,8 +215,14 @@ void MacroActionTwitch::CreateStreamClip(
|
|||
void MacroActionTwitch::StartCommercial(
|
||||
const std::shared_ptr<TwitchToken> &token) const
|
||||
{
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "broadcaster_id", token->GetUserID().c_str());
|
||||
obs_data_set_string(data, "broadcaster_id", id->c_str());
|
||||
obs_data_set_int(data, "length", _duration.Seconds());
|
||||
auto result = SendPostRequest(*token, "https://api.twitch.tv",
|
||||
"/helix/channels/commercial", {},
|
||||
|
|
@ -227,17 +254,21 @@ void MacroActionTwitch::StartCommercial(
|
|||
void MacroActionTwitch::SendChatAnnouncement(
|
||||
const std::shared_ptr<TwitchToken> &token) const
|
||||
{
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "message", _announcementMessage.c_str());
|
||||
obs_data_set_string(
|
||||
data, "color",
|
||||
announcementColorsTwitch.at(_announcementColor).c_str());
|
||||
auto userId = token->GetUserID();
|
||||
|
||||
auto result = SendPostRequest(
|
||||
*token, "https://api.twitch.tv", "/helix/chat/announcements",
|
||||
{{"broadcaster_id", userId}, {"moderator_id", userId}},
|
||||
data.Get());
|
||||
{{"broadcaster_id", *id}, {"moderator_id", *id}}, data.Get());
|
||||
|
||||
if (result.status != 204) {
|
||||
blog(LOG_INFO, "Failed to send chat announcement! (%d)",
|
||||
|
|
@ -248,14 +279,18 @@ void MacroActionTwitch::SendChatAnnouncement(
|
|||
void MacroActionTwitch::SetChatEmoteOnlyMode(
|
||||
const std::shared_ptr<TwitchToken> &token, bool enable) const
|
||||
{
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_bool(data, "emote_mode", enable);
|
||||
auto userId = token->GetUserID();
|
||||
|
||||
auto result = SendPatchRequest(
|
||||
*token, "https://api.twitch.tv", "/helix/chat/settings",
|
||||
{{"broadcaster_id", userId}, {"moderator_id", userId}},
|
||||
data.Get());
|
||||
{{"broadcaster_id", *id}, {"moderator_id", *id}}, data.Get());
|
||||
|
||||
if (result.status != 200) {
|
||||
blog(LOG_INFO, "Failed to %s chat's emote-only mode! (%d)",
|
||||
|
|
@ -265,9 +300,14 @@ void MacroActionTwitch::SetChatEmoteOnlyMode(
|
|||
|
||||
void MacroActionTwitch::StartRaid(const std::shared_ptr<TwitchToken> &token)
|
||||
{
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_string(data, "from_broadcaster_id",
|
||||
token->GetUserID().c_str());
|
||||
obs_data_set_string(data, "from_broadcaster_id", id->c_str());
|
||||
obs_data_set_string(data, "to_broadcaster_id",
|
||||
_channel.GetUserID(*token).c_str());
|
||||
auto result = SendPostRequest(*token, "https://api.twitch.tv",
|
||||
|
|
@ -398,6 +438,12 @@ bool MacroActionTwitch::ResolveVariableSelectionToRewardId(
|
|||
|
||||
void MacroActionTwitch::GetRewardInfo(const std::shared_ptr<TwitchToken> &token)
|
||||
{
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_useVariableForRewardSelection &&
|
||||
!ResolveVariableSelectionToRewardId(token)) {
|
||||
if (VerboseLoggingEnabled()) {
|
||||
|
|
@ -416,7 +462,7 @@ void MacroActionTwitch::GetRewardInfo(const std::shared_ptr<TwitchToken> &token)
|
|||
}
|
||||
|
||||
httplib::Params params = {
|
||||
{"broadcaster_id", token->GetUserID()},
|
||||
{"broadcaster_id", *id},
|
||||
{"id", _useVariableForRewardSelection ? _lastResolvedRewardId
|
||||
: _pointsReward.id},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1096,6 +1096,12 @@ void MacroConditionTwitch::AddChannelGenericEventSubscription(
|
|||
return;
|
||||
}
|
||||
|
||||
const auto id = token->GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto channelID = _channel.GetUserID(*token);
|
||||
if (!TwitchChannel::IsValid(channelID)) {
|
||||
vblog(LOG_INFO, "skip %s because of invalid channel selection",
|
||||
|
|
@ -1114,7 +1120,7 @@ void MacroConditionTwitch::AddChannelGenericEventSubscription(
|
|||
|
||||
if (includeModeratorId) {
|
||||
obs_data_set_string(condition, "moderator_user_id",
|
||||
token->GetUserID().c_str());
|
||||
id->c_str());
|
||||
}
|
||||
|
||||
obs_data_apply(condition, extraConditions);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,12 @@ void TwitchTagList::Save(obs_data_t *obj) const
|
|||
|
||||
void TwitchTagList::SetStreamTags(const TwitchToken &token) const
|
||||
{
|
||||
const auto id = token.GetUserID();
|
||||
if (!id) {
|
||||
vblog(LOG_INFO, "%s skip - invalid user id", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
nlohmann::json j;
|
||||
j["tags"] = toVector();
|
||||
|
||||
|
|
@ -47,8 +53,7 @@ void TwitchTagList::SetStreamTags(const TwitchToken &token) const
|
|||
|
||||
auto result = SendPatchRequest(token, "https://api.twitch.tv",
|
||||
"/helix/channels",
|
||||
{{"broadcaster_id", token.GetUserID()}},
|
||||
j.dump());
|
||||
{{"broadcaster_id", *id}}, j.dump());
|
||||
|
||||
if (result.status != 204) {
|
||||
blog(LOG_INFO, "Failed to set stream tags! (%d)",
|
||||
|
|
|
|||
|
|
@ -206,7 +206,9 @@ void TwitchToken::Save(obs_data_t *obj) const
|
|||
{
|
||||
Item::Save(obj);
|
||||
obs_data_set_string(obj, "token", _token.c_str());
|
||||
obs_data_set_string(obj, "userID", _userID.c_str());
|
||||
if (_userID) {
|
||||
obs_data_set_string(obj, "userID", _userID->c_str());
|
||||
}
|
||||
obs_data_set_bool(obj, "validateEventSubTimestamps",
|
||||
_validateEventSubTimestamps);
|
||||
obs_data_set_bool(obj, "warnIfInvalid", _warnIfInvalid);
|
||||
|
|
@ -266,7 +268,7 @@ void TwitchToken::SetToken(const std::string &value)
|
|||
SendGetRequest(*this, "https://api.twitch.tv", "/helix/users");
|
||||
if (res.status != 200) {
|
||||
blog(LOG_WARNING, "failed to get Twitch user id from token!");
|
||||
_userID = -1;
|
||||
_userID = {};
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -318,12 +320,35 @@ bool TwitchToken::IsValid(bool forceUpdate) const
|
|||
cli.Get("/oauth2/validate", httplib::Params{}, headers);
|
||||
_lastValidityCheckTime = std::chrono::system_clock::now();
|
||||
_lastValidityCheckValue = _token;
|
||||
_lastValidityCheckResult = response && response->status == 200;
|
||||
if (!_lastValidityCheckResult) {
|
||||
|
||||
if (!response || response->status != 200) {
|
||||
blog(LOG_INFO, "Twitch token %s is not valid!",
|
||||
_name.c_str());
|
||||
_lastValidityCheckResult = false;
|
||||
return false;
|
||||
}
|
||||
return _lastValidityCheckResult;
|
||||
|
||||
OBSDataAutoRelease replyData =
|
||||
obs_data_create_from_json(response->body.c_str());
|
||||
const char *id = obs_data_get_string(replyData, "user_id");
|
||||
if (!id) {
|
||||
blog(LOG_INFO,
|
||||
"Twitch token %s does validity check did not report user_id! Assume invalid!",
|
||||
_name.c_str());
|
||||
_lastValidityCheckResult = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_userID && _userID != id) {
|
||||
blog(LOG_INFO,
|
||||
"Twitch token %s does not match expected user (got %s, expected %s)!",
|
||||
_name.c_str(), id, _userID->c_str());
|
||||
_lastValidityCheckResult = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
_lastValidityCheckResult = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
const bool tokenChanged = _lastValidityCheckValue != _token;
|
||||
|
|
@ -729,6 +754,7 @@ void TwitchTokenSettingsDialog::RequestToken()
|
|||
|
||||
auto scope = QString::fromStdString(
|
||||
generateScopeString(GetEnabledOptions()));
|
||||
_validationTimer.stop();
|
||||
_tokenGrabber.SetTokenScope(scope);
|
||||
_tokenGrabber.start();
|
||||
_tokenStatus->setText(obs_module_text(
|
||||
|
|
@ -766,6 +792,7 @@ void TwitchTokenSettingsDialog::GotToken(const std::optional<QString> &value)
|
|||
Q_ARG(const QString &, name));
|
||||
SetTokenInfoVisible(true);
|
||||
_requestToken->setEnabled(true);
|
||||
_validationTimer.start();
|
||||
}
|
||||
|
||||
std::set<TokenOption> TwitchTokenSettingsDialog::GetEnabledOptions()
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public:
|
|||
void SetToken(const std::string &);
|
||||
bool IsEmpty() const { return _token.empty(); }
|
||||
std::optional<std::string> GetToken() const;
|
||||
std::string GetUserID() const { return _userID; }
|
||||
std::optional<std::string> GetUserID() const { return _userID; }
|
||||
std::shared_ptr<EventSub> GetEventSub();
|
||||
bool ValidateTimestamps() const { return _validateEventSubTimestamps; }
|
||||
bool IsValid(bool forceUpdate = false) const;
|
||||
|
|
@ -65,7 +65,7 @@ private:
|
|||
mutable std::string _lastValidityCheckValue;
|
||||
mutable bool _lastValidityCheckResult = false;
|
||||
mutable std::chrono::system_clock::time_point _lastValidityCheckTime;
|
||||
std::string _userID;
|
||||
std::optional<std::string> _userID;
|
||||
std::set<TokenOption> _tokenOptions = TokenOption::GetAllTokenOptions();
|
||||
std::shared_ptr<EventSub> _eventSub;
|
||||
bool _validateEventSubTimestamps = false;
|
||||
|
|
|
|||
|
|
@ -153,6 +153,25 @@ static QStringList getCellLabels(TwitchToken *token, bool addName = true)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void updateConnectionStatus(QTableWidget *table)
|
||||
{
|
||||
for (int row = 0; row < table->rowCount(); row++) {
|
||||
auto item = table->item(row, 0);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto weakToken = GetWeakTwitchTokenByQString(item->text());
|
||||
auto token = weakToken.lock();
|
||||
if (!token) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateItemTableRow(table, row,
|
||||
getCellLabels(token.get(), false));
|
||||
}
|
||||
}
|
||||
|
||||
static void openSettingsDialog()
|
||||
{
|
||||
auto selectedRows =
|
||||
|
|
@ -174,6 +193,7 @@ static void openSettingsDialog()
|
|||
|
||||
TwitchTokenSettingsDialog::AskForSettings(GetSettingsWindow(),
|
||||
*token.get());
|
||||
updateConnectionStatus(tabWidget->Table());
|
||||
}
|
||||
|
||||
static const QStringList headers =
|
||||
|
|
@ -202,25 +222,6 @@ TwitchConnectionsTable::TwitchConnectionsTable(QTabWidget *parent)
|
|||
SetHelpVisible(GetTwitchTokens().empty());
|
||||
}
|
||||
|
||||
static void updateConnectionStatus(QTableWidget *table)
|
||||
{
|
||||
for (int row = 0; row < table->rowCount(); row++) {
|
||||
auto item = table->item(row, 0);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto weakToken = GetWeakTwitchTokenByQString(item->text());
|
||||
auto token = weakToken.lock();
|
||||
if (!token) {
|
||||
continue;
|
||||
}
|
||||
|
||||
UpdateItemTableRow(table, row,
|
||||
getCellLabels(token.get(), false));
|
||||
}
|
||||
}
|
||||
|
||||
static QStringList getInvalidTokens()
|
||||
{
|
||||
QStringList tokens;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user