mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Merge remote-tracking branch 'refs/remotes/origin/master'
This commit is contained in:
commit
affef2c5a2
|
@ -5,11 +5,13 @@
|
||||||
- Minor: Added customizable timeout buttons to the user info popup
|
- Minor: Added customizable timeout buttons to the user info popup
|
||||||
- Minor: Deprecate loading of "v1" window layouts. If you haven't updated Chatterino in more than 2 years, there's a chance you will lose your window layout.
|
- Minor: Deprecate loading of "v1" window layouts. If you haven't updated Chatterino in more than 2 years, there's a chance you will lose your window layout.
|
||||||
- Minor: Disable checking for updates on unsupported platforms (#1874)
|
- Minor: Disable checking for updates on unsupported platforms (#1874)
|
||||||
|
- Minor: Changed the English in two rate-limited system messages (#1878)
|
||||||
- Bugfix: Fix bug preventing users from setting the highlight color of the second entry in the "User" highlights tab (#1898)
|
- Bugfix: Fix bug preventing users from setting the highlight color of the second entry in the "User" highlights tab (#1898)
|
||||||
- Bugfix: Fix bug where the "check user follow state" event could trigger a network request requesting the user to follow or unfollow a user. By itself its quite harmless as it just repeats to Twitch the same follow state we had, so no follows should have been lost by this but it meant there was a rogue network request that was fired that could cause a crash (#1906)
|
- Bugfix: Fix bug where the "check user follow state" event could trigger a network request requesting the user to follow or unfollow a user. By itself its quite harmless as it just repeats to Twitch the same follow state we had, so no follows should have been lost by this but it meant there was a rogue network request that was fired that could cause a crash (#1906)
|
||||||
- Bugfix: /usercard command will now respect the "Automatically close user popup" setting (#1918)
|
- Bugfix: /usercard command will now respect the "Automatically close user popup" setting (#1918)
|
||||||
- Bugfix: Handle symlinks properly when saving commands & settings (#1856, #1908)
|
- Bugfix: Handle symlinks properly when saving commands & settings (#1856, #1908)
|
||||||
- Bugfix: Starting Chatterino in a minimized state after an update will no longer cause a crash
|
- Bugfix: Starting Chatterino in a minimized state after an update will no longer cause a crash
|
||||||
|
- Bugfix: Modify the emote parsing to handle some edge-cases with dots and stuff (#1704, #1714)
|
||||||
|
|
||||||
## 2.2.0
|
## 2.2.0
|
||||||
|
|
||||||
|
|
|
@ -336,7 +336,7 @@ void TwitchIrcServer::onMessageSendRequested(TwitchChannel *channel,
|
||||||
if (this->lastErrorTimeSpeed_ + 30s < now)
|
if (this->lastErrorTimeSpeed_ + 30s < now)
|
||||||
{
|
{
|
||||||
auto errorMessage =
|
auto errorMessage =
|
||||||
makeSystemMessage("sending messages too fast");
|
makeSystemMessage("You are sending messages too quickly.");
|
||||||
|
|
||||||
channel->addMessage(errorMessage);
|
channel->addMessage(errorMessage);
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ void TwitchIrcServer::onMessageSendRequested(TwitchChannel *channel,
|
||||||
if (this->lastErrorTimeAmount_ + 30s < now)
|
if (this->lastErrorTimeAmount_ + 30s < now)
|
||||||
{
|
{
|
||||||
auto errorMessage =
|
auto errorMessage =
|
||||||
makeSystemMessage("sending too many messages");
|
makeSystemMessage("You are sending too many messages.");
|
||||||
|
|
||||||
channel->addMessage(errorMessage);
|
channel->addMessage(errorMessage);
|
||||||
|
|
||||||
|
|
|
@ -282,7 +282,7 @@ MessagePtr TwitchMessageBuilder::build()
|
||||||
}
|
}
|
||||||
|
|
||||||
// twitch emotes
|
// twitch emotes
|
||||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> twitchEmotes;
|
std::vector<TwitchEmoteOccurence> twitchEmotes;
|
||||||
|
|
||||||
iterator = this->tags.find("emotes");
|
iterator = this->tags.find("emotes");
|
||||||
if (iterator != this->tags.end())
|
if (iterator != this->tags.end())
|
||||||
|
@ -307,12 +307,11 @@ MessagePtr TwitchMessageBuilder::build()
|
||||||
|
|
||||||
std::sort(twitchEmotes.begin(), twitchEmotes.end(),
|
std::sort(twitchEmotes.begin(), twitchEmotes.end(),
|
||||||
[](const auto &a, const auto &b) {
|
[](const auto &a, const auto &b) {
|
||||||
return std::get<0>(a) < std::get<0>(b);
|
return a.start < b.start; //
|
||||||
});
|
});
|
||||||
twitchEmotes.erase(std::unique(twitchEmotes.begin(), twitchEmotes.end(),
|
twitchEmotes.erase(std::unique(twitchEmotes.begin(), twitchEmotes.end(),
|
||||||
[](const auto &first, const auto &second) {
|
[](const auto &first, const auto &second) {
|
||||||
return std::get<0>(first) ==
|
return first.start == second.start;
|
||||||
std::get<0>(second);
|
|
||||||
}),
|
}),
|
||||||
twitchEmotes.end());
|
twitchEmotes.end());
|
||||||
|
|
||||||
|
@ -339,47 +338,90 @@ MessagePtr TwitchMessageBuilder::build()
|
||||||
return this->release();
|
return this->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool doesWordContainATwitchEmote(
|
||||||
|
int cursor, const QString &word,
|
||||||
|
const std::vector<TwitchEmoteOccurence> &twitchEmotes,
|
||||||
|
std::vector<TwitchEmoteOccurence>::const_iterator ¤tTwitchEmoteIt)
|
||||||
|
{
|
||||||
|
if (currentTwitchEmoteIt == twitchEmotes.end())
|
||||||
|
{
|
||||||
|
// No emote to add!
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto ¤tTwitchEmote = *currentTwitchEmoteIt;
|
||||||
|
|
||||||
|
auto wordEnd = cursor + word.length();
|
||||||
|
|
||||||
|
// Check if this emote fits within the word boundaries
|
||||||
|
if (currentTwitchEmote.start < cursor || currentTwitchEmote.end > wordEnd)
|
||||||
|
{
|
||||||
|
// this emote does not fit xd
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void TwitchMessageBuilder::addWords(
|
void TwitchMessageBuilder::addWords(
|
||||||
const QStringList &words,
|
const QStringList &words,
|
||||||
const std::vector<std::tuple<int, EmotePtr, EmoteName>> &twitchEmotes)
|
const std::vector<TwitchEmoteOccurence> &twitchEmotes)
|
||||||
{
|
{
|
||||||
auto i = int();
|
// cursor currently indicates what character index we're currently operating in the full list of words
|
||||||
auto currentTwitchEmote = twitchEmotes.begin();
|
int cursor = 0;
|
||||||
|
auto currentTwitchEmoteIt = twitchEmotes.begin();
|
||||||
|
|
||||||
for (auto word : words)
|
for (auto word : words)
|
||||||
{
|
{
|
||||||
// check if it's a twitch emote twitch emote
|
while (doesWordContainATwitchEmote(cursor, word, twitchEmotes,
|
||||||
while (currentTwitchEmote != twitchEmotes.end() &&
|
currentTwitchEmoteIt))
|
||||||
std::get<0>(*currentTwitchEmote) < i)
|
|
||||||
{
|
{
|
||||||
++currentTwitchEmote;
|
auto wordEnd = cursor + word.length();
|
||||||
}
|
const auto ¤tTwitchEmote = *currentTwitchEmoteIt;
|
||||||
if (currentTwitchEmote != twitchEmotes.end() &&
|
|
||||||
std::get<0>(*currentTwitchEmote) == i)
|
if (currentTwitchEmote.start == cursor)
|
||||||
{
|
|
||||||
auto emoteImage = std::get<1>(*currentTwitchEmote);
|
|
||||||
if (emoteImage == nullptr)
|
|
||||||
{
|
|
||||||
qDebug() << "emoteImage nullptr"
|
|
||||||
<< std::get<2>(*currentTwitchEmote).string;
|
|
||||||
}
|
|
||||||
this->emplace<EmoteElement>(emoteImage,
|
|
||||||
MessageElementFlag::TwitchEmote);
|
|
||||||
|
|
||||||
i += word.length() + 1;
|
|
||||||
|
|
||||||
int len = std::get<2>(*currentTwitchEmote).string.length();
|
|
||||||
currentTwitchEmote++;
|
|
||||||
|
|
||||||
if (len < word.length())
|
|
||||||
{
|
{
|
||||||
|
// This emote exists right at the start of the word!
|
||||||
|
this->emplace<EmoteElement>(currentTwitchEmote.ptr,
|
||||||
|
MessageElementFlag::TwitchEmote);
|
||||||
|
auto len = currentTwitchEmote.name.string.length();
|
||||||
|
cursor += len;
|
||||||
word = word.mid(len);
|
word = word.mid(len);
|
||||||
this->message().elements.back()->setTrailingSpace(false);
|
|
||||||
}
|
++currentTwitchEmoteIt;
|
||||||
else
|
|
||||||
{
|
if (word.isEmpty())
|
||||||
|
{
|
||||||
|
// space
|
||||||
|
cursor += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->message().elements.back()->setTrailingSpace(false);
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emote is not at the start
|
||||||
|
|
||||||
|
// 1. Add text before the emote
|
||||||
|
QString preText = word.left(currentTwitchEmote.start - cursor);
|
||||||
|
for (auto &variant : getApp()->emotes->emojis.parse(preText))
|
||||||
|
{
|
||||||
|
boost::apply_visitor(
|
||||||
|
[&](auto &&arg) { this->addTextOrEmoji(arg); }, variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor += preText.size();
|
||||||
|
|
||||||
|
word = word.mid(preText.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (word.isEmpty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// split words
|
// split words
|
||||||
|
@ -389,7 +431,7 @@ void TwitchMessageBuilder::addWords(
|
||||||
variant);
|
variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
i += word.size() + 1;
|
cursor += word.size() + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,36 +702,32 @@ void TwitchMessageBuilder::appendUsername()
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchMessageBuilder::runIgnoreReplaces(
|
void TwitchMessageBuilder::runIgnoreReplaces(
|
||||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> &twitchEmotes)
|
std::vector<TwitchEmoteOccurence> &twitchEmotes)
|
||||||
{
|
{
|
||||||
auto phrases = getCSettings().ignoredMessages.readOnly();
|
auto phrases = getCSettings().ignoredMessages.readOnly();
|
||||||
auto removeEmotesInRange =
|
auto removeEmotesInRange = [](int pos, int len,
|
||||||
[](int pos, int len,
|
auto &twitchEmotes) mutable {
|
||||||
std::vector<std::tuple<int, EmotePtr, EmoteName>>
|
auto it = std::partition(
|
||||||
&twitchEmotes) mutable {
|
twitchEmotes.begin(), twitchEmotes.end(),
|
||||||
auto it =
|
[pos, len](const auto &item) {
|
||||||
std::partition(twitchEmotes.begin(), twitchEmotes.end(),
|
return !((item.start >= pos) && item.start < (pos + len));
|
||||||
[pos, len](const auto &item) {
|
});
|
||||||
return !((std::get<0>(item) >= pos) &&
|
for (auto copy = it; copy != twitchEmotes.end(); ++copy)
|
||||||
std::get<0>(item) < (pos + len));
|
{
|
||||||
});
|
if ((*copy).ptr == nullptr)
|
||||||
for (auto copy = it; copy != twitchEmotes.end(); ++copy)
|
|
||||||
{
|
{
|
||||||
if (std::get<1>(*copy) == nullptr)
|
qDebug() << "remem nullptr" << (*copy).name.string;
|
||||||
{
|
|
||||||
qDebug() << "remem nullptr" << std::get<2>(*copy).string;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> v(
|
}
|
||||||
it, twitchEmotes.end());
|
std::vector<TwitchEmoteOccurence> v(it, twitchEmotes.end());
|
||||||
twitchEmotes.erase(it, twitchEmotes.end());
|
twitchEmotes.erase(it, twitchEmotes.end());
|
||||||
return v;
|
return v;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto shiftIndicesAfter = [&twitchEmotes](int pos, int by) mutable {
|
auto shiftIndicesAfter = [&twitchEmotes](int pos, int by) mutable {
|
||||||
for (auto &item : twitchEmotes)
|
for (auto &item : twitchEmotes)
|
||||||
{
|
{
|
||||||
auto &index = std::get<0>(item);
|
auto &index = item.start;
|
||||||
if (index >= pos)
|
if (index >= pos)
|
||||||
{
|
{
|
||||||
index += by;
|
index += by;
|
||||||
|
@ -717,8 +755,12 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
||||||
{
|
{
|
||||||
qDebug() << "emote null" << emote.first.string;
|
qDebug() << "emote null" << emote.first.string;
|
||||||
}
|
}
|
||||||
twitchEmotes.push_back(std::tuple<int, EmotePtr, EmoteName>{
|
twitchEmotes.push_back(TwitchEmoteOccurence{
|
||||||
startIndex + pos, emote.second, emote.first});
|
startIndex + pos,
|
||||||
|
startIndex + pos + emote.first.string.length(),
|
||||||
|
emote.second,
|
||||||
|
emote.first,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos += word.length() + 1;
|
pos += word.length() + 1;
|
||||||
|
@ -776,13 +818,13 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
||||||
|
|
||||||
for (auto &tup : vret)
|
for (auto &tup : vret)
|
||||||
{
|
{
|
||||||
if (std::get<1>(tup) == nullptr)
|
if (tup.ptr == nullptr)
|
||||||
{
|
{
|
||||||
qDebug() << "v nullptr" << std::get<2>(tup).string;
|
qDebug() << "v nullptr" << tup.name.string;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QRegularExpression emoteregex(
|
QRegularExpression emoteregex(
|
||||||
"\\b" + std::get<2>(tup).string + "\\b",
|
"\\b" + tup.name.string + "\\b",
|
||||||
QRegularExpression::UseUnicodePropertiesOption);
|
QRegularExpression::UseUnicodePropertiesOption);
|
||||||
auto _match = emoteregex.match(midExtendedRef);
|
auto _match = emoteregex.match(midExtendedRef);
|
||||||
if (_match.hasMatch())
|
if (_match.hasMatch())
|
||||||
|
@ -790,7 +832,7 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
||||||
int last = _match.lastCapturedIndex();
|
int last = _match.lastCapturedIndex();
|
||||||
for (int i = 0; i <= last; ++i)
|
for (int i = 0; i <= last; ++i)
|
||||||
{
|
{
|
||||||
std::get<0>(tup) = from + _match.capturedStart();
|
tup.start = from + _match.capturedStart();
|
||||||
twitchEmotes.push_back(std::move(tup));
|
twitchEmotes.push_back(std::move(tup));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -845,13 +887,13 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
||||||
|
|
||||||
for (auto &tup : vret)
|
for (auto &tup : vret)
|
||||||
{
|
{
|
||||||
if (std::get<1>(tup) == nullptr)
|
if (tup.ptr == nullptr)
|
||||||
{
|
{
|
||||||
qDebug() << "v nullptr" << std::get<2>(tup).string;
|
qDebug() << "v nullptr" << tup.name.string;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QRegularExpression emoteregex(
|
QRegularExpression emoteregex(
|
||||||
"\\b" + std::get<2>(tup).string + "\\b",
|
"\\b" + tup.name.string + "\\b",
|
||||||
QRegularExpression::UseUnicodePropertiesOption);
|
QRegularExpression::UseUnicodePropertiesOption);
|
||||||
auto match = emoteregex.match(midExtendedRef);
|
auto match = emoteregex.match(midExtendedRef);
|
||||||
if (match.hasMatch())
|
if (match.hasMatch())
|
||||||
|
@ -859,7 +901,7 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
||||||
int last = match.lastCapturedIndex();
|
int last = match.lastCapturedIndex();
|
||||||
for (int i = 0; i <= last; ++i)
|
for (int i = 0; i <= last; ++i)
|
||||||
{
|
{
|
||||||
std::get<0>(tup) = from + match.capturedStart();
|
tup.start = from + match.capturedStart();
|
||||||
twitchEmotes.push_back(std::move(tup));
|
twitchEmotes.push_back(std::move(tup));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -874,8 +916,7 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchMessageBuilder::appendTwitchEmote(
|
void TwitchMessageBuilder::appendTwitchEmote(
|
||||||
const QString &emote,
|
const QString &emote, std::vector<TwitchEmoteOccurence> &vec,
|
||||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> &vec,
|
|
||||||
std::vector<int> &correctPositions)
|
std::vector<int> &correctPositions)
|
||||||
{
|
{
|
||||||
auto app = getApp();
|
auto app = getApp();
|
||||||
|
@ -914,13 +955,13 @@ void TwitchMessageBuilder::appendTwitchEmote(
|
||||||
|
|
||||||
auto name =
|
auto name =
|
||||||
EmoteName{this->originalMessage_.mid(start, end - start + 1)};
|
EmoteName{this->originalMessage_.mid(start, end - start + 1)};
|
||||||
auto tup = std::tuple<int, EmotePtr, EmoteName>{
|
TwitchEmoteOccurence emoteOccurence{
|
||||||
start, app->emotes->twitch.getOrCreateEmote(id, name), name};
|
start, end, app->emotes->twitch.getOrCreateEmote(id, name), name};
|
||||||
if (std::get<1>(tup) == nullptr)
|
if (emoteOccurence.ptr == nullptr)
|
||||||
{
|
{
|
||||||
qDebug() << "nullptr" << std::get<2>(tup).string;
|
qDebug() << "nullptr" << emoteOccurence.name.string;
|
||||||
}
|
}
|
||||||
vec.push_back(std::move(tup));
|
vec.push_back(std::move(emoteOccurence));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,13 @@ using EmotePtr = std::shared_ptr<const Emote>;
|
||||||
class Channel;
|
class Channel;
|
||||||
class TwitchChannel;
|
class TwitchChannel;
|
||||||
|
|
||||||
|
struct TwitchEmoteOccurence {
|
||||||
|
int start;
|
||||||
|
int end;
|
||||||
|
EmotePtr ptr;
|
||||||
|
EmoteName name;
|
||||||
|
};
|
||||||
|
|
||||||
class TwitchMessageBuilder : public SharedMessageBuilder
|
class TwitchMessageBuilder : public SharedMessageBuilder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -52,19 +59,17 @@ private:
|
||||||
void parseMessageID();
|
void parseMessageID();
|
||||||
void parseRoomID();
|
void parseRoomID();
|
||||||
void appendUsername();
|
void appendUsername();
|
||||||
void runIgnoreReplaces(
|
|
||||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> &twitchEmotes);
|
void runIgnoreReplaces(std::vector<TwitchEmoteOccurence> &twitchEmotes);
|
||||||
|
|
||||||
boost::optional<EmotePtr> getTwitchBadge(const Badge &badge);
|
boost::optional<EmotePtr> getTwitchBadge(const Badge &badge);
|
||||||
void appendTwitchEmote(
|
void appendTwitchEmote(const QString &emote,
|
||||||
const QString &emote,
|
std::vector<TwitchEmoteOccurence> &vec,
|
||||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> &vec,
|
std::vector<int> &correctPositions);
|
||||||
std::vector<int> &correctPositions);
|
|
||||||
Outcome tryAppendEmote(const EmoteName &name);
|
Outcome tryAppendEmote(const EmoteName &name);
|
||||||
|
|
||||||
void addWords(
|
void addWords(const QStringList &words,
|
||||||
const QStringList &words,
|
const std::vector<TwitchEmoteOccurence> &twitchEmotes);
|
||||||
const std::vector<std::tuple<int, EmotePtr, EmoteName>> &twitchEmotes);
|
|
||||||
void addTextOrEmoji(EmotePtr emote) override;
|
void addTextOrEmoji(EmotePtr emote) override;
|
||||||
void addTextOrEmoji(const QString &value) override;
|
void addTextOrEmoji(const QString &value) override;
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,8 @@ void Window::addCustomTitlebarButtons()
|
||||||
void Window::addDebugStuff()
|
void Window::addDebugStuff()
|
||||||
{
|
{
|
||||||
#ifdef C_DEBUG
|
#ifdef C_DEBUG
|
||||||
std::vector<QString> cheerMessages, subMessages, miscMessages, linkMessages;
|
std::vector<QString> cheerMessages, subMessages, miscMessages, linkMessages,
|
||||||
|
emoteTestMessages;
|
||||||
|
|
||||||
cheerMessages = getSampleCheerMessage();
|
cheerMessages = getSampleCheerMessage();
|
||||||
auto validLinks = getValidLinks();
|
auto validLinks = getValidLinks();
|
||||||
|
@ -222,6 +223,14 @@ void Window::addDebugStuff()
|
||||||
const char *channelRewardMessage2 = "{ \"type\": \"MESSAGE\", \"data\": { \"topic\": \"community-points-channel-v1.11148817\", \"message\": { \"type\": \"reward-redeemed\", \"data\": { \"timestamp\": \"2020-07-13T20:19:31.430785354Z\", \"redemption\": { \"id\": \"b9628798-1b4e-4122-b2a6-031658df6755\", \"user\": { \"id\": \"91800084\", \"login\": \"cranken1337\", \"display_name\": \"cranken1337\" }, \"channel_id\": \"11148817\", \"redeemed_at\": \"2020-07-13T20:19:31.345237005Z\", \"reward\": { \"id\": \"313969fe-cc9f-4a0a-83c6-172acbd96957\", \"channel_id\": \"11148817\", \"title\": \"annoying reward pogchamp\", \"prompt\": \"\", \"cost\": 3000, \"is_user_input_required\": false, \"is_sub_only\": false, \"image\": null, \"default_image\": { \"url_1x\": \"https://static-cdn.jtvnw.net/custom-reward-images/default-1.png\", \"url_2x\": \"https://static-cdn.jtvnw.net/custom-reward-images/default-2.png\", \"url_4x\": \"https://static-cdn.jtvnw.net/custom-reward-images/default-4.png\" }, \"background_color\": \"#52ACEC\", \"is_enabled\": true, \"is_paused\": false, \"is_in_stock\": true, \"max_per_stream\": { \"is_enabled\": false, \"max_per_stream\": 0 }, \"should_redemptions_skip_request_queue\": false, \"template_id\": null, \"updated_for_indicator_at\": \"2020-01-20T04:33:33.624956679Z\" }, \"status\": \"UNFULFILLED\", \"cursor\": \"Yjk2Mjg3OTgtMWI0ZS00MTIyLWIyYTYtMDMxNjU4ZGY2NzU1X18yMDIwLTA3LTEzVDIwOjE5OjMxLjM0NTIzNzAwNVo=\" } } } } }";
|
const char *channelRewardMessage2 = "{ \"type\": \"MESSAGE\", \"data\": { \"topic\": \"community-points-channel-v1.11148817\", \"message\": { \"type\": \"reward-redeemed\", \"data\": { \"timestamp\": \"2020-07-13T20:19:31.430785354Z\", \"redemption\": { \"id\": \"b9628798-1b4e-4122-b2a6-031658df6755\", \"user\": { \"id\": \"91800084\", \"login\": \"cranken1337\", \"display_name\": \"cranken1337\" }, \"channel_id\": \"11148817\", \"redeemed_at\": \"2020-07-13T20:19:31.345237005Z\", \"reward\": { \"id\": \"313969fe-cc9f-4a0a-83c6-172acbd96957\", \"channel_id\": \"11148817\", \"title\": \"annoying reward pogchamp\", \"prompt\": \"\", \"cost\": 3000, \"is_user_input_required\": false, \"is_sub_only\": false, \"image\": null, \"default_image\": { \"url_1x\": \"https://static-cdn.jtvnw.net/custom-reward-images/default-1.png\", \"url_2x\": \"https://static-cdn.jtvnw.net/custom-reward-images/default-2.png\", \"url_4x\": \"https://static-cdn.jtvnw.net/custom-reward-images/default-4.png\" }, \"background_color\": \"#52ACEC\", \"is_enabled\": true, \"is_paused\": false, \"is_in_stock\": true, \"max_per_stream\": { \"is_enabled\": false, \"max_per_stream\": 0 }, \"should_redemptions_skip_request_queue\": false, \"template_id\": null, \"updated_for_indicator_at\": \"2020-01-20T04:33:33.624956679Z\" }, \"status\": \"UNFULFILLED\", \"cursor\": \"Yjk2Mjg3OTgtMWI0ZS00MTIyLWIyYTYtMDMxNjU4ZGY2NzU1X18yMDIwLTA3LTEzVDIwOjE5OjMxLjM0NTIzNzAwNVo=\" } } } } }";
|
||||||
const char *channelRewardIRCMessage(R"(@badge-info=subscriber/43;badges=subscriber/42;color=#1E90FF;custom-reward-id=313969fe-cc9f-4a0a-83c6-172acbd96957;display-name=Cranken1337;emotes=;flags=;id=3cee3f27-a1d0-44d1-a606-722cebdad08b;mod=0;room-id=11148817;subscriber=1;tmi-sent-ts=1594756484132;turbo=0;user-id=91800084;user-type= :cranken1337!cranken1337@cranken1337.tmi.twitch.tv PRIVMSG #pajlada :wow, amazing reward)");
|
const char *channelRewardIRCMessage(R"(@badge-info=subscriber/43;badges=subscriber/42;color=#1E90FF;custom-reward-id=313969fe-cc9f-4a0a-83c6-172acbd96957;display-name=Cranken1337;emotes=;flags=;id=3cee3f27-a1d0-44d1-a606-722cebdad08b;mod=0;room-id=11148817;subscriber=1;tmi-sent-ts=1594756484132;turbo=0;user-id=91800084;user-type= :cranken1337!cranken1337@cranken1337.tmi.twitch.tv PRIVMSG #pajlada :wow, amazing reward)");
|
||||||
|
|
||||||
|
emoteTestMessages.emplace_back(R"(@badge-info=subscriber/3;badges=subscriber/3;color=#0000FF;display-name=Linkoping;emotes=25:40-44;flags=17-26:S.6;id=744f9c58-b180-4f46-bd9e-b515b5ef75c1;mod=0;room-id=11148817;subscriber=1;tmi-sent-ts=1566335866017;turbo=0;user-id=91673457;user-type= :linkoping!linkoping@linkoping.tmi.twitch.tv PRIVMSG #pajlada :Då kan du begära skadestånd och förtal Kappa)");
|
||||||
|
emoteTestMessages.emplace_back(R"(@badge-info=subscriber/1;badges=subscriber/0;color=;display-name=jhoelsc;emotes=301683486:46-58,60-72,74-86/301683544:88-100;flags=0-4:S.6;id=1f1afcdd-d94c-4699-b35f-d214deb1e11a;mod=0;room-id=11148817;subscriber=1;tmi-sent-ts=1588640587462;turbo=0;user-id=505763008;user-type= :jhoelsc!jhoelsc@jhoelsc.tmi.twitch.tv PRIVMSG #pajlada :pensé que no habría directo que bueno que si staryuukiLove staryuukiLove staryuukiLove staryuukiBits)");
|
||||||
|
emoteTestMessages.emplace_back(R"(@badge-info=subscriber/34;badges=moderator/1,subscriber/24;color=#FF0000;display-name=테스트계정420;emotes=41:6-13,16-23;flags=;id=97c28382-e8d2-45a0-bb5d-2305fc4ef139;mod=1;room-id=11148817;subscriber=1;tmi-sent-ts=1590922036771;turbo=0;user-id=117166826;user-type=mod :testaccount_420!testaccount_420@testaccount_420.tmi.twitch.tv PRIVMSG #pajlada :-tags Kreygasm, Kreygasm)");
|
||||||
|
emoteTestMessages.emplace_back(R"(@badge-info=subscriber/34;badges=moderator/1,subscriber/24;color=#FF0000;display-name=테스트계정420;emotes=25:24-28/41:6-13,15-22;flags=;id=5a36536b-a952-43f7-9c41-88c829371b7a;mod=1;room-id=11148817;subscriber=1;tmi-sent-ts=1590922039721;turbo=0;user-id=117166826;user-type=mod :testaccount_420!testaccount_420@testaccount_420.tmi.twitch.tv PRIVMSG #pajlada :-tags Kreygasm,Kreygasm Kappa (no space then space))");
|
||||||
|
emoteTestMessages.emplace_back(R"(@badge-info=subscriber/34;badges=moderator/1,subscriber/24;color=#FF0000;display-name=테스트계정420;emotes=25:6-10/1902:12-16/88:18-25;flags=;id=aed9e67e-f8cd-493e-aa6b-da054edd7292;mod=1;room-id=11148817;subscriber=1;tmi-sent-ts=1590922042881;turbo=0;user-id=117166826;user-type=mod :testaccount_420!testaccount_420@testaccount_420.tmi.twitch.tv PRIVMSG #pajlada :-tags Kappa.Keepo.PogChamp.extratext (3 emotes with extra text))");
|
||||||
|
emoteTestMessages.emplace_back(R"(@badge-info=;badges=moderator/1,partner/1;color=#5B99FF;display-name=StreamElements;emotes=86:30-39/822112:73-79;flags=22-27:S.5;id=03c3eec9-afd1-4858-a2e0-fccbf6ad8d1a;mod=1;room-id=11148817;subscriber=0;tmi-sent-ts=1588638345928;turbo=0;user-id=100135110;user-type=mod :streamelements!streamelements@streamelements.tmi.twitch.tv PRIVMSG #pajlada :╔ACTION A LOJA AINDA NÃO ESTÁ PRONTA BibleThump , AGUARDE... NOVIDADES EM BREVE FortOne╔)");
|
||||||
|
emoteTestMessages.emplace_back(R"(@badge-info=subscriber/20;badges=moderator/1,subscriber/12;color=#19E6E6;display-name=randers;emotes=25:39-43;flags=;id=3ea97f01-abb2-4acf-bdb8-f52e79cd0324;mod=1;room-id=11148817;subscriber=1;tmi-sent-ts=1588837097115;turbo=0;user-id=40286300;user-type=mod :randers!randers@randers.tmi.twitch.tv PRIVMSG #pajlada :Då kan du begära skadestånd och förtal Kappa)");
|
||||||
|
emoteTestMessages.emplace_back(R"(@badge-info=subscriber/34;badges=moderator/1,subscriber/24;color=#FF0000;display-name=테스트계정420;emotes=41:6-13,15-22;flags=;id=a3196c7e-be4c-4b49-9c5a-8b8302b50c2a;mod=1;room-id=11148817;subscriber=1;tmi-sent-ts=1590922213730;turbo=0;user-id=117166826;user-type=mod :testaccount_420!testaccount_420@testaccount_420.tmi.twitch.tv PRIVMSG #pajlada :-tags Kreygasm,Kreygasm (no space))");
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
createWindowShortcut(this, "F6", [=] {
|
createWindowShortcut(this, "F6", [=] {
|
||||||
|
@ -268,6 +277,13 @@ void Window::addDebugStuff()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
createWindowShortcut(this, "F11", [=] {
|
||||||
|
const auto &messages = emoteTestMessages;
|
||||||
|
static int index = 0;
|
||||||
|
const auto &msg = messages[index++ % messages.size()];
|
||||||
|
getApp()->twitch.server->addFakeMessage(msg);
|
||||||
|
});
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue