Fix chatters recursion not working (#4114)

This commit is contained in:
pajlada 2022-11-05 12:56:17 +01:00 committed by GitHub
parent e531161c7f
commit 2ec26f57cc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 139 additions and 68 deletions

View file

@ -70,7 +70,7 @@
- Minor: Migrated /commercial to Helix API. (#4094)
- Minor: Added stream titles to windows live toast notifications. (#1297)
- Minor: Make menus and placeholders display appropriate custom key combos. (#4045)
- Minor: Migrated /chatters to Helix API. (#4088, #4097)
- Minor: Migrated /chatters to Helix API. (#4088, #4097, #4114)
- Minor: Migrated /mods to Helix API. (#4103)
- Minor: Add settings tooltips. (#3437)
- Bugfix: Connection to Twitch PubSub now recovers more reliably. (#3643, #3716)

View file

@ -878,60 +878,109 @@ void CommandController::initialize(Settings &, Paths &paths)
return "";
});
this->registerCommand("/chatters", [](const auto &words, auto channel) {
auto formatError = [](HelixGetChattersError error, QString message) {
using Error = HelixGetChattersError;
auto formatChattersError = [](HelixGetChattersError error,
QString message) {
using Error = HelixGetChattersError;
QString errorMessage = QString("Failed to get chatter count: ");
QString errorMessage = QString("Failed to get chatter count: ");
switch (error)
{
case Error::Forwarded: {
errorMessage += message;
}
break;
case Error::UserMissingScope: {
errorMessage += "Missing required scope. "
"Re-login with your "
"account and try again.";
}
break;
case Error::UserNotAuthorized: {
errorMessage += "You must have moderator permissions to "
"use this command.";
}
break;
case Error::Unknown: {
errorMessage += "An unknown error has occurred.";
}
break;
switch (error)
{
case Error::Forwarded: {
errorMessage += message;
}
return errorMessage;
};
break;
auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
case Error::UserMissingScope: {
errorMessage += "Missing required scope. "
"Re-login with your "
"account and try again.";
}
break;
case Error::UserNotAuthorized: {
errorMessage += "You must have moderator permissions to "
"use this command.";
}
break;
case Error::Unknown: {
errorMessage += "An unknown error has occurred.";
}
break;
}
return errorMessage;
};
this->registerCommand(
"/chatters", [formatChattersError](const auto &words, auto channel) {
auto *twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
if (twitchChannel == nullptr)
{
channel->addMessage(makeSystemMessage(
"The /chatters command only works in Twitch Channels"));
return "";
}
// Refresh chatter list via helix api for mods
getHelix()->getChatters(
twitchChannel->roomId(),
getApp()->accounts->twitch.getCurrent()->getUserId(), 1,
[channel](auto result) {
channel->addMessage(makeSystemMessage(
QString("Chatter count: %1")
.arg(localizeNumbers(result.total))));
},
[channel, formatChattersError](auto error, auto message) {
auto errorMessage = formatChattersError(error, message);
channel->addMessage(makeSystemMessage(errorMessage));
});
return "";
});
this->registerCommand("/test-chatters", [formatChattersError](
const auto & /*words*/,
auto channel) {
auto *twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
if (twitchChannel == nullptr)
{
channel->addMessage(makeSystemMessage(
"The /chatters command only works in Twitch Channels"));
"The /test-chatters command only works in Twitch Channels"));
return "";
}
// Refresh chatter list via helix api for mods
getHelix()->getChatters(
twitchChannel->roomId(),
getApp()->accounts->twitch.getCurrent()->getUserId(), 1,
[channel](auto result) {
channel->addMessage(
makeSystemMessage(QString("Chatter count: %1")
.arg(localizeNumbers(result.total))));
getApp()->accounts->twitch.getCurrent()->getUserId(), 5000,
[channel, twitchChannel](auto result) {
QStringList entries;
for (const auto &username : result.chatters)
{
entries << username;
}
QString prefix = "Chatters ";
if (result.total > 5000)
{
prefix += QString("(5000/%1):").arg(result.total);
}
else
{
prefix += QString("(%1):").arg(result.total);
}
MessageBuilder builder;
TwitchMessageBuilder::listOfUsersSystemMessage(
prefix, entries, twitchChannel, &builder);
channel->addMessage(builder.release());
},
[channel, formatError](auto error, auto message) {
auto errorMessage = formatError(error, message);
[channel, formatChattersError](auto error, auto message) {
auto errorMessage = formatChattersError(error, message);
channel->addMessage(makeSystemMessage(errorMessage));
});

View file

@ -12,6 +12,8 @@ using namespace chatterino;
static constexpr auto NUM_MODERATORS_TO_FETCH_PER_REQUEST = 100;
static constexpr auto NUM_CHATTERS_TO_FETCH = 1000;
} // namespace
namespace chatterino {
@ -1790,6 +1792,37 @@ void Helix::updateChatSettings(
.execute();
}
void Helix::onFetchChattersSuccess(
std::shared_ptr<HelixChatters> finalChatters, QString broadcasterID,
QString moderatorID, int maxChattersToFetch,
ResultCallback<HelixChatters> successCallback,
FailureCallback<HelixGetChattersError, QString> failureCallback,
HelixChatters chatters)
{
qCDebug(chatterinoTwitch)
<< "Fetched" << chatters.chatters.size() << "chatters";
finalChatters->chatters.merge(chatters.chatters);
finalChatters->total = chatters.total;
if (chatters.cursor.isEmpty() ||
finalChatters->chatters.size() >= maxChattersToFetch)
{
// Done paginating
successCallback(*finalChatters);
return;
}
this->fetchChatters(
broadcasterID, moderatorID, NUM_CHATTERS_TO_FETCH, chatters.cursor,
[=](auto chatters) {
this->onFetchChattersSuccess(
finalChatters, broadcasterID, moderatorID, maxChattersToFetch,
successCallback, failureCallback, chatters);
},
failureCallback);
}
// https://dev.twitch.tv/docs/api/reference#get-chatters
void Helix::fetchChatters(
QString broadcasterID, QString moderatorID, int first, QString after,
@ -2191,36 +2224,17 @@ void Helix::getChatters(
ResultCallback<HelixChatters> successCallback,
FailureCallback<HelixGetChattersError, QString> failureCallback)
{
static const auto NUM_CHATTERS_TO_FETCH = 1000;
auto finalChatters = std::make_shared<HelixChatters>();
auto fetchSuccess = [this, broadcasterID, moderatorID, maxChattersToFetch,
finalChatters, successCallback,
failureCallback](auto fs) {
return [=](auto chatters) {
qCDebug(chatterinoTwitch)
<< "Fetched" << chatters.chatters.size() << "chatters";
finalChatters->chatters.merge(chatters.chatters);
finalChatters->total = chatters.total;
if (chatters.cursor.isEmpty() ||
finalChatters->chatters.size() >= maxChattersToFetch)
{
// Done paginating
successCallback(*finalChatters);
return;
}
this->fetchChatters(broadcasterID, moderatorID,
NUM_CHATTERS_TO_FETCH, chatters.cursor, fs,
failureCallback);
};
};
// Initiate the recursive calls
this->fetchChatters(broadcasterID, moderatorID, NUM_CHATTERS_TO_FETCH, "",
fetchSuccess(fetchSuccess), failureCallback);
this->fetchChatters(
broadcasterID, moderatorID, NUM_CHATTERS_TO_FETCH, "",
[=](auto chatters) {
this->onFetchChattersSuccess(
finalChatters, broadcasterID, moderatorID, maxChattersToFetch,
successCallback, failureCallback, chatters);
},
failureCallback);
}
// https://dev.twitch.tv/docs/api/reference#get-moderators

View file

@ -1206,6 +1206,14 @@ protected:
FailureCallback<HelixUpdateChatSettingsError, QString> failureCallback)
final;
// Recursive boy
void onFetchChattersSuccess(
std::shared_ptr<HelixChatters> finalChatters, QString broadcasterID,
QString moderatorID, int maxChattersToFetch,
ResultCallback<HelixChatters> successCallback,
FailureCallback<HelixGetChattersError, QString> failureCallback,
HelixChatters chatters);
// Get chatters list - This method is what actually runs the API request
// https://dev.twitch.tv/docs/api/reference#get-chatters
void fetchChatters(