#pragma once #include "event-sub.hpp" #include #include #include #include #include #include #include #include namespace advss { class TwitchConnectionSelection; class TwitchTokenSettingsDialog; class TokenOption { public: void Load(obs_data_t *obj); void Save(obs_data_t *obj) const; std::string GetLocale() const; static const std::unordered_map & GetTokenOptionMap(); static std::set GetAllTokenOptions(); bool operator<(const TokenOption &other) const; std::string apiId = ""; private: const static std::unordered_map _apiIdToLocale; }; class TwitchToken : public Item { public: TwitchToken() = default; TwitchToken(const TwitchToken &); TwitchToken &operator=(const TwitchToken &); static std::shared_ptr Create() { return std::make_shared(); } void Load(obs_data_t *obj); void Save(obs_data_t *obj) const; std::string GetName() { return _name; } bool OptionIsActive(const TokenOption &option) const; bool OptionIsEnabled(const TokenOption &option) const; bool AnyOptionIsEnabled(const std::vector &options) const; void SetToken(const std::string &); bool IsEmpty() const { return _token.empty(); } 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; bool WarnIfInvalid() const { return _warnIfInvalid; } void SetWarnIfInvalid(bool value) { _warnIfInvalid = value; } size_t PermissionCount() const { return _tokenOptions.size(); } private: std::string _token; mutable std::mutex _cacheMutex; mutable std::string _lastValidityCheckValue; mutable bool _lastValidityCheckResult = false; mutable std::chrono::system_clock::time_point _lastValidityCheckTime; std::string _userID; std::set _tokenOptions = TokenOption::GetAllTokenOptions(); std::shared_ptr _eventSub; bool _validateEventSubTimestamps = false; bool _warnIfInvalid = true; static bool _setup; friend TwitchConnectionSelection; friend TwitchTokenSettingsDialog; }; class TokenGrabberThread : public QThread { Q_OBJECT public: ~TokenGrabberThread(); void SetTokenScope(const QString &value) { _scope = value; } signals: void GotToken(const std::optional &); protected: void run() override; private: void Stop(); QString _scope; std::optional _tokenString; static int _timeout; std::mutex _mutex; std::atomic_bool _stopWaiting = {false}; std::condition_variable _cv; std::thread _serverThread; httplib::Server _server; }; class TwitchTokenSettingsDialog : public ItemSettingsDialog { Q_OBJECT public: TwitchTokenSettingsDialog(QWidget *parent, const TwitchToken &); static bool AskForSettings(QWidget *parent, TwitchToken &settings); private slots: void ShowToken(); void HideToken(); void TokenOptionChanged(int); void RequestToken(); void GotToken(const std::optional &); void CheckIfTokenValid(); private: std::set GetEnabledOptions(); void SetTokenInfoVisible(bool); QPushButton *_requestToken; QPushButton *_showToken; QLineEdit *_currentTokenValue; QLabel *_tokenStatus; QGridLayout *_generalSettingsGrid; int _nameRow = -1; int _tokenValueRow = -1; TokenGrabberThread _tokenGrabber; TwitchToken _currentToken; std::unordered_map _optionWidgets; QCheckBox *_validateTimestamps; QCheckBox *_warnIfInvalid; QTimer _validationTimer; }; class TwitchConnectionSelection : public ItemSelection { Q_OBJECT public: TwitchConnectionSelection(QWidget *parent = 0); void SetToken(const std::string &); void SetToken(const std::weak_ptr &); }; // Helper class so that it is not required to add signals to the // AdvSceneSwitcher class for handling adding and removing Twitch connections class TwitchConnectionSignalManager : public QObject { Q_OBJECT public: static TwitchConnectionSignalManager *Instance(); private: signals: // Rename signal not required as name is based on Twitch account name // and item name cannot be manually changed void Add(const QString &); void Remove(const QString &); }; TwitchToken *GetTwitchTokenByName(const QString &); TwitchToken *GetTwitchTokenByName(const std::string &); std::weak_ptr GetWeakTwitchTokenByName(const std::string &name); std::weak_ptr GetWeakTwitchTokenByQString(const QString &name); std::string GetWeakTwitchTokenName(std::weak_ptr); bool TokenIsValid(const std::weak_ptr &token); std::deque> &GetTwitchTokens(); } // namespace advss Q_DECLARE_METATYPE(advss::TwitchToken *);