From 111853c574beb29e29d664c55714ec72ce0c3e6a Mon Sep 17 00:00:00 2001 From: fourtf Date: Sat, 14 Jul 2018 14:24:18 +0200 Subject: [PATCH] improving TwitchChannel --- .clang-format | 2 +- chatterino.pro | 958 +++++++++--------- src/common/Channel.cpp | 5 + src/common/Channel.hpp | 3 + src/common/Common.hpp | 12 +- src/common/NetworkRequest.cpp | 4 +- src/common/NetworkResult.cpp | 2 +- src/common/uniqueaccess.cpp | 1 + src/common/uniqueaccess.hpp | 81 ++ src/providers/twitch/IrcMessageHandler.cpp | 9 +- src/providers/twitch/PubsubClient.cpp | 2 +- src/providers/twitch/TwitchChannel.cpp | 273 +++-- src/providers/twitch/TwitchChannel.hpp | 56 +- src/providers/twitch/TwitchMessageBuilder.cpp | 4 +- src/providers/twitch/TwitchServer.cpp | 10 +- src/widgets/splits/SplitHeader.cpp | 4 +- 16 files changed, 752 insertions(+), 674 deletions(-) create mode 100644 src/common/uniqueaccess.cpp create mode 100644 src/common/uniqueaccess.hpp diff --git a/.clang-format b/.clang-format index 6e663cb67..e141fff60 100644 --- a/.clang-format +++ b/.clang-format @@ -15,7 +15,7 @@ BreakBeforeBraces: Custom AccessModifierOffset: -4 ConstructorInitializerAllOnOneLineOrOnePerLine: false AllowShortFunctionsOnASingleLine: false -AllowShortIfStatementsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: false DerivePointerBinding: false BraceWrapping: { diff --git a/chatterino.pro b/chatterino.pro index a7450cc82..f180f0715 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -1,478 +1,480 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-12-28T18:23:35 -# -#------------------------------------------------- - -message(----) - -QT += widgets core gui network multimedia svg -CONFIG += communi -COMMUNI += core model util -CONFIG += c++14 -INCLUDEPATH += src/ -TARGET = chatterino -TEMPLATE = app -DEFINES += QT_DEPRECATED_WARNINGS -PRECOMPILED_HEADER = src/PrecompiledHeader.hpp -CONFIG += precompile_header - -useBreakpad { - LIBS += -L$$PWD/lib/qBreakpad/handler/build - include(lib/qBreakpad/qBreakpad.pri) - DEFINES += C_USE_BREAKPAD -} - -# https://bugreports.qt.io/browse/QTBUG-27018 -equals(QMAKE_CXX, "clang++")|equals(QMAKE_CXX, "g++") { - TARGET = bin/chatterino -} - -# Icons -macx:ICON = resources/images/chatterino2.icns -win32:RC_FILE = resources/windows.rc - - -macx { - LIBS += -L/usr/local/lib -} - -# Submodules -include(dependencies/rapidjson.pri) -include(dependencies/settings.pri) -include(dependencies/signals.pri) -include(dependencies/humanize.pri) -include(dependencies/fmt.pri) -DEFINES += IRC_NAMESPACE=Communi -include(dependencies/libcommuni.pri) -include(dependencies/websocketpp.pri) -include(dependencies/openssl.pri) -include(dependencies/boost.pri) - -# Optional feature: QtWebEngine -#exists ($(QTDIR)/include/QtWebEngine/QtWebEngine) { -# message(Using QWebEngine) -# QT += webenginewidgets -# DEFINES += "USEWEBENGINE" -#} - -linux { - LIBS += -lrt -} - -win32 { - LIBS += -luser32 -} - -# OSX include directory -macx { - INCLUDEPATH += /usr/local/include -} - -# Optional dependency on Windows SDK 7 -!contains(QMAKE_TARGET.arch, x86_64) { - win32:exists(C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\Windows.h) { - LIBS += -L"C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib" \ - -ldwmapi - - DEFINES += "USEWINSDK" - message(Using Windows SDK 7) - } -} - -# Optional dependency on Windows SDK 10 -contains(QMAKE_TARGET.arch, x86_64) { - WIN_SDK_VERSION = $$(WindowsSDKVersion) - !isEmpty(WIN_SDK_VERSION) { - !equals(WIN_SDK_VERSION, "\\") { - DEFINES += "USEWINSDK" - message(Using Windows SDK 10) - } - } -} - -werr { - QMAKE_CXXFLAGS += -Werror - - message("Enabling error on warning") -} - -SOURCES += \ - src/Application.cpp \ - src/common/Channel.cpp \ - src/common/CompletionModel.cpp \ - src/common/Emotemap.cpp \ - src/common/NetworkData.cpp \ - src/common/NetworkManager.cpp \ - src/common/NetworkRequest.cpp \ - src/common/NetworkResult.cpp \ - src/common/NetworkTimer.cpp \ - src/controllers/accounts/Account.cpp \ - src/controllers/accounts/AccountController.cpp \ - src/controllers/accounts/AccountModel.cpp \ - src/controllers/commands/Command.cpp \ - src/controllers/commands/CommandController.cpp \ - src/controllers/commands/CommandModel.cpp \ - src/controllers/highlights/HighlightController.cpp \ - src/controllers/highlights/HighlightModel.cpp \ - src/controllers/highlights/HighlightBlacklistModel.cpp \ - src/controllers/highlights/UserHighlightModel.cpp \ - src/controllers/ignores/IgnoreController.cpp \ - src/controllers/ignores/IgnoreModel.cpp \ - src/controllers/taggedusers/TaggedUser.cpp \ - src/controllers/taggedusers/TaggedUsersController.cpp \ - src/controllers/taggedusers/TaggedUsersModel.cpp \ - src/main.cpp \ - src/messages/Image.cpp \ - src/messages/layouts/MessageLayout.cpp \ - src/messages/layouts/MessageLayoutContainer.cpp \ - src/messages/layouts/MessageLayoutElement.cpp \ - src/messages/Link.cpp \ - src/messages/Message.cpp \ - src/messages/MessageBuilder.cpp \ - src/messages/MessageColor.cpp \ - src/messages/MessageElement.cpp \ - src/providers/bttv/BttvEmotes.cpp \ - src/providers/emoji/Emojis.cpp \ - src/providers/ffz/FfzEmotes.cpp \ - src/providers/irc/AbstractIrcServer.cpp \ - src/providers/irc/IrcAccount.cpp \ - src/providers/irc/IrcChannel2.cpp \ - src/providers/irc/IrcConnection2.cpp \ - src/providers/irc/IrcServer.cpp \ - src/providers/twitch/IrcMessageHandler.cpp \ - src/providers/twitch/PartialTwitchUser.cpp \ - src/providers/twitch/PubsubActions.cpp \ - src/providers/twitch/PubsubHelpers.cpp \ - src/providers/twitch/TwitchAccount.cpp \ - src/providers/twitch/TwitchAccountManager.cpp \ - src/providers/twitch/TwitchChannel.cpp \ - src/providers/twitch/TwitchEmotes.cpp \ - src/providers/twitch/TwitchHelpers.cpp \ - src/providers/twitch/TwitchMessageBuilder.cpp \ - src/providers/twitch/TwitchServer.cpp \ - src/providers/twitch/TwitchUser.cpp \ - src/common/ChatterinoSetting.cpp \ - src/singletons/helper/GifTimer.cpp \ - src/singletons/helper/LoggingChannel.cpp \ - src/controllers/moderationactions/ModerationAction.cpp \ - src/singletons/WindowManager.cpp \ - src/util/DebugCount.cpp \ - src/util/RapidjsonHelpers.cpp \ - src/util/StreamLink.cpp \ - src/util/WindowsHelper.cpp \ - src/widgets/AccountSwitchPopupWidget.cpp \ - src/widgets/AccountSwitchWidget.cpp \ - src/widgets/AttachedWindow.cpp \ - src/widgets/BaseWidget.cpp \ - src/widgets/BaseWindow.cpp \ - src/widgets/dialogs/EmotePopup.cpp \ - src/widgets/dialogs/LastRunCrashDialog.cpp \ - src/widgets/dialogs/LoginDialog.cpp \ - src/widgets/dialogs/LogsPopup.cpp \ - src/widgets/dialogs/NotificationPopup.cpp \ - src/widgets/dialogs/QualityPopup.cpp \ - src/widgets/dialogs/SelectChannelDialog.cpp \ - src/widgets/dialogs/SettingsDialog.cpp \ - src/widgets/dialogs/TextInputDialog.cpp \ - src/widgets/dialogs/UserInfoPopup.cpp \ - src/widgets/dialogs/WelcomeDialog.cpp \ - src/widgets/helper/ChannelView.cpp \ - src/widgets/helper/ComboBoxItemDelegate.cpp \ - src/widgets/helper/DebugPopup.cpp \ - src/widgets/helper/EditableModelView.cpp \ - src/widgets/helper/NotebookButton.cpp \ - src/widgets/helper/NotebookTab.cpp \ - src/widgets/helper/ResizingTextEdit.cpp \ - src/widgets/helper/RippleEffectButton.cpp \ - src/widgets/helper/RippleEffectLabel.cpp \ - src/widgets/helper/ScrollbarHighlight.cpp \ - src/widgets/helper/SearchPopup.cpp \ - src/widgets/helper/SettingsDialogTab.cpp \ - src/widgets/helper/SignalLabel.cpp \ - src/widgets/helper/TitlebarButton.cpp \ - src/widgets/Label.cpp \ - src/widgets/Notebook.cpp \ - src/widgets/Scrollbar.cpp \ - src/widgets/settingspages/AboutPage.cpp \ - src/widgets/settingspages/AccountsPage.cpp \ - src/widgets/settingspages/BrowserExtensionPage.cpp \ - src/widgets/settingspages/CommandPage.cpp \ - src/widgets/settingspages/EmotesPage.cpp \ - src/widgets/settingspages/ExternalToolsPage.cpp \ - src/widgets/settingspages/HighlightingPage.cpp \ - src/widgets/settingspages/KeyboardSettingsPage.cpp \ - src/widgets/settingspages/LogsPage.cpp \ - src/widgets/settingspages/ModerationPage.cpp \ - src/widgets/settingspages/SettingsPage.cpp \ - src/widgets/settingspages/SpecialChannelsPage.cpp \ - src/widgets/splits/Split.cpp \ - src/widgets/splits/SplitContainer.cpp \ - src/widgets/splits/SplitHeader.cpp \ - src/widgets/splits/SplitInput.cpp \ - src/widgets/splits/SplitOverlay.cpp \ - src/widgets/StreamView.cpp \ - src/widgets/TooltipWidget.cpp \ - src/widgets/Window.cpp \ - src/common/LinkParser.cpp \ - src/controllers/moderationactions/ModerationActions.cpp \ - src/singletons/NativeMessaging.cpp \ - src/singletons/Emotes.cpp \ - src/singletons/Fonts.cpp \ - src/singletons/Logging.cpp \ - src/singletons/Paths.cpp \ - src/singletons/Resources.cpp \ - src/singletons/Settings.cpp \ - src/singletons/Updates.cpp \ - src/singletons/Theme.cpp \ - src/controllers/moderationactions/ModerationActionModel.cpp \ - src/widgets/settingspages/LookPage.cpp \ - src/widgets/settingspages/FeelPage.cpp \ - src/util/InitUpdateButton.cpp \ - src/widgets/dialogs/UpdateDialog.cpp \ - src/widgets/settingspages/IgnoresPage.cpp \ - src/providers/twitch/PubsubClient.cpp \ - src/providers/twitch/TwitchApi.cpp - -HEADERS += \ - src/Application.hpp \ - src/common/Channel.hpp \ - src/common/Common.hpp \ - src/common/CompletionModel.hpp \ - src/common/Emotemap.hpp \ - src/common/FlagsEnum.hpp \ - src/common/LockedObject.hpp \ - src/common/MutexValue.hpp \ - src/common/NetworkCommon.hpp \ - src/common/NetworkData.hpp \ - src/common/NetworkManager.hpp \ - src/common/NetworkRequest.hpp \ - src/common/NetworkRequester.hpp \ - src/common/NetworkResult.hpp \ - src/common/NetworkTimer.hpp \ - src/common/NetworkWorker.hpp \ - src/common/NullablePtr.hpp \ - src/common/Property.hpp \ - src/common/ProviderId.hpp \ - src/common/SerializeCustom.hpp \ - src/common/SignalVectorModel.hpp \ - src/common/UrlFetch.hpp \ - src/common/Version.hpp \ - src/controllers/accounts/Account.hpp \ - src/controllers/accounts/AccountController.hpp \ - src/controllers/accounts/AccountModel.hpp \ - src/controllers/commands/Command.hpp \ - src/controllers/commands/CommandController.hpp \ - src/controllers/commands/CommandModel.hpp \ - src/controllers/highlights/HighlightController.hpp \ - src/controllers/highlights/HighlightModel.hpp \ - src/controllers/highlights/HighlightBlacklistModel.hpp \ - src/controllers/highlights/HighlightPhrase.hpp \ - src/controllers/highlights/HighlightBlacklistUser.hpp \ - src/controllers/highlights/UserHighlightModel.hpp \ - src/controllers/ignores/IgnoreController.hpp \ - src/controllers/ignores/IgnoreModel.hpp \ - src/controllers/ignores/IgnorePhrase.hpp \ - src/controllers/taggedusers/TaggedUser.hpp \ - src/controllers/taggedusers/TaggedUsersController.hpp \ - src/controllers/taggedusers/TaggedUsersModel.hpp \ - src/debug/AssertInGuiThread.hpp \ - src/debug/Benchmark.hpp \ - src/debug/Log.hpp \ - src/messages/Image.hpp \ - src/messages/layouts/MessageLayout.hpp \ - src/messages/layouts/MessageLayoutContainer.hpp \ - src/messages/layouts/MessageLayoutElement.hpp \ - src/messages/LimitedQueue.hpp \ - src/messages/LimitedQueueSnapshot.hpp \ - src/messages/Link.hpp \ - src/messages/Message.hpp \ - src/messages/MessageBuilder.hpp \ - src/messages/MessageColor.hpp \ - src/messages/MessageElement.hpp \ - src/messages/MessageParseArgs.hpp \ - src/messages/Selection.hpp \ - src/PrecompiledHeader.hpp \ - src/providers/bttv/BttvEmotes.hpp \ - src/providers/emoji/Emojis.hpp \ - src/providers/ffz/FfzEmotes.hpp \ - src/providers/irc/AbstractIrcServer.hpp \ - src/providers/irc/IrcAccount.hpp \ - src/providers/irc/IrcChannel2.hpp \ - src/providers/irc/IrcConnection2.hpp \ - src/providers/irc/IrcServer.hpp \ - src/providers/twitch/EmoteValue.hpp \ - src/providers/twitch/IrcMessageHandler.hpp \ - src/providers/twitch/PartialTwitchUser.hpp \ - src/providers/twitch/PubsubActions.hpp \ - src/providers/twitch/PubsubHelpers.hpp \ - src/providers/twitch/TwitchAccount.hpp \ - src/providers/twitch/TwitchAccountManager.hpp \ - src/providers/twitch/TwitchChannel.hpp \ - src/providers/twitch/TwitchEmotes.hpp \ - src/providers/twitch/TwitchHelpers.hpp \ - src/providers/twitch/TwitchMessageBuilder.hpp \ - src/providers/twitch/TwitchServer.hpp \ - src/providers/twitch/TwitchUser.hpp \ - src/common/ChatterinoSetting.hpp \ - src/singletons/helper/GifTimer.hpp \ - src/singletons/helper/LoggingChannel.hpp \ - src/controllers/moderationactions/ModerationAction.hpp \ - src/singletons/WindowManager.hpp \ - src/util/Clamp.hpp \ - src/util/CombinePath.hpp \ - src/util/ConcurrentMap.hpp \ - src/util/DebugCount.hpp \ - src/util/DistanceBetweenPoints.hpp \ - src/util/Helpers.hpp \ - src/util/IrcHelpers.hpp \ - src/util/LayoutCreator.hpp \ - src/util/PostToThread.hpp \ - src/util/QStringHash.hpp \ - src/util/RapidjsonHelpers.hpp \ - src/util/RemoveScrollAreaBackground.hpp \ - src/util/SharedPtrElementLess.hpp \ - src/util/StandardItemHelper.hpp \ - src/util/StreamLink.hpp \ - src/util/WindowsHelper.hpp \ - src/widgets/AccountSwitchPopupWidget.hpp \ - src/widgets/AccountSwitchWidget.hpp \ - src/widgets/AttachedWindow.hpp \ - src/widgets/BaseWidget.hpp \ - src/widgets/BaseWindow.hpp \ - src/widgets/dialogs/EmotePopup.hpp \ - src/widgets/dialogs/LastRunCrashDialog.hpp \ - src/widgets/dialogs/LoginDialog.hpp \ - src/widgets/dialogs/LogsPopup.hpp \ - src/widgets/dialogs/NotificationPopup.hpp \ - src/widgets/dialogs/QualityPopup.hpp \ - src/widgets/dialogs/SelectChannelDialog.hpp \ - src/widgets/dialogs/SettingsDialog.hpp \ - src/widgets/dialogs/TextInputDialog.hpp \ - src/widgets/dialogs/UserInfoPopup.hpp \ - src/widgets/dialogs/WelcomeDialog.hpp \ - src/widgets/helper/ChannelView.hpp \ - src/widgets/helper/ComboBoxItemDelegate.hpp \ - src/widgets/helper/DebugPopup.hpp \ - src/widgets/helper/EditableModelView.hpp \ - src/widgets/helper/Line.hpp \ - src/widgets/helper/NotebookButton.hpp \ - src/widgets/helper/NotebookTab.hpp \ - src/widgets/helper/ResizingTextEdit.hpp \ - src/widgets/helper/RippleEffectButton.hpp \ - src/widgets/helper/RippleEffectLabel.hpp \ - src/widgets/helper/ScrollbarHighlight.hpp \ - src/widgets/helper/SearchPopup.hpp \ - src/widgets/helper/SettingsDialogTab.hpp \ - src/widgets/helper/Shortcut.hpp \ - src/widgets/helper/SignalLabel.hpp \ - src/widgets/helper/TitlebarButton.hpp \ - src/widgets/Label.hpp \ - src/widgets/Notebook.hpp \ - src/widgets/Scrollbar.hpp \ - src/widgets/settingspages/AboutPage.hpp \ - src/widgets/settingspages/AccountsPage.hpp \ - src/widgets/settingspages/BrowserExtensionPage.hpp \ - src/widgets/settingspages/CommandPage.hpp \ - src/widgets/settingspages/EmotesPage.hpp \ - src/widgets/settingspages/ExternalToolsPage.hpp \ - src/widgets/settingspages/HighlightingPage.hpp \ - src/widgets/settingspages/KeyboardSettingsPage.hpp \ - src/widgets/settingspages/LogsPage.hpp \ - src/widgets/settingspages/ModerationPage.hpp \ - src/widgets/settingspages/SettingsPage.hpp \ - src/widgets/settingspages/SpecialChannelsPage.hpp \ - src/widgets/splits/Split.hpp \ - src/widgets/splits/SplitContainer.hpp \ - src/widgets/splits/SplitHeader.hpp \ - src/widgets/splits/SplitInput.hpp \ - src/widgets/splits/SplitOverlay.hpp \ - src/widgets/StreamView.hpp \ - src/widgets/TooltipWidget.hpp \ - src/widgets/Window.hpp \ - src/providers/twitch/TwitchCommon.hpp \ - src/util/IsBigEndian.hpp \ - src/common/LinkParser.hpp \ - src/controllers/moderationactions/ModerationActions.hpp \ - src/singletons/Emotes.hpp \ - src/singletons/Fonts.hpp \ - src/singletons/Logging.hpp \ - src/singletons/Paths.hpp \ - src/singletons/Resources.hpp \ - src/singletons/Settings.hpp \ - src/singletons/Updates.hpp \ - src/singletons/NativeMessaging.hpp \ - src/singletons/Theme.hpp \ - src/common/SimpleSignalVector.hpp \ - src/common/SignalVector.hpp \ - src/widgets/dialogs/LogsPopup.hpp \ - src/common/Singleton.hpp \ - src/controllers/moderationactions/ModerationActionModel.hpp \ - src/widgets/settingspages/LookPage.hpp \ - src/widgets/settingspages/FeelPage.hpp \ - src/util/InitUpdateButton.hpp \ - src/widgets/dialogs/UpdateDialog.hpp \ - src/widgets/settingspages/IgnoresPage.hpp \ - src/providers/twitch/PubsubClient.hpp \ - src/providers/twitch/TwitchApi.hpp - -RESOURCES += \ - resources/resources.qrc \ - -DISTFILES += - -FORMS += - -# Define warning flags for Chatterino -win32-msvc* { - QMAKE_CXXFLAGS_WARN_ON = /W4 - # 4714 - function marked as __forceinline not inlined - # 4996 - occurs when the compiler encounters a function or variable that is marked as deprecated. - # These functions may have a different preferred name, may be insecure or have - # a more secure variant, or may be obsolete. - # 4505 - unreferenced local version has been removed - # 4127 - conditional expression is constant - # 4503 - decorated name length exceeded, name was truncated - # 4100 - unreferences formal parameter - # 4305 - possible truncation of data - # 4267 - possible loss of data in return - QMAKE_CXXFLAGS_WARN_ON += /wd4714 - QMAKE_CXXFLAGS_WARN_ON += /wd4996 - QMAKE_CXXFLAGS_WARN_ON += /wd4505 - QMAKE_CXXFLAGS_WARN_ON += /wd4127 - QMAKE_CXXFLAGS_WARN_ON += /wd4503 - QMAKE_CXXFLAGS_WARN_ON += /wd4100 - QMAKE_CXXFLAGS_WARN_ON += /wd4305 - QMAKE_CXXFLAGS_WARN_ON += /wd4267 - -} else { - QMAKE_CXXFLAGS_WARN_ON = -Wall - QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function - QMAKE_CXXFLAGS_WARN_ON += -Wno-switch - QMAKE_CXXFLAGS_WARN_ON += -Wno-deprecated-declarations - QMAKE_CXXFLAGS_WARN_ON += -Wno-sign-compare - QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable - QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-private-field - - # Disabling strict-aliasing warnings for now, although we probably want to re-enable this in the future - QMAKE_CXXFLAGS_WARN_ON += -Wno-strict-aliasing - - QMAKE_CXXFLAGS_WARN_ON += -Werror=return-type - - equals(QMAKE_CXX, "clang++") { - QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-local-typedef - } else { - QMAKE_CXXFLAGS_WARN_ON += -Wno-class-memaccess - } -} - -# do not use windows min/max macros -#win32 { -# DEFINES += NOMINMAX -#} - -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -linux { - QMAKE_LFLAGS += -lrt -} +#------------------------------------------------- +# +# Project created by QtCreator 2016-12-28T18:23:35 +# +#------------------------------------------------- + +message(----) + +QT += widgets core gui network multimedia svg +CONFIG += communi +COMMUNI += core model util +CONFIG += c++14 +INCLUDEPATH += src/ +TARGET = chatterino +TEMPLATE = app +DEFINES += QT_DEPRECATED_WARNINGS +PRECOMPILED_HEADER = src/PrecompiledHeader.hpp +CONFIG += precompile_header + +useBreakpad { + LIBS += -L$$PWD/lib/qBreakpad/handler/build + include(lib/qBreakpad/qBreakpad.pri) + DEFINES += C_USE_BREAKPAD +} + +# https://bugreports.qt.io/browse/QTBUG-27018 +equals(QMAKE_CXX, "clang++")|equals(QMAKE_CXX, "g++") { + TARGET = bin/chatterino +} + +# Icons +macx:ICON = resources/images/chatterino2.icns +win32:RC_FILE = resources/windows.rc + + +macx { + LIBS += -L/usr/local/lib +} + +# Submodules +include(dependencies/rapidjson.pri) +include(dependencies/settings.pri) +include(dependencies/signals.pri) +include(dependencies/humanize.pri) +include(dependencies/fmt.pri) +DEFINES += IRC_NAMESPACE=Communi +include(dependencies/libcommuni.pri) +include(dependencies/websocketpp.pri) +include(dependencies/openssl.pri) +include(dependencies/boost.pri) + +# Optional feature: QtWebEngine +#exists ($(QTDIR)/include/QtWebEngine/QtWebEngine) { +# message(Using QWebEngine) +# QT += webenginewidgets +# DEFINES += "USEWEBENGINE" +#} + +linux { + LIBS += -lrt +} + +win32 { + LIBS += -luser32 +} + +# OSX include directory +macx { + INCLUDEPATH += /usr/local/include +} + +# Optional dependency on Windows SDK 7 +!contains(QMAKE_TARGET.arch, x86_64) { + win32:exists(C:\Program Files\Microsoft SDKs\Windows\v7.1\Include\Windows.h) { + LIBS += -L"C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib" \ + -ldwmapi + + DEFINES += "USEWINSDK" + message(Using Windows SDK 7) + } +} + +# Optional dependency on Windows SDK 10 +contains(QMAKE_TARGET.arch, x86_64) { + WIN_SDK_VERSION = $$(WindowsSDKVersion) + !isEmpty(WIN_SDK_VERSION) { + !equals(WIN_SDK_VERSION, "\\") { + DEFINES += "USEWINSDK" + message(Using Windows SDK 10) + } + } +} + +werr { + QMAKE_CXXFLAGS += -Werror + + message("Enabling error on warning") +} + +SOURCES += \ + src/Application.cpp \ + src/common/Channel.cpp \ + src/common/CompletionModel.cpp \ + src/common/Emotemap.cpp \ + src/common/NetworkData.cpp \ + src/common/NetworkManager.cpp \ + src/common/NetworkRequest.cpp \ + src/common/NetworkResult.cpp \ + src/common/NetworkTimer.cpp \ + src/controllers/accounts/Account.cpp \ + src/controllers/accounts/AccountController.cpp \ + src/controllers/accounts/AccountModel.cpp \ + src/controllers/commands/Command.cpp \ + src/controllers/commands/CommandController.cpp \ + src/controllers/commands/CommandModel.cpp \ + src/controllers/highlights/HighlightController.cpp \ + src/controllers/highlights/HighlightModel.cpp \ + src/controllers/highlights/HighlightBlacklistModel.cpp \ + src/controllers/highlights/UserHighlightModel.cpp \ + src/controllers/ignores/IgnoreController.cpp \ + src/controllers/ignores/IgnoreModel.cpp \ + src/controllers/taggedusers/TaggedUser.cpp \ + src/controllers/taggedusers/TaggedUsersController.cpp \ + src/controllers/taggedusers/TaggedUsersModel.cpp \ + src/main.cpp \ + src/messages/Image.cpp \ + src/messages/layouts/MessageLayout.cpp \ + src/messages/layouts/MessageLayoutContainer.cpp \ + src/messages/layouts/MessageLayoutElement.cpp \ + src/messages/Link.cpp \ + src/messages/Message.cpp \ + src/messages/MessageBuilder.cpp \ + src/messages/MessageColor.cpp \ + src/messages/MessageElement.cpp \ + src/providers/bttv/BttvEmotes.cpp \ + src/providers/emoji/Emojis.cpp \ + src/providers/ffz/FfzEmotes.cpp \ + src/providers/irc/AbstractIrcServer.cpp \ + src/providers/irc/IrcAccount.cpp \ + src/providers/irc/IrcChannel2.cpp \ + src/providers/irc/IrcConnection2.cpp \ + src/providers/irc/IrcServer.cpp \ + src/providers/twitch/IrcMessageHandler.cpp \ + src/providers/twitch/PartialTwitchUser.cpp \ + src/providers/twitch/PubsubActions.cpp \ + src/providers/twitch/PubsubHelpers.cpp \ + src/providers/twitch/TwitchAccount.cpp \ + src/providers/twitch/TwitchAccountManager.cpp \ + src/providers/twitch/TwitchChannel.cpp \ + src/providers/twitch/TwitchEmotes.cpp \ + src/providers/twitch/TwitchHelpers.cpp \ + src/providers/twitch/TwitchMessageBuilder.cpp \ + src/providers/twitch/TwitchServer.cpp \ + src/providers/twitch/TwitchUser.cpp \ + src/common/ChatterinoSetting.cpp \ + src/singletons/helper/GifTimer.cpp \ + src/singletons/helper/LoggingChannel.cpp \ + src/controllers/moderationactions/ModerationAction.cpp \ + src/singletons/WindowManager.cpp \ + src/util/DebugCount.cpp \ + src/util/RapidjsonHelpers.cpp \ + src/util/StreamLink.cpp \ + src/util/WindowsHelper.cpp \ + src/widgets/AccountSwitchPopupWidget.cpp \ + src/widgets/AccountSwitchWidget.cpp \ + src/widgets/AttachedWindow.cpp \ + src/widgets/BaseWidget.cpp \ + src/widgets/BaseWindow.cpp \ + src/widgets/dialogs/EmotePopup.cpp \ + src/widgets/dialogs/LastRunCrashDialog.cpp \ + src/widgets/dialogs/LoginDialog.cpp \ + src/widgets/dialogs/LogsPopup.cpp \ + src/widgets/dialogs/NotificationPopup.cpp \ + src/widgets/dialogs/QualityPopup.cpp \ + src/widgets/dialogs/SelectChannelDialog.cpp \ + src/widgets/dialogs/SettingsDialog.cpp \ + src/widgets/dialogs/TextInputDialog.cpp \ + src/widgets/dialogs/UserInfoPopup.cpp \ + src/widgets/dialogs/WelcomeDialog.cpp \ + src/widgets/helper/ChannelView.cpp \ + src/widgets/helper/ComboBoxItemDelegate.cpp \ + src/widgets/helper/DebugPopup.cpp \ + src/widgets/helper/EditableModelView.cpp \ + src/widgets/helper/NotebookButton.cpp \ + src/widgets/helper/NotebookTab.cpp \ + src/widgets/helper/ResizingTextEdit.cpp \ + src/widgets/helper/RippleEffectButton.cpp \ + src/widgets/helper/RippleEffectLabel.cpp \ + src/widgets/helper/ScrollbarHighlight.cpp \ + src/widgets/helper/SearchPopup.cpp \ + src/widgets/helper/SettingsDialogTab.cpp \ + src/widgets/helper/SignalLabel.cpp \ + src/widgets/helper/TitlebarButton.cpp \ + src/widgets/Label.cpp \ + src/widgets/Notebook.cpp \ + src/widgets/Scrollbar.cpp \ + src/widgets/settingspages/AboutPage.cpp \ + src/widgets/settingspages/AccountsPage.cpp \ + src/widgets/settingspages/BrowserExtensionPage.cpp \ + src/widgets/settingspages/CommandPage.cpp \ + src/widgets/settingspages/EmotesPage.cpp \ + src/widgets/settingspages/ExternalToolsPage.cpp \ + src/widgets/settingspages/HighlightingPage.cpp \ + src/widgets/settingspages/KeyboardSettingsPage.cpp \ + src/widgets/settingspages/LogsPage.cpp \ + src/widgets/settingspages/ModerationPage.cpp \ + src/widgets/settingspages/SettingsPage.cpp \ + src/widgets/settingspages/SpecialChannelsPage.cpp \ + src/widgets/splits/Split.cpp \ + src/widgets/splits/SplitContainer.cpp \ + src/widgets/splits/SplitHeader.cpp \ + src/widgets/splits/SplitInput.cpp \ + src/widgets/splits/SplitOverlay.cpp \ + src/widgets/StreamView.cpp \ + src/widgets/TooltipWidget.cpp \ + src/widgets/Window.cpp \ + src/common/LinkParser.cpp \ + src/controllers/moderationactions/ModerationActions.cpp \ + src/singletons/NativeMessaging.cpp \ + src/singletons/Emotes.cpp \ + src/singletons/Fonts.cpp \ + src/singletons/Logging.cpp \ + src/singletons/Paths.cpp \ + src/singletons/Resources.cpp \ + src/singletons/Settings.cpp \ + src/singletons/Updates.cpp \ + src/singletons/Theme.cpp \ + src/controllers/moderationactions/ModerationActionModel.cpp \ + src/widgets/settingspages/LookPage.cpp \ + src/widgets/settingspages/FeelPage.cpp \ + src/util/InitUpdateButton.cpp \ + src/widgets/dialogs/UpdateDialog.cpp \ + src/widgets/settingspages/IgnoresPage.cpp \ + src/providers/twitch/PubsubClient.cpp \ + src/providers/twitch/TwitchApi.cpp \ + src/common/uniqueaccess.cpp + +HEADERS += \ + src/Application.hpp \ + src/common/Channel.hpp \ + src/common/Common.hpp \ + src/common/CompletionModel.hpp \ + src/common/Emotemap.hpp \ + src/common/FlagsEnum.hpp \ + src/common/LockedObject.hpp \ + src/common/MutexValue.hpp \ + src/common/NetworkCommon.hpp \ + src/common/NetworkData.hpp \ + src/common/NetworkManager.hpp \ + src/common/NetworkRequest.hpp \ + src/common/NetworkRequester.hpp \ + src/common/NetworkResult.hpp \ + src/common/NetworkTimer.hpp \ + src/common/NetworkWorker.hpp \ + src/common/NullablePtr.hpp \ + src/common/Property.hpp \ + src/common/ProviderId.hpp \ + src/common/SerializeCustom.hpp \ + src/common/SignalVectorModel.hpp \ + src/common/UrlFetch.hpp \ + src/common/Version.hpp \ + src/controllers/accounts/Account.hpp \ + src/controllers/accounts/AccountController.hpp \ + src/controllers/accounts/AccountModel.hpp \ + src/controllers/commands/Command.hpp \ + src/controllers/commands/CommandController.hpp \ + src/controllers/commands/CommandModel.hpp \ + src/controllers/highlights/HighlightController.hpp \ + src/controllers/highlights/HighlightModel.hpp \ + src/controllers/highlights/HighlightBlacklistModel.hpp \ + src/controllers/highlights/HighlightPhrase.hpp \ + src/controllers/highlights/HighlightBlacklistUser.hpp \ + src/controllers/highlights/UserHighlightModel.hpp \ + src/controllers/ignores/IgnoreController.hpp \ + src/controllers/ignores/IgnoreModel.hpp \ + src/controllers/ignores/IgnorePhrase.hpp \ + src/controllers/taggedusers/TaggedUser.hpp \ + src/controllers/taggedusers/TaggedUsersController.hpp \ + src/controllers/taggedusers/TaggedUsersModel.hpp \ + src/debug/AssertInGuiThread.hpp \ + src/debug/Benchmark.hpp \ + src/debug/Log.hpp \ + src/messages/Image.hpp \ + src/messages/layouts/MessageLayout.hpp \ + src/messages/layouts/MessageLayoutContainer.hpp \ + src/messages/layouts/MessageLayoutElement.hpp \ + src/messages/LimitedQueue.hpp \ + src/messages/LimitedQueueSnapshot.hpp \ + src/messages/Link.hpp \ + src/messages/Message.hpp \ + src/messages/MessageBuilder.hpp \ + src/messages/MessageColor.hpp \ + src/messages/MessageElement.hpp \ + src/messages/MessageParseArgs.hpp \ + src/messages/Selection.hpp \ + src/PrecompiledHeader.hpp \ + src/providers/bttv/BttvEmotes.hpp \ + src/providers/emoji/Emojis.hpp \ + src/providers/ffz/FfzEmotes.hpp \ + src/providers/irc/AbstractIrcServer.hpp \ + src/providers/irc/IrcAccount.hpp \ + src/providers/irc/IrcChannel2.hpp \ + src/providers/irc/IrcConnection2.hpp \ + src/providers/irc/IrcServer.hpp \ + src/providers/twitch/EmoteValue.hpp \ + src/providers/twitch/IrcMessageHandler.hpp \ + src/providers/twitch/PartialTwitchUser.hpp \ + src/providers/twitch/PubsubActions.hpp \ + src/providers/twitch/PubsubHelpers.hpp \ + src/providers/twitch/TwitchAccount.hpp \ + src/providers/twitch/TwitchAccountManager.hpp \ + src/providers/twitch/TwitchChannel.hpp \ + src/providers/twitch/TwitchEmotes.hpp \ + src/providers/twitch/TwitchHelpers.hpp \ + src/providers/twitch/TwitchMessageBuilder.hpp \ + src/providers/twitch/TwitchServer.hpp \ + src/providers/twitch/TwitchUser.hpp \ + src/common/ChatterinoSetting.hpp \ + src/singletons/helper/GifTimer.hpp \ + src/singletons/helper/LoggingChannel.hpp \ + src/controllers/moderationactions/ModerationAction.hpp \ + src/singletons/WindowManager.hpp \ + src/util/Clamp.hpp \ + src/util/CombinePath.hpp \ + src/util/ConcurrentMap.hpp \ + src/util/DebugCount.hpp \ + src/util/DistanceBetweenPoints.hpp \ + src/util/Helpers.hpp \ + src/util/IrcHelpers.hpp \ + src/util/LayoutCreator.hpp \ + src/util/PostToThread.hpp \ + src/util/QStringHash.hpp \ + src/util/RapidjsonHelpers.hpp \ + src/util/RemoveScrollAreaBackground.hpp \ + src/util/SharedPtrElementLess.hpp \ + src/util/StandardItemHelper.hpp \ + src/util/StreamLink.hpp \ + src/util/WindowsHelper.hpp \ + src/widgets/AccountSwitchPopupWidget.hpp \ + src/widgets/AccountSwitchWidget.hpp \ + src/widgets/AttachedWindow.hpp \ + src/widgets/BaseWidget.hpp \ + src/widgets/BaseWindow.hpp \ + src/widgets/dialogs/EmotePopup.hpp \ + src/widgets/dialogs/LastRunCrashDialog.hpp \ + src/widgets/dialogs/LoginDialog.hpp \ + src/widgets/dialogs/LogsPopup.hpp \ + src/widgets/dialogs/NotificationPopup.hpp \ + src/widgets/dialogs/QualityPopup.hpp \ + src/widgets/dialogs/SelectChannelDialog.hpp \ + src/widgets/dialogs/SettingsDialog.hpp \ + src/widgets/dialogs/TextInputDialog.hpp \ + src/widgets/dialogs/UserInfoPopup.hpp \ + src/widgets/dialogs/WelcomeDialog.hpp \ + src/widgets/helper/ChannelView.hpp \ + src/widgets/helper/ComboBoxItemDelegate.hpp \ + src/widgets/helper/DebugPopup.hpp \ + src/widgets/helper/EditableModelView.hpp \ + src/widgets/helper/Line.hpp \ + src/widgets/helper/NotebookButton.hpp \ + src/widgets/helper/NotebookTab.hpp \ + src/widgets/helper/ResizingTextEdit.hpp \ + src/widgets/helper/RippleEffectButton.hpp \ + src/widgets/helper/RippleEffectLabel.hpp \ + src/widgets/helper/ScrollbarHighlight.hpp \ + src/widgets/helper/SearchPopup.hpp \ + src/widgets/helper/SettingsDialogTab.hpp \ + src/widgets/helper/Shortcut.hpp \ + src/widgets/helper/SignalLabel.hpp \ + src/widgets/helper/TitlebarButton.hpp \ + src/widgets/Label.hpp \ + src/widgets/Notebook.hpp \ + src/widgets/Scrollbar.hpp \ + src/widgets/settingspages/AboutPage.hpp \ + src/widgets/settingspages/AccountsPage.hpp \ + src/widgets/settingspages/BrowserExtensionPage.hpp \ + src/widgets/settingspages/CommandPage.hpp \ + src/widgets/settingspages/EmotesPage.hpp \ + src/widgets/settingspages/ExternalToolsPage.hpp \ + src/widgets/settingspages/HighlightingPage.hpp \ + src/widgets/settingspages/KeyboardSettingsPage.hpp \ + src/widgets/settingspages/LogsPage.hpp \ + src/widgets/settingspages/ModerationPage.hpp \ + src/widgets/settingspages/SettingsPage.hpp \ + src/widgets/settingspages/SpecialChannelsPage.hpp \ + src/widgets/splits/Split.hpp \ + src/widgets/splits/SplitContainer.hpp \ + src/widgets/splits/SplitHeader.hpp \ + src/widgets/splits/SplitInput.hpp \ + src/widgets/splits/SplitOverlay.hpp \ + src/widgets/StreamView.hpp \ + src/widgets/TooltipWidget.hpp \ + src/widgets/Window.hpp \ + src/providers/twitch/TwitchCommon.hpp \ + src/util/IsBigEndian.hpp \ + src/common/LinkParser.hpp \ + src/controllers/moderationactions/ModerationActions.hpp \ + src/singletons/Emotes.hpp \ + src/singletons/Fonts.hpp \ + src/singletons/Logging.hpp \ + src/singletons/Paths.hpp \ + src/singletons/Resources.hpp \ + src/singletons/Settings.hpp \ + src/singletons/Updates.hpp \ + src/singletons/NativeMessaging.hpp \ + src/singletons/Theme.hpp \ + src/common/SimpleSignalVector.hpp \ + src/common/SignalVector.hpp \ + src/widgets/dialogs/LogsPopup.hpp \ + src/common/Singleton.hpp \ + src/controllers/moderationactions/ModerationActionModel.hpp \ + src/widgets/settingspages/LookPage.hpp \ + src/widgets/settingspages/FeelPage.hpp \ + src/util/InitUpdateButton.hpp \ + src/widgets/dialogs/UpdateDialog.hpp \ + src/widgets/settingspages/IgnoresPage.hpp \ + src/providers/twitch/PubsubClient.hpp \ + src/providers/twitch/TwitchApi.hpp \ + src/common/uniqueaccess.hpp + +RESOURCES += \ + resources/resources.qrc \ + +DISTFILES += + +FORMS += + +# Define warning flags for Chatterino +win32-msvc* { + QMAKE_CXXFLAGS_WARN_ON = /W4 + # 4714 - function marked as __forceinline not inlined + # 4996 - occurs when the compiler encounters a function or variable that is marked as deprecated. + # These functions may have a different preferred name, may be insecure or have + # a more secure variant, or may be obsolete. + # 4505 - unreferenced local version has been removed + # 4127 - conditional expression is constant + # 4503 - decorated name length exceeded, name was truncated + # 4100 - unreferences formal parameter + # 4305 - possible truncation of data + # 4267 - possible loss of data in return + QMAKE_CXXFLAGS_WARN_ON += /wd4714 + QMAKE_CXXFLAGS_WARN_ON += /wd4996 + QMAKE_CXXFLAGS_WARN_ON += /wd4505 + QMAKE_CXXFLAGS_WARN_ON += /wd4127 + QMAKE_CXXFLAGS_WARN_ON += /wd4503 + QMAKE_CXXFLAGS_WARN_ON += /wd4100 + QMAKE_CXXFLAGS_WARN_ON += /wd4305 + QMAKE_CXXFLAGS_WARN_ON += /wd4267 + +} else { + QMAKE_CXXFLAGS_WARN_ON = -Wall + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-function + QMAKE_CXXFLAGS_WARN_ON += -Wno-switch + QMAKE_CXXFLAGS_WARN_ON += -Wno-deprecated-declarations + QMAKE_CXXFLAGS_WARN_ON += -Wno-sign-compare + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-variable + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-private-field + + # Disabling strict-aliasing warnings for now, although we probably want to re-enable this in the future + QMAKE_CXXFLAGS_WARN_ON += -Wno-strict-aliasing + + QMAKE_CXXFLAGS_WARN_ON += -Werror=return-type + + equals(QMAKE_CXX, "clang++") { + QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-local-typedef + } else { + QMAKE_CXXFLAGS_WARN_ON += -Wno-class-memaccess + } +} + +# do not use windows min/max macros +#win32 { +# DEFINES += NOMINMAX +#} + +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +linux { + QMAKE_LFLAGS += -lrt +} diff --git a/src/common/Channel.cpp b/src/common/Channel.cpp index 26d9e536e..a0ffc511f 100644 --- a/src/common/Channel.cpp +++ b/src/common/Channel.cpp @@ -215,4 +215,9 @@ void Channel::onConnected() { } +std::weak_ptr Channel::weak_from_this() +{ + return std::weak_ptr(this->shared_from_this()); +} + } // namespace chatterino diff --git a/src/common/Channel.hpp b/src/common/Channel.hpp index 552349419..99172c108 100644 --- a/src/common/Channel.hpp +++ b/src/common/Channel.hpp @@ -65,6 +65,9 @@ public: CompletionModel completionModel; + // pre c++17 polyfill + std::weak_ptr weak_from_this(); + protected: virtual void onConnected(); diff --git a/src/common/Common.hpp b/src/common/Common.hpp index f73ea030b..3a573163d 100644 --- a/src/common/Common.hpp +++ b/src/common/Common.hpp @@ -27,14 +27,14 @@ const Qt::KeyboardModifiers showResizeHandlesModifiers = Qt::ControlModifier; static const char *ANONYMOUS_USERNAME_LABEL ATTR_UNUSED = " - anonymous - "; -#define return_if(x) \ - if ((x)) { \ - return; \ +#define return_if(condition) \ + if ((condition)) { \ + return; \ } -#define return_unless(x) \ - if (!(x)) { \ - return; \ +#define return_unless(condition) \ + if (!(condition)) { \ + return; \ } } // namespace chatterino diff --git a/src/common/NetworkRequest.cpp b/src/common/NetworkRequest.cpp index 0311c09e9..62929fe2a 100644 --- a/src/common/NetworkRequest.cpp +++ b/src/common/NetworkRequest.cpp @@ -212,9 +212,7 @@ void NetworkRequest::doRequest() return; } - QByteArray readBytes = reply->readAll(); - QByteArray bytes; - bytes.setRawData(readBytes.data(), readBytes.size()); + QByteArray bytes = reply->readAll(); data->writeToCache(bytes); NetworkResult result(bytes); diff --git a/src/common/NetworkResult.cpp b/src/common/NetworkResult.cpp index 80eb582ff..6d8b70067 100644 --- a/src/common/NetworkResult.cpp +++ b/src/common/NetworkResult.cpp @@ -25,7 +25,7 @@ QJsonObject NetworkResult::parseJson() const rapidjson::Document NetworkResult::parseRapidJson() const { - rapidjson::Document ret(rapidjson::kNullType); + rapidjson::Document ret(rapidjson::kObjectType); rapidjson::ParseResult result = ret.Parse(this->data_.data(), this->data_.length()); diff --git a/src/common/uniqueaccess.cpp b/src/common/uniqueaccess.cpp new file mode 100644 index 000000000..12e1c8846 --- /dev/null +++ b/src/common/uniqueaccess.cpp @@ -0,0 +1 @@ +#include "uniqueaccess.hpp" diff --git a/src/common/uniqueaccess.hpp b/src/common/uniqueaccess.hpp new file mode 100644 index 000000000..2f2a2be36 --- /dev/null +++ b/src/common/uniqueaccess.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include +#include + +namespace chatterino { + +template +class AccessGuard +{ +public: + AccessGuard(T &element, std::mutex &mutex) + : element_(element) + , mutex_(mutex) + { + this->mutex_.lock(); + } + + ~AccessGuard() + { + this->mutex_.unlock(); + } + + T *operator->() const + { + return &this->element_; + } + + T &operator*() const + { + return this->element_; + } + +private: + T &element_; + std::mutex &mutex_; +}; + +template +class UniqueAccess +{ +public: + template ::value>::type * = 0> + UniqueAccess() + : element_(T()) + { + } + + UniqueAccess(const T &element) + : element_(element) + { + } + + UniqueAccess(T &&element) + : element_(element) + { + } + + UniqueAccess &operator=(const T &element) + { + this->element_ = element; + return *this; + } + + UniqueAccess &operator=(T &&element) + { + this->element_ = element; + return *this; + } + + AccessGuard access() + { + return AccessGuard(this->element_, this->mutex_); + } + +private: + T element_; + std::mutex mutex_; +}; + +} // namespace chatterino diff --git a/src/providers/twitch/IrcMessageHandler.cpp b/src/providers/twitch/IrcMessageHandler.cpp index 904c772c8..de6ab30a9 100644 --- a/src/providers/twitch/IrcMessageHandler.cpp +++ b/src/providers/twitch/IrcMessageHandler.cpp @@ -85,18 +85,17 @@ void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message) return; } auto chan = app->twitch.server->getChannelOrEmpty(chanName); - TwitchChannel *twitchChannel = dynamic_cast(chan.get()); - if (twitchChannel) { + if (auto *twitchChannel = dynamic_cast(chan.get())) { // room-id decltype(tags.find("xD")) it; if ((it = tags.find("room-id")) != tags.end()) { - auto roomID = it.value().toString(); + auto roomId = it.value().toString(); - twitchChannel->setRoomID(roomID); + twitchChannel->setRoomID(roomId); - app->resources->loadChannelData(roomID); + app->resources->loadChannelData(roomId); } // Room modes diff --git a/src/providers/twitch/PubsubClient.cpp b/src/providers/twitch/PubsubClient.cpp index 726f54915..0ea37481a 100644 --- a/src/providers/twitch/PubsubClient.cpp +++ b/src/providers/twitch/PubsubClient.cpp @@ -513,7 +513,7 @@ void PubSub::listenToChannelModerationActions(const QString &channelID, assert(!channelID.isEmpty()); assert(account != nullptr); QString userID = account->getUserId(); - assert(!userID.isEmpty()); + if (userID.isEmpty()) return; std::string topic(fS("chat_moderator_actions.{}.{}", userID, channelID)); diff --git a/src/providers/twitch/TwitchChannel.cpp b/src/providers/twitch/TwitchChannel.cpp index 4c1285f6f..2fa2a6c8e 100644 --- a/src/providers/twitch/TwitchChannel.cpp +++ b/src/providers/twitch/TwitchChannel.cpp @@ -31,78 +31,35 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection { Log("[TwitchChannel:{}] Opened", this->name); - this->startRefreshLiveStatusTimer(60 * 1000); + this->refreshChannelEmotes(); + this->refreshViewerList(); - auto app = getApp(); - this->reloadChannelEmotes(); + this->managedConnect(getApp()->accounts->twitch.currentUserChanged, + [=] { this->setMod(false); }); - this->managedConnect(app->accounts->twitch.currentUserChanged, - [this]() { this->setMod(false); }); + // pubsub + this->userStateChanged.connect([=] { this->refreshPubsub(); }); + this->roomIDChanged.connect([=] { this->refreshPubsub(); }); + this->managedConnect(getApp()->accounts->twitch.currentUserChanged, + [=] { this->refreshPubsub(); }); + this->refreshPubsub(); - auto refreshPubSubState = [=]() { - if (!this->hasModRights()) { - return; - } + // room id loaded -> refresh live status + this->roomIDChanged.connect([this]() { this->refreshLiveStatus(); }); - if (this->roomID.isEmpty()) { - return; - } + // timers + QObject::connect(&this->chattersListTimer_, &QTimer::timeout, + [=] { this->refreshViewerList(); }); + this->chattersListTimer_.start(5 * 60 * 1000); - auto account = app->accounts->twitch.getCurrent(); - if (account && !account->getUserId().isEmpty()) { - app->twitch.pubsub->listenToChannelModerationActions(this->roomID, account); - } - }; - - this->userStateChanged.connect(refreshPubSubState); - this->roomIDchanged.connect(refreshPubSubState); - this->managedConnect(app->accounts->twitch.currentUserChanged, refreshPubSubState); - refreshPubSubState(); - - this->fetchMessages.connect([this] { - this->fetchRecentMessages(); // - }); + QObject::connect(&this->liveStatusTimer_, &QTimer::timeout, [=] { this->refreshLiveStatus(); }); + this->liveStatusTimer_.start(60 * 1000); + // -- this->messageSuffix_.append(' '); this->messageSuffix_.append(QChar(0x206D)); - static QStringList jsonLabels = {"moderators", "staff", "admins", "global_mods", "viewers"}; - auto refreshChatters = [=](QJsonObject obj) { - QJsonObject chattersObj = obj.value("chatters").toObject(); - for (int i = 0; i < jsonLabels.size(); i++) { - foreach (const QJsonValue &v, chattersObj.value(jsonLabels.at(i)).toArray()) { - this->completionModel.addUser(v.toString()); - } - } - }; - - auto doRefreshChatters = [=]() { - const auto streamStatus = this->getStreamStatus(); - - if (app->settings->onlyFetchChattersForSmallerStreamers) { - if (streamStatus.live && streamStatus.viewerCount > app->settings->smallStreamerLimit) { - return; - } - } - - NetworkRequest request("https://tmi.twitch.tv/group/user/" + this->name + "/chatters"); - - request.setCaller(QThread::currentThread()); - request.onSuccess([refreshChatters](auto result) { - refreshChatters(result.parseJson()); // - - return true; - }); - - request.execute(); - }; - - doRefreshChatters(); - - this->chattersListTimer = new QTimer; - QObject::connect(this->chattersListTimer, &QTimer::timeout, doRefreshChatters); - this->chattersListTimer->start(5 * 60 * 1000); - + // debugging #if 0 for (int i = 0; i < 1000; i++) { this->addMessage(Message::createSystemMessage("asdf")); @@ -110,15 +67,6 @@ TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection #endif } -TwitchChannel::~TwitchChannel() -{ - this->liveStatusTimer->stop(); - this->liveStatusTimer->deleteLater(); - - this->chattersListTimer->stop(); - this->chattersListTimer->deleteLater(); -} - bool TwitchChannel::isEmpty() const { return this->name.isEmpty(); @@ -129,14 +77,7 @@ bool TwitchChannel::canSendMessage() const return !this->isEmpty(); } -void TwitchChannel::setRoomID(const QString &_roomID) -{ - this->roomID = _roomID; - this->roomIDchanged.invoke(); - this->fetchMessages.invoke(); -} - -void TwitchChannel::reloadChannelEmotes() +void TwitchChannel::refreshChannelEmotes() { auto app = getApp(); @@ -249,16 +190,16 @@ void TwitchChannel::addJoinedUser(const QString &user) void TwitchChannel::addPartedUser(const QString &user) { - auto *app = getApp(); + auto app = getApp(); if (user == app->accounts->twitch.getCurrent()->getUserName() || - !app->settings->showJoins.getValue()) { + !getSettings()->showJoins.getValue()) { return; } std::lock_guard guard(this->partedUserMutex_); - partedUsers_ << user; + this->partedUsers_ << user; if (!this->partedUsersMergeQueued_) { this->partedUsersMergeQueued_ = true; @@ -277,6 +218,18 @@ void TwitchChannel::addPartedUser(const QString &user) } } +QString TwitchChannel::getRoomID() const +{ + return this->roomID_.get(); +} + +void TwitchChannel::setRoomID(const QString &id) +{ + this->roomID_.set(id); + this->roomIDChanged.invoke(); + this->loadRecentMessages(); +} + TwitchChannel::RoomModes TwitchChannel::getRoomModes() { std::lock_guard lock(this->roomModeMutex_); @@ -318,13 +271,15 @@ void TwitchChannel::setLive(bool newLiveStatus) } if (gotNewLiveStatus) { - this->updateLiveInfo.invoke(); + this->liveStatusChanged.invoke(); } } void TwitchChannel::refreshLiveStatus() { - if (this->roomID.isEmpty()) { + auto roomID = this->getRoomID(); + + if (roomID.isEmpty()) { Log("[TwitchChannel:{}] Refreshing live status (Missing ID)", this->name); this->setLive(false); return; @@ -332,13 +287,11 @@ void TwitchChannel::refreshLiveStatus() Log("[TwitchChannel:{}] Refreshing live status", this->name); - QString url("https://api.twitch.tv/kraken/streams/" + this->roomID); + QString url("https://api.twitch.tv/kraken/streams/" + roomID); - std::weak_ptr weak = this->shared_from_this(); + auto request = makeGetStreamRequest(roomID, QThread::currentThread()); - auto request = makeGetStreamRequest(this->roomID, QThread::currentThread()); - - request.onSuccess([weak](auto result) { + request.onSuccess([weak = this->weak_from_this()](auto result) { auto d = result.parseRapidJson(); ChannelPtr shared = weak.lock(); @@ -384,6 +337,7 @@ void TwitchChannel::refreshLiveStatus() { std::lock_guard lock(channel->streamStatusMutex_); + StreamStatus status; channel->streamStatus_.live = true; channel->streamStatus_.viewerCount = stream["viewers"].GetUint(); channel->streamStatus_.game = stream["game"].GetString(); @@ -413,7 +367,7 @@ void TwitchChannel::refreshLiveStatus() } // Signal all listeners that the stream status has been updated - channel->updateLiveInfo.invoke(); + channel->liveStatusChanged.invoke(); return true; }); @@ -421,70 +375,109 @@ void TwitchChannel::refreshLiveStatus() request.execute(); } -void TwitchChannel::startRefreshLiveStatusTimer(int intervalMS) +void TwitchChannel::initializeLiveStatusTimer(int intervalMS) { - this->liveStatusTimer = new QTimer; - QObject::connect(this->liveStatusTimer, &QTimer::timeout, [this]() { - this->refreshLiveStatus(); // - }); - - // When the Room ID of a twitch channel has been set, refresh the live status an extra time - this->roomIDchanged.connect([this]() { - this->refreshLiveStatus(); // - }); - - this->liveStatusTimer->start(intervalMS); } -void TwitchChannel::fetchRecentMessages() +void TwitchChannel::loadRecentMessages() { static QString genericURL = "https://tmi.twitch.tv/api/rooms/%1/recent_messages?client_id=" + getDefaultClientID(); - NetworkRequest request(genericURL.arg(this->roomID)); + NetworkRequest request(genericURL.arg(this->getRoomID())); request.makeAuthorizedV5(getDefaultClientID()); request.setCaller(QThread::currentThread()); - std::weak_ptr weak = this->shared_from_this(); - - request.onSuccess([weak](auto result) { - auto obj = result.parseJson(); + request.onSuccess([this, weak = this->weak_from_this()](auto result) { + // channel still exists? ChannelPtr shared = weak.lock(); + if (!shared) return false; - if (!shared) { - return false; - } - - auto channel = dynamic_cast(shared.get()); - assert(channel != nullptr); - - static auto readConnection = channel->readConnection_; - - QJsonArray msgArray = obj.value("messages").toArray(); - if (msgArray.empty()) { - return false; - } - - std::vector messages; - - for (const QJsonValueRef _msg : msgArray) { - QByteArray content = _msg.toString().toUtf8(); - auto msg = Communi::IrcMessage::fromData(content, readConnection); - auto privMsg = static_cast(msg); - - MessageParseArgs args; - TwitchMessageBuilder builder(channel, privMsg, args); - if (!builder.isIgnored()) { - messages.push_back(builder.build()); - } - } - - channel->addMessagesAtStart(messages); - - return true; + // parse json + return this->parseRecentMessages(result.parseJson()); }); request.execute(); } +bool TwitchChannel::parseRecentMessages(const QJsonObject &jsonRoot) +{ + QJsonArray jsonMessages = jsonRoot.value("messages").toArray(); + if (jsonMessages.empty()) { + return false; + } + + std::vector messages; + + for (const auto jsonMessage : jsonMessages) { + auto content = jsonMessage.toString().toUtf8(); + auto message = Communi::IrcMessage::fromData(content, this->readConnection_); + auto privMsg = dynamic_cast(message); + assert(privMsg); + + MessageParseArgs args; + TwitchMessageBuilder builder(this, privMsg, args); + if (!builder.isIgnored()) { + messages.push_back(builder.build()); + } + } + + this->addMessagesAtStart(messages); + + return true; +} + +void TwitchChannel::refreshPubsub() +{ + // listen to moderation actions + if (!this->hasModRights()) return; + auto roomId = this->getRoomID(); + if (roomId.isEmpty()) return; + + auto account = getApp()->accounts->twitch.getCurrent(); + getApp()->twitch2->pubsub->listenToChannelModerationActions(roomId, account); +} + +void TwitchChannel::refreshViewerList() +{ + // setting? + const auto streamStatus = this->getStreamStatus(); + + if (getSettings()->onlyFetchChattersForSmallerStreamers) { + if (streamStatus.live && streamStatus.viewerCount > getSettings()->smallStreamerLimit) { + return; + } + } + + // get viewer list + NetworkRequest request("https://tmi.twitch.tv/group/user/" + this->name + "/chatters"); + + request.setCaller(QThread::currentThread()); + request.onSuccess([this, weak = this->weak_from_this()](auto result) { + // channel still exists? + auto shared = weak.lock(); + if (!shared) return false; + + return this->parseViewerList(result.parseJson()); + }); + + request.execute(); +} + +bool TwitchChannel::parseViewerList(const QJsonObject &jsonRoot) +{ + static QStringList categories = {"moderators", "staff", "admins", "global_mods", "viewers"}; + + // parse json + QJsonObject jsonCategories = jsonRoot.value("chatters").toObject(); + + for (const auto &category : categories) { + for (const auto jsonCategory : jsonCategories.value(category).toArray()) { + this->completionModel.addUser(jsonCategory.toString()); + } + } + + return true; +} + } // namespace chatterino diff --git a/src/providers/twitch/TwitchChannel.hpp b/src/providers/twitch/TwitchChannel.hpp index 7b4e8a638..950c9f9d1 100644 --- a/src/providers/twitch/TwitchChannel.hpp +++ b/src/providers/twitch/TwitchChannel.hpp @@ -18,9 +18,6 @@ class TwitchServer; class TwitchChannel final : public Channel, pajlada::Signals::SignalHolder { - QTimer *liveStatusTimer; - QTimer *chattersListTimer; - public: struct StreamStatus { bool live = false; @@ -46,22 +43,32 @@ public: QString broadcasterLang; }; - ~TwitchChannel() final; - - void reloadChannelEmotes(); - bool isEmpty() const override; bool canSendMessage() const override; void sendMessage(const QString &message) override; + bool isLive() const; virtual bool isMod() const override; void setMod(bool value); virtual bool isBroadcaster() const override; + QString getRoomID() const; + void setRoomID(const QString &id); + RoomModes getRoomModes(); + void setRoomModes(const RoomModes &roomModes_); + StreamStatus getStreamStatus() const; + void addRecentChatter(const std::shared_ptr &message) final; void addJoinedUser(const QString &user); void addPartedUser(const QString &user); + struct NameOptions { + QString displayName; + QString localizedName; + }; + + void refreshChannelEmotes(); + const std::shared_ptr bttvChannelEmotes; const std::shared_ptr ffzChannelEmotes; @@ -69,35 +76,24 @@ public: const QString channelURL; const QString popoutPlayerURL; - void setRoomID(const QString &_roomID); - pajlada::Signals::NoArgSignal roomIDchanged; - pajlada::Signals::NoArgSignal updateLiveInfo; + pajlada::Signals::NoArgSignal roomIDChanged; + pajlada::Signals::NoArgSignal liveStatusChanged; - pajlada::Signals::NoArgBoltSignal fetchMessages; pajlada::Signals::NoArgSignal userStateChanged; pajlada::Signals::NoArgSignal roomModesChanged; - QString roomID; - - RoomModes getRoomModes(); - void setRoomModes(const RoomModes &roomModes_); - - StreamStatus getStreamStatus() const; - - struct NameOptions { - QString displayName; - QString localizedName; - }; - - bool isLive() const; - private: explicit TwitchChannel(const QString &channelName, Communi::IrcConnection *readConnection); - void setLive(bool newLiveStatus); + void initializeLiveStatusTimer(int intervalMS); void refreshLiveStatus(); - void startRefreshLiveStatusTimer(int intervalMS); - void fetchRecentMessages(); + void refreshPubsub(); + void refreshViewerList(); + bool parseViewerList(const QJsonObject &jsonRoot); + void loadRecentMessages(); + bool parseRecentMessages(const QJsonObject &jsonRoot); + + void setLive(bool newLiveStatus); mutable std::mutex streamStatusMutex_; StreamStatus streamStatus_; @@ -110,6 +106,7 @@ private: QString lastSentMessage_; RoomModes roomModes_; std::mutex roomModeMutex_; + MutexValue roomID_; QObject object_; std::mutex joinedUserMutex_; @@ -125,6 +122,9 @@ private: std::map recentChatters_; std::mutex recentChattersMutex_; + QTimer liveStatusTimer_; + QTimer chattersListTimer_; + friend class TwitchServer; }; diff --git a/src/providers/twitch/TwitchMessageBuilder.cpp b/src/providers/twitch/TwitchMessageBuilder.cpp index 73defdf4a..659111220 100644 --- a/src/providers/twitch/TwitchMessageBuilder.cpp +++ b/src/providers/twitch/TwitchMessageBuilder.cpp @@ -298,8 +298,8 @@ void TwitchMessageBuilder::parseRoomID() if (iterator != std::end(this->tags)) { this->roomID_ = iterator.value().toString(); - if (this->twitchChannel->roomID.isEmpty()) { - this->twitchChannel->roomID = this->roomID_; + if (this->twitchChannel->getRoomID().isEmpty()) { + this->twitchChannel->setRoomID(this->roomID_); } } } diff --git a/src/providers/twitch/TwitchServer.cpp b/src/providers/twitch/TwitchServer.cpp index 247d28fe1..8e5ad173c 100644 --- a/src/providers/twitch/TwitchServer.cpp +++ b/src/providers/twitch/TwitchServer.cpp @@ -161,16 +161,12 @@ std::shared_ptr TwitchServer::getChannelOrEmptyByID(const QString &chan for (const auto &weakChannel : this->channels) { auto channel = weakChannel.lock(); - if (!channel) { - continue; - } + if (!channel) continue; auto twitchChannel = std::dynamic_pointer_cast(channel); - if (!twitchChannel) { - continue; - } + if (!twitchChannel) continue; - if (twitchChannel->roomID == channelID) { + if (twitchChannel->getRoomID() == channelID) { return twitchChannel; } } diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index e37938302..4f007012c 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -284,7 +284,7 @@ void SplitHeader::initializeChannelSignals() TwitchChannel *twitchChannel = dynamic_cast(channel.get()); if (twitchChannel) { - this->managedConnections_.emplace_back(twitchChannel->updateLiveInfo.connect([this]() { + this->managedConnections_.emplace_back(twitchChannel->liveStatusChanged.connect([this]() { this->updateChannelText(); // })); } @@ -494,7 +494,7 @@ void SplitHeader::menuReloadChannelEmotes() TwitchChannel *twitchChannel = dynamic_cast(channel.get()); if (twitchChannel) { - twitchChannel->reloadChannelEmotes(); + twitchChannel->refreshChannelEmotes(); } }