feat: add /endpoll and /cancelpoll commands for broadcasters (#6605)

Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
iProdigy
2025-11-29 14:12:21 -06:00
committed by GitHub
parent e06021293c
commit b9446990a7
7 changed files with 352 additions and 1 deletions
+97
View File
@@ -3276,6 +3276,103 @@ void Helix::createPoll(QString broadcasterID, QString title,
.execute();
}
void Helix::getPolls(const QString broadcasterID, QStringList ids,
const int first, const QString after,
ResultCallback<HelixPolls> successCallback,
FailureCallback<QString> failureCallback)
{
QUrlQuery urlQuery;
urlQuery.addQueryItem("broadcaster_id", broadcasterID);
urlQuery.addQueryItem("first", QString::number(first));
if (!after.isEmpty())
{
urlQuery.addQueryItem("after", after);
}
for (const auto &id : ids)
{
urlQuery.addQueryItem("id", id);
}
this->makeGet("polls", urlQuery)
.onSuccess([successCallback](const auto &result) {
if (result.status() != 200)
{
qCWarning(chatterinoTwitch)
<< "Success result for getting polls was "
<< result.formatError() << "but we expected it to be 200";
}
const auto response = result.parseJson();
successCallback(HelixPolls(response));
})
.onError([failureCallback](const auto &result) -> void {
if (!result.status())
{
failureCallback(result.formatError());
return;
}
auto obj = result.parseJson();
auto message = obj.value("message").toString();
if (!message.isEmpty())
{
failureCallback(message);
}
else
{
failureCallback(result.formatError());
}
})
.execute();
}
void Helix::endPoll(const QString broadcasterID, const QString id,
const bool immediatelyHide,
ResultCallback<HelixPoll> successCallback,
FailureCallback<QString> failureCallback)
{
QJsonObject payload;
payload.insert("broadcaster_id", broadcasterID);
payload.insert("id", id);
payload.insert("status", immediatelyHide ? "ARCHIVED" : "TERMINATED");
this->makePatch("polls", {})
.json(payload)
.onSuccess([successCallback](const NetworkResult &result) {
if (result.status() != 200)
{
qCWarning(chatterinoTwitch)
<< "Success result for ending a poll was "
<< result.formatError() << "but we expected it to be 200";
}
const auto response = result.parseJson();
const auto data = HelixPolls(response);
successCallback(data.polls.front());
})
.onError([failureCallback](const NetworkResult &result) -> void {
if (!result.status())
{
failureCallback(result.formatError());
return;
}
const auto obj = result.parseJson();
const auto message = obj.value("message").toString();
if (!message.isEmpty())
{
failureCallback(message);
}
else
{
failureCallback(result.formatError());
}
})
.execute();
}
void Helix::createPrediction(const QString broadcasterID, const QString title,
QStringList outcomes,
const std::chrono::seconds duration,
+71
View File
@@ -464,6 +464,55 @@ struct HelixSendMessageArgs {
QString replyParentMessageID;
};
struct HelixPollChoice {
QString id;
QString title;
int votes;
explicit HelixPollChoice(const QJsonObject &jsonObject)
: id(jsonObject.value("id").toString())
, title(jsonObject.value("title").toString())
, votes(jsonObject.value("votes").toInt())
{
}
};
struct HelixPoll {
QString id;
QString title;
std::vector<HelixPollChoice> choices;
QString status;
explicit HelixPoll(const QJsonObject &jsonObject)
: id(jsonObject.value("id").toString())
, title(jsonObject.value("title").toString())
, status(jsonObject.value("status").toString())
{
for (const auto &data = jsonObject.value("choices").toArray();
const auto &c : data)
{
HelixPollChoice choice(c.toObject());
this->choices.push_back(choice);
}
}
};
struct HelixPolls {
std::vector<HelixPoll> polls;
HelixPolls() = default;
explicit HelixPolls(const QJsonObject &jsonObject)
{
for (const auto &data = jsonObject.value("data").toArray();
const auto &p : data)
{
HelixPoll poll(p.toObject());
this->polls.push_back(poll);
}
}
};
enum class HelixAnnouncementColor {
Blue,
Green,
@@ -1218,6 +1267,18 @@ public:
int pointsPerVote, ResultCallback<> successCallback,
FailureCallback<QString> failureCallback) = 0;
/// https://dev.twitch.tv/docs/api/reference#get-polls
virtual void getPolls(QString broadcasterID, QStringList ids, int first,
QString after,
ResultCallback<HelixPolls> successCallback,
FailureCallback<QString> failureCallback) = 0;
/// https://dev.twitch.tv/docs/api/reference#end-poll
virtual void endPoll(QString broadcasterID, QString id,
bool immediatelyHide,
ResultCallback<HelixPoll> successCallback,
FailureCallback<QString> failureCallback) = 0;
/// https://dev.twitch.tv/docs/api/reference#create-prediction
virtual void createPrediction(QString broadcasterID, QString title,
QStringList choices,
@@ -1586,6 +1647,16 @@ public:
ResultCallback<> successCallback,
FailureCallback<QString> failureCallback) final;
/// https://dev.twitch.tv/docs/api/reference#get-polls
void getPolls(QString broadcasterID, QStringList ids, int first,
QString after, ResultCallback<HelixPolls> successCallback,
FailureCallback<QString> failureCallback) final;
/// https://dev.twitch.tv/docs/api/reference#end-poll
void endPoll(QString broadcasterID, QString id, bool immediatelyHide,
ResultCallback<HelixPoll> successCallback,
FailureCallback<QString> failureCallback) final;
/// https://dev.twitch.tv/docs/api/reference#create-prediction
void createPrediction(QString broadcasterID, QString title,
QStringList outcomes, std::chrono::seconds duration,