Compare commits

...

3 Commits

Author SHA1 Message Date
WarmUpTill
c8f4e524ba Make deps/exprtk dependency optional 2026-09-28 21:10:59 +02:00
WarmUpTill
b104f98d02 Fix Twitch token status not reflecting reality when cached user ID empty 2026-09-25 19:43:24 +02:00
WarmUpTill
abc8c3708f Fix Twitch token being treated as invalid after load with broken config
Some checks failed
debian-build / build (push) Has been cancelled
Push to master / Check Formatting 🔍 (push) Has been cancelled
Push to master / Build Project 🧱 (push) Has been cancelled
Push to master / Create Release 🛫 (push) Has been cancelled
2026-09-23 09:32:30 +02:00
5 changed files with 53 additions and 14 deletions

View File

@@ -383,8 +383,18 @@ target_precompile_headers(${LIB_NAME} PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/lib/pch.hpp") "${CMAKE_CURRENT_SOURCE_DIR}/lib/pch.hpp")
target_include_directories( target_include_directories(
${LIB_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib" ${LIB_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib")
"${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk/exprtk.hpp")
target_include_directories(${LIB_NAME}
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
target_compile_definitions(${LIB_NAME} PRIVATE EXPRTK_SUPPORT=1)
else()
message(
STATUS
"${PROJECT_NAME}: deps/exprtk not found - math expression support disabled"
)
endif()
if(NOT nlohmann_json_DIR if(NOT nlohmann_json_DIR
AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deps/json/CMakeLists.txt") AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deps/json/CMakeLists.txt")

View File

@@ -2,13 +2,16 @@
#include "obs-module-helper.hpp" #include "obs-module-helper.hpp"
#include <climits> #include <climits>
#ifdef EXPRTK_SUPPORT
#include <exprtk.hpp> #include <exprtk.hpp>
#include <random> #include <random>
#endif
namespace advss { namespace advss {
std::variant<double, std::string> EvalMathExpression(const std::string &expr) std::variant<double, std::string> EvalMathExpression(const std::string &expr)
{ {
#ifdef EXPRTK_SUPPORT
static auto randomFunc = []() { static auto randomFunc = []() {
thread_local std::mt19937 gen(std::random_device{}()); thread_local std::mt19937 gen(std::random_device{}());
thread_local std::uniform_real_distribution<double> dis(0.0, thread_local std::uniform_real_distribution<double> dis(0.0,
@@ -26,6 +29,7 @@ std::variant<double, std::string> EvalMathExpression(const std::string &expr)
if (parser.compile(expr, expression)) { if (parser.compile(expr, expression)) {
return expression.value(); return expression.value();
} }
#endif
return std::string(obs_module_text( return std::string(obs_module_text(
"AdvSceneSwitcher.math.expressionFail")) + "AdvSceneSwitcher.math.expressionFail")) +
" \"" + expr + "\""; " \"" + expr + "\"";

View File

@@ -233,7 +233,12 @@ void TwitchToken::Load(obs_data_t *obj)
{ {
Item::Load(obj); Item::Load(obj);
_token = obs_data_get_string(obj, "token"); _token = obs_data_get_string(obj, "token");
_userID = obs_data_get_string(obj, "userID"); if (obs_data_has_user_value(obj, "userID") &&
*obs_data_get_string(obj, "userID") != '\0') {
_userID = obs_data_get_string(obj, "userID");
} else {
_userID = {};
}
obs_data_set_default_bool(obj, "validateEventSubTimestamps", true); obs_data_set_default_bool(obj, "validateEventSubTimestamps", true);
_validateEventSubTimestamps = _validateEventSubTimestamps =
obs_data_get_bool(obj, "validateEventSubTimestamps"); obs_data_get_bool(obj, "validateEventSubTimestamps");
@@ -255,7 +260,7 @@ void TwitchToken::Save(obs_data_t *obj) const
{ {
Item::Save(obj); Item::Save(obj);
obs_data_set_string(obj, "token", _token.c_str()); obs_data_set_string(obj, "token", _token.c_str());
if (_userID) { if (_userID && !_userID->empty()) {
obs_data_set_string(obj, "userID", _userID->c_str()); obs_data_set_string(obj, "userID", _userID->c_str());
} }
obs_data_set_bool(obj, "validateEventSubTimestamps", obs_data_set_bool(obj, "validateEventSubTimestamps",
@@ -310,7 +315,7 @@ bool TwitchToken::AnyOptionIsEnabled(
return false; return false;
} }
void TwitchToken::SetToken(const std::string &value) bool TwitchToken::SetToken(const std::string &value)
{ {
_token = value; _token = value;
auto res = auto res =
@@ -318,21 +323,34 @@ void TwitchToken::SetToken(const std::string &value)
if (res.status != 200) { if (res.status != 200) {
blog(LOG_WARNING, "failed to get Twitch user id from token!"); blog(LOG_WARNING, "failed to get Twitch user id from token!");
_userID = {}; _userID = {};
return; return false;
} }
bool gotUserID = false;
OBSDataArrayAutoRelease array = obs_data_get_array(res.data, "data"); OBSDataArrayAutoRelease array = obs_data_get_array(res.data, "data");
size_t count = obs_data_array_count(array); size_t count = obs_data_array_count(array);
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
OBSDataAutoRelease arrayObj = obs_data_array_item(array, i); OBSDataAutoRelease arrayObj = obs_data_array_item(array, i);
_userID = obs_data_get_string(arrayObj, "id"); std::string id = obs_data_get_string(arrayObj, "id");
if (id.empty()) {
blog(LOG_WARNING,
"Twitch /helix/users response did not contain a user id!");
continue;
}
_userID = id;
_name = obs_data_get_string(arrayObj, "display_name"); _name = obs_data_get_string(arrayObj, "display_name");
gotUserID = true;
}
if (!gotUserID) {
return false;
} }
// Trigger resubscribes with new token // Trigger resubscribes with new token
if (_eventSub) { if (_eventSub) {
_eventSub->ClearActiveSubscriptions(); _eventSub->ClearActiveSubscriptions();
} }
return true;
} }
std::optional<std::string> TwitchToken::GetToken() const std::optional<std::string> TwitchToken::GetToken() const
@@ -388,7 +406,7 @@ bool TwitchToken::IsValid(bool forceUpdate) const
return false; return false;
} }
if (_userID && _userID != id) { if (_userID && !_userID->empty() && _userID != id) {
blog(LOG_INFO, blog(LOG_INFO,
"Twitch token %s does not match expected user (got %s, expected %s)!", "Twitch token %s does not match expected user (got %s, expected %s)!",
_name.c_str(), id, _userID->c_str()); _name.c_str(), id, _userID->c_str());
@@ -396,6 +414,10 @@ bool TwitchToken::IsValid(bool forceUpdate) const
return false; return false;
} }
if (!_userID || _userID->empty()) {
_userID = id;
}
_lastValidityCheckResult = true; _lastValidityCheckResult = true;
return true; return true;
}; };
@@ -819,9 +841,9 @@ void TwitchTokenSettingsDialog::GotToken(const std::optional<QString> &value)
return; return;
} }
_currentToken.SetToken(value.value().toStdString()); bool success = _currentToken.SetToken(value.value().toStdString());
auto name = QString::fromStdString(_currentToken._name); auto name = QString::fromStdString(_currentToken._name);
if (name.isEmpty()) { if (!success || name.isEmpty()) {
_tokenStatus->setText(obs_module_text( _tokenStatus->setText(obs_module_text(
"AdvSceneSwitcher.twitchToken.request.fail")); "AdvSceneSwitcher.twitchToken.request.fail"));
_name->setText(""); _name->setText("");

View File

@@ -48,7 +48,7 @@ public:
bool OptionIsActive(const TokenOption &option) const; bool OptionIsActive(const TokenOption &option) const;
bool OptionIsEnabled(const TokenOption &option) const; bool OptionIsEnabled(const TokenOption &option) const;
bool AnyOptionIsEnabled(const std::vector<TokenOption> &options) const; bool AnyOptionIsEnabled(const std::vector<TokenOption> &options) const;
void SetToken(const std::string &); bool SetToken(const std::string &);
bool IsEmpty() const { return _token.empty(); } bool IsEmpty() const { return _token.empty(); }
std::optional<std::string> GetToken() const; std::optional<std::string> GetToken() const;
std::optional<std::string> GetUserID() const { return _userID; } std::optional<std::string> GetUserID() const { return _userID; }
@@ -65,7 +65,7 @@ private:
mutable std::string _lastValidityCheckValue; mutable std::string _lastValidityCheckValue;
mutable bool _lastValidityCheckResult = false; mutable bool _lastValidityCheckResult = false;
mutable std::chrono::system_clock::time_point _lastValidityCheckTime; mutable std::chrono::system_clock::time_point _lastValidityCheckTime;
std::optional<std::string> _userID; mutable std::optional<std::string> _userID;
std::set<TokenOption> _tokenOptions = TokenOption::GetAllTokenOptions(); std::set<TokenOption> _tokenOptions = TokenOption::GetAllTokenOptions();
std::shared_ptr<EventSub> _eventSub; std::shared_ptr<EventSub> _eventSub;
bool _validateEventSubTimestamps = false; bool _validateEventSubTimestamps = false;

View File

@@ -85,8 +85,11 @@ target_sources(
${PROJECT_NAME} ${PROJECT_NAME}
PRIVATE test-math.cpp ${ADVSS_SOURCE_DIR}/lib/utils/math-helpers.cpp PRIVATE test-math.cpp ${ADVSS_SOURCE_DIR}/lib/utils/math-helpers.cpp
${ADVSS_SOURCE_DIR}/lib/utils/obs-module-helper.cpp) ${ADVSS_SOURCE_DIR}/lib/utils/obs-module-helper.cpp)
target_include_directories(${PROJECT_NAME} if(EXISTS "${ADVSS_SOURCE_DIR}/deps/exprtk/exprtk.hpp")
PRIVATE ${ADVSS_SOURCE_DIR}/deps/exprtk) target_include_directories(${PROJECT_NAME}
PRIVATE ${ADVSS_SOURCE_DIR}/deps/exprtk)
target_compile_definitions(${PROJECT_NAME} PRIVATE EXPRTK_SUPPORT=1)
endif()
if(MSVC) if(MSVC)
target_compile_options(${PROJECT_NAME} PUBLIC /MP /d2FH4- /wd4267 /bigobj) target_compile_options(${PROJECT_NAME} PUBLIC /MP /d2FH4- /wd4267 /bigobj)