mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
sdf
This commit is contained in:
parent
4716894027
commit
7a7b714e78
15 changed files with 437 additions and 18 deletions
10
account.cpp
Normal file
10
account.cpp
Normal file
|
@ -0,0 +1,10 @@
|
|||
#include "account.h"
|
||||
|
||||
const Account* Account::m_anon = new Account("justinfan123", "", "");
|
||||
|
||||
Account::Account(QString username, QString oauthToken, QString oauthClient)
|
||||
{
|
||||
m_oauthClient = oauthClient;
|
||||
m_oauthToken = oauthToken;
|
||||
m_username = username;
|
||||
}
|
39
account.h
Normal file
39
account.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef ACCOUNT_H
|
||||
#define ACCOUNT_H
|
||||
|
||||
#include "QString"
|
||||
|
||||
class Account
|
||||
{
|
||||
public:
|
||||
Account(QString username, QString oauthToken, QString oauthClient);
|
||||
|
||||
static const Account* anon() {
|
||||
return m_anon;
|
||||
}
|
||||
|
||||
const QString& username() {
|
||||
return m_username;
|
||||
}
|
||||
|
||||
const QString& oauthToken() {
|
||||
return m_oauthToken;
|
||||
}
|
||||
|
||||
const QString& oauthClient() {
|
||||
return m_oauthClient;
|
||||
}
|
||||
|
||||
bool isAnon() {
|
||||
return m_username.startsWith("justinfan");
|
||||
}
|
||||
|
||||
private:
|
||||
const static Account* m_anon;
|
||||
|
||||
QString m_username;
|
||||
QString m_oauthClient;
|
||||
QString m_oauthToken;
|
||||
};
|
||||
|
||||
#endif // ACCOUNT_H
|
14
asyncexec.h
Normal file
14
asyncexec.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef ASYNCEXEC_H
|
||||
#define ASYNCEXEC_H
|
||||
|
||||
#include "QThreadPool"
|
||||
#include "QRunnable"
|
||||
#include "lambdaqrunnable.h"
|
||||
#include "qcoreapplication.h"
|
||||
|
||||
#define async_start QThreadPool::globalInstance()->start(new LambdaQRunnable(
|
||||
#define async_end ));
|
||||
#define async_exec(a) QThreadPool::globalInstance()->start(new LambdaQRunnable([]{ a; }));
|
||||
|
||||
|
||||
#endif // ASYNCEXEC_H
|
|
@ -46,7 +46,11 @@ SOURCES += main.cpp\
|
|||
scrollbar.cpp \
|
||||
scrollbarhighlight.cpp \
|
||||
ircmanager.cpp \
|
||||
lambdaqrunnable.cpp
|
||||
lambdaqrunnable.cpp \
|
||||
account.cpp \
|
||||
emotes.cpp \
|
||||
lazyloadedimage.cpp \
|
||||
concurrentmap.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
chatwidget.h \
|
||||
|
@ -66,7 +70,13 @@ HEADERS += mainwindow.h \
|
|||
scrollbar.h \
|
||||
scrollbarhighlight.h \
|
||||
ircmanager.h \
|
||||
lambdaqrunnable.h
|
||||
lambdaqrunnable.h \
|
||||
asyncexec.h \
|
||||
account.h \
|
||||
emotes.h \
|
||||
lazyloadedimage.h \
|
||||
twitchemotevalue.h \
|
||||
concurrentmap.h
|
||||
|
||||
FORMS += \
|
||||
dialog.ui
|
||||
|
|
7
concurrentmap.cpp
Normal file
7
concurrentmap.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "concurrentmap.h"
|
||||
|
||||
//template<typename TKey, typename TValue>
|
||||
//ConcurrentMap<TKey, TValue>::ConcurrentMap()
|
||||
//{
|
||||
|
||||
//}
|
60
concurrentmap.h
Normal file
60
concurrentmap.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef CONCURRENTMAP_H
|
||||
#define CONCURRENTMAP_H
|
||||
|
||||
#include "QMutex"
|
||||
#include "QMap"
|
||||
#include "functional"
|
||||
|
||||
template<typename TKey, typename TValue>
|
||||
class ConcurrentMap
|
||||
{
|
||||
public:
|
||||
ConcurrentMap() {
|
||||
mutex = new QMutex();
|
||||
map = new QMap<TKey, TValue>();
|
||||
}
|
||||
|
||||
bool tryGet(const TKey &name, TValue& value) {
|
||||
mutex->lock();
|
||||
auto a = map->find(name);
|
||||
if (a == map->end()) {
|
||||
mutex->unlock();
|
||||
value = NULL;
|
||||
return false;
|
||||
}
|
||||
mutex->unlock();
|
||||
value = a.value();
|
||||
return true;
|
||||
}
|
||||
|
||||
TValue getOrAdd(const TKey &name, function<TValue ()> addLambda) {
|
||||
mutex->lock();
|
||||
auto a = map->find(name);
|
||||
if (a == map->end()) {
|
||||
TValue value = addLambda();
|
||||
map->insert(name, value);
|
||||
mutex->unlock();
|
||||
return value;
|
||||
}
|
||||
mutex->unlock();
|
||||
return a.value();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
mutex->lock();
|
||||
map->clear();
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
void insert(const TKey &name, const TValue &value) {
|
||||
mutex->lock();
|
||||
map->insert(name, value);
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
QMutex* mutex;
|
||||
QMap<TKey, TValue>* map;
|
||||
};
|
||||
|
||||
#endif // CONCURRENTMAP_H
|
32
emotes.cpp
Normal file
32
emotes.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "emotes.h"
|
||||
|
||||
ConcurrentMap<QString, TwitchEmoteValue*>* Emotes::m_twitchEmotes = new ConcurrentMap<QString, TwitchEmoteValue*>();
|
||||
ConcurrentMap<QString, LazyLoadedImage* >* Emotes::m_bttvEmotes = new ConcurrentMap<QString, LazyLoadedImage* >();
|
||||
ConcurrentMap<QString, LazyLoadedImage* >* Emotes::m_ffzEmotes = new ConcurrentMap<QString, LazyLoadedImage* >();
|
||||
ConcurrentMap<QString, LazyLoadedImage* >* Emotes::m_chatterinoEmotes = new ConcurrentMap<QString, LazyLoadedImage* >();
|
||||
ConcurrentMap<QString, LazyLoadedImage* >* Emotes::m_bttvChannelEmoteFromCaches = new ConcurrentMap<QString, LazyLoadedImage* >();
|
||||
ConcurrentMap<QString, LazyLoadedImage* >* Emotes::m_fFzChannelEmoteFromCaches = new ConcurrentMap<QString, LazyLoadedImage* >();
|
||||
ConcurrentMap<int, LazyLoadedImage* >* Emotes::m_twitchEmoteFromCache = new ConcurrentMap<int, LazyLoadedImage* >();
|
||||
ConcurrentMap<int, LazyLoadedImage* >* Emotes::m_miscImageFromCache = new ConcurrentMap<int, LazyLoadedImage* >();
|
||||
|
||||
//QMutex* Emotes::mutexBttvEmote = new QMutex();
|
||||
//QMap<QString, LazyLoadedImage*>* Emotes::mapBttvEmote = new QMap<QString, LazyLoadedImage*>();
|
||||
|
||||
//LazyLoadedImage* Emotes::getBttvEmote(const QString &name) {
|
||||
// mutexBttvEmote->lock();
|
||||
// auto a = mapBttvEmote->find(name);
|
||||
// if (a == mapBttvEmote->end()) {
|
||||
// mutexBttvEmote->unlock();
|
||||
// return NULL;
|
||||
// }
|
||||
// mutexBttvEmote->unlock();
|
||||
// return a.value();
|
||||
//}
|
||||
|
||||
//void
|
||||
|
||||
|
||||
Emotes::Emotes()
|
||||
{
|
||||
|
||||
}
|
35
emotes.h
Normal file
35
emotes.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef EMOTES_H
|
||||
#define EMOTES_H
|
||||
|
||||
#include "twitchemotevalue.h"
|
||||
#include "lazyloadedimage.h"
|
||||
#include "QMutex"
|
||||
#include "QMap"
|
||||
#include "concurrentmap.h"
|
||||
|
||||
class Emotes
|
||||
{
|
||||
public:
|
||||
static ConcurrentMap<QString, TwitchEmoteValue*>& twitchEmotes() { return *m_twitchEmotes ; }
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >& bttvEmotes() { return *m_bttvEmotes ; }
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >& ffzEmotes() { return *m_ffzEmotes ; }
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >& chatterinoEmotes() { return *m_chatterinoEmotes ; }
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >& bttvChannelEmoteFromCaches() { return *m_bttvChannelEmoteFromCaches; }
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >& fFzChannelEmoteFromCaches() { return *m_fFzChannelEmoteFromCaches ; }
|
||||
static ConcurrentMap<int, LazyLoadedImage* >& twitchEmoteFromCache() { return *m_twitchEmoteFromCache ; }
|
||||
static ConcurrentMap<int, LazyLoadedImage* >& miscImageFromCache() { return *m_miscImageFromCache ; }
|
||||
|
||||
private:
|
||||
Emotes();
|
||||
|
||||
static ConcurrentMap<QString, TwitchEmoteValue*>* m_twitchEmotes;
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >* m_bttvEmotes;
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >* m_ffzEmotes;
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >* m_chatterinoEmotes;
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >* m_bttvChannelEmoteFromCaches;
|
||||
static ConcurrentMap<QString, LazyLoadedImage* >* m_fFzChannelEmoteFromCaches;
|
||||
static ConcurrentMap<int, LazyLoadedImage* >* m_twitchEmoteFromCache;
|
||||
static ConcurrentMap<int, LazyLoadedImage* >* m_miscImageFromCache;
|
||||
};
|
||||
|
||||
#endif // EMOTES_H
|
167
ircmanager.cpp
167
ircmanager.cpp
|
@ -2,27 +2,33 @@
|
|||
#include "ircconnection.h"
|
||||
#include "irccommand.h"
|
||||
#include "future"
|
||||
#include "QThreadPool"
|
||||
#include "QRunnable"
|
||||
#include "lambdaqrunnable.h"
|
||||
#include "qcoreapplication.h"
|
||||
#include "QNetworkReply"
|
||||
#include "asyncexec.h"
|
||||
#include "qnetworkrequest.h"
|
||||
#include "QJsonDocument"
|
||||
#include "QJsonObject"
|
||||
#include "QJsonArray"
|
||||
|
||||
Account* IrcManager::account = NULL;
|
||||
IrcConnection* IrcManager::connection = NULL;
|
||||
QMutex* IrcManager::connectionMutex = new QMutex();
|
||||
long IrcManager::connectionIteration = 0;
|
||||
const QString IrcManager::defaultClientId = "7ue61iz46fz11y3cugd0l3tawb4taal";
|
||||
QNetworkAccessManager* IrcManager::accessManager = new QNetworkAccessManager();
|
||||
|
||||
QObject* IrcManager::parent = new QObject();
|
||||
QMap<QString, bool>* IrcManager::twitchBlockedUsers = new QMap<QString, bool>;
|
||||
QMutex* IrcManager::twitchBlockedUsersMutex = new QMutex();
|
||||
|
||||
IrcManager::IrcManager()
|
||||
{
|
||||
|
||||
// account = Account::anon();
|
||||
}
|
||||
|
||||
void IrcManager::connect()
|
||||
{
|
||||
disconnect();
|
||||
|
||||
QThreadPool::globalInstance()->start(new LambdaQRunnable([]{ beginConnecting(); return false; }));
|
||||
async_exec(beginConnecting());
|
||||
}
|
||||
|
||||
void IrcManager::beginConnecting()
|
||||
|
@ -38,6 +44,68 @@ void IrcManager::beginConnecting()
|
|||
&IrcConnection::privateMessageReceived,
|
||||
&privateMessageReceived);
|
||||
|
||||
if (account->isAnon()) {
|
||||
// fetch ignored users
|
||||
QString username = account->username();
|
||||
QString oauthClient = account->oauthClient();
|
||||
QString oauthToken = account->oauthToken();
|
||||
|
||||
{
|
||||
QString nextLink = "https://api.twitch.tv/kraken/users/" + username +
|
||||
"/blocks?limit=" + 100 +
|
||||
"&client_id=" + oauthClient;
|
||||
|
||||
QNetworkRequest req(QUrl(nextLink + "&oauth_token=" + oauthToken));
|
||||
QNetworkReply *reply = accessManager->get(req);
|
||||
|
||||
QObject::connect(reply, &QNetworkReply::finished, [=]{
|
||||
twitchBlockedUsersMutex->lock();
|
||||
twitchBlockedUsers->clear();
|
||||
twitchBlockedUsersMutex->unlock();
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
|
||||
QJsonObject root = jsonDoc.object();
|
||||
|
||||
//nextLink = root.value("_links").toObject().value("next").toString();
|
||||
|
||||
auto blocks = root.value("blocks").toArray();
|
||||
|
||||
twitchBlockedUsersMutex->lock();
|
||||
for (QJsonValue block : blocks) {
|
||||
QJsonObject user = block.toObject().value("user").toObject();
|
||||
// display_name
|
||||
twitchBlockedUsers->insert(user.value("name").toString().toLower(), true);
|
||||
}
|
||||
twitchBlockedUsersMutex->unlock();
|
||||
});
|
||||
}
|
||||
|
||||
// fetch available twitch emtoes
|
||||
{
|
||||
QNetworkRequest req(QUrl("https://api.twitch.tv/kraken/users/" + username + "/emotes?oauth_token=" + oauthToken + "&client_id=" + oauthClient));
|
||||
QNetworkReply *reply = accessManager->get(req);
|
||||
|
||||
QObject::connect(reply, &QNetworkReply::finished, [=]{
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonDocument jsonDoc(QJsonDocument::fromJson(data));
|
||||
QJsonObject root = jsonDoc.object();
|
||||
|
||||
//nextLink = root.value("_links").toObject().value("next").toString();
|
||||
|
||||
auto blocks = root.value("blocks").toArray();
|
||||
|
||||
twitchBlockedUsersMutex->lock();
|
||||
for (QJsonValue block : blocks) {
|
||||
QJsonObject user = block.toObject().value("user").toObject();
|
||||
// display_name
|
||||
twitchBlockedUsers->insert(user.value("name").toString().toLower(), true);
|
||||
}
|
||||
twitchBlockedUsersMutex->unlock();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
c->setHost("irc.chat.twitch.tv");
|
||||
c->setPort(6667);
|
||||
|
||||
|
@ -77,10 +145,93 @@ void IrcManager::disconnect()
|
|||
|
||||
void IrcManager::messageReceived(IrcMessage *message)
|
||||
{
|
||||
// qInfo(message->());
|
||||
qInfo(message->command().toStdString().c_str());
|
||||
|
||||
// if (message->command() == "")
|
||||
}
|
||||
|
||||
void IrcManager::privateMessageReceived(IrcPrivateMessage *message)
|
||||
{
|
||||
qInfo(message->content().toStdString().c_str());
|
||||
}
|
||||
|
||||
bool IrcManager::isTwitchBlockedUser(QString const &username)
|
||||
{
|
||||
twitchBlockedUsersMutex->lock();
|
||||
|
||||
auto iterator = twitchBlockedUsers->find(username);
|
||||
|
||||
if (iterator == twitchBlockedUsers->end()) {
|
||||
twitchBlockedUsersMutex->unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
twitchBlockedUsersMutex->unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IrcManager::tryAddIgnoredUser(QString const &username, QString& errorMessage)
|
||||
{
|
||||
QUrl url("https://api.twitch.tv/kraken/users/" + account->username() +
|
||||
"/blocks/" + username +
|
||||
"?oauth_token=" + account->oauthToken() +
|
||||
"&client_id=" + account->oauthClient());
|
||||
|
||||
QNetworkRequest request(url);
|
||||
auto reply = accessManager->put(request, QByteArray());
|
||||
reply->waitForReadyRead(10000);
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError)
|
||||
{
|
||||
twitchBlockedUsersMutex->lock();
|
||||
twitchBlockedUsers->insert(username, true);
|
||||
twitchBlockedUsersMutex->unlock();
|
||||
|
||||
delete reply;
|
||||
return true;
|
||||
}
|
||||
|
||||
errorMessage = "Error while ignoring user \"" + username + "\": " + reply->errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
void IrcManager::addIgnoredUser(QString const &username)
|
||||
{
|
||||
QString errorMessage;
|
||||
if (tryAddIgnoredUser(username, errorMessage)) {
|
||||
#warning "xD"
|
||||
}
|
||||
}
|
||||
|
||||
bool IrcManager::tryRemoveIgnoredUser(QString const &username, QString& errorMessage)
|
||||
{
|
||||
QUrl url("https://api.twitch.tv/kraken/users/" + account->username() +
|
||||
"/blocks/" + username +
|
||||
"?oauth_token=" + account->oauthToken() +
|
||||
"&client_id=" + account->oauthClient());
|
||||
|
||||
QNetworkRequest request(url);
|
||||
auto reply = accessManager->deleteResource(request);
|
||||
reply->waitForReadyRead(10000);
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError)
|
||||
{
|
||||
twitchBlockedUsersMutex->lock();
|
||||
twitchBlockedUsers->remove(username);
|
||||
twitchBlockedUsersMutex->unlock();
|
||||
|
||||
delete reply;
|
||||
return true;
|
||||
}
|
||||
|
||||
errorMessage = "Error while unignoring user \"" + username + "\": " + reply->errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
void IrcManager::removeIgnoredUser(QString const &username)
|
||||
{
|
||||
QString errorMessage;
|
||||
if (tryRemoveIgnoredUser(username, errorMessage)) {
|
||||
#warning "xD"
|
||||
}
|
||||
}
|
||||
|
|
21
ircmanager.h
21
ircmanager.h
|
@ -5,6 +5,10 @@
|
|||
|
||||
#include "IrcMessage"
|
||||
#include "QMutex"
|
||||
#include "QString"
|
||||
#include "QMap"
|
||||
#include "account.h"
|
||||
#include "qnetworkaccessmanager.h"
|
||||
|
||||
class IrcManager
|
||||
{
|
||||
|
@ -12,12 +16,25 @@ public:
|
|||
static void connect();
|
||||
static void disconnect();
|
||||
|
||||
static const QString defaultClientId;
|
||||
|
||||
bool isTwitchBlockedUser(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);
|
||||
|
||||
static Account* account;
|
||||
|
||||
private:
|
||||
IrcManager();
|
||||
|
||||
static void beginConnecting();
|
||||
static QMap<QString, bool>* twitchBlockedUsers;
|
||||
static QMutex* twitchBlockedUsersMutex;
|
||||
|
||||
static QObject* parent;
|
||||
static QNetworkAccessManager* accessManager;
|
||||
|
||||
static void beginConnecting();
|
||||
|
||||
static IrcConnection* connection;
|
||||
static QMutex* connectionMutex;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "lambdaqrunnable.h"
|
||||
|
||||
LambdaQRunnable::LambdaQRunnable(std::function<bool ()> action)
|
||||
LambdaQRunnable::LambdaQRunnable(std::function<void ()> action)
|
||||
{
|
||||
this->action = action;
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
class LambdaQRunnable : public QRunnable
|
||||
{
|
||||
public:
|
||||
LambdaQRunnable(std::function<bool ()> action);
|
||||
LambdaQRunnable(std::function<void ()> action);
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
std::function<bool ()> action;
|
||||
std::function<void ()> action;
|
||||
};
|
||||
|
||||
#endif // LAMBDAQRUNNABLE_H
|
||||
|
|
6
lazyloadedimage.cpp
Normal file
6
lazyloadedimage.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "lazyloadedimage.h"
|
||||
|
||||
LazyLoadedImage::LazyLoadedImage()
|
||||
{
|
||||
|
||||
}
|
11
lazyloadedimage.h
Normal file
11
lazyloadedimage.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef LAZYLOADEDIMAGE_H
|
||||
#define LAZYLOADEDIMAGE_H
|
||||
|
||||
|
||||
class LazyLoadedImage
|
||||
{
|
||||
public:
|
||||
LazyLoadedImage();
|
||||
};
|
||||
|
||||
#endif // LAZYLOADEDIMAGE_H
|
27
twitchemotevalue.h
Normal file
27
twitchemotevalue.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef TWITCHEMOTEVALUE_H
|
||||
#define TWITCHEMOTEVALUE_H
|
||||
|
||||
#include "QString"
|
||||
|
||||
struct TwitchEmoteValue
|
||||
{
|
||||
public:
|
||||
int set() {
|
||||
return m_set;
|
||||
}
|
||||
|
||||
int id() {
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString channelName() {
|
||||
return m_channelName;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_set;
|
||||
int m_id;
|
||||
QString m_channelName;
|
||||
};
|
||||
|
||||
#endif // TWITCHEMOTEVALUE_H
|
Loading…
Reference in a new issue