mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
refactored irc
This commit is contained in:
parent
12b30eb2ed
commit
b351c40d29
56 changed files with 1397 additions and 1154 deletions
336
chatterino.pro
336
chatterino.pro
|
@ -90,196 +90,204 @@ SOURCES += \
|
||||||
src/application.cpp \
|
src/application.cpp \
|
||||||
src/channel.cpp \
|
src/channel.cpp \
|
||||||
src/channeldata.cpp \
|
src/channeldata.cpp \
|
||||||
src/singletons/ircmanager.cpp \
|
|
||||||
src/messages/link.cpp \
|
|
||||||
src/messages/message.cpp \
|
|
||||||
src/widgets/notebook.cpp \
|
|
||||||
src/widgets/helper/notebookbutton.cpp \
|
|
||||||
src/widgets/helper/notebooktab.cpp \
|
|
||||||
src/widgets/scrollbar.cpp \
|
|
||||||
src/widgets/helper/scrollbarhighlight.cpp \
|
|
||||||
src/widgets/settingsdialog.cpp \
|
|
||||||
src/widgets/helper/settingsdialogtab.cpp \
|
|
||||||
src/widgets/textinputdialog.cpp \
|
|
||||||
src/singletons/loggingmanager.cpp \
|
|
||||||
src/singletons/helper/loggingchannel.cpp \
|
|
||||||
src/singletons/windowmanager.cpp \
|
|
||||||
src/singletons/channelmanager.cpp \
|
|
||||||
src/singletons/fontmanager.cpp \
|
|
||||||
src/singletons/settingsmanager.cpp \
|
|
||||||
src/singletons/emotemanager.cpp \
|
|
||||||
src/messages/messagebuilder.cpp \
|
|
||||||
src/twitch/twitchmessagebuilder.cpp \
|
|
||||||
src/widgets/titlebar.cpp \
|
|
||||||
src/singletons/accountmanager.cpp \
|
|
||||||
src/twitch/twitchuser.cpp \
|
|
||||||
src/ircaccount.cpp \
|
|
||||||
src/widgets/accountpopup.cpp \
|
|
||||||
src/widgets/basewidget.cpp \
|
|
||||||
src/widgets/helper/resizingtextedit.cpp \
|
|
||||||
src/singletons/completionmanager.cpp \
|
|
||||||
src/widgets/logindialog.cpp \
|
|
||||||
src/widgets/qualitypopup.cpp \
|
|
||||||
src/widgets/emotepopup.cpp \
|
|
||||||
src/widgets/helper/channelview.cpp \
|
|
||||||
src/twitch/twitchchannel.cpp \
|
|
||||||
src/widgets/helper/rippleeffectlabel.cpp \
|
|
||||||
src/widgets/helper/rippleeffectbutton.cpp \
|
|
||||||
src/messages/messagecolor.cpp \
|
|
||||||
src/util/networkmanager.cpp \
|
|
||||||
src/singletons/commandmanager.cpp \
|
|
||||||
src/widgets/split.cpp \
|
|
||||||
src/widgets/helper/splitinput.cpp \
|
|
||||||
src/widgets/helper/splitheader.cpp \
|
|
||||||
src/widgets/splitcontainer.cpp \
|
|
||||||
src/widgets/helper/droppreview.cpp \
|
|
||||||
src/widgets/window.cpp \
|
|
||||||
src/widgets/helper/splitcolumn.cpp \
|
|
||||||
src/widgets/accountswitchwidget.cpp \
|
|
||||||
src/widgets/accountswitchpopupwidget.cpp \
|
|
||||||
src/widgets/tooltipwidget.cpp \
|
|
||||||
src/singletons/thememanager.cpp \
|
|
||||||
src/twitch/twitchaccountmanager.cpp \
|
|
||||||
src/singletons/helper/completionmodel.cpp \
|
|
||||||
src/singletons/resourcemanager.cpp \
|
|
||||||
src/singletons/helper/ircmessagehandler.cpp \
|
|
||||||
src/singletons/pathmanager.cpp \
|
|
||||||
src/widgets/helper/searchpopup.cpp \
|
|
||||||
src/messages/messageelement.cpp \
|
|
||||||
src/messages/image.cpp \
|
src/messages/image.cpp \
|
||||||
src/messages/layouts/messagelayout.cpp \
|
src/messages/layouts/messagelayout.cpp \
|
||||||
src/messages/layouts/messagelayoutelement.cpp \
|
|
||||||
src/messages/layouts/messagelayoutcontainer.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/irc/abstractircserver.cpp \
|
||||||
|
src/providers/twitch/ircmessagehandler.cpp \
|
||||||
|
src/providers/twitch/twitchaccount.cpp \
|
||||||
|
src/providers/twitch/twitchaccountmanager.cpp \
|
||||||
|
src/providers/twitch/twitchchannel.cpp \
|
||||||
|
src/providers/twitch/twitchmessagebuilder.cpp \
|
||||||
|
src/providers/twitch/twitchserver.cpp \
|
||||||
|
src/singletons/accountmanager.cpp \
|
||||||
|
src/singletons/channelmanager.cpp \
|
||||||
|
src/singletons/commandmanager.cpp \
|
||||||
|
src/singletons/completionmanager.cpp \
|
||||||
|
src/singletons/emotemanager.cpp \
|
||||||
|
src/singletons/fontmanager.cpp \
|
||||||
|
src/singletons/helper/completionmodel.cpp \
|
||||||
|
src/singletons/helper/loggingchannel.cpp \
|
||||||
|
src/singletons/helper/moderationaction.cpp \
|
||||||
|
src/singletons/loggingmanager.cpp \
|
||||||
|
src/singletons/pathmanager.cpp \
|
||||||
|
src/singletons/resourcemanager.cpp \
|
||||||
|
src/singletons/settingsmanager.cpp \
|
||||||
|
src/singletons/thememanager.cpp \
|
||||||
|
src/singletons/windowmanager.cpp \
|
||||||
|
src/util/networkmanager.cpp \
|
||||||
|
src/util/networkrequest.cpp \
|
||||||
|
src/widgets/accountpopup.cpp \
|
||||||
|
src/widgets/accountswitchpopupwidget.cpp \
|
||||||
|
src/widgets/accountswitchwidget.cpp \
|
||||||
|
src/widgets/basewidget.cpp \
|
||||||
|
src/widgets/basewindow.cpp \
|
||||||
|
src/widgets/emotepopup.cpp \
|
||||||
|
src/widgets/helper/channelview.cpp \
|
||||||
|
src/widgets/helper/droppreview.cpp \
|
||||||
|
src/widgets/helper/label.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/splitcolumn.cpp \
|
||||||
|
src/widgets/helper/splitheader.cpp \
|
||||||
|
src/widgets/helper/splitinput.cpp \
|
||||||
|
src/widgets/helper/titlebarbutton.cpp \
|
||||||
|
src/widgets/logindialog.cpp \
|
||||||
|
src/widgets/notebook.cpp \
|
||||||
|
src/widgets/qualitypopup.cpp \
|
||||||
|
src/widgets/scrollbar.cpp \
|
||||||
|
src/widgets/settingsdialog.cpp \
|
||||||
|
src/widgets/settingspages/aboutpage.cpp \
|
||||||
|
src/widgets/settingspages/accountspage.cpp \
|
||||||
src/widgets/settingspages/appearancepage.cpp \
|
src/widgets/settingspages/appearancepage.cpp \
|
||||||
src/widgets/settingspages/settingspage.cpp \
|
|
||||||
src/widgets/settingspages/behaviourpage.cpp \
|
src/widgets/settingspages/behaviourpage.cpp \
|
||||||
src/widgets/settingspages/commandpage.cpp \
|
src/widgets/settingspages/commandpage.cpp \
|
||||||
src/widgets/settingspages/emotespage.cpp \
|
src/widgets/settingspages/emotespage.cpp \
|
||||||
src/widgets/settingspages/highlightingpage.cpp \
|
src/widgets/settingspages/highlightingpage.cpp \
|
||||||
src/widgets/settingspages/accountspage.cpp \
|
|
||||||
src/widgets/settingspages/aboutpage.cpp \
|
|
||||||
src/widgets/settingspages/moderationpage.cpp \
|
|
||||||
src/widgets/settingspages/logspage.cpp \
|
|
||||||
src/widgets/basewindow.cpp \
|
|
||||||
src/singletons/helper/moderationaction.cpp \
|
|
||||||
src/widgets/streamview.cpp \
|
|
||||||
src/util/networkrequest.cpp \
|
|
||||||
src/widgets/settingspages/ignoreuserspage.cpp \
|
|
||||||
src/widgets/settingspages/ignoremessagespage.cpp \
|
src/widgets/settingspages/ignoremessagespage.cpp \
|
||||||
src/widgets/settingspages/specialchannelspage.cpp \
|
src/widgets/settingspages/ignoreuserspage.cpp \
|
||||||
src/widgets/settingspages/keyboardsettingspage.cpp \
|
src/widgets/settingspages/keyboardsettingspage.cpp \
|
||||||
src/widgets/helper/titlebarbutton.cpp \
|
src/widgets/settingspages/logspage.cpp \
|
||||||
src/widgets/helper/label.cpp
|
src/widgets/settingspages/moderationpage.cpp \
|
||||||
|
src/widgets/settingspages/settingspage.cpp \
|
||||||
|
src/widgets/settingspages/specialchannelspage.cpp \
|
||||||
|
src/widgets/split.cpp \
|
||||||
|
src/widgets/splitcontainer.cpp \
|
||||||
|
src/widgets/streamview.cpp \
|
||||||
|
src/widgets/textinputdialog.cpp \
|
||||||
|
src/widgets/titlebar.cpp \
|
||||||
|
src/widgets/tooltipwidget.cpp \
|
||||||
|
src/widgets/window.cpp \
|
||||||
|
src/providers/irc/_ircaccount.cpp \
|
||||||
|
src/providers/irc/_ircserver.cpp \
|
||||||
|
src/providers/irc/_ircchannel.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/precompiled_header.hpp \
|
src/precompiled_header.hpp \
|
||||||
src/util/posttothread.hpp \
|
|
||||||
src/channel.hpp \
|
src/channel.hpp \
|
||||||
src/util/concurrentmap.hpp \
|
|
||||||
src/emojis.hpp \
|
|
||||||
src/singletons/ircmanager.hpp \
|
|
||||||
src/messages/link.hpp \
|
|
||||||
src/messages/message.hpp \
|
|
||||||
src/twitch/emotevalue.hpp \
|
|
||||||
src/widgets/notebook.hpp \
|
|
||||||
src/widgets/helper/notebookbutton.hpp \
|
|
||||||
src/widgets/helper/notebooktab.hpp \
|
|
||||||
src/widgets/scrollbar.hpp \
|
|
||||||
src/widgets/helper/scrollbarhighlight.hpp \
|
|
||||||
src/widgets/settingsdialog.hpp \
|
|
||||||
src/widgets/helper/settingsdialogtab.hpp \
|
|
||||||
src/widgets/helper/signallabel.hpp \
|
|
||||||
src/widgets/textinputdialog.hpp \
|
|
||||||
src/widgets/helper/resizingtextedit.hpp \
|
|
||||||
src/messages/limitedqueue.hpp \
|
|
||||||
src/messages/limitedqueuesnapshot.hpp \
|
|
||||||
src/singletons/loggingmanager.hpp \
|
|
||||||
src/singletons/helper/loggingchannel.hpp \
|
|
||||||
src/singletons/channelmanager.hpp \
|
|
||||||
src/singletons/windowmanager.hpp \
|
|
||||||
src/singletons/settingsmanager.hpp \
|
|
||||||
src/singletons/fontmanager.hpp \
|
|
||||||
src/singletons/emotemanager.hpp \
|
|
||||||
src/util/urlfetch.hpp \
|
|
||||||
src/messages/messageparseargs.hpp \
|
|
||||||
src/messages/messagebuilder.hpp \
|
|
||||||
src/twitch/twitchmessagebuilder.hpp \
|
|
||||||
src/widgets/titlebar.hpp \
|
|
||||||
src/singletons/accountmanager.hpp \
|
|
||||||
src/twitch/twitchuser.hpp \
|
|
||||||
src/ircaccount.hpp \
|
|
||||||
src/widgets/accountpopup.hpp \
|
|
||||||
src/util/distancebetweenpoints.hpp \
|
|
||||||
src/widgets/basewidget.hpp \
|
|
||||||
src/singletons/completionmanager.hpp \
|
|
||||||
src/widgets/helper/channelview.hpp \
|
|
||||||
src/twitch/twitchchannel.hpp \
|
|
||||||
src/widgets/helper/rippleeffectbutton.hpp \
|
|
||||||
src/widgets/helper/rippleeffectlabel.hpp \
|
|
||||||
src/widgets/qualitypopup.hpp \
|
|
||||||
src/widgets/emotepopup.hpp \
|
|
||||||
src/messages/messagecolor.hpp \
|
|
||||||
src/util/nativeeventhelper.hpp \
|
|
||||||
src/debug/log.hpp \
|
|
||||||
src/util/benchmark.hpp \
|
|
||||||
src/util/networkmanager.hpp \
|
|
||||||
src/singletons/commandmanager.hpp \
|
|
||||||
src/widgets/split.hpp \
|
|
||||||
src/widgets/helper/splitheader.hpp \
|
|
||||||
src/widgets/helper/splitinput.hpp \
|
|
||||||
src/widgets/window.hpp \
|
|
||||||
src/widgets/splitcontainer.hpp \
|
|
||||||
src/widgets/helper/droppreview.hpp \
|
|
||||||
src/widgets/helper/splitcolumn.hpp \
|
|
||||||
src/util/irchelpers.hpp \
|
|
||||||
src/util/helpers.hpp \
|
|
||||||
src/widgets/accountswitchwidget.hpp \
|
|
||||||
src/widgets/accountswitchpopupwidget.hpp \
|
|
||||||
src/const.hpp \
|
src/const.hpp \
|
||||||
src/widgets/tooltipwidget.hpp \
|
src/debug/log.hpp \
|
||||||
src/singletons/thememanager.hpp \
|
src/emojis.hpp \
|
||||||
src/twitch/twitchaccountmanager.hpp \
|
|
||||||
src/singletons/helper/completionmodel.hpp \
|
|
||||||
src/singletons/helper/chatterinosetting.hpp \
|
|
||||||
src/singletons/resourcemanager.hpp \
|
|
||||||
src/util/emotemap.hpp \
|
|
||||||
src/singletons/helper/ircmessagehandler.hpp \
|
|
||||||
src/util/serialize-custom.hpp \
|
|
||||||
src/messages/highlightphrase.hpp \
|
src/messages/highlightphrase.hpp \
|
||||||
src/messages/selection.hpp \
|
|
||||||
src/singletons/pathmanager.hpp \
|
|
||||||
src/widgets/helper/searchpopup.hpp \
|
|
||||||
src/widgets/helper/shortcut.hpp \
|
|
||||||
src/messages/messageelement.hpp \
|
|
||||||
src/messages/image.hpp \
|
src/messages/image.hpp \
|
||||||
src/messages/layouts/messagelayout.hpp \
|
src/messages/layouts/messagelayout.hpp \
|
||||||
src/messages/layouts/messagelayoutelement.hpp \
|
|
||||||
src/messages/layouts/messagelayoutcontainer.hpp \
|
src/messages/layouts/messagelayoutcontainer.hpp \
|
||||||
src/util/property.hpp \
|
src/messages/layouts/messagelayoutelement.hpp \
|
||||||
src/widgets/settingspages/appearancepage.hpp \
|
src/messages/limitedqueue.hpp \
|
||||||
src/widgets/settingspages/settingspage.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/providers/twitch/emotevalue.hpp \
|
||||||
|
src/providers/twitch/ircmessagehandler.hpp \
|
||||||
|
src/providers/twitch/twitchaccount.hpp \
|
||||||
|
src/providers/twitch/twitchaccountmanager.hpp \
|
||||||
|
src/providers/twitch/twitchchannel.hpp \
|
||||||
|
src/providers/twitch/twitchmessagebuilder.hpp \
|
||||||
|
src/providers/twitch/twitchserver.hpp \
|
||||||
|
src/singletons/accountmanager.hpp \
|
||||||
|
src/singletons/channelmanager.hpp \
|
||||||
|
src/singletons/commandmanager.hpp \
|
||||||
|
src/singletons/completionmanager.hpp \
|
||||||
|
src/singletons/emotemanager.hpp \
|
||||||
|
src/singletons/fontmanager.hpp \
|
||||||
|
src/singletons/helper/chatterinosetting.hpp \
|
||||||
|
src/singletons/helper/completionmodel.hpp \
|
||||||
|
src/singletons/helper/loggingchannel.hpp \
|
||||||
|
src/singletons/helper/moderationaction.hpp \
|
||||||
|
src/singletons/loggingmanager.hpp \
|
||||||
|
src/singletons/pathmanager.hpp \
|
||||||
|
src/singletons/providermanager.hp \
|
||||||
|
src/singletons/resourcemanager.hpp \
|
||||||
|
src/singletons/settingsmanager.hpp \
|
||||||
|
src/singletons/thememanager.hpp \
|
||||||
|
src/singletons/windowmanager.hpp \
|
||||||
|
src/util/benchmark.hpp \
|
||||||
|
src/util/concurrentmap.hpp \
|
||||||
|
src/util/distancebetweenpoints.hpp \
|
||||||
|
src/util/emotemap.hpp \
|
||||||
|
src/util/flagsenum.hpp \
|
||||||
|
src/util/helpers.hpp \
|
||||||
|
src/util/irchelpers.hpp \
|
||||||
src/util/layoutcreator.hpp \
|
src/util/layoutcreator.hpp \
|
||||||
|
src/util/nativeeventhelper.hpp \
|
||||||
|
src/util/networkmanager.hpp \
|
||||||
|
src/util/networkrequest.hpp \
|
||||||
|
src/util/networkrequester.hpp \
|
||||||
|
src/util/networkworker.hpp \
|
||||||
|
src/util/posttothread.hpp \
|
||||||
|
src/util/property.hpp \
|
||||||
|
src/util/serialize-custom.hpp \
|
||||||
|
src/util/urlfetch.hpp \
|
||||||
|
src/widgets/accountpopup.hpp \
|
||||||
|
src/widgets/accountswitchpopupwidget.hpp \
|
||||||
|
src/widgets/accountswitchwidget.hpp \
|
||||||
|
src/widgets/basewidget.hpp \
|
||||||
|
src/widgets/basewindow.hpp \
|
||||||
|
src/widgets/emotepopup.hpp \
|
||||||
|
src/widgets/helper/channelview.hpp \
|
||||||
|
src/widgets/helper/droppreview.hpp \
|
||||||
|
src/widgets/helper/label.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/splitcolumn.hpp \
|
||||||
|
src/widgets/helper/splitheader.hpp \
|
||||||
|
src/widgets/helper/splitinput.hpp \
|
||||||
|
src/widgets/helper/titlebarbutton.hpp \
|
||||||
|
src/widgets/notebook.hpp \
|
||||||
|
src/widgets/qualitypopup.hpp \
|
||||||
|
src/widgets/scrollbar.hpp \
|
||||||
|
src/widgets/settingsdialog.hpp \
|
||||||
|
src/widgets/settingspages/aboutpage.hpp \
|
||||||
|
src/widgets/settingspages/accountspage.hpp \
|
||||||
|
src/widgets/settingspages/appearancepage.hpp \
|
||||||
src/widgets/settingspages/behaviourpage.hpp \
|
src/widgets/settingspages/behaviourpage.hpp \
|
||||||
src/widgets/settingspages/commandpage.hpp \
|
src/widgets/settingspages/commandpage.hpp \
|
||||||
src/widgets/settingspages/emotespage.hpp \
|
src/widgets/settingspages/emotespage.hpp \
|
||||||
src/widgets/settingspages/highlightingpage.hpp \
|
src/widgets/settingspages/highlightingpage.hpp \
|
||||||
src/widgets/settingspages/accountspage.hpp \
|
|
||||||
src/widgets/settingspages/aboutpage.hpp \
|
|
||||||
src/widgets/settingspages/moderationpage.hpp \
|
|
||||||
src/widgets/settingspages/logspage.hpp \
|
|
||||||
src/widgets/basewindow.hpp \
|
|
||||||
src/singletons/helper/moderationaction.hpp \
|
|
||||||
src/widgets/streamview.hpp \
|
|
||||||
src/util/networkrequest.hpp \
|
|
||||||
src/util/networkworker.hpp \
|
|
||||||
src/util/networkrequester.hpp \
|
|
||||||
src/widgets/settingspages/ignoreuserspage.hpp \
|
|
||||||
src/widgets/settingspages/ignoremessagespage.hpp \
|
src/widgets/settingspages/ignoremessagespage.hpp \
|
||||||
src/widgets/settingspages/specialchannelspage.hpp \
|
src/widgets/settingspages/ignoreuserspage.hpp \
|
||||||
src/widgets/settingspages/keyboardsettingspage.hpp \
|
src/widgets/settingspages/keyboardsettingspage.hpp \
|
||||||
src/widgets/helper/titlebarbutton.hpp \
|
src/widgets/settingspages/logspage.hpp \
|
||||||
src/widgets/helper/label.hpp \
|
src/widgets/settingspages/moderationpage.hpp \
|
||||||
src/util/flagsenum.hpp
|
src/widgets/settingspages/settingspage.hpp \
|
||||||
|
src/widgets/settingspages/specialchannelspage.hpp \
|
||||||
|
src/widgets/split.hpp \
|
||||||
|
src/widgets/splitcontainer.hpp \
|
||||||
|
src/widgets/streamview.hpp \
|
||||||
|
src/widgets/textinputdialog.hpp \
|
||||||
|
src/widgets/titlebar.hpp \
|
||||||
|
src/widgets/tooltipwidget.hpp \
|
||||||
|
src/widgets/window.hpp \
|
||||||
|
src/common.hpp \
|
||||||
|
src/providers/irc/_ircchannel.hpp \
|
||||||
|
src/providers/irc/_ircaccount.hpp \
|
||||||
|
src/providers/irc/_ircserver.hpp \
|
||||||
|
src/providers/irc/abstractircserver.hpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources/resources.qrc
|
resources/resources.qrc
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#include "application.hpp"
|
#include "application.hpp"
|
||||||
#include "singletons/loggingmanager.hpp"
|
#include "providers/twitch/twitchserver.hpp"
|
||||||
#include "singletons/accountmanager.hpp"
|
#include "singletons/accountmanager.hpp"
|
||||||
#include "singletons/commandmanager.hpp"
|
#include "singletons/commandmanager.hpp"
|
||||||
#include "singletons/emotemanager.hpp"
|
#include "singletons/emotemanager.hpp"
|
||||||
|
#include "singletons/loggingmanager.hpp"
|
||||||
#include "singletons/settingsmanager.hpp"
|
#include "singletons/settingsmanager.hpp"
|
||||||
#include "singletons/thememanager.hpp"
|
#include "singletons/thememanager.hpp"
|
||||||
#include "singletons/windowmanager.hpp"
|
#include "singletons/windowmanager.hpp"
|
||||||
|
@ -42,7 +43,7 @@ Application::~Application()
|
||||||
int Application::run(QApplication &qtApp)
|
int Application::run(QApplication &qtApp)
|
||||||
{
|
{
|
||||||
// Start connecting to the IRC Servers (Twitch only for now)
|
// Start connecting to the IRC Servers (Twitch only for now)
|
||||||
singletons::IrcManager::getInstance().connect();
|
providers::twitch::TwitchServer::getInstance().connect();
|
||||||
|
|
||||||
// Show main window
|
// Show main window
|
||||||
singletons::WindowManager::getInstance().getMainWindow().show();
|
singletons::WindowManager::getInstance().getMainWindow().show();
|
||||||
|
|
|
@ -23,9 +23,14 @@ Channel::Channel(const QString &_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Channel::~Channel()
|
||||||
|
{
|
||||||
|
this->destroyed.invoke();
|
||||||
|
}
|
||||||
|
|
||||||
bool Channel::isEmpty() const
|
bool Channel::isEmpty() const
|
||||||
{
|
{
|
||||||
return false;
|
return this->name.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
messages::LimitedQueueSnapshot<messages::MessagePtr> Channel::getMessageSnapshot()
|
messages::LimitedQueueSnapshot<messages::MessagePtr> Channel::getMessageSnapshot()
|
||||||
|
@ -103,4 +108,13 @@ void Channel::sendMessage(const QString &message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Channel> Channel::getEmpty()
|
||||||
|
{
|
||||||
|
static std::shared_ptr<Channel> channel(new Channel(""));
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Channel::onConnected()
|
||||||
|
{
|
||||||
|
}
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -23,11 +23,15 @@ class Channel : public std::enable_shared_from_this<Channel>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Channel(const QString &_name);
|
explicit Channel(const QString &_name);
|
||||||
|
virtual ~Channel();
|
||||||
|
|
||||||
|
pajlada::Signals::Signal<const QString &, const QString &> sendMessageSignal;
|
||||||
|
|
||||||
boost::signals2::signal<void(messages::MessagePtr &)> messageRemovedFromStart;
|
boost::signals2::signal<void(messages::MessagePtr &)> messageRemovedFromStart;
|
||||||
boost::signals2::signal<void(messages::MessagePtr &)> messageAppended;
|
boost::signals2::signal<void(messages::MessagePtr &)> messageAppended;
|
||||||
boost::signals2::signal<void(std::vector<messages::MessagePtr> &)> messagesAddedAtStart;
|
boost::signals2::signal<void(std::vector<messages::MessagePtr> &)> messagesAddedAtStart;
|
||||||
boost::signals2::signal<void(size_t index, messages::MessagePtr &)> messageReplaced;
|
boost::signals2::signal<void(size_t index, messages::MessagePtr &)> messageReplaced;
|
||||||
|
pajlada::Signals::NoArgSignal destroyed;
|
||||||
|
|
||||||
virtual bool isEmpty() const;
|
virtual bool isEmpty() const;
|
||||||
messages::LimitedQueueSnapshot<messages::MessagePtr> getMessageSnapshot();
|
messages::LimitedQueueSnapshot<messages::MessagePtr> getMessageSnapshot();
|
||||||
|
@ -58,6 +62,11 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::shared_ptr<Channel> getEmpty();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void onConnected();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
messages::LimitedQueue<messages::MessagePtr> messages;
|
messages::LimitedQueue<messages::MessagePtr> messages;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <boost/preprocessor.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace chatterino {
|
#include "debug/log.hpp"
|
||||||
|
|
||||||
enum class HighlightState {
|
namespace chatterino {
|
||||||
None,
|
|
||||||
Highlighted,
|
enum class HighlightState {
|
||||||
NewMessage,
|
None,
|
||||||
};
|
Highlighted,
|
||||||
|
NewMessage,
|
||||||
inline QString qS(const std::string &string)
|
};
|
||||||
{
|
|
||||||
return QString::fromStdString(string);
|
inline QString qS(const std::string &string)
|
||||||
}
|
{
|
||||||
|
return QString::fromStdString(string);
|
||||||
} // namespace chatterino
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
|
|
|
@ -6,10 +6,11 @@ namespace chatterino {
|
||||||
|
|
||||||
static const QString ANONYMOUS_USERNAME_LABEL(" - anonymous - ");
|
static const QString ANONYMOUS_USERNAME_LABEL(" - anonymous - ");
|
||||||
|
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
|
||||||
static const QString ANONYMOUS_USERNAME("justinfan64537");
|
static const QString ANONYMOUS_USERNAME("justinfan64537");
|
||||||
|
}
|
||||||
} // namespace twitch
|
} // namespace providers
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
#include "ircaccount.hpp"
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
IrcUser2::IrcUser2(const QString &_userName, const QString &_nickName, const QString &_realName,
|
|
||||||
const QString &_password)
|
|
||||||
: userName(_userName)
|
|
||||||
, nickName(_nickName)
|
|
||||||
, realName(_realName)
|
|
||||||
, password(_password)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &IrcUser2::getUserName() const
|
|
||||||
{
|
|
||||||
return this->userName;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &IrcUser2::getNickName() const
|
|
||||||
{
|
|
||||||
return this->nickName;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &IrcUser2::getRealName() const
|
|
||||||
{
|
|
||||||
return this->realName;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &IrcUser2::getPassword() const
|
|
||||||
{
|
|
||||||
return this->password;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
|
@ -1,25 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
class IrcUser2
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
IrcUser2(const QString &userName, const QString &nickName, const QString &realName,
|
|
||||||
const QString &password);
|
|
||||||
|
|
||||||
const QString &getUserName() const;
|
|
||||||
const QString &getNickName() const;
|
|
||||||
const QString &getRealName() const;
|
|
||||||
const QString &getPassword() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString userName;
|
|
||||||
QString nickName;
|
|
||||||
QString realName;
|
|
||||||
QString password;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
|
@ -87,7 +87,8 @@ void Image::loadImage()
|
||||||
|
|
||||||
singletons::EmoteManager::getInstance().incGeneration();
|
singletons::EmoteManager::getInstance().incGeneration();
|
||||||
|
|
||||||
postToThread([] { singletons::WindowManager::getInstance().layoutVisibleChatWidgets(); });
|
util::postToThread(
|
||||||
|
[] { singletons::WindowManager::getInstance().layoutVisibleChatWidgets(); });
|
||||||
});
|
});
|
||||||
|
|
||||||
singletons::EmoteManager::getInstance().getGifUpdateSignal().connect([=]() {
|
singletons::EmoteManager::getInstance().getGifUpdateSignal().connect([=]() {
|
||||||
|
|
|
@ -20,8 +20,7 @@ class Image;
|
||||||
|
|
||||||
namespace layouts {
|
namespace layouts {
|
||||||
|
|
||||||
struct MessageLayoutElement : boost::noncopyable
|
struct MessageLayoutElement : boost::noncopyable {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
MessageLayoutElement(MessageElement &creator, const QSize &size);
|
MessageLayoutElement(MessageElement &creator, const QSize &size);
|
||||||
|
|
||||||
|
@ -47,7 +46,6 @@ protected:
|
||||||
private:
|
private:
|
||||||
QRect rect;
|
QRect rect;
|
||||||
Link link;
|
Link link;
|
||||||
// bool isInNewLine;
|
|
||||||
MessageElement &creator;
|
MessageElement &creator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
37
src/providers/irc/_ircaccount.cpp
Normal file
37
src/providers/irc/_ircaccount.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include "_ircaccount.hpp"
|
||||||
|
|
||||||
|
// namespace chatterino {
|
||||||
|
// namespace providers {
|
||||||
|
// namespace irc {
|
||||||
|
// IrcAccount::IrcAccount(const QString &_userName, const QString &_nickName, const QString
|
||||||
|
// &_realName,
|
||||||
|
// const QString &_password)
|
||||||
|
// : userName(_userName)
|
||||||
|
// , nickName(_nickName)
|
||||||
|
// , realName(_realName)
|
||||||
|
// , password(_password)
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
|
// const QString &IrcAccount::getUserName() const
|
||||||
|
//{
|
||||||
|
// return this->userName;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// const QString &IrcAccount::getNickName() const
|
||||||
|
//{
|
||||||
|
// return this->nickName;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// const QString &IrcAccount::getRealName() const
|
||||||
|
//{
|
||||||
|
// return this->realName;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// const QString &IrcAccount::getPassword() const
|
||||||
|
//{
|
||||||
|
// return this->password;
|
||||||
|
//}
|
||||||
|
//} // namespace irc
|
||||||
|
//} // namespace providers
|
||||||
|
//} // namespace chatterino
|
27
src/providers/irc/_ircaccount.hpp
Normal file
27
src/providers/irc/_ircaccount.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
// namespace chatterino {
|
||||||
|
// namespace providers {
|
||||||
|
// namespace irc {
|
||||||
|
// class IrcAccount
|
||||||
|
//{
|
||||||
|
// public:
|
||||||
|
// IrcAccount(const QString &userName, const QString &nickName, const QString &realName,
|
||||||
|
// const QString &password);
|
||||||
|
|
||||||
|
// const QString &getUserName() const;
|
||||||
|
// const QString &getNickName() const;
|
||||||
|
// const QString &getRealName() const;
|
||||||
|
// const QString &getPassword() const;
|
||||||
|
|
||||||
|
// private:
|
||||||
|
// QString userName;
|
||||||
|
// QString nickName;
|
||||||
|
// QString realName;
|
||||||
|
// QString password;
|
||||||
|
//};
|
||||||
|
//} // namespace irc
|
||||||
|
//} // namespace providers
|
||||||
|
//} // namespace chatterino
|
11
src/providers/irc/_ircchannel.cpp
Normal file
11
src/providers/irc/_ircchannel.cpp
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include "_ircchannel.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace irc {
|
||||||
|
// IrcChannel::IrcChannel()
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
} // namespace irc
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
13
src/providers/irc/_ircchannel.hpp
Normal file
13
src/providers/irc/_ircchannel.hpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace irc {
|
||||||
|
// class IrcChannel
|
||||||
|
//{
|
||||||
|
// public:
|
||||||
|
// IrcChannel();
|
||||||
|
//};
|
||||||
|
} // namespace irc
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
14
src/providers/irc/_ircserver.cpp
Normal file
14
src/providers/irc/_ircserver.cpp
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include "_ircserver.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace irc {
|
||||||
|
// IrcServer::IrcServer(const QString &hostname, int port)
|
||||||
|
//{
|
||||||
|
// this->initConnection();
|
||||||
|
//}
|
||||||
|
} // namespace irc
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
25
src/providers/irc/_ircserver.hpp
Normal file
25
src/providers/irc/_ircserver.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "providers/irc/_ircaccount.hpp"
|
||||||
|
#include "providers/irc/abstractircserver.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace irc {
|
||||||
|
// class IrcServer
|
||||||
|
//{
|
||||||
|
// public:
|
||||||
|
// IrcServer(const QString &hostname, int port);
|
||||||
|
|
||||||
|
// void setAccount(std::shared_ptr<IrcAccount> newAccount);
|
||||||
|
// std::shared_ptr<IrcAccount> getAccount() const;
|
||||||
|
|
||||||
|
// protected:
|
||||||
|
// virtual void initializeConnection(Communi::IrcConnection *connection, bool isReadConnection);
|
||||||
|
|
||||||
|
// virtual void privateMessageReceived(Communi::IrcPrivateMessage *message);
|
||||||
|
// virtual void messageReceived(Communi::IrcMessage *message);
|
||||||
|
//};
|
||||||
|
} // namespace irc
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
226
src/providers/irc/abstractircserver.cpp
Normal file
226
src/providers/irc/abstractircserver.cpp
Normal file
|
@ -0,0 +1,226 @@
|
||||||
|
#include "abstractircserver.hpp"
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "messages/limitedqueuesnapshot.hpp"
|
||||||
|
#include "messages/message.hpp"
|
||||||
|
|
||||||
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace irc {
|
||||||
|
|
||||||
|
AbstractIrcServer::AbstractIrcServer()
|
||||||
|
{
|
||||||
|
// Initialize the connections
|
||||||
|
this->writeConnection.reset(new Communi::IrcConnection);
|
||||||
|
this->writeConnection->moveToThread(QCoreApplication::instance()->thread());
|
||||||
|
|
||||||
|
QObject::connect(this->writeConnection.get(), &Communi::IrcConnection::messageReceived,
|
||||||
|
[this](auto msg) { this->writeConnectionMessageReceived(msg); });
|
||||||
|
|
||||||
|
// Listen to read connection message signals
|
||||||
|
this->readConnection.reset(new Communi::IrcConnection);
|
||||||
|
this->readConnection->moveToThread(QCoreApplication::instance()->thread());
|
||||||
|
|
||||||
|
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::messageReceived,
|
||||||
|
[this](auto msg) { this->messageReceived(msg); });
|
||||||
|
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::privateMessageReceived,
|
||||||
|
[this](auto msg) { this->privateMessageReceived(msg); });
|
||||||
|
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::connected,
|
||||||
|
[this] { this->onConnected(); });
|
||||||
|
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::disconnected,
|
||||||
|
[this] { this->onDisconnected(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
Communi::IrcConnection *AbstractIrcServer::getReadConnection() const
|
||||||
|
{
|
||||||
|
return this->readConnection.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::connect()
|
||||||
|
{
|
||||||
|
this->disconnect();
|
||||||
|
|
||||||
|
// if (this->hasSeperateWriteConnection()) {
|
||||||
|
this->initializeConnection(this->writeConnection.get(), false, true);
|
||||||
|
this->initializeConnection(this->readConnection.get(), true, false);
|
||||||
|
// } else {
|
||||||
|
// this->initializeConnection(this->readConnection.get(), true, true);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fourtf: this should be asynchronous
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock1(this->connectionMutex);
|
||||||
|
std::lock_guard<std::mutex> lock2(this->channelMutex);
|
||||||
|
|
||||||
|
for (std::weak_ptr<Channel> &weak : this->channels.values()) {
|
||||||
|
std::shared_ptr<Channel> chan = weak.lock();
|
||||||
|
if (!chan) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->writeConnection->sendRaw("JOIN #" + chan->name);
|
||||||
|
this->readConnection->sendRaw("JOIN #" + chan->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->writeConnection->open();
|
||||||
|
this->readConnection->open();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->onConnected();
|
||||||
|
this->connected.invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::disconnect()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(this->connectionMutex);
|
||||||
|
|
||||||
|
this->readConnection->close();
|
||||||
|
this->writeConnection->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::sendMessage(const QString &channelName, const QString &message)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> locker(this->connectionMutex);
|
||||||
|
|
||||||
|
// fourtf: trim the message if it's sent from twitch chat
|
||||||
|
|
||||||
|
if (this->writeConnection) {
|
||||||
|
this->writeConnection->sendRaw("PRIVMSG #" + channelName + " :" + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::writeConnectionMessageReceived(Communi::IrcMessage *message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Channel> AbstractIrcServer::addChannel(const QString &channelName)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->channelMutex);
|
||||||
|
|
||||||
|
// value exists
|
||||||
|
auto it = this->channels.find(channelName);
|
||||||
|
if (it != this->channels.end()) {
|
||||||
|
std::shared_ptr<Channel> chan = it.value().lock();
|
||||||
|
|
||||||
|
if (chan) {
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// value doesn't exist
|
||||||
|
std::shared_ptr<Channel> chan = this->createChannel(channelName);
|
||||||
|
if (!chan) {
|
||||||
|
return Channel::getEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString clojuresInCppAreShit = channelName;
|
||||||
|
|
||||||
|
this->channels.insert(channelName, chan);
|
||||||
|
chan->destroyed.connect([this, clojuresInCppAreShit] {
|
||||||
|
// fourtf: issues when the server itself in destroyed
|
||||||
|
|
||||||
|
debug::Log("[AbstractIrcServer::addChannel] {} was destroyed", clojuresInCppAreShit);
|
||||||
|
this->channels.remove(clojuresInCppAreShit);
|
||||||
|
});
|
||||||
|
|
||||||
|
// join irc channel
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock2(this->connectionMutex);
|
||||||
|
if (this->readConnection) {
|
||||||
|
this->readConnection->sendRaw("JOIN #" + channelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->writeConnection) {
|
||||||
|
this->writeConnection->sendRaw("JOIN #" + channelName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Channel> AbstractIrcServer::getChannel(const QString &channelName)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->channelMutex);
|
||||||
|
|
||||||
|
// value exists
|
||||||
|
auto it = this->channels.find(channelName);
|
||||||
|
if (it != this->channels.end()) {
|
||||||
|
std::shared_ptr<Channel> chan = it.value().lock();
|
||||||
|
|
||||||
|
if (chan) {
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Channel::getEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::onConnected()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->channelMutex);
|
||||||
|
|
||||||
|
MessagePtr connMsg = Message::createSystemMessage("connected to chat");
|
||||||
|
MessagePtr reconnMsg = Message::createSystemMessage("reconnected to chat");
|
||||||
|
|
||||||
|
for (std::weak_ptr<Channel> &weak : this->channels.values()) {
|
||||||
|
std::shared_ptr<Channel> chan = weak.lock();
|
||||||
|
if (!chan) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LimitedQueueSnapshot<MessagePtr> snapshot = chan->getMessageSnapshot();
|
||||||
|
|
||||||
|
bool replaceMessage =
|
||||||
|
snapshot.getLength() > 0 &&
|
||||||
|
snapshot[snapshot.getLength() - 1]->flags & Message::DisconnectedMessage;
|
||||||
|
|
||||||
|
if (replaceMessage) {
|
||||||
|
chan->replaceMessage(snapshot[snapshot.getLength() - 1], reconnMsg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
chan->addMessage(connMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::onDisconnected()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->channelMutex);
|
||||||
|
|
||||||
|
MessagePtr msg = Message::createSystemMessage("disconnected from chat");
|
||||||
|
msg->flags &= Message::DisconnectedMessage;
|
||||||
|
|
||||||
|
for (std::weak_ptr<Channel> &weak : this->channels.values()) {
|
||||||
|
std::shared_ptr<Channel> chan = weak.lock();
|
||||||
|
if (!chan) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
chan->addMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Channel> AbstractIrcServer::getCustomChannel(const QString &channelName)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::addFakeMessage(const QString &data)
|
||||||
|
{
|
||||||
|
auto fakeMessage = Communi::IrcMessage::fromData(data.toUtf8(), this->readConnection.get());
|
||||||
|
|
||||||
|
this->privateMessageReceived(qobject_cast<Communi::IrcPrivateMessage *>(fakeMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::privateMessageReceived(Communi::IrcPrivateMessage *message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AbstractIrcServer::messageReceived(Communi::IrcMessage *message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
} // namespace irc
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
63
src/providers/irc/abstractircserver.hpp
Normal file
63
src/providers/irc/abstractircserver.hpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <IrcMessage>
|
||||||
|
#include <mutex>
|
||||||
|
#include <pajlada/signals/signal.hpp>
|
||||||
|
|
||||||
|
#include "channel.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace irc {
|
||||||
|
class AbstractIrcServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// connection
|
||||||
|
Communi::IrcConnection *getReadConnection() const;
|
||||||
|
|
||||||
|
void connect();
|
||||||
|
void disconnect();
|
||||||
|
|
||||||
|
void sendMessage(const QString &channelName, const QString &message);
|
||||||
|
|
||||||
|
// channels
|
||||||
|
std::shared_ptr<Channel> addChannel(const QString &channelName);
|
||||||
|
std::shared_ptr<Channel> getChannel(const QString &channelName);
|
||||||
|
|
||||||
|
// signals
|
||||||
|
pajlada::Signals::NoArgSignal connected;
|
||||||
|
pajlada::Signals::NoArgSignal disconnected;
|
||||||
|
pajlada::Signals::Signal<Communi::IrcPrivateMessage *> onPrivateMessage;
|
||||||
|
|
||||||
|
void addFakeMessage(const QString &data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AbstractIrcServer();
|
||||||
|
|
||||||
|
virtual void initializeConnection(Communi::IrcConnection *connection, bool isRead,
|
||||||
|
bool isWrite) = 0;
|
||||||
|
virtual std::shared_ptr<Channel> createChannel(const QString &channelName) = 0;
|
||||||
|
|
||||||
|
virtual void privateMessageReceived(Communi::IrcPrivateMessage *message);
|
||||||
|
virtual void messageReceived(Communi::IrcMessage *message);
|
||||||
|
virtual void writeConnectionMessageReceived(Communi::IrcMessage *message);
|
||||||
|
|
||||||
|
virtual void onConnected();
|
||||||
|
virtual void onDisconnected();
|
||||||
|
|
||||||
|
virtual std::shared_ptr<Channel> getCustomChannel(const QString &channelName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initConnection();
|
||||||
|
|
||||||
|
QMap<QString, std::weak_ptr<Channel>> channels;
|
||||||
|
|
||||||
|
std::unique_ptr<Communi::IrcConnection> writeConnection = nullptr;
|
||||||
|
std::unique_ptr<Communi::IrcConnection> readConnection = nullptr;
|
||||||
|
|
||||||
|
std::mutex connectionMutex;
|
||||||
|
std::mutex channelMutex;
|
||||||
|
};
|
||||||
|
} // namespace irc
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
|
@ -3,6 +3,7 @@
|
||||||
#include "QString"
|
#include "QString"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
|
||||||
struct EmoteValue {
|
struct EmoteValue {
|
||||||
|
@ -29,4 +30,5 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
|
@ -5,73 +5,83 @@
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
#include "messages/limitedqueue.hpp"
|
#include "messages/limitedqueue.hpp"
|
||||||
#include "messages/message.hpp"
|
#include "messages/message.hpp"
|
||||||
#include "singletons/channelmanager.hpp"
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
|
//#include "singletons/channelmanager.hpp"
|
||||||
#include "singletons/resourcemanager.hpp"
|
#include "singletons/resourcemanager.hpp"
|
||||||
#include "singletons/windowmanager.hpp"
|
#include "singletons/windowmanager.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
#include "twitchserver.hpp"
|
||||||
|
|
||||||
|
using namespace chatterino::singletons;
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace singletons {
|
namespace providers {
|
||||||
namespace helper {
|
namespace twitch {
|
||||||
|
|
||||||
IrcMessageHandler::IrcMessageHandler(ChannelManager &_channelManager,
|
IrcMessageHandler::IrcMessageHandler(singletons::ResourceManager &_resourceManager)
|
||||||
ResourceManager &_resourceManager)
|
: resourceManager(_resourceManager)
|
||||||
: channelManager(_channelManager)
|
|
||||||
, resourceManager(_resourceManager)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
IrcMessageHandler &IrcMessageHandler::getInstance()
|
IrcMessageHandler &IrcMessageHandler::getInstance()
|
||||||
{
|
{
|
||||||
static IrcMessageHandler instance(ChannelManager::getInstance(),
|
static IrcMessageHandler instance(singletons::ResourceManager::getInstance());
|
||||||
ResourceManager::getInstance());
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message)
|
void IrcMessageHandler::handleRoomStateMessage(Communi::IrcMessage *message)
|
||||||
{
|
{
|
||||||
const auto &tags = message->tags();
|
const auto &tags = message->tags();
|
||||||
|
|
||||||
auto iterator = tags.find("room-id");
|
auto iterator = tags.find("room-id");
|
||||||
|
|
||||||
if (iterator != tags.end()) {
|
if (iterator != tags.end()) {
|
||||||
auto roomID = iterator.value().toString();
|
auto roomID = iterator.value().toString();
|
||||||
|
|
||||||
auto channel =
|
QStringList words = QString(message->toData()).split("#");
|
||||||
this->channelManager.getTwitchChannel(QString(message->toData()).split("#").at(1));
|
|
||||||
auto twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get());
|
// ensure the format is valid
|
||||||
if (twitchChannel != nullptr) {
|
if (words.length() < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString channelName = words.at(1);
|
||||||
|
|
||||||
|
auto channel = TwitchServer::getInstance().getChannel(channelName);
|
||||||
|
|
||||||
|
if (auto twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get())) {
|
||||||
|
// set the room id of the channel
|
||||||
twitchChannel->setRoomID(roomID);
|
twitchChannel->setRoomID(roomID);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->resourceManager.loadChannelData(roomID);
|
ResourceManager::getInstance().loadChannelData(roomID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
|
void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
|
||||||
{
|
{
|
||||||
assert(message->parameters().length() >= 1);
|
// check parameter count
|
||||||
|
if (message->parameters().length() < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
auto rawChannelName = message->parameter(0);
|
QString chanName = message->parameter(0);
|
||||||
|
|
||||||
assert(rawChannelName.length() >= 2);
|
// check channel name length
|
||||||
|
if (chanName.length() >= 2)
|
||||||
|
return;
|
||||||
|
|
||||||
auto trimmedChannelName = rawChannelName.mid(1);
|
chanName = chanName.mid(1);
|
||||||
|
|
||||||
auto c = this->channelManager.getTwitchChannel(trimmedChannelName);
|
// get channel
|
||||||
|
auto chan = TwitchServer::getInstance().getChannel(chanName);
|
||||||
|
|
||||||
if (!c) {
|
if (!chan) {
|
||||||
debug::Log(
|
debug::Log("[IrcMessageHandler:handleClearChatMessage] Twitch channel {} not found",
|
||||||
"[IrcMessageHandler:handleClearChatMessage] Channel {} not found in channel manager",
|
chanName);
|
||||||
trimmedChannelName);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the chat has been cleared by a moderator
|
// check if the chat has been cleared by a moderator
|
||||||
if (message->parameters().length() == 1) {
|
if (message->parameters().length() == 1) {
|
||||||
c->addMessage(Message::createSystemMessage("Chat has been cleared by a moderator."));
|
chan->addMessage(Message::createSystemMessage("Chat has been cleared by a moderator."));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +102,7 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the notice that the user has been timed out
|
// add the notice that the user has been timed out
|
||||||
LimitedQueueSnapshot<MessagePtr> snapshot = c->getMessageSnapshot();
|
LimitedQueueSnapshot<MessagePtr> snapshot = chan->getMessageSnapshot();
|
||||||
bool addMessage = true;
|
bool addMessage = true;
|
||||||
int snapshotLength = snapshot.getLength();
|
int snapshotLength = snapshot.getLength();
|
||||||
|
|
||||||
|
@ -100,14 +110,14 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
|
||||||
if (snapshot[i]->flags & Message::Timeout && snapshot[i]->loginName == username) {
|
if (snapshot[i]->flags & Message::Timeout && snapshot[i]->loginName == username) {
|
||||||
MessagePtr replacement(
|
MessagePtr replacement(
|
||||||
Message::createTimeoutMessage(username, durationInSeconds, reason, true));
|
Message::createTimeoutMessage(username, durationInSeconds, reason, true));
|
||||||
c->replaceMessage(snapshot[i], replacement);
|
chan->replaceMessage(snapshot[i], replacement);
|
||||||
addMessage = false;
|
addMessage = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addMessage) {
|
if (addMessage) {
|
||||||
c->addMessage(Message::createTimeoutMessage(username, durationInSeconds, reason, false));
|
chan->addMessage(Message::createTimeoutMessage(username, durationInSeconds, reason, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable the messages from the user
|
// disable the messages from the user
|
||||||
|
@ -118,7 +128,7 @@ void IrcMessageHandler::handleClearChatMessage(Communi::IrcMessage *message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// refresh all
|
// refresh all
|
||||||
WindowManager::getInstance().repaintVisibleChatWidgets(c.get());
|
WindowManager::getInstance().repaintVisibleChatWidgets(chan.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message)
|
void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message)
|
||||||
|
@ -129,7 +139,7 @@ void IrcMessageHandler::handleUserStateMessage(Communi::IrcMessage *message)
|
||||||
auto rawChannelName = message->parameters().at(0);
|
auto rawChannelName = message->parameters().at(0);
|
||||||
auto trimmedChannelName = rawChannelName.mid(1);
|
auto trimmedChannelName = rawChannelName.mid(1);
|
||||||
|
|
||||||
auto c = this->channelManager.getTwitchChannel(trimmedChannelName);
|
auto c = TwitchServer::getInstance().getChannel(trimmedChannelName);
|
||||||
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(c.get());
|
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(c.get());
|
||||||
if (tc != nullptr) {
|
if (tc != nullptr) {
|
||||||
tc->setMod(_mod == "1");
|
tc->setMod(_mod == "1");
|
||||||
|
@ -149,7 +159,8 @@ void IrcMessageHandler::handleUserNoticeMessage(Communi::IrcMessage *message)
|
||||||
|
|
||||||
void IrcMessageHandler::handleModeMessage(Communi::IrcMessage *message)
|
void IrcMessageHandler::handleModeMessage(Communi::IrcMessage *message)
|
||||||
{
|
{
|
||||||
auto channel = channelManager.getTwitchChannel(message->parameter(0).remove(0, 1));
|
auto channel = TwitchServer::getInstance().getChannel(message->parameter(0).remove(0, 1));
|
||||||
|
|
||||||
if (message->parameter(1) == "+o") {
|
if (message->parameter(1) == "+o") {
|
||||||
channel->modList.append(message->parameter(2));
|
channel->modList.append(message->parameter(2));
|
||||||
} else if (message->parameter(1) == "-o") {
|
} else if (message->parameter(1) == "-o") {
|
||||||
|
@ -165,24 +176,25 @@ void IrcMessageHandler::handleNoticeMessage(Communi::IrcNoticeMessage *message)
|
||||||
MessagePtr msg = Message::createSystemMessage(message->content());
|
MessagePtr msg = Message::createSystemMessage(message->content());
|
||||||
|
|
||||||
if (broadcast) {
|
if (broadcast) {
|
||||||
this->channelManager.doOnAll([msg](const auto &c) {
|
// fourtf: send to all twitch channels
|
||||||
c->addMessage(msg); //
|
// this->channelManager.doOnAll([msg](const auto &c) {
|
||||||
});
|
// c->addMessage(msg); //
|
||||||
|
// });
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto trimmedChannelName = rawChannelName.mid(1);
|
auto trimmedChannelName = rawChannelName.mid(1);
|
||||||
|
|
||||||
auto c = this->channelManager.getTwitchChannel(trimmedChannelName);
|
auto channel = TwitchServer::getInstance().getChannel(trimmedChannelName);
|
||||||
|
|
||||||
if (!c) {
|
if (!channel) {
|
||||||
debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager",
|
debug::Log("[IrcManager:handleNoticeMessage] Channel {} not found in channel manager",
|
||||||
trimmedChannelName);
|
trimmedChannelName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->addMessage(msg);
|
channel->addMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrcMessageHandler::handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message)
|
void IrcMessageHandler::handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message)
|
||||||
|
@ -202,6 +214,6 @@ void IrcMessageHandler::handleWriteConnectionNoticeMessage(Communi::IrcNoticeMes
|
||||||
|
|
||||||
this->handleNoticeMessage(message);
|
this->handleNoticeMessage(message);
|
||||||
}
|
}
|
||||||
} // namespace helper
|
} // namespace twitch
|
||||||
} // namespace singletons
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
|
@ -6,14 +6,15 @@ namespace chatterino {
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
class ChannelManager;
|
class ChannelManager;
|
||||||
class ResourceManager;
|
class ResourceManager;
|
||||||
|
} // namespace singletons
|
||||||
|
|
||||||
namespace helper {
|
namespace providers {
|
||||||
|
namespace twitch {
|
||||||
class IrcMessageHandler
|
class IrcMessageHandler
|
||||||
{
|
{
|
||||||
IrcMessageHandler(ChannelManager &channelManager, ResourceManager &resourceManager);
|
IrcMessageHandler(singletons::ResourceManager &resourceManager);
|
||||||
|
|
||||||
ChannelManager &channelManager;
|
singletons::ResourceManager &resourceManager;
|
||||||
ResourceManager &resourceManager;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static IrcMessageHandler &getInstance();
|
static IrcMessageHandler &getInstance();
|
||||||
|
@ -27,6 +28,6 @@ public:
|
||||||
void handleNoticeMessage(Communi::IrcNoticeMessage *message);
|
void handleNoticeMessage(Communi::IrcNoticeMessage *message);
|
||||||
void handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message);
|
void handleWriteConnectionNoticeMessage(Communi::IrcNoticeMessage *message);
|
||||||
};
|
};
|
||||||
}
|
} // namespace twitch
|
||||||
}
|
} // namespace providers
|
||||||
}
|
} // namespace chatterino
|
70
src/providers/twitch/twitchaccount.cpp
Normal file
70
src/providers/twitch/twitchaccount.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "providers/twitch/twitchaccount.hpp"
|
||||||
|
#include "const.hpp"
|
||||||
|
#include "util/urlfetch.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace twitch {
|
||||||
|
TwitchAccount::TwitchAccount(const QString &_username, const QString &_oauthToken,
|
||||||
|
const QString &_oauthClient)
|
||||||
|
: userName(_username)
|
||||||
|
, oauthClient(_oauthClient)
|
||||||
|
, oauthToken(_oauthToken)
|
||||||
|
, _isAnon(_username == ANONYMOUS_USERNAME)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &TwitchAccount::getUserName() const
|
||||||
|
{
|
||||||
|
return this->userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &TwitchAccount::getOAuthClient() const
|
||||||
|
{
|
||||||
|
return this->oauthClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &TwitchAccount::getOAuthToken() const
|
||||||
|
{
|
||||||
|
return this->oauthToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &TwitchAccount::getUserId() const
|
||||||
|
{
|
||||||
|
return this->userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchAccount::setUserId(const QString &id)
|
||||||
|
{
|
||||||
|
this->userId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TwitchAccount::setOAuthClient(const QString &newClientID)
|
||||||
|
{
|
||||||
|
if (this->oauthClient.compare(newClientID) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->oauthClient = newClientID;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TwitchAccount::setOAuthToken(const QString &newOAuthToken)
|
||||||
|
{
|
||||||
|
if (this->oauthToken.compare(newOAuthToken) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->oauthToken = newOAuthToken;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TwitchAccount::isAnon() const
|
||||||
|
{
|
||||||
|
return this->_isAnon;
|
||||||
|
}
|
||||||
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
|
@ -1,19 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ircaccount.hpp"
|
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
class TwitchAccount
|
||||||
class TwitchUser : public IrcUser2
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TwitchUser(const QString &username, const QString &oauthToken, const QString &oauthClient);
|
TwitchAccount(const QString &username, const QString &oauthToken, const QString &oauthClient);
|
||||||
|
|
||||||
|
const QString &getUserName() const;
|
||||||
const QString &getOAuthToken() const;
|
const QString &getOAuthToken() const;
|
||||||
const QString &getOAuthClient() const;
|
const QString &getOAuthClient() const;
|
||||||
|
|
||||||
const QString &getUserId() const;
|
const QString &getUserId() const;
|
||||||
void setUserId(const QString &id);
|
void setUserId(const QString &id);
|
||||||
|
|
||||||
|
@ -28,11 +28,12 @@ public:
|
||||||
bool isAnon() const;
|
bool isAnon() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString _oauthClient;
|
QString oauthClient;
|
||||||
QString _oauthToken;
|
QString oauthToken;
|
||||||
QString _userId;
|
QString userId;
|
||||||
|
QString userName;
|
||||||
const bool _isAnon;
|
const bool _isAnon;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
|
@ -1,15 +1,16 @@
|
||||||
#include "twitchaccountmanager.hpp"
|
#include "providers/twitch/twitchaccountmanager.hpp"
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
#include "const.hpp"
|
#include "const.hpp"
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
|
||||||
TwitchAccountManager::TwitchAccountManager()
|
TwitchAccountManager::TwitchAccountManager()
|
||||||
{
|
{
|
||||||
this->anonymousUser.reset(new twitch::TwitchUser(twitch::ANONYMOUS_USERNAME, "", ""));
|
this->anonymousUser.reset(new TwitchAccount(ANONYMOUS_USERNAME, "", ""));
|
||||||
|
|
||||||
this->currentUsername.connect([this](const auto &newValue, auto) {
|
this->currentUsername.connect([this](const auto &newValue, auto) {
|
||||||
QString newUsername(QString::fromStdString(newValue));
|
QString newUsername(QString::fromStdString(newValue));
|
||||||
|
@ -28,7 +29,7 @@ TwitchAccountManager::TwitchAccountManager()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<twitch::TwitchUser> TwitchAccountManager::getCurrent()
|
std::shared_ptr<TwitchAccount> TwitchAccountManager::getCurrent()
|
||||||
{
|
{
|
||||||
if (!this->currentUser) {
|
if (!this->currentUser) {
|
||||||
return this->anonymousUser;
|
return this->anonymousUser;
|
||||||
|
@ -50,7 +51,7 @@ std::vector<QString> TwitchAccountManager::getUsernames() const
|
||||||
return userNames;
|
return userNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<twitch::TwitchUser> TwitchAccountManager::findUserByUsername(
|
std::shared_ptr<TwitchAccount> TwitchAccountManager::findUserByUsername(
|
||||||
const QString &username) const
|
const QString &username) const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(this->mutex);
|
std::lock_guard<std::mutex> lock(this->mutex);
|
||||||
|
@ -107,7 +108,7 @@ void TwitchAccountManager::reloadUsers()
|
||||||
} break;
|
} break;
|
||||||
case AddUserResponse::UserValuesUpdated: {
|
case AddUserResponse::UserValuesUpdated: {
|
||||||
debug::Log("User {} already exists, and values updated!", userData.username);
|
debug::Log("User {} already exists, and values updated!", userData.username);
|
||||||
if (userData.username == this->getCurrent()->getNickName()) {
|
if (userData.username == this->getCurrent()->getUserName()) {
|
||||||
debug::Log("It was the current user, so we need to reconnect stuff!");
|
debug::Log("It was the current user, so we need to reconnect stuff!");
|
||||||
this->userChanged.invoke();
|
this->userChanged.invoke();
|
||||||
}
|
}
|
||||||
|
@ -132,7 +133,7 @@ bool TwitchAccountManager::removeUser(const QString &username)
|
||||||
|
|
||||||
this->mutex.lock();
|
this->mutex.lock();
|
||||||
this->users.erase(std::remove_if(this->users.begin(), this->users.end(), [username](auto user) {
|
this->users.erase(std::remove_if(this->users.begin(), this->users.end(), [username](auto user) {
|
||||||
if (user->getNickName() == username) {
|
if (user->getUserName() == username) {
|
||||||
std::string userID(user->getUserId().toStdString());
|
std::string userID(user->getUserId().toStdString());
|
||||||
assert(!userID.empty());
|
assert(!userID.empty());
|
||||||
pajlada::Settings::SettingManager::removeSetting("/accounts/uid" + userID);
|
pajlada::Settings::SettingManager::removeSetting("/accounts/uid" + userID);
|
||||||
|
@ -174,8 +175,8 @@ TwitchAccountManager::AddUserResponse TwitchAccountManager::addUser(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto newUser = std::make_shared<twitch::TwitchUser>(userData.username, userData.oauthToken,
|
auto newUser =
|
||||||
userData.clientID);
|
std::make_shared<TwitchAccount>(userData.username, userData.oauthToken, userData.clientID);
|
||||||
|
|
||||||
// Set users User ID without the uid prefix
|
// Set users User ID without the uid prefix
|
||||||
newUser->setUserId(userData.userID);
|
newUser->setUserId(userData.userID);
|
||||||
|
@ -188,4 +189,5 @@ TwitchAccountManager::AddUserResponse TwitchAccountManager::addUser(
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "twitch/twitchuser.hpp"
|
#include "providers/twitch/twitchaccount.hpp"
|
||||||
|
|
||||||
#include <pajlada/settings/setting.hpp>
|
#include <pajlada/settings/setting.hpp>
|
||||||
|
|
||||||
|
@ -16,9 +16,8 @@ namespace chatterino {
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
class AccountManager;
|
class AccountManager;
|
||||||
}
|
}
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
|
||||||
class TwitchAccountManager
|
class TwitchAccountManager
|
||||||
{
|
{
|
||||||
TwitchAccountManager();
|
TwitchAccountManager();
|
||||||
|
@ -32,11 +31,11 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns the current twitchUsers, or the anonymous user if we're not currently logged in
|
// Returns the current twitchUsers, or the anonymous user if we're not currently logged in
|
||||||
std::shared_ptr<twitch::TwitchUser> getCurrent();
|
std::shared_ptr<TwitchAccount> getCurrent();
|
||||||
|
|
||||||
std::vector<QString> getUsernames() const;
|
std::vector<QString> getUsernames() const;
|
||||||
|
|
||||||
std::shared_ptr<twitch::TwitchUser> findUserByUsername(const QString &username) const;
|
std::shared_ptr<TwitchAccount> findUserByUsername(const QString &username) const;
|
||||||
bool userExists(const QString &username) const;
|
bool userExists(const QString &username) const;
|
||||||
|
|
||||||
void reloadUsers();
|
void reloadUsers();
|
||||||
|
@ -55,14 +54,14 @@ private:
|
||||||
};
|
};
|
||||||
AddUserResponse addUser(const UserData &data);
|
AddUserResponse addUser(const UserData &data);
|
||||||
|
|
||||||
std::shared_ptr<twitch::TwitchUser> currentUser;
|
std::shared_ptr<TwitchAccount> currentUser;
|
||||||
|
|
||||||
std::shared_ptr<twitch::TwitchUser> anonymousUser;
|
std::shared_ptr<TwitchAccount> anonymousUser;
|
||||||
std::vector<std::shared_ptr<twitch::TwitchUser>> users;
|
std::vector<std::shared_ptr<TwitchAccount>> users;
|
||||||
mutable std::mutex mutex;
|
mutable std::mutex mutex;
|
||||||
|
|
||||||
friend class chatterino::singletons::AccountManager;
|
friend class chatterino::singletons::AccountManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
|
@ -1,20 +1,22 @@
|
||||||
#include "twitchchannel.hpp"
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
|
#include "common.hpp"
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
#include "messages/message.hpp"
|
#include "messages/message.hpp"
|
||||||
|
#include "providers/twitch/twitchmessagebuilder.hpp"
|
||||||
#include "singletons/channelmanager.hpp"
|
#include "singletons/channelmanager.hpp"
|
||||||
#include "singletons/emotemanager.hpp"
|
#include "singletons/emotemanager.hpp"
|
||||||
#include "singletons/ircmanager.hpp"
|
#include "singletons/ircmanager.hpp"
|
||||||
#include "singletons/settingsmanager.hpp"
|
#include "singletons/settingsmanager.hpp"
|
||||||
#include "twitch/twitchmessagebuilder.hpp"
|
|
||||||
#include "util/urlfetch.hpp"
|
#include "util/urlfetch.hpp"
|
||||||
|
|
||||||
|
#include <IrcConnection>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
TwitchChannel::TwitchChannel(const QString &channelName, Communi::IrcConnection *_readConnection)
|
||||||
TwitchChannel::TwitchChannel(const QString &channelName)
|
|
||||||
: Channel(channelName)
|
: Channel(channelName)
|
||||||
, bttvChannelEmotes(new util::EmoteMap)
|
, bttvChannelEmotes(new util::EmoteMap)
|
||||||
, ffzChannelEmotes(new util::EmoteMap)
|
, ffzChannelEmotes(new util::EmoteMap)
|
||||||
|
@ -23,6 +25,7 @@ TwitchChannel::TwitchChannel(const QString &channelName)
|
||||||
, popoutPlayerURL("https://player.twitch.tv/?channel=" + name)
|
, popoutPlayerURL("https://player.twitch.tv/?channel=" + name)
|
||||||
, isLive(false)
|
, isLive(false)
|
||||||
, mod(false)
|
, mod(false)
|
||||||
|
, readConnecetion(_readConnection)
|
||||||
{
|
{
|
||||||
debug::Log("[TwitchChannel:{}] Opened", this->name);
|
debug::Log("[TwitchChannel:{}] Opened", this->name);
|
||||||
|
|
||||||
|
@ -42,9 +45,6 @@ TwitchChannel::TwitchChannel(const QString &channelName)
|
||||||
this->fetchRecentMessages(); //
|
this->fetchRecentMessages(); //
|
||||||
});
|
});
|
||||||
|
|
||||||
this->connectedConnection = singletons::IrcManager::getInstance().connected.connect(
|
|
||||||
[this] { this->userStateChanged(); });
|
|
||||||
|
|
||||||
this->messageSuffix.append(' ');
|
this->messageSuffix.append(' ');
|
||||||
this->messageSuffix.append(QChar(0x206D));
|
this->messageSuffix.append(QChar(0x206D));
|
||||||
}
|
}
|
||||||
|
@ -95,8 +95,9 @@ void TwitchChannel::sendMessage(const QString &message)
|
||||||
|
|
||||||
parsedMessage = parsedMessage.trimmed();
|
parsedMessage = parsedMessage.trimmed();
|
||||||
|
|
||||||
if (parsedMessage.isEmpty())
|
if (parsedMessage.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (singletons::SettingManager::getInstance().allowDuplicateMessages) {
|
if (singletons::SettingManager::getInstance().allowDuplicateMessages) {
|
||||||
if (parsedMessage == this->lastSentMessage) {
|
if (parsedMessage == this->lastSentMessage) {
|
||||||
|
@ -106,7 +107,7 @@ void TwitchChannel::sendMessage(const QString &message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
singletons::IrcManager::getInstance().sendMessage(this->name, parsedMessage);
|
this->sendMessageSignal.invoke(this->name, parsedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TwitchChannel::isMod() const
|
bool TwitchChannel::isMod() const
|
||||||
|
@ -227,7 +228,7 @@ void TwitchChannel::fetchRecentMessages()
|
||||||
}
|
}
|
||||||
|
|
||||||
TwitchChannel *channel = dynamic_cast<TwitchChannel *>(shared.get());
|
TwitchChannel *channel = dynamic_cast<TwitchChannel *>(shared.get());
|
||||||
static auto readConnection = singletons::IrcManager::getInstance().getReadConnection();
|
static auto readConnection = channel->readConnecetion;
|
||||||
|
|
||||||
auto msgArray = obj.value("messages").toArray();
|
auto msgArray = obj.value("messages").toArray();
|
||||||
if (msgArray.size() > 0) {
|
if (msgArray.size() > 0) {
|
||||||
|
@ -249,4 +250,5 @@ void TwitchChannel::fetchRecentMessages()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
|
@ -1,19 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <IrcConnection>
|
||||||
|
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
|
#include "common.hpp"
|
||||||
#include "singletons/emotemanager.hpp"
|
#include "singletons/emotemanager.hpp"
|
||||||
#include "singletons/ircmanager.hpp"
|
#include "singletons/ircmanager.hpp"
|
||||||
#include "util/concurrentmap.hpp"
|
#include "util/concurrentmap.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
class TwitchServer;
|
||||||
class TwitchChannel : public Channel
|
class TwitchChannel final : public Channel
|
||||||
{
|
{
|
||||||
QTimer *liveStatusTimer;
|
QTimer *liveStatusTimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit TwitchChannel(const QString &channelName);
|
|
||||||
~TwitchChannel();
|
~TwitchChannel();
|
||||||
|
|
||||||
void reloadChannelEmotes();
|
void reloadChannelEmotes();
|
||||||
|
@ -49,6 +52,8 @@ public:
|
||||||
QString streamUptime;
|
QString streamUptime;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
explicit TwitchChannel(const QString &channelName, Communi::IrcConnection *readConnection);
|
||||||
|
|
||||||
void setLive(bool newLiveStatus);
|
void setLive(bool newLiveStatus);
|
||||||
void refreshLiveStatus();
|
void refreshLiveStatus();
|
||||||
|
|
||||||
|
@ -59,7 +64,11 @@ private:
|
||||||
bool mod;
|
bool mod;
|
||||||
QByteArray messageSuffix;
|
QByteArray messageSuffix;
|
||||||
QString lastSentMessage;
|
QString lastSentMessage;
|
||||||
};
|
|
||||||
|
|
||||||
|
Communi::IrcConnection *readConnecetion;
|
||||||
|
|
||||||
|
friend class TwitchServer;
|
||||||
|
};
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
|
@ -1,12 +1,12 @@
|
||||||
#include "twitchmessagebuilder.hpp"
|
#include "providers/twitch/twitchmessagebuilder.hpp"
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
#include "singletons/emotemanager.hpp"
|
#include "singletons/emotemanager.hpp"
|
||||||
#include "singletons/ircmanager.hpp"
|
#include "singletons/ircmanager.hpp"
|
||||||
#include "singletons/resourcemanager.hpp"
|
#include "singletons/resourcemanager.hpp"
|
||||||
#include "singletons/settingsmanager.hpp"
|
#include "singletons/settingsmanager.hpp"
|
||||||
#include "singletons/thememanager.hpp"
|
#include "singletons/thememanager.hpp"
|
||||||
#include "singletons/windowmanager.hpp"
|
#include "singletons/windowmanager.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
@ -15,6 +15,7 @@
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
|
|
||||||
TwitchMessageBuilder::TwitchMessageBuilder(Channel *_channel,
|
TwitchMessageBuilder::TwitchMessageBuilder(Channel *_channel,
|
||||||
|
@ -707,4 +708,5 @@ bool TwitchMessageBuilder::tryParseCheermote(const QString &string)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
|
@ -12,6 +12,7 @@
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
class Channel;
|
class Channel;
|
||||||
|
|
||||||
|
namespace providers {
|
||||||
namespace twitch {
|
namespace twitch {
|
||||||
class TwitchChannel;
|
class TwitchChannel;
|
||||||
|
|
||||||
|
@ -64,4 +65,5 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace twitch
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
148
src/providers/twitch/twitchserver.cpp
Normal file
148
src/providers/twitch/twitchserver.cpp
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
#include "twitchserver.hpp"
|
||||||
|
|
||||||
|
#include "providers/twitch/ircmessagehandler.hpp"
|
||||||
|
#include "providers/twitch/twitchaccount.hpp"
|
||||||
|
#include "providers/twitch/twitchmessagebuilder.hpp"
|
||||||
|
#include "singletons/accountmanager.hpp"
|
||||||
|
#include "util/posttothread.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
using namespace Communi;
|
||||||
|
using namespace chatterino::singletons;
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace twitch {
|
||||||
|
TwitchServer::TwitchServer()
|
||||||
|
: whispersChannel(new Channel("/mentions"))
|
||||||
|
, mentionsChannel(new Channel("/mentions"))
|
||||||
|
{
|
||||||
|
AccountManager::getInstance().Twitch.userChanged.connect([this]() { //
|
||||||
|
util::postToThread([this] { this->connect(); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TwitchServer &TwitchServer::getInstance()
|
||||||
|
{
|
||||||
|
static TwitchServer s;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchServer::initializeConnection(IrcConnection *connection, bool isRead, bool isWrite)
|
||||||
|
{
|
||||||
|
std::shared_ptr<TwitchAccount> account = AccountManager::getInstance().Twitch.getCurrent();
|
||||||
|
|
||||||
|
QString username = account->getUserName();
|
||||||
|
// QString oauthClient = account->getOAuthClient();
|
||||||
|
QString oauthToken = account->getOAuthToken();
|
||||||
|
|
||||||
|
if (!oauthToken.startsWith("oauth:")) {
|
||||||
|
oauthToken.prepend("oauth:");
|
||||||
|
}
|
||||||
|
|
||||||
|
connection->setUserName(username);
|
||||||
|
connection->setNickName(username);
|
||||||
|
connection->setRealName(username);
|
||||||
|
|
||||||
|
if (!account->isAnon()) {
|
||||||
|
connection->setPassword(oauthToken);
|
||||||
|
|
||||||
|
// fourtf: ignored users
|
||||||
|
// this->refreshIgnoredUsers(username, oauthClient, oauthToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
connection->sendCommand(IrcCommand::createCapability("REQ", "twitch.tv/membership"));
|
||||||
|
connection->sendCommand(IrcCommand::createCapability("REQ", "twitch.tv/commands"));
|
||||||
|
connection->sendCommand(IrcCommand::createCapability("REQ", "twitch.tv/tags"));
|
||||||
|
|
||||||
|
connection->setHost("irc.chat.twitch.tv");
|
||||||
|
connection->setPort(6667);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Channel> TwitchServer::createChannel(const QString &channelName)
|
||||||
|
{
|
||||||
|
TwitchChannel *channel = new TwitchChannel(channelName, this->getReadConnection());
|
||||||
|
|
||||||
|
channel->sendMessageSignal.connect(
|
||||||
|
[this](auto chan, auto msg) { this->sendMessage(chan, msg); });
|
||||||
|
|
||||||
|
return std::shared_ptr<Channel>(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchServer::privateMessageReceived(IrcPrivateMessage *message)
|
||||||
|
{
|
||||||
|
this->onPrivateMessage.invoke(message);
|
||||||
|
auto chan = TwitchServer::getInstance().getChannel(message->target().mid(1));
|
||||||
|
|
||||||
|
if (!chan) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
messages::MessageParseArgs args;
|
||||||
|
|
||||||
|
TwitchMessageBuilder builder(chan.get(), message, args);
|
||||||
|
|
||||||
|
if (!builder.isIgnored()) {
|
||||||
|
messages::MessagePtr _message = builder.build();
|
||||||
|
if (_message->flags & messages::Message::Highlighted) {
|
||||||
|
TwitchServer::getInstance().mentionsChannel->addMessage(_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
chan->addMessage(_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchServer::messageReceived(IrcMessage *message)
|
||||||
|
{
|
||||||
|
// this->readConnection
|
||||||
|
if (message->type() == IrcMessage::Type::Private) {
|
||||||
|
// We already have a handler for private messages
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString &command = message->command();
|
||||||
|
|
||||||
|
if (command == "ROOMSTATE") {
|
||||||
|
IrcMessageHandler::getInstance().handleRoomStateMessage(message);
|
||||||
|
} else if (command == "CLEARCHAT") {
|
||||||
|
IrcMessageHandler::getInstance().handleClearChatMessage(message);
|
||||||
|
} else if (command == "USERSTATE") {
|
||||||
|
IrcMessageHandler::getInstance().handleUserStateMessage(message);
|
||||||
|
} else if (command == "WHISPER") {
|
||||||
|
IrcMessageHandler::getInstance().handleWhisperMessage(message);
|
||||||
|
} else if (command == "USERNOTICE") {
|
||||||
|
IrcMessageHandler::getInstance().handleUserNoticeMessage(message);
|
||||||
|
} else if (command == "MODE") {
|
||||||
|
IrcMessageHandler::getInstance().handleModeMessage(message);
|
||||||
|
} else if (command == "NOTICE") {
|
||||||
|
IrcMessageHandler::getInstance().handleNoticeMessage(
|
||||||
|
static_cast<IrcNoticeMessage *>(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchServer::writeConnectionMessageReceived(IrcMessage *message)
|
||||||
|
{
|
||||||
|
switch (message->type()) {
|
||||||
|
case IrcMessage::Type::Notice: {
|
||||||
|
IrcMessageHandler::getInstance().handleWriteConnectionNoticeMessage(
|
||||||
|
static_cast<IrcNoticeMessage *>(message));
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Channel> TwitchServer::getCustomChannel(const QString &channelName)
|
||||||
|
{
|
||||||
|
if (channelName == "/whispers") {
|
||||||
|
return whispersChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelName == "/mentions") {
|
||||||
|
return mentionsChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
35
src/providers/twitch/twitchserver.hpp
Normal file
35
src/providers/twitch/twitchserver.hpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "providers/irc/abstractircserver.hpp"
|
||||||
|
#include "providers/twitch/twitchaccount.hpp"
|
||||||
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace providers {
|
||||||
|
namespace twitch {
|
||||||
|
class TwitchServer final : public irc::AbstractIrcServer
|
||||||
|
{
|
||||||
|
TwitchServer();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static TwitchServer &getInstance();
|
||||||
|
|
||||||
|
const ChannelPtr whispersChannel;
|
||||||
|
const ChannelPtr mentionsChannel;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void initializeConnection(Communi::IrcConnection *connection, bool isRead,
|
||||||
|
bool isWrite) override;
|
||||||
|
virtual std::shared_ptr<Channel> createChannel(const QString &channelName) override;
|
||||||
|
|
||||||
|
virtual void privateMessageReceived(Communi::IrcPrivateMessage *message) override;
|
||||||
|
virtual void messageReceived(Communi::IrcMessage *message) override;
|
||||||
|
virtual void writeConnectionMessageReceived(Communi::IrcMessage *message) override;
|
||||||
|
|
||||||
|
virtual std::shared_ptr<Channel> getCustomChannel(const QString &channelname) override;
|
||||||
|
};
|
||||||
|
} // namespace twitch
|
||||||
|
} // namespace providers
|
||||||
|
} // namespace chatterino
|
|
@ -43,5 +43,5 @@ void AccountManager::load()
|
||||||
this->Twitch.userChanged.invoke();
|
this->Twitch.userChanged.invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace singletons
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "twitch/twitchaccountmanager.hpp"
|
#include "providers/twitch/twitchaccountmanager.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
|
@ -14,7 +14,7 @@ public:
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
|
|
||||||
twitch::TwitchAccountManager Twitch;
|
providers::twitch::TwitchAccountManager Twitch;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace singletons
|
} // namespace singletons
|
||||||
|
|
|
@ -1,142 +1,140 @@
|
||||||
#include "singletons/channelmanager.hpp"
|
//#include "singletons/channelmanager.hpp"
|
||||||
#include "singletons/ircmanager.hpp"
|
//#include "singletons/ircmanager.hpp"
|
||||||
|
|
||||||
using namespace chatterino::twitch;
|
// namespace chatterino {
|
||||||
|
// namespace singletons {
|
||||||
|
|
||||||
namespace chatterino {
|
// ChannelManager &ChannelManager::getInstance()
|
||||||
namespace singletons {
|
//{
|
||||||
|
// static ChannelManager instance;
|
||||||
|
// return instance;
|
||||||
|
//}
|
||||||
|
|
||||||
ChannelManager &ChannelManager::getInstance()
|
// ChannelManager::ChannelManager()
|
||||||
{
|
// : whispersChannel(new Channel("/whispers"))
|
||||||
static ChannelManager instance;
|
// , mentionsChannel(new Channel("/mentions"))
|
||||||
return instance;
|
// , emptyChannel(new Channel(""))
|
||||||
}
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
ChannelManager::ChannelManager()
|
// const std::vector<ChannelPtr> ChannelManager::getItems()
|
||||||
: whispersChannel(new Channel("/whispers"))
|
//{
|
||||||
, mentionsChannel(new Channel("/mentions"))
|
// QMutexLocker locker(&this->channelsMutex);
|
||||||
, emptyChannel(new Channel(""))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<ChannelPtr> ChannelManager::getItems()
|
// std::vector<ChannelPtr> items;
|
||||||
{
|
|
||||||
QMutexLocker locker(&this->channelsMutex);
|
|
||||||
|
|
||||||
std::vector<ChannelPtr> items;
|
// for (auto &item : this->twitchChannels.values()) {
|
||||||
|
// items.push_back(std::get<0>(item));
|
||||||
|
// }
|
||||||
|
|
||||||
for (auto &item : this->twitchChannels.values()) {
|
// return items;
|
||||||
items.push_back(std::get<0>(item));
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
// ChannelPtr ChannelManager::addTwitchChannel(const QString &rawChannelName)
|
||||||
}
|
//{
|
||||||
|
// QString channelName = rawChannelName.toLower();
|
||||||
|
|
||||||
ChannelPtr ChannelManager::addTwitchChannel(const QString &rawChannelName)
|
// if (channelName.length() > 1 && channelName.at(0) == '/') {
|
||||||
{
|
// return this->getTwitchChannel(channelName);
|
||||||
QString channelName = rawChannelName.toLower();
|
// }
|
||||||
|
|
||||||
if (channelName.length() > 1 && channelName.at(0) == '/') {
|
// if (channelName.length() > 0 && channelName.at(0) == '#') {
|
||||||
return this->getTwitchChannel(channelName);
|
// channelName = channelName.mid(1);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (channelName.length() > 0 && channelName.at(0) == '#') {
|
// QMutexLocker locker(&this->channelsMutex);
|
||||||
channelName = channelName.mid(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
QMutexLocker locker(&this->channelsMutex);
|
// auto it = this->twitchChannels.find(channelName);
|
||||||
|
|
||||||
auto it = this->twitchChannels.find(channelName);
|
// if (it == this->twitchChannels.end()) {
|
||||||
|
// auto channel = std::make_shared<TwitchChannel>(channelName);
|
||||||
|
|
||||||
if (it == this->twitchChannels.end()) {
|
// this->twitchChannels.insert(channelName, std::make_tuple(channel, 1));
|
||||||
auto channel = std::make_shared<TwitchChannel>(channelName);
|
|
||||||
|
|
||||||
this->twitchChannels.insert(channelName, std::make_tuple(channel, 1));
|
// this->ircJoin.invoke(channelName);
|
||||||
|
|
||||||
this->ircJoin.invoke(channelName);
|
// return channel;
|
||||||
|
// }
|
||||||
|
|
||||||
return channel;
|
// std::get<1>(it.value())++;
|
||||||
}
|
|
||||||
|
|
||||||
std::get<1>(it.value())++;
|
// return std::get<0>(it.value());
|
||||||
|
//}
|
||||||
|
|
||||||
return std::get<0>(it.value());
|
// ChannelPtr ChannelManager::getTwitchChannel(const QString &channel)
|
||||||
}
|
//{
|
||||||
|
// QMutexLocker locker(&this->channelsMutex);
|
||||||
|
|
||||||
ChannelPtr ChannelManager::getTwitchChannel(const QString &channel)
|
// QString c = channel.toLower();
|
||||||
{
|
|
||||||
QMutexLocker locker(&this->channelsMutex);
|
|
||||||
|
|
||||||
QString c = channel.toLower();
|
// if (channel.length() > 1 && channel.at(0) == '/') {
|
||||||
|
// if (c == "/whispers") {
|
||||||
|
// return whispersChannel;
|
||||||
|
// }
|
||||||
|
|
||||||
if (channel.length() > 1 && channel.at(0) == '/') {
|
// if (c == "/mentions") {
|
||||||
if (c == "/whispers") {
|
// return mentionsChannel;
|
||||||
return whispersChannel;
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
if (c == "/mentions") {
|
// return emptyChannel;
|
||||||
return mentionsChannel;
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
return emptyChannel;
|
// auto a = this->twitchChannels.find(c);
|
||||||
}
|
|
||||||
|
|
||||||
auto a = this->twitchChannels.find(c);
|
// if (a == this->twitchChannels.end()) {
|
||||||
|
// return emptyChannel;
|
||||||
|
// }
|
||||||
|
|
||||||
if (a == this->twitchChannels.end()) {
|
// return std::get<0>(a.value());
|
||||||
return emptyChannel;
|
//}
|
||||||
}
|
|
||||||
|
|
||||||
return std::get<0>(a.value());
|
// void ChannelManager::removeTwitchChannel(const QString &channel)
|
||||||
}
|
//{
|
||||||
|
// QMutexLocker locker(&this->channelsMutex);
|
||||||
|
|
||||||
void ChannelManager::removeTwitchChannel(const QString &channel)
|
// if (channel.length() > 1 && channel.at(0) == '/') {
|
||||||
{
|
// return;
|
||||||
QMutexLocker locker(&this->channelsMutex);
|
// }
|
||||||
|
|
||||||
if (channel.length() > 1 && channel.at(0) == '/') {
|
// QString c = channel.toLower();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString c = channel.toLower();
|
// auto a = this->twitchChannels.find(c);
|
||||||
|
|
||||||
auto a = this->twitchChannels.find(c);
|
// if (a == this->twitchChannels.end()) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
if (a == this->twitchChannels.end()) {
|
// std::get<1>(a.value())--;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::get<1>(a.value())--;
|
// if (std::get<1>(a.value()) == 0) {
|
||||||
|
// this->ircPart.invoke(c);
|
||||||
|
// this->twitchChannels.remove(c);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
if (std::get<1>(a.value()) == 0) {
|
// const std::string &ChannelManager::getUserID(const std::string &username)
|
||||||
this->ircPart.invoke(c);
|
//{
|
||||||
this->twitchChannels.remove(c);
|
// /* TODO: Implement
|
||||||
}
|
// auto it = this->usernameToID.find(username);
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &ChannelManager::getUserID(const std::string &username)
|
// if (it != std::end(this->usernameToID)) {
|
||||||
{
|
// return *it;
|
||||||
/* TODO: Implement
|
// }
|
||||||
auto it = this->usernameToID.find(username);
|
// */
|
||||||
|
|
||||||
if (it != std::end(this->usernameToID)) {
|
// static std::string temporary = "xd";
|
||||||
return *it;
|
// return temporary;
|
||||||
}
|
//}
|
||||||
*/
|
|
||||||
|
|
||||||
static std::string temporary = "xd";
|
// void ChannelManager::doOnAll(std::function<void(ChannelPtr)> func)
|
||||||
return temporary;
|
//{
|
||||||
}
|
// for (const auto &channel : this->twitchChannels) {
|
||||||
|
// func(std::get<0>(channel));
|
||||||
|
// }
|
||||||
|
|
||||||
void ChannelManager::doOnAll(std::function<void(ChannelPtr)> func)
|
// func(this->whispersChannel);
|
||||||
{
|
// func(this->mentionsChannel);
|
||||||
for (const auto &channel : this->twitchChannels) {
|
//}
|
||||||
func(std::get<0>(channel));
|
|
||||||
}
|
|
||||||
|
|
||||||
func(this->whispersChannel);
|
//} // namespace singletons
|
||||||
func(this->mentionsChannel);
|
//} // namespace chatterino
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,49 +1,44 @@
|
||||||
#pragma once
|
//#pragma once
|
||||||
|
|
||||||
#include "channel.hpp"
|
//#include "channel.hpp"
|
||||||
#include "channeldata.hpp"
|
//#include "channeldata.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
//#include "providers/twitch/twitchchannel.hpp"
|
||||||
|
|
||||||
#include <map>
|
//#include <map>
|
||||||
|
|
||||||
namespace chatterino {
|
// namespace chatterino {
|
||||||
namespace singletons {
|
// namespace singletons {
|
||||||
class IrcManager;
|
// class IrcManager;
|
||||||
|
|
||||||
class ChannelManager
|
// class ChannelManager
|
||||||
{
|
//{
|
||||||
explicit ChannelManager();
|
// explicit ChannelManager();
|
||||||
|
|
||||||
public:
|
// public:
|
||||||
static ChannelManager &getInstance();
|
// static ChannelManager &getInstance();
|
||||||
|
|
||||||
const std::vector<ChannelPtr> getItems();
|
// const std::vector<ChannelPtr> getItems();
|
||||||
|
|
||||||
ChannelPtr addTwitchChannel(const QString &channel);
|
// const std::string &getUserID(const std::string &username);
|
||||||
ChannelPtr getTwitchChannel(const QString &channel);
|
|
||||||
void removeTwitchChannel(const QString &channel);
|
|
||||||
|
|
||||||
const std::string &getUserID(const std::string &username);
|
// void doOnAll(std::function<void(ChannelPtr)> func);
|
||||||
|
|
||||||
void doOnAll(std::function<void(ChannelPtr)> func);
|
// // Special channels
|
||||||
|
// const ChannelPtr whispersChannel;
|
||||||
|
// const ChannelPtr mentionsChannel;
|
||||||
|
// const ChannelPtr emptyChannel;
|
||||||
|
|
||||||
// Special channels
|
// private:
|
||||||
const ChannelPtr whispersChannel;
|
// std::map<std::string, std::string> usernameToID;
|
||||||
const ChannelPtr mentionsChannel;
|
// std::map<std::string, ChannelData> channelDatas;
|
||||||
const ChannelPtr emptyChannel;
|
|
||||||
|
|
||||||
private:
|
// QMutex channelsMutex;
|
||||||
std::map<std::string, std::string> usernameToID;
|
// QMap<QString, std::tuple<std::shared_ptr<TwitchChannel>, int>> twitchChannels;
|
||||||
std::map<std::string, ChannelData> channelDatas;
|
|
||||||
|
|
||||||
QMutex channelsMutex;
|
// pajlada::Signals::Signal<const QString &> ircJoin;
|
||||||
QMap<QString, std::tuple<std::shared_ptr<twitch::TwitchChannel>, int>> twitchChannels;
|
// pajlada::Signals::Signal<const QString &> ircPart;
|
||||||
|
|
||||||
pajlada::Signals::Signal<const QString &> ircJoin;
|
// friend class singletons::IrcManager;
|
||||||
pajlada::Signals::Signal<const QString &> ircPart;
|
//};
|
||||||
|
//} // namespace singletons
|
||||||
friend class singletons::IrcManager;
|
//} // namespace chatterino
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
|
|
||||||
|
using namespace chatterino::providers::twitch;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace singletons {
|
namespace singletons {
|
||||||
|
@ -88,8 +90,7 @@ QStringList CommandManager::getCommands()
|
||||||
return this->commandsStringList;
|
return this->commandsStringList;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CommandManager::execCommand(const QString &text, ChannelPtr channel,
|
QString CommandManager::execCommand(const QString &text, ChannelPtr channel, bool dryRun)
|
||||||
bool dryRun)
|
|
||||||
{
|
{
|
||||||
QStringList words = text.split(' ', QString::SkipEmptyParts);
|
QStringList words = text.split(' ', QString::SkipEmptyParts);
|
||||||
Command command;
|
Command command;
|
||||||
|
@ -104,7 +105,7 @@ QString CommandManager::execCommand(const QString &text, ChannelPtr channel,
|
||||||
QString commandName = words[0];
|
QString commandName = words[0];
|
||||||
|
|
||||||
// check if default command exists
|
// check if default command exists
|
||||||
auto *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get());
|
auto *twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
|
||||||
|
|
||||||
if (!dryRun && twitchChannel != nullptr) {
|
if (!dryRun && twitchChannel != nullptr) {
|
||||||
if (commandName == "/uptime") {
|
if (commandName == "/uptime") {
|
||||||
|
@ -115,22 +116,26 @@ QString CommandManager::execCommand(const QString &text, ChannelPtr channel,
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
} else if (commandName == "/ignore" && words.size() >= 2) {
|
} else if (commandName == "/ignore" && words.size() >= 2) {
|
||||||
QString messageText;
|
// fourtf: ignore user
|
||||||
|
// QString messageText;
|
||||||
|
|
||||||
if (IrcManager::getInstance().tryAddIgnoredUser(words.at(1), messageText)) {
|
// if (IrcManager::getInstance().tryAddIgnoredUser(words.at(1),
|
||||||
messageText = "Ignored user \"" + words.at(1) + "\".";
|
// messageText)) {
|
||||||
}
|
// messageText = "Ignored user \"" + words.at(1) + "\".";
|
||||||
|
// }
|
||||||
|
|
||||||
channel->addMessage(messages::Message::createSystemMessage(messageText));
|
// channel->addMessage(messages::Message::createSystemMessage(messageText));
|
||||||
return "";
|
return "";
|
||||||
} else if (commandName == "/unignore") {
|
} else if (commandName == "/unignore") {
|
||||||
QString messageText;
|
// fourtf: ignore user
|
||||||
|
// QString messageText;
|
||||||
|
|
||||||
if (IrcManager::getInstance().tryRemoveIgnoredUser(words.at(1), messageText)) {
|
// if (IrcManager::getInstance().tryRemoveIgnoredUser(words.at(1),
|
||||||
messageText = "Ignored user \"" + words.at(1) + "\".";
|
// messageText)) {
|
||||||
}
|
// messageText = "Ignored user \"" + words.at(1) + "\".";
|
||||||
|
// }
|
||||||
|
|
||||||
channel->addMessage(messages::Message::createSystemMessage(messageText));
|
// channel->addMessage(messages::Message::createSystemMessage(messageText));
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,18 +13,18 @@ CompletionManager &CompletionManager::getInstance()
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletionModel *CompletionManager::createModel(const std::string &channelName)
|
CompletionModel *CompletionManager::createModel(const QString &channelName)
|
||||||
{
|
{
|
||||||
auto it = this->models.find(channelName);
|
auto it = this->models.find(channelName);
|
||||||
if (it != this->models.end()) {
|
if (it != this->models.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletionModel *ret = new CompletionModel(qS(channelName));
|
CompletionModel *ret = new CompletionModel(channelName);
|
||||||
this->models[channelName] = ret;
|
this->models[channelName] = ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace singletons
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
}
|
|
||||||
|
|
|
@ -16,11 +16,11 @@ class CompletionManager
|
||||||
public:
|
public:
|
||||||
static CompletionManager &getInstance();
|
static CompletionManager &getInstance();
|
||||||
|
|
||||||
CompletionModel *createModel(const std::string &channelName);
|
CompletionModel *createModel(const QString &channelName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, CompletionModel *> models;
|
std::map<QString, CompletionModel *> models;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace singletons
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
}
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#define TWITCH_EMOTE_TEMPLATE "https://static-cdn.jtvnw.net/emoticons/v1/{id}/{scale}"
|
#define TWITCH_EMOTE_TEMPLATE "https://static-cdn.jtvnw.net/emoticons/v1/{id}/{scale}"
|
||||||
|
|
||||||
|
using namespace chatterino::providers::twitch;
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
@ -206,7 +207,7 @@ void EmoteManager::reloadFFZChannelEmotes(const QString &channelName,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
util::ConcurrentMap<QString, twitch::EmoteValue *> &EmoteManager::getTwitchEmotes()
|
util::ConcurrentMap<QString, providers::twitch::EmoteValue *> &EmoteManager::getTwitchEmotes()
|
||||||
{
|
{
|
||||||
return _twitchEmotes;
|
return _twitchEmotes;
|
||||||
}
|
}
|
||||||
|
@ -420,9 +421,9 @@ QString EmoteManager::replaceShortCodes(const QString &text)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmoteManager::refreshTwitchEmotes(const std::shared_ptr<twitch::TwitchUser> &user)
|
void EmoteManager::refreshTwitchEmotes(const std::shared_ptr<TwitchAccount> &user)
|
||||||
{
|
{
|
||||||
debug::Log("Loading Twitch emotes for user {}", user->getNickName());
|
debug::Log("Loading Twitch emotes for user {}", user->getUserName());
|
||||||
|
|
||||||
const auto &roomID = user->getUserId();
|
const auto &roomID = user->getUserId();
|
||||||
const auto &clientID = user->getOAuthClient();
|
const auto &clientID = user->getOAuthClient();
|
||||||
|
@ -462,9 +463,7 @@ void EmoteManager::refreshTwitchEmotes(const std::shared_ptr<twitch::TwitchUser>
|
||||||
}
|
}
|
||||||
|
|
||||||
emoteData.filled = true;
|
emoteData.filled = true;
|
||||||
}
|
});
|
||||||
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmoteManager::loadBTTVEmotes()
|
void EmoteManager::loadBTTVEmotes()
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
#include "emojis.hpp"
|
#include "emojis.hpp"
|
||||||
#include "messages/image.hpp"
|
#include "messages/image.hpp"
|
||||||
|
#include "providers/twitch/emotevalue.hpp"
|
||||||
|
#include "providers/twitch/twitchaccount.hpp"
|
||||||
#include "signalvector.hpp"
|
#include "signalvector.hpp"
|
||||||
#include "twitch/emotevalue.hpp"
|
|
||||||
#include "twitch/twitchuser.hpp"
|
|
||||||
#include "util/concurrentmap.hpp"
|
#include "util/concurrentmap.hpp"
|
||||||
#include "util/emotemap.hpp"
|
#include "util/emotemap.hpp"
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ public:
|
||||||
void reloadFFZChannelEmotes(const QString &channelName,
|
void reloadFFZChannelEmotes(const QString &channelName,
|
||||||
std::weak_ptr<util::EmoteMap> channelEmoteMap);
|
std::weak_ptr<util::EmoteMap> channelEmoteMap);
|
||||||
|
|
||||||
util::ConcurrentMap<QString, twitch::EmoteValue *> &getTwitchEmotes();
|
util::ConcurrentMap<QString, providers::twitch::EmoteValue *> &getTwitchEmotes();
|
||||||
util::EmoteMap &getFFZEmotes();
|
util::EmoteMap &getFFZEmotes();
|
||||||
util::EmoteMap &getChatterinoEmotes();
|
util::EmoteMap &getChatterinoEmotes();
|
||||||
util::EmoteMap &getBTTVChannelEmoteFromCaches();
|
util::EmoteMap &getBTTVChannelEmoteFromCaches();
|
||||||
|
@ -92,7 +92,7 @@ public:
|
||||||
std::vector<std::string> emojiShortCodes;
|
std::vector<std::string> emojiShortCodes;
|
||||||
|
|
||||||
/// Twitch emotes
|
/// Twitch emotes
|
||||||
void refreshTwitchEmotes(const std::shared_ptr<twitch::TwitchUser> &user);
|
void refreshTwitchEmotes(const std::shared_ptr<providers::twitch::TwitchAccount> &user);
|
||||||
|
|
||||||
struct TwitchAccountEmoteData {
|
struct TwitchAccountEmoteData {
|
||||||
struct TwitchEmote {
|
struct TwitchEmote {
|
||||||
|
@ -112,7 +112,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// emote code
|
// emote code
|
||||||
util::ConcurrentMap<QString, twitch::EmoteValue *> _twitchEmotes;
|
util::ConcurrentMap<QString, providers::twitch::EmoteValue *> _twitchEmotes;
|
||||||
|
|
||||||
// emote id
|
// emote id
|
||||||
util::ConcurrentMap<long, util::EmoteData> _twitchEmoteFromCache;
|
util::ConcurrentMap<long, util::EmoteData> _twitchEmoteFromCache;
|
||||||
|
|
|
@ -61,18 +61,19 @@ void CompletionModel::refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Channel-specific: Usernames
|
// Channel-specific: Usernames
|
||||||
auto c = singletons::ChannelManager::getInstance().getTwitchChannel(this->channelName);
|
// fourtf: only works with twitch chat
|
||||||
auto usernames = c->getUsernamesForCompletions();
|
// auto c = singletons::ChannelManager::getInstance().getTwitchChannel(this->channelName);
|
||||||
for (const auto &name : usernames) {
|
// auto usernames = c->getUsernamesForCompletions();
|
||||||
assert(!name.displayName.isEmpty());
|
// for (const auto &name : usernames) {
|
||||||
this->addString(name.displayName);
|
// assert(!name.displayName.isEmpty());
|
||||||
this->addString('@' + name.displayName);
|
// this->addString(name.displayName);
|
||||||
|
// this->addString('@' + name.displayName);
|
||||||
|
|
||||||
if (!name.localizedName.isEmpty()) {
|
// if (!name.localizedName.isEmpty()) {
|
||||||
this->addString(name.localizedName);
|
// this->addString(name.localizedName);
|
||||||
this->addString('@' + name.localizedName);
|
// this->addString('@' + name.localizedName);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompletionModel::addString(const std::string &str)
|
void CompletionModel::addString(const std::string &str)
|
||||||
|
@ -86,5 +87,5 @@ void CompletionModel::addString(const QString &str)
|
||||||
// Always add a space at the end of completions
|
// Always add a space at the end of completions
|
||||||
this->emotes.push_back(str + " ");
|
this->emotes.push_back(str + " ");
|
||||||
}
|
}
|
||||||
}
|
} // namespace singletons
|
||||||
}
|
} // namespace chatterino
|
||||||
|
|
|
@ -2,15 +2,14 @@
|
||||||
#include "channel.hpp"
|
#include "channel.hpp"
|
||||||
#include "debug/log.hpp"
|
#include "debug/log.hpp"
|
||||||
#include "messages/messageparseargs.hpp"
|
#include "messages/messageparseargs.hpp"
|
||||||
|
#include "providers/twitch/twitchaccount.hpp"
|
||||||
|
#include "providers/twitch/twitchmessagebuilder.hpp"
|
||||||
#include "singletons/accountmanager.hpp"
|
#include "singletons/accountmanager.hpp"
|
||||||
#include "singletons/channelmanager.hpp"
|
#include "singletons/channelmanager.hpp"
|
||||||
#include "singletons/emotemanager.hpp"
|
#include "singletons/emotemanager.hpp"
|
||||||
#include "singletons/helper/ircmessagehandler.hpp"
|
|
||||||
#include "singletons/resourcemanager.hpp"
|
#include "singletons/resourcemanager.hpp"
|
||||||
#include "singletons/settingsmanager.hpp"
|
#include "singletons/settingsmanager.hpp"
|
||||||
#include "singletons/windowmanager.hpp"
|
#include "singletons/windowmanager.hpp"
|
||||||
#include "twitch/twitchmessagebuilder.hpp"
|
|
||||||
#include "twitch/twitchuser.hpp"
|
|
||||||
#include "util/posttothread.hpp"
|
#include "util/posttothread.hpp"
|
||||||
#include "util/urlfetch.hpp"
|
#include "util/urlfetch.hpp"
|
||||||
|
|
||||||
|
@ -25,412 +24,122 @@
|
||||||
|
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
// void IrcManager::refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
||||||
namespace singletons {
|
// const QString &oauthToken)
|
||||||
|
//{
|
||||||
IrcManager::IrcManager(ChannelManager &_channelManager, ResourceManager &_resources,
|
// QString nextLink = "https://api.twitch.tv/kraken/users/" + username + "/blocks?limit=" + 100 +
|
||||||
AccountManager &_accountManager)
|
// "&client_id=" + oauthClient;
|
||||||
: channelManager(_channelManager)
|
//
|
||||||
, resources(_resources)
|
// QNetworkAccessManager *manager = new QNetworkAccessManager();
|
||||||
, accountManager(_accountManager)
|
// QNetworkRequest req(QUrl(nextLink + "&oauth_token=" + oauthToken));
|
||||||
{
|
// QNetworkReply *reply = manager->get(req);
|
||||||
this->account = accountManager.Twitch.getCurrent();
|
//
|
||||||
accountManager.Twitch.userChanged.connect([this]() {
|
// QObject::connect(reply, &QNetworkReply::finished, [=] {
|
||||||
this->setUser(accountManager.Twitch.getCurrent());
|
// this->twitchBlockedUsersMutex.lock();
|
||||||
|
// this->twitchBlockedUsers.clear();
|
||||||
debug::Log("[IrcManager] Reconnecting to Twitch IRC as new user {}",
|
// this->twitchBlockedUsersMutex.unlock();
|
||||||
this->account->getUserName());
|
//
|
||||||
|
// QByteArray data = reply->readAll();
|
||||||
postToThread([this] { this->connect(); });
|
// QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
|
||||||
});
|
// QJsonObject root = jsonDoc.object();
|
||||||
|
//
|
||||||
// Initialize the connections
|
// // nextLink =
|
||||||
this->writeConnection.reset(new Communi::IrcConnection);
|
// // root.value("this->links").toObject().value("next").toString();
|
||||||
this->writeConnection->moveToThread(QCoreApplication::instance()->thread());
|
//
|
||||||
|
// auto blocks = root.value("blocks").toArray();
|
||||||
QObject::connect(this->writeConnection.get(), &Communi::IrcConnection::messageReceived, this,
|
//
|
||||||
&IrcManager::writeConnectionMessageReceived);
|
// this->twitchBlockedUsersMutex.lock();
|
||||||
|
// for (QJsonValue block : blocks) {
|
||||||
this->readConnection.reset(new Communi::IrcConnection);
|
// QJsonObject user = block.toObject().value("user").toObject();
|
||||||
this->readConnection->moveToThread(QCoreApplication::instance()->thread());
|
// // displaythis->name
|
||||||
|
// this->twitchBlockedUsers.insert(user.value("name").toString().toLower(), true);
|
||||||
// Listen to read connection message signals
|
// }
|
||||||
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::messageReceived, this,
|
// this->twitchBlockedUsersMutex.unlock();
|
||||||
&IrcManager::messageReceived);
|
//
|
||||||
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::privateMessageReceived,
|
// manager->deleteLater();
|
||||||
this, &IrcManager::privateMessageReceived);
|
// });
|
||||||
|
//}
|
||||||
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::connected, this,
|
//
|
||||||
&IrcManager::onConnected);
|
//// XXX: This does not fit in IrcManager
|
||||||
QObject::connect(this->readConnection.get(), &Communi::IrcConnection::disconnected, this,
|
// bool IrcManager::isTwitchUserBlocked(QString const &username)
|
||||||
&IrcManager::onDisconnected);
|
//{
|
||||||
|
// QMutexLocker locker(&this->twitchBlockedUsersMutex);
|
||||||
// join and part chats on event
|
//
|
||||||
ChannelManager::getInstance().ircJoin.connect(
|
// auto iterator = this->twitchBlockedUsers.find(username);
|
||||||
[this](const QString &name) { this->joinChannel(name); });
|
//
|
||||||
ChannelManager::getInstance().ircPart.connect(
|
// return iterator != this->twitchBlockedUsers.end();
|
||||||
[this](const QString &name) { this->partChannel(name); });
|
//}
|
||||||
}
|
//
|
||||||
|
//// XXX: This does not fit in IrcManager
|
||||||
IrcManager &IrcManager::getInstance()
|
// bool IrcManager::tryAddIgnoredUser(QString const &username, QString &errorMessage)
|
||||||
{
|
//{
|
||||||
static IrcManager instance(ChannelManager::getInstance(),
|
// assert(this->account);
|
||||||
singletons::ResourceManager::getInstance(),
|
//
|
||||||
AccountManager::getInstance());
|
// QUrl url("https://api.twitch.tv/kraken/users/" + this->account->getUserName() + "/blocks/" +
|
||||||
return instance;
|
// username + "?oauth_token=" + this->account->getOAuthToken() +
|
||||||
}
|
// "&client_id=" + this->account->getOAuthClient());
|
||||||
|
//
|
||||||
void IrcManager::setUser(std::shared_ptr<twitch::TwitchUser> newAccount)
|
// QNetworkRequest request(url);
|
||||||
{
|
// auto reply = this->networkAccessManager.put(request, QByteArray());
|
||||||
this->account = newAccount;
|
// reply->waitForReadyRead(10000);
|
||||||
}
|
//
|
||||||
|
// if (reply->error() == QNetworkReply::NoError) {
|
||||||
void IrcManager::connect()
|
// this->twitchBlockedUsersMutex.lock();
|
||||||
{
|
// this->twitchBlockedUsers.insert(username, true);
|
||||||
this->disconnect();
|
// this->twitchBlockedUsersMutex.unlock();
|
||||||
|
//
|
||||||
this->initializeConnection(this->writeConnection, false);
|
// return true;
|
||||||
this->initializeConnection(this->readConnection, true);
|
// }
|
||||||
|
//
|
||||||
// XXX(pajlada): Disabled the async_exec for now, because if we happen to run the
|
// reply->deleteLater();
|
||||||
// `beginConnecting` function in a different thread than last time, we won't be able to connect
|
//
|
||||||
// because we can't clean up the previous connection properly
|
// errorMessage = "Error while ignoring user \"" + username + "\": " + reply->errorString();
|
||||||
// async_exec([this] { beginConnecting(); });
|
//
|
||||||
this->beginConnecting();
|
// return false;
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
void IrcManager::initializeConnection(const std::unique_ptr<Communi::IrcConnection> &connection,
|
//// XXX: This does not fit in IrcManager
|
||||||
bool isReadConnection)
|
// void IrcManager::addIgnoredUser(QString const &username)
|
||||||
{
|
//{
|
||||||
assert(this->account);
|
// QString errorMessage;
|
||||||
|
// if (!tryAddIgnoredUser(username, errorMessage)) {
|
||||||
QString username = this->account->getUserName();
|
// // TODO: Implement IrcManager::addIgnoredUser
|
||||||
QString oauthClient = this->account->getOAuthClient();
|
// }
|
||||||
QString oauthToken = this->account->getOAuthToken();
|
//}
|
||||||
if (!oauthToken.startsWith("oauth:")) {
|
//
|
||||||
oauthToken.prepend("oauth:");
|
//// XXX: This does not fit in IrcManager
|
||||||
}
|
// bool IrcManager::tryRemoveIgnoredUser(QString const &username, QString &errorMessage)
|
||||||
|
//{
|
||||||
connection->setUserName(username);
|
// assert(this->account);
|
||||||
connection->setNickName(username);
|
//
|
||||||
connection->setRealName(username);
|
// QUrl url("https://api.twitch.tv/kraken/users/" + this->account->getUserName() + "/blocks/" +
|
||||||
|
// username + "?oauth_token=" + this->account->getOAuthToken() +
|
||||||
if (!this->account->isAnon()) {
|
// "&client_id=" + this->account->getOAuthClient());
|
||||||
connection->setPassword(oauthToken);
|
//
|
||||||
|
// QNetworkRequest request(url);
|
||||||
this->refreshIgnoredUsers(username, oauthClient, oauthToken);
|
// auto reply = this->networkAccessManager.deleteResource(request);
|
||||||
}
|
// reply->waitForReadyRead(10000);
|
||||||
|
//
|
||||||
if (isReadConnection) {
|
// if (reply->error() == QNetworkReply::NoError) {
|
||||||
connection->sendCommand(
|
// this->twitchBlockedUsersMutex.lock();
|
||||||
Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership"));
|
// this->twitchBlockedUsers.remove(username);
|
||||||
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/commands"));
|
// this->twitchBlockedUsersMutex.unlock();
|
||||||
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/tags"));
|
//
|
||||||
} else {
|
// return true;
|
||||||
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/tags"));
|
// }
|
||||||
|
//
|
||||||
connection->sendCommand(
|
// reply->deleteLater();
|
||||||
Communi::IrcCommand::createCapability("REQ", "twitch.tv/membership"));
|
//
|
||||||
connection->sendCommand(Communi::IrcCommand::createCapability("REQ", "twitch.tv/commands"));
|
// errorMessage = "Error while unignoring user \"" + username + "\": " + reply->errorString();
|
||||||
}
|
//
|
||||||
|
// return false;
|
||||||
connection->setHost("irc.chat.twitch.tv");
|
//}
|
||||||
connection->setPort(6667);
|
//
|
||||||
}
|
//// XXX: This does not fit in IrcManager
|
||||||
|
// void IrcManager::removeIgnoredUser(QString const &username)
|
||||||
void IrcManager::refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
//{
|
||||||
const QString &oauthToken)
|
// QString errorMessage;
|
||||||
{
|
// if (!tryRemoveIgnoredUser(username, errorMessage)) {
|
||||||
QString nextLink = "https://api.twitch.tv/kraken/users/" + username + "/blocks?limit=" + 100 +
|
// // TODO: Implement IrcManager::removeIgnoredUser
|
||||||
"&client_id=" + oauthClient;
|
// }
|
||||||
|
//}
|
||||||
QNetworkAccessManager *manager = new QNetworkAccessManager();
|
|
||||||
QNetworkRequest req(QUrl(nextLink + "&oauth_token=" + oauthToken));
|
|
||||||
QNetworkReply *reply = manager->get(req);
|
|
||||||
|
|
||||||
QObject::connect(reply, &QNetworkReply::finished, [=] {
|
|
||||||
this->twitchBlockedUsersMutex.lock();
|
|
||||||
this->twitchBlockedUsers.clear();
|
|
||||||
this->twitchBlockedUsersMutex.unlock();
|
|
||||||
|
|
||||||
QByteArray data = reply->readAll();
|
|
||||||
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
|
|
||||||
QJsonObject root = jsonDoc.object();
|
|
||||||
|
|
||||||
// nextLink =
|
|
||||||
// root.value("this->links").toObject().value("next").toString();
|
|
||||||
|
|
||||||
auto blocks = root.value("blocks").toArray();
|
|
||||||
|
|
||||||
this->twitchBlockedUsersMutex.lock();
|
|
||||||
for (QJsonValue block : blocks) {
|
|
||||||
QJsonObject user = block.toObject().value("user").toObject();
|
|
||||||
// displaythis->name
|
|
||||||
this->twitchBlockedUsers.insert(user.value("name").toString().toLower(), true);
|
|
||||||
}
|
|
||||||
this->twitchBlockedUsersMutex.unlock();
|
|
||||||
|
|
||||||
manager->deleteLater();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::beginConnecting()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> locker(this->connectionMutex);
|
|
||||||
|
|
||||||
for (auto &channel : this->channelManager.getItems()) {
|
|
||||||
this->writeConnection->sendRaw("JOIN #" + channel->name);
|
|
||||||
this->readConnection->sendRaw("JOIN #" + channel->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->writeConnection->open();
|
|
||||||
this->readConnection->open();
|
|
||||||
|
|
||||||
this->connected();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::disconnect()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> locker(this->connectionMutex);
|
|
||||||
|
|
||||||
this->readConnection->close();
|
|
||||||
this->writeConnection->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::sendMessage(const QString &channelName, QString message)
|
|
||||||
{
|
|
||||||
QString trimmedMessage = message.trimmed();
|
|
||||||
if (trimmedMessage.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->connectionMutex.lock();
|
|
||||||
|
|
||||||
if (this->writeConnection) {
|
|
||||||
this->writeConnection->sendRaw("PRIVMSG #" + channelName + " :" + trimmedMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->connectionMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::joinChannel(const QString &channelName)
|
|
||||||
{
|
|
||||||
this->connectionMutex.lock();
|
|
||||||
|
|
||||||
if (this->readConnection && this->writeConnection) {
|
|
||||||
this->readConnection->sendRaw("JOIN #" + channelName);
|
|
||||||
this->writeConnection->sendRaw("JOIN #" + channelName);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->connectionMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::partChannel(const QString &channelName)
|
|
||||||
{
|
|
||||||
this->connectionMutex.lock();
|
|
||||||
|
|
||||||
if (this->readConnection && this->writeConnection) {
|
|
||||||
this->readConnection->sendRaw("PART #" + channelName);
|
|
||||||
this->writeConnection->sendRaw("PART #" + channelName);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->connectionMutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::privateMessageReceived(Communi::IrcPrivateMessage *message)
|
|
||||||
{
|
|
||||||
this->onPrivateMessage.invoke(message);
|
|
||||||
auto c = this->channelManager.getTwitchChannel(message->target().mid(1));
|
|
||||||
|
|
||||||
if (!c) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// auto xd = message->content();
|
|
||||||
// auto xd2 = message->toData();
|
|
||||||
|
|
||||||
// debug::Log("HEHE: {}", xd2.toStdString());
|
|
||||||
|
|
||||||
messages::MessageParseArgs args;
|
|
||||||
|
|
||||||
twitch::TwitchMessageBuilder builder(c.get(), message, args);
|
|
||||||
|
|
||||||
if (!builder.isIgnored()) {
|
|
||||||
messages::MessagePtr _message = builder.build();
|
|
||||||
if (_message->flags & messages::Message::Highlighted) {
|
|
||||||
singletons::ChannelManager::getInstance().mentionsChannel->addMessage(_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
c->addMessage(_message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::messageReceived(Communi::IrcMessage *message)
|
|
||||||
{
|
|
||||||
if (message->type() == Communi::IrcMessage::Type::Private) {
|
|
||||||
// We already have a handler for private messages
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &command = message->command();
|
|
||||||
|
|
||||||
if (command == "ROOMSTATE") {
|
|
||||||
helper::IrcMessageHandler::getInstance().handleRoomStateMessage(message);
|
|
||||||
} else if (command == "CLEARCHAT") {
|
|
||||||
helper::IrcMessageHandler::getInstance().handleClearChatMessage(message);
|
|
||||||
} else if (command == "USERSTATE") {
|
|
||||||
helper::IrcMessageHandler::getInstance().handleUserStateMessage(message);
|
|
||||||
} else if (command == "WHISPER") {
|
|
||||||
helper::IrcMessageHandler::getInstance().handleWhisperMessage(message);
|
|
||||||
} else if (command == "USERNOTICE") {
|
|
||||||
helper::IrcMessageHandler::getInstance().handleUserNoticeMessage(message);
|
|
||||||
} else if (command == "MODE") {
|
|
||||||
helper::IrcMessageHandler::getInstance().handleModeMessage(message);
|
|
||||||
} else if (command == "NOTICE") {
|
|
||||||
helper::IrcMessageHandler::getInstance().handleNoticeMessage(
|
|
||||||
static_cast<Communi::IrcNoticeMessage *>(message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::writeConnectionMessageReceived(Communi::IrcMessage *message)
|
|
||||||
{
|
|
||||||
switch (message->type()) {
|
|
||||||
case Communi::IrcMessage::Type::Notice: {
|
|
||||||
helper::IrcMessageHandler::getInstance().handleWriteConnectionNoticeMessage(
|
|
||||||
static_cast<Communi::IrcNoticeMessage *>(message));
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: This does not fit in IrcManager
|
|
||||||
bool IrcManager::isTwitchUserBlocked(QString const &username)
|
|
||||||
{
|
|
||||||
QMutexLocker locker(&this->twitchBlockedUsersMutex);
|
|
||||||
|
|
||||||
auto iterator = this->twitchBlockedUsers.find(username);
|
|
||||||
|
|
||||||
return iterator != this->twitchBlockedUsers.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: This does not fit in IrcManager
|
|
||||||
bool IrcManager::tryAddIgnoredUser(QString const &username, QString &errorMessage)
|
|
||||||
{
|
|
||||||
assert(this->account);
|
|
||||||
|
|
||||||
QUrl url("https://api.twitch.tv/kraken/users/" + this->account->getUserName() + "/blocks/" +
|
|
||||||
username + "?oauth_token=" + this->account->getOAuthToken() +
|
|
||||||
"&client_id=" + this->account->getOAuthClient());
|
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
|
||||||
auto reply = this->networkAccessManager.put(request, QByteArray());
|
|
||||||
reply->waitForReadyRead(10000);
|
|
||||||
|
|
||||||
if (reply->error() == QNetworkReply::NoError) {
|
|
||||||
this->twitchBlockedUsersMutex.lock();
|
|
||||||
this->twitchBlockedUsers.insert(username, true);
|
|
||||||
this->twitchBlockedUsersMutex.unlock();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
reply->deleteLater();
|
|
||||||
|
|
||||||
errorMessage = "Error while ignoring user \"" + username + "\": " + reply->errorString();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: This does not fit in IrcManager
|
|
||||||
void IrcManager::addIgnoredUser(QString const &username)
|
|
||||||
{
|
|
||||||
QString errorMessage;
|
|
||||||
if (!tryAddIgnoredUser(username, errorMessage)) {
|
|
||||||
// TODO: Implement IrcManager::addIgnoredUser
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: This does not fit in IrcManager
|
|
||||||
bool IrcManager::tryRemoveIgnoredUser(QString const &username, QString &errorMessage)
|
|
||||||
{
|
|
||||||
assert(this->account);
|
|
||||||
|
|
||||||
QUrl url("https://api.twitch.tv/kraken/users/" + this->account->getUserName() + "/blocks/" +
|
|
||||||
username + "?oauth_token=" + this->account->getOAuthToken() +
|
|
||||||
"&client_id=" + this->account->getOAuthClient());
|
|
||||||
|
|
||||||
QNetworkRequest request(url);
|
|
||||||
auto reply = this->networkAccessManager.deleteResource(request);
|
|
||||||
reply->waitForReadyRead(10000);
|
|
||||||
|
|
||||||
if (reply->error() == QNetworkReply::NoError) {
|
|
||||||
this->twitchBlockedUsersMutex.lock();
|
|
||||||
this->twitchBlockedUsers.remove(username);
|
|
||||||
this->twitchBlockedUsersMutex.unlock();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
reply->deleteLater();
|
|
||||||
|
|
||||||
errorMessage = "Error while unignoring user \"" + username + "\": " + reply->errorString();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: This does not fit in IrcManager
|
|
||||||
void IrcManager::removeIgnoredUser(QString const &username)
|
|
||||||
{
|
|
||||||
QString errorMessage;
|
|
||||||
if (!tryRemoveIgnoredUser(username, errorMessage)) {
|
|
||||||
// TODO: Implement IrcManager::removeIgnoredUser
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::onConnected()
|
|
||||||
{
|
|
||||||
MessagePtr connMsg = Message::createSystemMessage("connected to chat");
|
|
||||||
MessagePtr reconnMsg = Message::createSystemMessage("reconnected to chat");
|
|
||||||
|
|
||||||
this->channelManager.doOnAll([connMsg, reconnMsg](ChannelPtr channel) {
|
|
||||||
assert(channel);
|
|
||||||
|
|
||||||
LimitedQueueSnapshot<MessagePtr> snapshot = channel->getMessageSnapshot();
|
|
||||||
|
|
||||||
bool replaceMessage =
|
|
||||||
snapshot.getLength() > 0 &&
|
|
||||||
snapshot[snapshot.getLength() - 1]->flags & Message::DisconnectedMessage;
|
|
||||||
|
|
||||||
if (replaceMessage) {
|
|
||||||
channel->replaceMessage(snapshot[snapshot.getLength() - 1], reconnMsg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
channel->addMessage(connMsg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::onDisconnected()
|
|
||||||
{
|
|
||||||
MessagePtr msg = Message::createSystemMessage("disconnected from chat");
|
|
||||||
msg->flags &= Message::DisconnectedMessage;
|
|
||||||
|
|
||||||
this->channelManager.doOnAll([msg](ChannelPtr channel) {
|
|
||||||
assert(channel);
|
|
||||||
channel->addMessage(msg);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Communi::IrcConnection *IrcManager::getReadConnection()
|
|
||||||
{
|
|
||||||
return this->readConnection.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IrcManager::addFakeMessage(const QString &data)
|
|
||||||
{
|
|
||||||
auto fakeMessage = Communi::IrcMessage::fromData(data.toUtf8(), this->readConnection.get());
|
|
||||||
|
|
||||||
this->privateMessageReceived(qobject_cast<Communi::IrcPrivateMessage *>(fakeMessage));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace singletons
|
|
||||||
} // namespace chatterino
|
|
||||||
|
|
|
@ -1,95 +1,13 @@
|
||||||
#pragma once
|
// bool isTwitchUserBlocked(QString const &username);
|
||||||
|
// bool tryAddIgnoredUser(QString const &username, QString &errorMessage);
|
||||||
|
// void addIgnoredUser(QString const &username);
|
||||||
|
// bool tryRemoveIgnoredUser(QString const &username, QString &errorMessage);
|
||||||
|
// void removeIgnoredUser(QString const &username);
|
||||||
|
|
||||||
#define TWITCH_MAX_MESSAGELENGTH 500
|
// QMap<QString, bool> twitchBlockedUsers;
|
||||||
|
// QMutex twitchBlockedUsersMutex;
|
||||||
|
|
||||||
#include "messages/message.hpp"
|
// QNetworkAccessManager networkAccessManager;
|
||||||
#include "twitch/twitchuser.hpp"
|
|
||||||
|
|
||||||
#include <ircconnection.h>
|
// void refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
||||||
#include <IrcMessage>
|
// const QString &oauthToken);
|
||||||
#include <QMap>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QNetworkAccessManager>
|
|
||||||
#include <QString>
|
|
||||||
#include <pajlada/signals/signal.hpp>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
namespace singletons {
|
|
||||||
|
|
||||||
class ChannelManager;
|
|
||||||
class ResourceManager;
|
|
||||||
class AccountManager;
|
|
||||||
class WindowManager;
|
|
||||||
|
|
||||||
class IrcManager : public QObject
|
|
||||||
{
|
|
||||||
IrcManager(ChannelManager &channelManager, ResourceManager &resources,
|
|
||||||
AccountManager &accountManager);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static IrcManager &getInstance();
|
|
||||||
|
|
||||||
void connect();
|
|
||||||
void disconnect();
|
|
||||||
|
|
||||||
bool isTwitchUserBlocked(QString const &username);
|
|
||||||
bool tryAddIgnoredUser(QString const &username, QString &errorMessage);
|
|
||||||
void addIgnoredUser(QString const &username);
|
|
||||||
bool tryRemoveIgnoredUser(QString const &username, QString &errorMessage);
|
|
||||||
void removeIgnoredUser(QString const &username);
|
|
||||||
|
|
||||||
void sendMessage(const QString &channelName, QString message);
|
|
||||||
|
|
||||||
void joinChannel(const QString &channelName);
|
|
||||||
void partChannel(const QString &channelName);
|
|
||||||
|
|
||||||
void setUser(std::shared_ptr<twitch::TwitchUser> newAccount);
|
|
||||||
|
|
||||||
pajlada::Signals::Signal<Communi::IrcPrivateMessage *> onPrivateMessage;
|
|
||||||
void privateMessageReceived(Communi::IrcPrivateMessage *message);
|
|
||||||
boost::signals2::signal<void()> connected;
|
|
||||||
|
|
||||||
Communi::IrcConnection *getReadConnection();
|
|
||||||
|
|
||||||
/// Debug function
|
|
||||||
void addFakeMessage(const QString &data);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ChannelManager &channelManager;
|
|
||||||
ResourceManager &resources;
|
|
||||||
AccountManager &accountManager;
|
|
||||||
|
|
||||||
// variables
|
|
||||||
std::shared_ptr<twitch::TwitchUser> account = nullptr;
|
|
||||||
|
|
||||||
std::unique_ptr<Communi::IrcConnection> writeConnection = nullptr;
|
|
||||||
std::unique_ptr<Communi::IrcConnection> readConnection = nullptr;
|
|
||||||
|
|
||||||
std::mutex connectionMutex;
|
|
||||||
|
|
||||||
QMap<QString, bool> twitchBlockedUsers;
|
|
||||||
QMutex twitchBlockedUsersMutex;
|
|
||||||
|
|
||||||
QNetworkAccessManager networkAccessManager;
|
|
||||||
|
|
||||||
void initializeConnection(const std::unique_ptr<Communi::IrcConnection> &connection,
|
|
||||||
bool isReadConnection);
|
|
||||||
|
|
||||||
void refreshIgnoredUsers(const QString &username, const QString &oauthClient,
|
|
||||||
const QString &oauthToken);
|
|
||||||
|
|
||||||
void beginConnecting();
|
|
||||||
|
|
||||||
void messageReceived(Communi::IrcMessage *message);
|
|
||||||
|
|
||||||
void writeConnectionMessageReceived(Communi::IrcMessage *message);
|
|
||||||
|
|
||||||
void onConnected();
|
|
||||||
void onDisconnected();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace singletons
|
|
||||||
} // namespace chatterino
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
#include "twitchuser.hpp"
|
|
||||||
#include "const.hpp"
|
|
||||||
#include "util/urlfetch.hpp"
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
namespace twitch {
|
|
||||||
|
|
||||||
TwitchUser::TwitchUser(const QString &username, const QString &oauthToken,
|
|
||||||
const QString &oauthClient)
|
|
||||||
: IrcUser2(username, username, username, "oauth:" + oauthToken)
|
|
||||||
, _oauthClient(oauthClient)
|
|
||||||
, _oauthToken(oauthToken)
|
|
||||||
, _isAnon(username == ANONYMOUS_USERNAME)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &TwitchUser::getOAuthClient() const
|
|
||||||
{
|
|
||||||
return this->_oauthClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &TwitchUser::getOAuthToken() const
|
|
||||||
{
|
|
||||||
return this->_oauthToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString &TwitchUser::getUserId() const
|
|
||||||
{
|
|
||||||
return this->_userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TwitchUser::setUserId(const QString &id)
|
|
||||||
{
|
|
||||||
this->_userId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TwitchUser::setOAuthClient(const QString &newClientID)
|
|
||||||
{
|
|
||||||
if (this->_oauthClient.compare(newClientID) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->_oauthClient = newClientID;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TwitchUser::setOAuthToken(const QString &newOAuthToken)
|
|
||||||
{
|
|
||||||
if (this->_oauthToken.compare(newOAuthToken) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->_oauthToken = newOAuthToken;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TwitchUser::isAnon() const
|
|
||||||
{
|
|
||||||
return this->_isAnon;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace twitch
|
|
||||||
} // namespace chatterino
|
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
#define async_exec(a) QThreadPool::globalInstance()->start(new LambdaRunnable(a));
|
#define async_exec(a) QThreadPool::globalInstance()->start(new LambdaRunnable(a));
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
namespace util {
|
||||||
class LambdaRunnable : public QRunnable
|
class LambdaRunnable : public QRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -52,3 +54,5 @@ static void postToThread(F &&fun, QObject *obj = qApp)
|
||||||
};
|
};
|
||||||
QCoreApplication::postEvent(obj, new Event(std::forward<F>(fun)));
|
QCoreApplication::postEvent(obj, new Event(std::forward<F>(fun)));
|
||||||
}
|
}
|
||||||
|
} // namespace util
|
||||||
|
} // namespace chatterino
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "basewindow.hpp"
|
#include "basewindow.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
#include "util/concurrentmap.hpp"
|
#include "util/concurrentmap.hpp"
|
||||||
|
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
|
|
||||||
#include "messages/messagebuilder.hpp"
|
#include "messages/messagebuilder.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
|
|
||||||
using namespace chatterino::twitch;
|
using namespace chatterino::providers::twitch;
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
@ -68,7 +68,7 @@ void EmotePopup::loadChannel(ChannelPtr _channel)
|
||||||
|
|
||||||
map.each([&](const QString &key, const util::EmoteData &value) {
|
map.each([&](const QString &key, const util::EmoteData &value) {
|
||||||
builder2.append((new EmoteElement(value, MessageElement::Flags::AlwaysShow))
|
builder2.append((new EmoteElement(value, MessageElement::Flags::AlwaysShow))
|
||||||
->setLink(Link(Link::InsertText, key)));
|
->setLink(Link(Link::InsertText, key)));
|
||||||
});
|
});
|
||||||
|
|
||||||
emoteChannel->addMessage(builder2.getMessage());
|
emoteChannel->addMessage(builder2.getMessage());
|
||||||
|
@ -107,7 +107,7 @@ void EmotePopup::loadEmojis()
|
||||||
|
|
||||||
emojis.each([this, &builder](const QString &key, const util::EmoteData &value) {
|
emojis.each([this, &builder](const QString &key, const util::EmoteData &value) {
|
||||||
builder.append((new EmoteElement(value, MessageElement::Flags::AlwaysShow))
|
builder.append((new EmoteElement(value, MessageElement::Flags::AlwaysShow))
|
||||||
->setLink(Link(Link::Type::InsertText, key)));
|
->setLink(Link(Link::Type::InsertText, key)));
|
||||||
});
|
});
|
||||||
emojiChannel->addMessage(builder.getMessage());
|
emojiChannel->addMessage(builder.getMessage());
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "messages/layouts/messagelayout.hpp"
|
#include "messages/layouts/messagelayout.hpp"
|
||||||
#include "messages/limitedqueuesnapshot.hpp"
|
#include "messages/limitedqueuesnapshot.hpp"
|
||||||
#include "messages/message.hpp"
|
#include "messages/message.hpp"
|
||||||
|
#include "providers/twitch/twitchserver.hpp"
|
||||||
#include "singletons/channelmanager.hpp"
|
#include "singletons/channelmanager.hpp"
|
||||||
#include "singletons/settingsmanager.hpp"
|
#include "singletons/settingsmanager.hpp"
|
||||||
#include "singletons/thememanager.hpp"
|
#include "singletons/thememanager.hpp"
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
#define LAYOUT_WIDTH (this->width() - (this->scrollBar.isVisible() ? 16 : 4) * this->getScale())
|
#define LAYOUT_WIDTH (this->width() - (this->scrollBar.isVisible() ? 16 : 4) * this->getScale())
|
||||||
|
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
using namespace chatterino::providers::twitch;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
@ -35,7 +37,7 @@ namespace widgets {
|
||||||
ChannelView::ChannelView(BaseWidget *parent)
|
ChannelView::ChannelView(BaseWidget *parent)
|
||||||
: BaseWidget(parent)
|
: BaseWidget(parent)
|
||||||
, scrollBar(this)
|
, scrollBar(this)
|
||||||
, userPopupWidget(std::shared_ptr<twitch::TwitchChannel>())
|
, userPopupWidget(std::shared_ptr<TwitchChannel>())
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
// this->setAttribute(Qt::WA_OpaquePaintEvent);
|
// this->setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
@ -476,7 +478,7 @@ messages::MessageElement::Flags ChannelView::getFlags() const
|
||||||
if (split->getModerationMode()) {
|
if (split->getModerationMode()) {
|
||||||
flags = (MessageElement::Flags)(flags | MessageElement::ModeratorTools);
|
flags = (MessageElement::Flags)(flags | MessageElement::ModeratorTools);
|
||||||
}
|
}
|
||||||
if (this->channel == singletons::ChannelManager::getInstance().mentionsChannel) {
|
if (this->channel == TwitchServer::getInstance().mentionsChannel) {
|
||||||
flags = (MessageElement::Flags)(flags | MessageElement::ChannelName);
|
flags = (MessageElement::Flags)(flags | MessageElement::ChannelName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "widgets/helper/resizingtextedit.hpp"
|
#include "widgets/helper/resizingtextedit.hpp"
|
||||||
|
#include "common.hpp"
|
||||||
#include "singletons/completionmanager.hpp"
|
#include "singletons/completionmanager.hpp"
|
||||||
|
|
||||||
ResizingTextEdit::ResizingTextEdit()
|
ResizingTextEdit::ResizingTextEdit()
|
||||||
|
@ -79,13 +80,17 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->key() == Qt::Key_Tab &&
|
bool doComplete =
|
||||||
(event->modifiers() & Qt::ControlModifier) == Qt::NoModifier) {
|
event->key() == Qt::Key_Tab && (event->modifiers() & Qt::ControlModifier) == Qt::NoModifier;
|
||||||
|
|
||||||
|
if (doComplete) {
|
||||||
|
// check if there is a completer
|
||||||
|
return_if_not(this->completer);
|
||||||
|
|
||||||
QString currentCompletionPrefix = this->textUnderCursor();
|
QString currentCompletionPrefix = this->textUnderCursor();
|
||||||
|
|
||||||
if (!currentCompletionPrefix.size()) {
|
// check if there is something to complete
|
||||||
return;
|
return_if_not(currentCompletionPrefix.size());
|
||||||
}
|
|
||||||
|
|
||||||
auto *completionModel =
|
auto *completionModel =
|
||||||
static_cast<chatterino::singletons::CompletionModel *>(this->completer->model());
|
static_cast<chatterino::singletons::CompletionModel *>(this->completer->model());
|
||||||
|
@ -109,6 +114,7 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
|
||||||
this->completer->complete();
|
this->completer->complete();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (hemirt)
|
// (hemirt)
|
||||||
// this resets the selection in the completion list, it should probably only trigger on actual
|
// this resets the selection in the completion list, it should probably only trigger on actual
|
||||||
// chat input (space, character) and not on every key input (pressing alt for example)
|
// chat input (space, character) and not on every key input (pressing alt for example)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "widgets/helper/splitheader.hpp"
|
#include "widgets/helper/splitheader.hpp"
|
||||||
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
|
#include "providers/twitch/twitchserver.hpp"
|
||||||
#include "singletons/resourcemanager.hpp"
|
#include "singletons/resourcemanager.hpp"
|
||||||
#include "singletons/thememanager.hpp"
|
#include "singletons/thememanager.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
|
||||||
#include "util/layoutcreator.hpp"
|
#include "util/layoutcreator.hpp"
|
||||||
#include "util/urlfetch.hpp"
|
#include "util/urlfetch.hpp"
|
||||||
#include "widgets/helper/label.hpp"
|
#include "widgets/helper/label.hpp"
|
||||||
|
@ -18,6 +19,8 @@
|
||||||
#include "widgets/streamview.hpp"
|
#include "widgets/streamview.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace chatterino::providers::twitch;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ void SplitHeader::addDropdownItems(RippleEffectButton *label)
|
||||||
#ifdef USEWEBENGINE
|
#ifdef USEWEBENGINE
|
||||||
this->dropdownMenu.addAction("Start watching", this, [this]{
|
this->dropdownMenu.addAction("Start watching", this, [this]{
|
||||||
ChannelPtr _channel = this->split->getChannel();
|
ChannelPtr _channel = this->split->getChannel();
|
||||||
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(_channel.get());
|
TwitchChannel *tc = dynamic_cast<TwitchChannel *>(_channel.get());
|
||||||
|
|
||||||
if (tc != nullptr) {
|
if (tc != nullptr) {
|
||||||
StreamView *view = new StreamView(_channel, "https://player.twitch.tv/?channel=" + tc->name);
|
StreamView *view = new StreamView(_channel, "https://player.twitch.tv/?channel=" + tc->name);
|
||||||
|
@ -128,7 +131,7 @@ void SplitHeader::initializeChannelSignals()
|
||||||
this->onlineStatusChangedConnection.disconnect();
|
this->onlineStatusChangedConnection.disconnect();
|
||||||
|
|
||||||
auto channel = this->split->getChannel();
|
auto channel = this->split->getChannel();
|
||||||
twitch::TwitchChannel *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get());
|
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
|
||||||
|
|
||||||
if (twitchChannel) {
|
if (twitchChannel) {
|
||||||
twitchChannel->onlineStatusChanged.connect([this]() {
|
twitchChannel->onlineStatusChanged.connect([this]() {
|
||||||
|
@ -150,13 +153,13 @@ void SplitHeader::scaleChangedEvent(float scale)
|
||||||
|
|
||||||
void SplitHeader::updateChannelText()
|
void SplitHeader::updateChannelText()
|
||||||
{
|
{
|
||||||
const std::string channelName = this->split->channelName;
|
const QString channelName = this->split->channelName;
|
||||||
if (channelName.empty()) {
|
if (channelName.isEmpty()) {
|
||||||
this->titleLabel->setText("<no channel>");
|
this->titleLabel->setText("<no channel>");
|
||||||
} else {
|
} else {
|
||||||
auto channel = this->split->getChannel();
|
auto channel = this->split->getChannel();
|
||||||
|
|
||||||
twitch::TwitchChannel *twitchChannel = dynamic_cast<twitch::TwitchChannel *>(channel.get());
|
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
|
||||||
|
|
||||||
if (twitchChannel != nullptr && twitchChannel->isLive) {
|
if (twitchChannel != nullptr && twitchChannel->isLive) {
|
||||||
this->isLive = true;
|
this->isLive = true;
|
||||||
|
@ -169,10 +172,10 @@ void SplitHeader::updateChannelText()
|
||||||
twitchChannel->streamViewerCount +
|
twitchChannel->streamViewerCount +
|
||||||
" viewers"
|
" viewers"
|
||||||
"</p>";
|
"</p>";
|
||||||
this->titleLabel->setText(QString::fromStdString(channelName) + " (live)");
|
this->titleLabel->setText(channelName + " (live)");
|
||||||
} else {
|
} else {
|
||||||
this->isLive = false;
|
this->isLive = false;
|
||||||
this->titleLabel->setText(QString::fromStdString(channelName));
|
this->titleLabel->setText(channelName);
|
||||||
this->tooltip = "";
|
this->tooltip = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +191,7 @@ void SplitHeader::updateModerationModeIcon()
|
||||||
bool modButtonVisible = false;
|
bool modButtonVisible = false;
|
||||||
ChannelPtr channel = this->split->getChannel();
|
ChannelPtr channel = this->split->getChannel();
|
||||||
|
|
||||||
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(channel.get());
|
TwitchChannel *tc = dynamic_cast<TwitchChannel *>(channel.get());
|
||||||
|
|
||||||
if (tc != nullptr && tc->hasModRights()) {
|
if (tc != nullptr && tc->hasModRights()) {
|
||||||
modButtonVisible = true;
|
modButtonVisible = true;
|
||||||
|
@ -268,7 +271,8 @@ void SplitHeader::menuReloadChannelEmotes()
|
||||||
|
|
||||||
void SplitHeader::menuManualReconnect()
|
void SplitHeader::menuManualReconnect()
|
||||||
{
|
{
|
||||||
singletons::IrcManager::getInstance().connect();
|
// fourtf: connection
|
||||||
|
providers::twitch::TwitchServer::getInstance().connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitHeader::menuShowChangelog()
|
void SplitHeader::menuShowChangelog()
|
||||||
|
|
|
@ -24,8 +24,8 @@ namespace widgets {
|
||||||
|
|
||||||
Notebook::Notebook(Window *parent, bool _showButtons, const std::string &settingPrefix)
|
Notebook::Notebook(Window *parent, bool _showButtons, const std::string &settingPrefix)
|
||||||
: BaseWidget(parent)
|
: BaseWidget(parent)
|
||||||
, parentWindow(parent)
|
|
||||||
, settingRoot(fS("{}/notebook", settingPrefix))
|
, settingRoot(fS("{}/notebook", settingPrefix))
|
||||||
|
, parentWindow(parent)
|
||||||
, addButton(this)
|
, addButton(this)
|
||||||
, settingsButton(this)
|
, settingsButton(this)
|
||||||
, userButton(this)
|
, userButton(this)
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
#include "widgets/split.hpp"
|
#include "widgets/split.hpp"
|
||||||
|
#include "providers/twitch/emotevalue.hpp"
|
||||||
|
#include "providers/twitch/twitchchannel.hpp"
|
||||||
|
#include "providers/twitch/twitchmessagebuilder.hpp"
|
||||||
|
#include "providers/twitch/twitchserver.hpp"
|
||||||
#include "singletons/channelmanager.hpp"
|
#include "singletons/channelmanager.hpp"
|
||||||
#include "singletons/settingsmanager.hpp"
|
#include "singletons/settingsmanager.hpp"
|
||||||
#include "singletons/thememanager.hpp"
|
#include "singletons/thememanager.hpp"
|
||||||
#include "singletons/windowmanager.hpp"
|
#include "singletons/windowmanager.hpp"
|
||||||
#include "twitch/twitchchannel.hpp"
|
|
||||||
#include "twitch/twitchmessagebuilder.hpp"
|
|
||||||
#include "util/urlfetch.hpp"
|
#include "util/urlfetch.hpp"
|
||||||
#include "widgets/helper/searchpopup.hpp"
|
#include "widgets/helper/searchpopup.hpp"
|
||||||
#include "widgets/helper/shortcut.hpp"
|
#include "widgets/helper/shortcut.hpp"
|
||||||
|
@ -34,6 +36,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
using namespace chatterino::providers::twitch;
|
||||||
using namespace chatterino::messages;
|
using namespace chatterino::messages;
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
@ -45,7 +48,7 @@ Split::Split(SplitContainer *parent, const std::string &_uuid)
|
||||||
, settingRoot(fS("/splits/{}", this->uuid))
|
, settingRoot(fS("/splits/{}", this->uuid))
|
||||||
, channelName(fS("{}/channelName", this->settingRoot))
|
, channelName(fS("{}/channelName", this->settingRoot))
|
||||||
, parentPage(*parent)
|
, parentPage(*parent)
|
||||||
, channel(singletons::ChannelManager::getInstance().emptyChannel)
|
, channel(Channel::getEmpty())
|
||||||
, vbox(this)
|
, vbox(this)
|
||||||
, header(this)
|
, header(this)
|
||||||
, view(this)
|
, view(this)
|
||||||
|
@ -122,7 +125,6 @@ Split::Split(SplitContainer *parent, const std::string &_uuid)
|
||||||
|
|
||||||
Split::~Split()
|
Split::~Split()
|
||||||
{
|
{
|
||||||
this->channelNameUpdated("");
|
|
||||||
this->usermodeChangedConnection.disconnect();
|
this->usermodeChangedConnection.disconnect();
|
||||||
this->channelIDChangedConnection.disconnect();
|
this->channelIDChangedConnection.disconnect();
|
||||||
}
|
}
|
||||||
|
@ -150,7 +152,7 @@ void Split::setChannel(ChannelPtr _newChannel)
|
||||||
|
|
||||||
this->channel = _newChannel;
|
this->channel = _newChannel;
|
||||||
|
|
||||||
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(_newChannel.get());
|
TwitchChannel *tc = dynamic_cast<TwitchChannel *>(_newChannel.get());
|
||||||
|
|
||||||
if (tc != nullptr) {
|
if (tc != nullptr) {
|
||||||
this->usermodeChangedConnection =
|
this->usermodeChangedConnection =
|
||||||
|
@ -198,20 +200,13 @@ bool Split::getModerationMode() const
|
||||||
return this->moderationMode;
|
return this->moderationMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Split::channelNameUpdated(const std::string &newChannelName)
|
void Split::channelNameUpdated(const QString &newChannelName)
|
||||||
{
|
{
|
||||||
auto &cman = singletons::ChannelManager::getInstance();
|
|
||||||
|
|
||||||
// remove current channel
|
|
||||||
if (!this->channel->isEmpty()) {
|
|
||||||
cman.removeTwitchChannel(this->channel->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update messages
|
// update messages
|
||||||
if (newChannelName.empty()) {
|
if (newChannelName.isEmpty()) {
|
||||||
this->setChannel(cman.emptyChannel);
|
this->setChannel(Channel::getEmpty());
|
||||||
} else {
|
} else {
|
||||||
this->setChannel(cman.addTwitchChannel(QString::fromStdString(newChannelName)));
|
this->setChannel(TwitchServer::getInstance().addChannel(newChannelName));
|
||||||
}
|
}
|
||||||
|
|
||||||
// update header
|
// update header
|
||||||
|
@ -226,13 +221,13 @@ bool Split::showChangeChannelPopup(const char *dialogTitle, bool empty)
|
||||||
dialog.setWindowTitle(dialogTitle);
|
dialog.setWindowTitle(dialogTitle);
|
||||||
|
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
dialog.setText(QString::fromStdString(this->channelName));
|
dialog.setText(this->channelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
if (dialog.exec() == QDialog::Accepted) {
|
||||||
QString newChannelName = dialog.getText().trimmed();
|
QString newChannelName = dialog.getText().trimmed();
|
||||||
|
|
||||||
this->channelName = newChannelName.toStdString();
|
this->channelName = newChannelName;
|
||||||
this->parentPage.refreshTitle();
|
this->parentPage.refreshTitle();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -355,7 +350,7 @@ void Split::doClearChat()
|
||||||
void Split::doOpenChannel()
|
void Split::doOpenChannel()
|
||||||
{
|
{
|
||||||
ChannelPtr _channel = this->channel;
|
ChannelPtr _channel = this->channel;
|
||||||
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(_channel.get());
|
TwitchChannel *tc = dynamic_cast<TwitchChannel *>(_channel.get());
|
||||||
|
|
||||||
if (tc != nullptr) {
|
if (tc != nullptr) {
|
||||||
QDesktopServices::openUrl("https://twitch.tv/" + tc->name);
|
QDesktopServices::openUrl("https://twitch.tv/" + tc->name);
|
||||||
|
@ -365,7 +360,7 @@ void Split::doOpenChannel()
|
||||||
void Split::doOpenPopupPlayer()
|
void Split::doOpenPopupPlayer()
|
||||||
{
|
{
|
||||||
ChannelPtr _channel = this->channel;
|
ChannelPtr _channel = this->channel;
|
||||||
twitch::TwitchChannel *tc = dynamic_cast<twitch::TwitchChannel *>(_channel.get());
|
TwitchChannel *tc = dynamic_cast<TwitchChannel *>(_channel.get());
|
||||||
|
|
||||||
if (tc != nullptr) {
|
if (tc != nullptr) {
|
||||||
QDesktopServices::openUrl("https://player.twitch.tv/?channel=" + tc->name);
|
QDesktopServices::openUrl("https://player.twitch.tv/?channel=" + tc->name);
|
||||||
|
@ -379,7 +374,7 @@ void Split::doOpenStreamlink()
|
||||||
preferredQuality = preferredQuality.toLower();
|
preferredQuality = preferredQuality.toLower();
|
||||||
// TODO(Confuseh): Default streamlink paths
|
// TODO(Confuseh): Default streamlink paths
|
||||||
QString path = settings.streamlinkPath;
|
QString path = settings.streamlinkPath;
|
||||||
QString channel = QString::fromStdString(this->channelName.getValue());
|
QString channel = this->channelName.getValue();
|
||||||
QFileInfo fileinfo = QFileInfo(path);
|
QFileInfo fileinfo = QFileInfo(path);
|
||||||
|
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty()) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "messages/layouts/messagelayoutelement.hpp"
|
#include "messages/layouts/messagelayoutelement.hpp"
|
||||||
#include "messages/limitedqueuesnapshot.hpp"
|
#include "messages/limitedqueuesnapshot.hpp"
|
||||||
#include "messages/messageelement.hpp"
|
#include "messages/messageelement.hpp"
|
||||||
|
#include "util/serialize-custom.hpp"
|
||||||
#include "widgets/basewidget.hpp"
|
#include "widgets/basewidget.hpp"
|
||||||
#include "widgets/helper/channelview.hpp"
|
#include "widgets/helper/channelview.hpp"
|
||||||
#include "widgets/helper/rippleeffectlabel.hpp"
|
#include "widgets/helper/rippleeffectlabel.hpp"
|
||||||
|
@ -46,7 +47,7 @@ public:
|
||||||
Split(SplitContainer *parent, const std::string &_uuid);
|
Split(SplitContainer *parent, const std::string &_uuid);
|
||||||
virtual ~Split();
|
virtual ~Split();
|
||||||
|
|
||||||
pajlada::Settings::Setting<std::string> channelName;
|
pajlada::Settings::Setting<QString> channelName;
|
||||||
boost::signals2::signal<void()> channelChanged;
|
boost::signals2::signal<void()> channelChanged;
|
||||||
|
|
||||||
ChannelView &getChannelView()
|
ChannelView &getChannelView()
|
||||||
|
@ -99,7 +100,7 @@ private:
|
||||||
|
|
||||||
void setChannel(ChannelPtr newChannel);
|
void setChannel(ChannelPtr newChannel);
|
||||||
void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user);
|
void doOpenAccountPopupWidget(AccountPopupWidget *widget, QString user);
|
||||||
void channelNameUpdated(const std::string &newChannelName);
|
void channelNameUpdated(const QString &newChannelName);
|
||||||
void handleModifiers(QEvent *event, Qt::KeyboardModifiers modifiers);
|
void handleModifiers(QEvent *event, Qt::KeyboardModifiers modifiers);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -30,10 +30,9 @@ SplitContainer::SplitContainer(Notebook *parent, NotebookTab *_tab, const std::s
|
||||||
: BaseWidget(parent->themeManager, parent)
|
: BaseWidget(parent->themeManager, parent)
|
||||||
, uuid(_uuid)
|
, uuid(_uuid)
|
||||||
, settingRoot(fS("/containers/{}", this->uuid))
|
, settingRoot(fS("/containers/{}", this->uuid))
|
||||||
, chats(fS("{}/chats", this->settingRoot))
|
|
||||||
, tab(_tab)
|
, tab(_tab)
|
||||||
|
, chats(fS("{}/chats", this->settingRoot))
|
||||||
, dropPreview(this)
|
, dropPreview(this)
|
||||||
, splits()
|
|
||||||
{
|
{
|
||||||
this->tab->page = this;
|
this->tab->page = this;
|
||||||
|
|
||||||
|
@ -468,8 +467,7 @@ void SplitContainer::refreshTitle()
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (const auto &chatWidget : this->splits) {
|
for (const auto &chatWidget : this->splits) {
|
||||||
auto channelName = QString::fromStdString(chatWidget->channelName.getValue());
|
auto channelName = chatWidget->channelName.getValue();
|
||||||
|
|
||||||
if (channelName.isEmpty()) {
|
if (channelName.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage
|
||||||
, settingRoot(fS("/windows/{}", windowName))
|
, settingRoot(fS("/windows/{}", windowName))
|
||||||
, windowGeometry(this->settingRoot)
|
, windowGeometry(this->settingRoot)
|
||||||
, dpi(this->getScale())
|
, dpi(this->getScale())
|
||||||
, themeManager(_themeManager)
|
|
||||||
, notebook(this, _isMainWindow, this->settingRoot)
|
, notebook(this, _isMainWindow, this->settingRoot)
|
||||||
{
|
{
|
||||||
singletons::AccountManager::getInstance().Twitch.currentUsername.connect(
|
singletons::AccountManager::getInstance().Twitch.currentUsername.connect(
|
||||||
|
@ -98,11 +97,11 @@ Window::Window(const QString &windowName, singletons::ThemeManager &_themeManage
|
||||||
cheerMessages.emplace_back(R"(@badges=subscriber/3,premium/1;bits=1;color=#FF0000;display-name=kalvarenga;emotes=;id=4744d6f0-de1d-475d-a3ff-38647113265a;mod=0;room-id=11148817;subscriber=1;tmi-sent-ts=1515782860740;turbo=0;user-id=108393131;user-type= :kalvarenga!kalvarenga@kalvarenga.tmi.twitch.tv PRIVMSG #pajlada :trihard1)");
|
cheerMessages.emplace_back(R"(@badges=subscriber/3,premium/1;bits=1;color=#FF0000;display-name=kalvarenga;emotes=;id=4744d6f0-de1d-475d-a3ff-38647113265a;mod=0;room-id=11148817;subscriber=1;tmi-sent-ts=1515782860740;turbo=0;user-id=108393131;user-type= :kalvarenga!kalvarenga@kalvarenga.tmi.twitch.tv PRIVMSG #pajlada :trihard1)");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
CreateWindowShortcut(this, "F5", [cheerMessages] {
|
// CreateWindowShortcut(this, "F5", [cheerMessages] {
|
||||||
auto &ircManager = singletons::IrcManager::getInstance();
|
// auto &ircManager = singletons::IrcManager::getInstance();
|
||||||
static int index = 0;
|
// static int index = 0;
|
||||||
ircManager.addFakeMessage(cheerMessages[index++ % cheerMessages.size()]);
|
// ircManager.addFakeMessage(cheerMessages[index++ % cheerMessages.size()]);
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::repaintVisibleChatWidgets(Channel *channel)
|
void Window::repaintVisibleChatWidgets(Channel *channel)
|
||||||
|
|
|
@ -60,8 +60,6 @@ protected:
|
||||||
virtual bool event(QEvent *event) override;
|
virtual bool event(QEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
singletons::ThemeManager &themeManager;
|
|
||||||
|
|
||||||
float dpi;
|
float dpi;
|
||||||
|
|
||||||
void loadGeometry();
|
void loadGeometry();
|
||||||
|
|
Loading…
Reference in a new issue