fixed and optimized the autocompletion
This commit is contained in:
@@ -49,6 +49,24 @@ auto parseRecentMessages(const QJsonObject &jsonRoot, TwitchChannel &channel)
|
||||
|
||||
return messages;
|
||||
}
|
||||
std::pair<Outcome, UsernameSet> parseChatters(const QJsonObject &jsonRoot)
|
||||
{
|
||||
static QStringList categories = {"moderators", "staff", "admins",
|
||||
"global_mods", "viewers"};
|
||||
|
||||
auto usernames = UsernameSet();
|
||||
|
||||
// parse json
|
||||
QJsonObject jsonCategories = jsonRoot.value("chatters").toObject();
|
||||
|
||||
for (const auto &category : categories) {
|
||||
for (auto jsonCategory : jsonCategories.value(category).toArray()) {
|
||||
usernames.insert(jsonCategory.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return {Success, std::move(usernames)};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv,
|
||||
@@ -72,22 +90,22 @@ TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv,
|
||||
[=] { this->setMod(false); });
|
||||
|
||||
// pubsub
|
||||
this->userStateChanged.connect([=] { this->refreshPubsub(); });
|
||||
this->managedConnect(getApp()->accounts->twitch.currentUserChanged,
|
||||
[=] { this->refreshPubsub(); });
|
||||
this->refreshPubsub();
|
||||
this->userStateChanged.connect([this] { this->refreshPubsub(); });
|
||||
|
||||
// room id loaded -> refresh live status
|
||||
this->roomIdChanged.connect([this]() {
|
||||
this->refreshPubsub();
|
||||
this->refreshLiveStatus();
|
||||
this->loadBadges();
|
||||
this->loadCheerEmotes();
|
||||
this->refreshBadges();
|
||||
this->refreshCheerEmotes();
|
||||
});
|
||||
|
||||
// timers
|
||||
QObject::connect(&this->chattersListTimer_, &QTimer::timeout,
|
||||
[=] { this->refreshViewerList(); });
|
||||
[=] { this->refreshChatters(); });
|
||||
this->chattersListTimer_.start(5 * 60 * 1000);
|
||||
|
||||
QObject::connect(&this->liveStatusTimer_, &QTimer::timeout,
|
||||
@@ -101,11 +119,17 @@ TwitchChannel::TwitchChannel(const QString &name, BttvEmotes &bttv,
|
||||
// debugging
|
||||
#if 0
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
this->addMessage(makeSystemMessage("asdf"));
|
||||
this->addMessage(makeSystemMessage("asef"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void TwitchChannel::initialize()
|
||||
{
|
||||
this->refreshChatters();
|
||||
this->refreshChannelEmotes();
|
||||
}
|
||||
|
||||
bool TwitchChannel::isEmpty() const
|
||||
{
|
||||
return this->getName().isEmpty();
|
||||
@@ -293,6 +317,11 @@ TwitchChannel::accessStreamStatus() const
|
||||
return this->streamStatus_.accessConst();
|
||||
}
|
||||
|
||||
AccessGuard<const UsernameSet> TwitchChannel::accessChatters() const
|
||||
{
|
||||
return this->chatters_.accessConst();
|
||||
}
|
||||
|
||||
const BttvEmotes &TwitchChannel::globalBttv() const
|
||||
{
|
||||
return this->globalBttv_;
|
||||
@@ -314,7 +343,7 @@ boost::optional<EmotePtr> TwitchChannel::bttvEmote(const EmoteName &name) const
|
||||
|
||||
boost::optional<EmotePtr> TwitchChannel::ffzEmote(const EmoteName &name) const
|
||||
{
|
||||
auto emotes = this->bttvEmotes_.get();
|
||||
auto emotes = this->ffzEmotes_.get();
|
||||
auto it = emotes->find(name);
|
||||
|
||||
if (it == emotes->end()) return boost::none;
|
||||
@@ -508,7 +537,7 @@ void TwitchChannel::refreshPubsub()
|
||||
account);
|
||||
}
|
||||
|
||||
void TwitchChannel::refreshViewerList()
|
||||
void TwitchChannel::refreshChatters()
|
||||
{
|
||||
// setting?
|
||||
const auto streamStatus = this->accessStreamStatus();
|
||||
@@ -531,31 +560,18 @@ void TwitchChannel::refreshViewerList()
|
||||
auto shared = weak.lock();
|
||||
if (!shared) return Failure;
|
||||
|
||||
return this->parseViewerList(result.parseJson());
|
||||
auto pair = parseChatters(result.parseJson());
|
||||
if (pair.first) {
|
||||
*this->chatters_.access() = std::move(pair.second);
|
||||
}
|
||||
|
||||
return pair.first;
|
||||
});
|
||||
|
||||
request.execute();
|
||||
}
|
||||
|
||||
Outcome TwitchChannel::parseViewerList(const QJsonObject &jsonRoot)
|
||||
{
|
||||
static QStringList categories = {"moderators", "staff", "admins",
|
||||
"global_mods", "viewers"};
|
||||
|
||||
// parse json
|
||||
QJsonObject jsonCategories = jsonRoot.value("chatters").toObject();
|
||||
|
||||
for (const auto &category : categories) {
|
||||
for (const auto jsonCategory :
|
||||
jsonCategories.value(category).toArray()) {
|
||||
this->completionModel.addUser(jsonCategory.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
void TwitchChannel::loadBadges()
|
||||
void TwitchChannel::refreshBadges()
|
||||
{
|
||||
auto url = Url{"https://badges.twitch.tv/v1/badges/channels/" +
|
||||
this->roomId() + "/display?language=en"};
|
||||
@@ -600,7 +616,7 @@ void TwitchChannel::loadBadges()
|
||||
req.execute();
|
||||
}
|
||||
|
||||
void TwitchChannel::loadCheerEmotes()
|
||||
void TwitchChannel::refreshCheerEmotes()
|
||||
{
|
||||
/*auto url = Url{"https://api.twitch.tv/kraken/bits/actions?channel_id=" +
|
||||
this->getRoomId()};
|
||||
@@ -664,7 +680,7 @@ void TwitchChannel::loadCheerEmotes()
|
||||
*/
|
||||
}
|
||||
|
||||
boost::optional<EmotePtr> TwitchChannel::getTwitchBadge(
|
||||
boost::optional<EmotePtr> TwitchChannel::twitchBadge(
|
||||
const QString &set, const QString &version) const
|
||||
{
|
||||
auto badgeSets = this->badgeSets_.access();
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <IrcConnection>
|
||||
|
||||
#include "common/Aliases.hpp"
|
||||
#include "common/Atomic.hpp"
|
||||
#include "common/Channel.hpp"
|
||||
#include "common/Outcome.hpp"
|
||||
#include "common/UniqueAccess.hpp"
|
||||
#include "common/UsernameSet.hpp"
|
||||
#include "providers/twitch/TwitchEmotes.hpp"
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <IrcConnection>
|
||||
#include <QColor>
|
||||
#include <QRegularExpression>
|
||||
#include <boost/optional.hpp>
|
||||
#include <mutex>
|
||||
#include <pajlada/signals/signalholder.hpp>
|
||||
@@ -37,11 +41,6 @@ public:
|
||||
QString streamType;
|
||||
};
|
||||
|
||||
struct UserState {
|
||||
bool mod;
|
||||
bool broadcaster;
|
||||
};
|
||||
|
||||
struct RoomModes {
|
||||
bool submode = false;
|
||||
bool r9k = false;
|
||||
@@ -51,32 +50,24 @@ public:
|
||||
QString broadcasterLang;
|
||||
};
|
||||
|
||||
void refreshChannelEmotes();
|
||||
void initialize();
|
||||
|
||||
// Channel methods
|
||||
virtual bool isEmpty() const override;
|
||||
virtual bool canSendMessage() const override;
|
||||
virtual void sendMessage(const QString &message) override;
|
||||
|
||||
// Auto completion
|
||||
void addRecentChatter(const MessagePtr &message) final;
|
||||
void addJoinedUser(const QString &user);
|
||||
void addPartedUser(const QString &user);
|
||||
|
||||
bool isLive() const;
|
||||
virtual bool isMod() const override;
|
||||
void setMod(bool value);
|
||||
virtual bool isBroadcaster() const override;
|
||||
|
||||
// Data
|
||||
const QString &subscriptionUrl();
|
||||
const QString &channelUrl();
|
||||
const QString &popoutPlayerUrl();
|
||||
bool isLive() const;
|
||||
QString roomId() const;
|
||||
void setRoomId(const QString &id);
|
||||
AccessGuard<const RoomModes> accessRoomModes() const;
|
||||
void setRoomModes(const RoomModes &roomModes_);
|
||||
AccessGuard<const StreamStatus> accessStreamStatus() const;
|
||||
AccessGuard<const UsernameSet> accessChatters() const;
|
||||
|
||||
// Emotes
|
||||
const BttvEmotes &globalBttv() const;
|
||||
@@ -86,58 +77,53 @@ public:
|
||||
std::shared_ptr<const EmoteMap> bttvEmotes() const;
|
||||
std::shared_ptr<const EmoteMap> ffzEmotes() const;
|
||||
|
||||
boost::optional<EmotePtr> getTwitchBadge(const QString &set,
|
||||
const QString &version) const;
|
||||
void refreshChannelEmotes();
|
||||
|
||||
// Badges
|
||||
boost::optional<EmotePtr> twitchBadge(const QString &set,
|
||||
const QString &version) const;
|
||||
|
||||
// Signals
|
||||
pajlada::Signals::NoArgSignal roomIdChanged;
|
||||
pajlada::Signals::NoArgSignal liveStatusChanged;
|
||||
pajlada::Signals::NoArgSignal userStateChanged;
|
||||
pajlada::Signals::NoArgSignal liveStatusChanged;
|
||||
pajlada::Signals::NoArgSignal roomModesChanged;
|
||||
|
||||
protected:
|
||||
void addRecentChatter(const MessagePtr &message) override;
|
||||
|
||||
private:
|
||||
struct NameOptions {
|
||||
QString displayName;
|
||||
QString localizedName;
|
||||
};
|
||||
|
||||
struct CheerEmote {
|
||||
// a Cheermote indicates one tier
|
||||
QColor color;
|
||||
int minBits;
|
||||
|
||||
EmotePtr animatedEmote;
|
||||
EmotePtr staticEmote;
|
||||
};
|
||||
|
||||
struct CheerEmoteSet {
|
||||
QRegularExpression regex;
|
||||
std::vector<CheerEmote> cheerEmotes;
|
||||
};
|
||||
|
||||
explicit TwitchChannel(const QString &channelName, BttvEmotes &bttv,
|
||||
FfzEmotes &ffz);
|
||||
explicit TwitchChannel(const QString &channelName, BttvEmotes &globalBttv,
|
||||
FfzEmotes &globalFfz);
|
||||
|
||||
// Methods
|
||||
void refreshLiveStatus();
|
||||
Outcome parseLiveStatus(const rapidjson::Document &document);
|
||||
void refreshPubsub();
|
||||
void refreshViewerList();
|
||||
Outcome parseViewerList(const QJsonObject &jsonRoot);
|
||||
void refreshChatters();
|
||||
void refreshBadges();
|
||||
void refreshCheerEmotes();
|
||||
void loadRecentMessages();
|
||||
|
||||
void addJoinedUser(const QString &user);
|
||||
void addPartedUser(const QString &user);
|
||||
void setLive(bool newLiveStatus);
|
||||
|
||||
void loadBadges();
|
||||
void loadCheerEmotes();
|
||||
void setMod(bool value);
|
||||
void setRoomId(const QString &id);
|
||||
void setRoomModes(const RoomModes &roomModes_);
|
||||
|
||||
// Data
|
||||
const QString subscriptionUrl_;
|
||||
const QString channelUrl_;
|
||||
const QString popoutPlayerUrl_;
|
||||
UniqueAccess<StreamStatus> streamStatus_;
|
||||
UniqueAccess<UserState> userState_;
|
||||
UniqueAccess<RoomModes> roomModes_;
|
||||
UniqueAccess<UsernameSet> chatters_; // maps 2 char prefix to set of names
|
||||
|
||||
// Emotes
|
||||
BttvEmotes &globalBttv_;
|
||||
@@ -145,6 +131,11 @@ private:
|
||||
Atomic<std::shared_ptr<const EmoteMap>> bttvEmotes_;
|
||||
Atomic<std::shared_ptr<const EmoteMap>> ffzEmotes_;
|
||||
|
||||
// Badges
|
||||
UniqueAccess<std::map<QString, std::map<QString, EmotePtr>>>
|
||||
badgeSets_; // "subscribers": { "0": ... "3": ... "6": ...
|
||||
UniqueAccess<std::vector<CheerEmoteSet>> cheerEmoteSets_;
|
||||
|
||||
bool mod_ = false;
|
||||
UniqueAccess<QString> roomID_;
|
||||
|
||||
@@ -153,10 +144,6 @@ private:
|
||||
UniqueAccess<QStringList> partedUsers_;
|
||||
bool partedUsersMergeQueued_ = false;
|
||||
|
||||
// "subscribers": { "0": ... "3": ... "6": ...
|
||||
UniqueAccess<std::map<QString, std::map<QString, EmotePtr>>> badgeSets_;
|
||||
UniqueAccess<std::vector<CheerEmoteSet>> cheerEmoteSets_;
|
||||
|
||||
// --
|
||||
QByteArray messageSuffix_;
|
||||
QString lastSentMessage_;
|
||||
@@ -165,6 +152,8 @@ private:
|
||||
QTimer chattersListTimer_;
|
||||
|
||||
friend class TwitchServer;
|
||||
friend class TwitchMessageBuilder;
|
||||
friend class IrcMessageHandler;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <QColor>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -11,10 +13,22 @@
|
||||
"https://static-cdn.jtvnw.net/emoticons/v1/{id}/{scale}"
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
struct Emote;
|
||||
using EmotePtr = std::shared_ptr<const Emote>;
|
||||
|
||||
struct CheerEmote {
|
||||
QColor color;
|
||||
int minBits;
|
||||
|
||||
EmotePtr animatedEmote;
|
||||
EmotePtr staticEmote;
|
||||
};
|
||||
|
||||
struct CheerEmoteSet {
|
||||
QRegularExpression regex;
|
||||
std::vector<CheerEmote> cheerEmotes;
|
||||
};
|
||||
|
||||
class TwitchEmotes
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -646,7 +646,7 @@ Outcome TwitchMessageBuilder::tryAppendEmote(const EmoteName &name)
|
||||
flags = MessageElementFlag::BttvEmote;
|
||||
} else if ((emote = this->twitchChannel->globalFfz().emote(name))) {
|
||||
flags = MessageElementFlag::FfzEmote;
|
||||
} else if (twitchChannel && (emote = this->twitchChannel->ffzEmote(name))) {
|
||||
} else if ((emote = this->twitchChannel->ffzEmote(name))) {
|
||||
flags = MessageElementFlag::FfzEmote;
|
||||
}
|
||||
|
||||
@@ -691,7 +691,7 @@ void TwitchMessageBuilder::appendTwitchBadges()
|
||||
// Try to fetch channel-specific bit badge
|
||||
try {
|
||||
if (twitchChannel)
|
||||
if (const auto &badge = this->twitchChannel->getTwitchBadge(
|
||||
if (const auto &badge = this->twitchChannel->twitchBadge(
|
||||
"bits", cheerAmount)) {
|
||||
this->emplace<EmoteElement>(
|
||||
badge.get(), MessageElementFlag::BadgeVanity)
|
||||
|
||||
@@ -85,7 +85,7 @@ std::shared_ptr<Channel> TwitchServer::createChannel(const QString &channelName)
|
||||
{
|
||||
auto channel = std::shared_ptr<TwitchChannel>(
|
||||
new TwitchChannel(channelName, this->bttv, this->ffz));
|
||||
channel->refreshChannelEmotes();
|
||||
channel->initialize();
|
||||
|
||||
channel->sendMessageSignal.connect(
|
||||
[this, channel = channel.get()](auto &chan, auto &msg, bool &sent) {
|
||||
|
||||
Reference in New Issue
Block a user