diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini index e3a225a1..6e94a970 100644 --- a/data/locale/en-US.ini +++ b/data/locale/en-US.ini @@ -1412,6 +1412,7 @@ AdvSceneSwitcher.twitchToken.moderator.chat.settings.manage="Manage channel's ch AdvSceneSwitcher.twitchToken.user.whispers.manage="Manage user's whispers." AdvSceneSwitcher.twitchToken.chat.read="View live stream chat messages." AdvSceneSwitcher.twitchToken.chat.edit="Send live stream chat messages." +AdvSceneSwitcher.twitchToken.validateTimestamps="Validate timestamps of received Twitch event messages. (Recommended)" AdvSceneSwitcher.twitch.selection.channel.open="Open channel" AdvSceneSwitcher.twitch.selection.channel.open.tooltip.details="Open channel in external application handling the HTTPS protocol." diff --git a/plugins/twitch/event-sub.cpp b/plugins/twitch/event-sub.cpp index 80fc62a9..d18cd3d6 100644 --- a/plugins/twitch/event-sub.cpp +++ b/plugins/twitch/event-sub.cpp @@ -127,6 +127,11 @@ void EventSub::ClearActiveSubscriptions() _activeSubscriptions.clear(); } +void EventSub::EnableTimestampValidation(bool enable) +{ + _validateTimestamps = enable; +} + void EventSub::Disconnect() { std::lock_guard lock(_connectMtx); @@ -318,7 +323,7 @@ void EventSub::OnMessage(connection_hdl, EventSubWSClient::message_ptr message) OBSDataAutoRelease metadata = obs_data_get_obj(json, "metadata"); std::string timestamp = obs_data_get_string(metadata, "message_timestamp"); - if (!isValidTimestamp(timestamp)) { + if (_validateTimestamps && !isValidTimestamp(timestamp)) { blog(LOG_WARNING, "Discarding Twitch EventSub with invalid timestamp %s", timestamp.c_str()); diff --git a/plugins/twitch/event-sub.hpp b/plugins/twitch/event-sub.hpp index 6860a5c7..710a9663 100644 --- a/plugins/twitch/event-sub.hpp +++ b/plugins/twitch/event-sub.hpp @@ -58,6 +58,7 @@ public: static std::string AddEventSubscription(std::shared_ptr, Subscription); void ClearActiveSubscriptions(); + void EnableTimestampValidation(bool enable); private: void OnOpen(connection_hdl hdl); @@ -89,6 +90,7 @@ private: std::atomic_bool _disconnect{false}; std::string _url; std::string _sessionID; + bool _validateTimestamps = true; std::deque _messageIDs; std::mutex _subscriptionMtx; diff --git a/plugins/twitch/token.cpp b/plugins/twitch/token.cpp index d95752e0..1bf4bde2 100644 --- a/plugins/twitch/token.cpp +++ b/plugins/twitch/token.cpp @@ -158,6 +158,9 @@ void TwitchToken::Load(obs_data_t *obj) Item::Load(obj); _token = obs_data_get_string(obj, "token"); _userID = obs_data_get_string(obj, "userID"); + obs_data_set_default_bool(obj, "validateEventSubTimestamps", true); + _validateEventSubTimestamps = + obs_data_get_bool(obj, "validateEventSubTimestamps"); _tokenOptions.clear(); OBSDataArrayAutoRelease options = obs_data_get_array(obj, "options"); size_t count = obs_data_array_count(options); @@ -174,6 +177,8 @@ 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()); + obs_data_set_bool(obj, "validateEventSubTimestamps", + _validateEventSubTimestamps); OBSDataArrayAutoRelease options = obs_data_array_create(); for (auto &option : _tokenOptions) { OBSDataAutoRelease arrayObj = obs_data_create(); @@ -260,6 +265,8 @@ std::shared_ptr TwitchToken::GetEventSub() { if (!_eventSub) { _eventSub = std::make_shared(); + _eventSub->EnableTimestampValidation( + _validateEventSubTimestamps); } return _eventSub; } @@ -445,7 +452,9 @@ TwitchTokenSettingsDialog::TwitchTokenSettingsDialog( _showToken(new QPushButton()), _currentTokenValue(new QLineEdit()), _tokenStatus(new QLabel()), - _generalSettingsGrid(new QGridLayout()) + _generalSettingsGrid(new QGridLayout()), + _validateTimestamps(new QCheckBox(obs_module_text( + "AdvSceneSwitcher.twitchToken.validateTimestamps"))) { _showToken->setMaximumWidth(22); _showToken->setFlat(true); @@ -511,6 +520,7 @@ TwitchTokenSettingsDialog::TwitchTokenSettingsDialog( auto layout = new QVBoxLayout(contentWidget); layout->addLayout(_generalSettingsGrid); layout->addWidget(optionsBox); + layout->addWidget(_validateTimestamps); layout->setContentsMargins(0, 0, 0, 0); scrollArea->setWidget(contentWidget); @@ -532,6 +542,8 @@ TwitchTokenSettingsDialog::TwitchTokenSettingsDialog( true); } + _validateTimestamps->setChecked(settings._validateEventSubTimestamps); + _currentToken = settings; QWidget::connect(&_validationTimer, &QTimer::timeout, this, @@ -737,6 +749,12 @@ bool TwitchTokenSettingsDialog::AskForSettings(QWidget *parent, settings = dialog._currentToken; settings._tokenOptions = dialog.GetEnabledOptions(); + settings._validateEventSubTimestamps = + dialog._validateTimestamps->isChecked(); + if (settings._eventSub) { + settings._eventSub->EnableTimestampValidation( + settings._validateEventSubTimestamps); + } return true; } diff --git a/plugins/twitch/token.hpp b/plugins/twitch/token.hpp index 99f33a23..13c00390 100644 --- a/plugins/twitch/token.hpp +++ b/plugins/twitch/token.hpp @@ -49,6 +49,7 @@ public: std::optional GetToken() const; std::string GetUserID() const { return _userID; } std::shared_ptr GetEventSub(); + bool ValidateTimestamps() const { return _validateEventSubTimestamps; } bool IsValid(bool forceUpdate = false) const; size_t PermissionCount() const { return _tokenOptions.size(); } @@ -57,6 +58,7 @@ private: std::string _userID; std::set _tokenOptions = TokenOption::GetAllTokenOptions(); std::shared_ptr _eventSub; + bool _validateEventSubTimestamps = true; static bool _setup; @@ -120,6 +122,7 @@ private: TokenGrabberThread _tokenGrabber; TwitchToken _currentToken; std::unordered_map _optionWidgets; + QCheckBox *_validateTimestamps; QTimer _validationTimer; };