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: 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: 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 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: 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: Modify the emote parsing to handle some edge-cases with dots and stuff (#1704, #1714)
|
||||
|
||||
## 2.2.0
|
||||
|
||||
|
|
|
@ -336,7 +336,7 @@ void TwitchIrcServer::onMessageSendRequested(TwitchChannel *channel,
|
|||
if (this->lastErrorTimeSpeed_ + 30s < now)
|
||||
{
|
||||
auto errorMessage =
|
||||
makeSystemMessage("sending messages too fast");
|
||||
makeSystemMessage("You are sending messages too quickly.");
|
||||
|
||||
channel->addMessage(errorMessage);
|
||||
|
||||
|
@ -357,7 +357,7 @@ void TwitchIrcServer::onMessageSendRequested(TwitchChannel *channel,
|
|||
if (this->lastErrorTimeAmount_ + 30s < now)
|
||||
{
|
||||
auto errorMessage =
|
||||
makeSystemMessage("sending too many messages");
|
||||
makeSystemMessage("You are sending too many messages.");
|
||||
|
||||
channel->addMessage(errorMessage);
|
||||
|
||||
|
|
|
@ -282,7 +282,7 @@ MessagePtr TwitchMessageBuilder::build()
|
|||
}
|
||||
|
||||
// twitch emotes
|
||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> twitchEmotes;
|
||||
std::vector<TwitchEmoteOccurence> twitchEmotes;
|
||||
|
||||
iterator = this->tags.find("emotes");
|
||||
if (iterator != this->tags.end())
|
||||
|
@ -307,12 +307,11 @@ MessagePtr TwitchMessageBuilder::build()
|
|||
|
||||
std::sort(twitchEmotes.begin(), twitchEmotes.end(),
|
||||
[](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(),
|
||||
[](const auto &first, const auto &second) {
|
||||
return std::get<0>(first) ==
|
||||
std::get<0>(second);
|
||||
return first.start == second.start;
|
||||
}),
|
||||
twitchEmotes.end());
|
||||
|
||||
|
@ -339,47 +338,90 @@ MessagePtr TwitchMessageBuilder::build()
|
|||
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(
|
||||
const QStringList &words,
|
||||
const std::vector<std::tuple<int, EmotePtr, EmoteName>> &twitchEmotes)
|
||||
const std::vector<TwitchEmoteOccurence> &twitchEmotes)
|
||||
{
|
||||
auto i = int();
|
||||
auto currentTwitchEmote = twitchEmotes.begin();
|
||||
// cursor currently indicates what character index we're currently operating in the full list of words
|
||||
int cursor = 0;
|
||||
auto currentTwitchEmoteIt = twitchEmotes.begin();
|
||||
|
||||
for (auto word : words)
|
||||
{
|
||||
// check if it's a twitch emote twitch emote
|
||||
while (currentTwitchEmote != twitchEmotes.end() &&
|
||||
std::get<0>(*currentTwitchEmote) < i)
|
||||
while (doesWordContainATwitchEmote(cursor, word, twitchEmotes,
|
||||
currentTwitchEmoteIt))
|
||||
{
|
||||
++currentTwitchEmote;
|
||||
}
|
||||
if (currentTwitchEmote != twitchEmotes.end() &&
|
||||
std::get<0>(*currentTwitchEmote) == i)
|
||||
{
|
||||
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())
|
||||
auto wordEnd = cursor + word.length();
|
||||
const auto ¤tTwitchEmote = *currentTwitchEmoteIt;
|
||||
|
||||
if (currentTwitchEmote.start == cursor)
|
||||
{
|
||||
// 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);
|
||||
this->message().elements.back()->setTrailingSpace(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
++currentTwitchEmoteIt;
|
||||
|
||||
if (word.isEmpty())
|
||||
{
|
||||
// space
|
||||
cursor += 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->message().elements.back()->setTrailingSpace(false);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -389,7 +431,7 @@ void TwitchMessageBuilder::addWords(
|
|||
variant);
|
||||
}
|
||||
|
||||
i += word.size() + 1;
|
||||
cursor += word.size() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -660,36 +702,32 @@ void TwitchMessageBuilder::appendUsername()
|
|||
}
|
||||
|
||||
void TwitchMessageBuilder::runIgnoreReplaces(
|
||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> &twitchEmotes)
|
||||
std::vector<TwitchEmoteOccurence> &twitchEmotes)
|
||||
{
|
||||
auto phrases = getCSettings().ignoredMessages.readOnly();
|
||||
auto removeEmotesInRange =
|
||||
[](int pos, int len,
|
||||
std::vector<std::tuple<int, EmotePtr, EmoteName>>
|
||||
&twitchEmotes) mutable {
|
||||
auto it =
|
||||
std::partition(twitchEmotes.begin(), twitchEmotes.end(),
|
||||
[pos, len](const auto &item) {
|
||||
return !((std::get<0>(item) >= pos) &&
|
||||
std::get<0>(item) < (pos + len));
|
||||
});
|
||||
for (auto copy = it; copy != twitchEmotes.end(); ++copy)
|
||||
auto removeEmotesInRange = [](int pos, int len,
|
||||
auto &twitchEmotes) mutable {
|
||||
auto it = std::partition(
|
||||
twitchEmotes.begin(), twitchEmotes.end(),
|
||||
[pos, len](const auto &item) {
|
||||
return !((item.start >= pos) && item.start < (pos + len));
|
||||
});
|
||||
for (auto copy = it; copy != twitchEmotes.end(); ++copy)
|
||||
{
|
||||
if ((*copy).ptr == nullptr)
|
||||
{
|
||||
if (std::get<1>(*copy) == nullptr)
|
||||
{
|
||||
qDebug() << "remem nullptr" << std::get<2>(*copy).string;
|
||||
}
|
||||
qDebug() << "remem nullptr" << (*copy).name.string;
|
||||
}
|
||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> v(
|
||||
it, twitchEmotes.end());
|
||||
twitchEmotes.erase(it, twitchEmotes.end());
|
||||
return v;
|
||||
};
|
||||
}
|
||||
std::vector<TwitchEmoteOccurence> v(it, twitchEmotes.end());
|
||||
twitchEmotes.erase(it, twitchEmotes.end());
|
||||
return v;
|
||||
};
|
||||
|
||||
auto shiftIndicesAfter = [&twitchEmotes](int pos, int by) mutable {
|
||||
for (auto &item : twitchEmotes)
|
||||
{
|
||||
auto &index = std::get<0>(item);
|
||||
auto &index = item.start;
|
||||
if (index >= pos)
|
||||
{
|
||||
index += by;
|
||||
|
@ -717,8 +755,12 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
|||
{
|
||||
qDebug() << "emote null" << emote.first.string;
|
||||
}
|
||||
twitchEmotes.push_back(std::tuple<int, EmotePtr, EmoteName>{
|
||||
startIndex + pos, emote.second, emote.first});
|
||||
twitchEmotes.push_back(TwitchEmoteOccurence{
|
||||
startIndex + pos,
|
||||
startIndex + pos + emote.first.string.length(),
|
||||
emote.second,
|
||||
emote.first,
|
||||
});
|
||||
}
|
||||
}
|
||||
pos += word.length() + 1;
|
||||
|
@ -776,13 +818,13 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
|||
|
||||
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;
|
||||
}
|
||||
QRegularExpression emoteregex(
|
||||
"\\b" + std::get<2>(tup).string + "\\b",
|
||||
"\\b" + tup.name.string + "\\b",
|
||||
QRegularExpression::UseUnicodePropertiesOption);
|
||||
auto _match = emoteregex.match(midExtendedRef);
|
||||
if (_match.hasMatch())
|
||||
|
@ -790,7 +832,7 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
|||
int last = _match.lastCapturedIndex();
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -845,13 +887,13 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
|||
|
||||
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;
|
||||
}
|
||||
QRegularExpression emoteregex(
|
||||
"\\b" + std::get<2>(tup).string + "\\b",
|
||||
"\\b" + tup.name.string + "\\b",
|
||||
QRegularExpression::UseUnicodePropertiesOption);
|
||||
auto match = emoteregex.match(midExtendedRef);
|
||||
if (match.hasMatch())
|
||||
|
@ -859,7 +901,7 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
|||
int last = match.lastCapturedIndex();
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -874,8 +916,7 @@ void TwitchMessageBuilder::runIgnoreReplaces(
|
|||
}
|
||||
|
||||
void TwitchMessageBuilder::appendTwitchEmote(
|
||||
const QString &emote,
|
||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> &vec,
|
||||
const QString &emote, std::vector<TwitchEmoteOccurence> &vec,
|
||||
std::vector<int> &correctPositions)
|
||||
{
|
||||
auto app = getApp();
|
||||
|
@ -914,13 +955,13 @@ void TwitchMessageBuilder::appendTwitchEmote(
|
|||
|
||||
auto name =
|
||||
EmoteName{this->originalMessage_.mid(start, end - start + 1)};
|
||||
auto tup = std::tuple<int, EmotePtr, EmoteName>{
|
||||
start, app->emotes->twitch.getOrCreateEmote(id, name), name};
|
||||
if (std::get<1>(tup) == nullptr)
|
||||
TwitchEmoteOccurence emoteOccurence{
|
||||
start, end, app->emotes->twitch.getOrCreateEmote(id, name), name};
|
||||
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 TwitchChannel;
|
||||
|
||||
struct TwitchEmoteOccurence {
|
||||
int start;
|
||||
int end;
|
||||
EmotePtr ptr;
|
||||
EmoteName name;
|
||||
};
|
||||
|
||||
class TwitchMessageBuilder : public SharedMessageBuilder
|
||||
{
|
||||
public:
|
||||
|
@ -52,19 +59,17 @@ private:
|
|||
void parseMessageID();
|
||||
void parseRoomID();
|
||||
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);
|
||||
void appendTwitchEmote(
|
||||
const QString &emote,
|
||||
std::vector<std::tuple<int, EmotePtr, EmoteName>> &vec,
|
||||
std::vector<int> &correctPositions);
|
||||
void appendTwitchEmote(const QString &emote,
|
||||
std::vector<TwitchEmoteOccurence> &vec,
|
||||
std::vector<int> &correctPositions);
|
||||
Outcome tryAppendEmote(const EmoteName &name);
|
||||
|
||||
void addWords(
|
||||
const QStringList &words,
|
||||
const std::vector<std::tuple<int, EmotePtr, EmoteName>> &twitchEmotes);
|
||||
void addWords(const QStringList &words,
|
||||
const std::vector<TwitchEmoteOccurence> &twitchEmotes);
|
||||
void addTextOrEmoji(EmotePtr emote) override;
|
||||
void addTextOrEmoji(const QString &value) override;
|
||||
|
||||
|
|
|
@ -177,7 +177,8 @@ void Window::addCustomTitlebarButtons()
|
|||
void Window::addDebugStuff()
|
||||
{
|
||||
#ifdef C_DEBUG
|
||||
std::vector<QString> cheerMessages, subMessages, miscMessages, linkMessages;
|
||||
std::vector<QString> cheerMessages, subMessages, miscMessages, linkMessages,
|
||||
emoteTestMessages;
|
||||
|
||||
cheerMessages = getSampleCheerMessage();
|
||||
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 *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
|
||||
|
||||
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
|
||||
} // namespace chatterino
|
||||
|
||||
|
|
Loading…
Reference in a new issue