-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Commands Editor: Add field for redemption trigger #170
Labels
bug
Something isn't working
Comments
Can I query for the channel's list of redemptions and populate a list in real-time? |
This is suspended since I dropped Twitch affiliate. |
diff --git a/bot.cpp b/bot.cpp
index 2df34aa..b99ca3b 100644
--- a/bot.cpp
+++ b/bot.cpp
@@ -46,11 +46,12 @@ const char *TWITCH_API_OPERATION_EMOTE_ONLY="emote only";
const char *TWITCH_API_OPERATION_STREAM_TITLE="stream title";
const char *TWITCH_API_OPERATION_STREAM_CATEGORY="stream category";
const char *TWITCH_API_OPERATION_LOAD_BADGES="badges";
-const char *TWITCH_API_OPERATION_SHOUTOUT="shoutout";
+const char *TWITCH_API_OPERATION_FETCH_REDEMPTIONS="redemption list";
const char *TWITCH_API_ERROR_TEMPLATE_INCOMPLETE="Response from requesting %1 was incomplete";
const char *TWITCH_API_ERROR_TEMPLATE_UNKNOWN="Something went wrong obtaining %1";
const char *TWITCH_API_ERROR_TEMPLATE_JSON_PARSE="Error parsing %1 JSON: %2";
const char *TWITCH_API_ERROR_AUTH="Auth token or client ID missing or invalid";
+const char *TWITCH_API_ERROR_SERVER="Twitch choked";
const char16_t *CHAT_BADGE_BROADCASTER=u"broadcaster";
const char16_t *CHAT_BADGE_MODERATOR=u"moderator";
const char16_t *CHAT_TAG_DISPLAY_NAME=u"display-name";
@@ -136,6 +137,11 @@ Bot::Bot(Music::Player &musicPlayer,Security &security,QObject *parent) : QObjec
connect(&vibeKeeper,&Music::Player::Print,this,&Bot::Print);
}
+void Bot::Initialize()
+{
+ FetchRedemptionList();
+}
+
void Bot::DeclareCommand(const Command &&command,NativeCommandFlag flag)
{
commands.insert({{command.Name(),command}});
@@ -606,6 +612,61 @@ void Bot::RestoreMusic()
vibeKeeper.DuckVolume(false);
}
+void Bot::FetchRedemptionList()
+{
+ Network::Request::Send({Twitch::Endpoint(Twitch::ENDPOINT_REDEMPTION_LIST)},Network::Method::GET,[this](QNetworkReply *reply) {
+ switch (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt())
+ {
+ case 400:
+ emit Print(u"Missing information or too many IDs specified"_s,TWITCH_API_OPERATION_FETCH_REDEMPTIONS);
+ return;
+ case 401:
+ emit Print(TWITCH_API_ERROR_AUTH,TWITCH_API_OPERATION_FETCH_REDEMPTIONS);
+ return;
+ case 403:
+ emit Print(u"The broadcaster does not qualify for redemptions"_s,TWITCH_API_OPERATION_FETCH_REDEMPTIONS);
+ return;
+ case 404:
+ emit Print(u"Specified redemptions were not found"_s,TWITCH_API_OPERATION_FETCH_REDEMPTIONS);
+ return;
+ case 500:
+ emit Print(TWITCH_API_ERROR_SERVER,TWITCH_API_OPERATION_FETCH_REDEMPTIONS);
+ return;
+ }
+
+ if (reply->error())
+ {
+ emit Print(u"Failed to obtain list of redemptions for unknown reason"_s,TWITCH_API_OPERATION_FETCH_REDEMPTIONS);
+ return;
+ }
+
+ const JSON::ParseResult parsedJSON=JSON::Parse(reply->readAll());
+ if (!parsedJSON)
+ {
+ emit Print(QString(TWITCH_API_ERROR_TEMPLATE_JSON_PARSE).arg(TWITCH_API_OPERATION_FETCH_REDEMPTIONS,parsedJSON.error));
+ return;
+ }
+
+ const QJsonObject object=parsedJSON().object();
+ auto jsonFieldData=object.find(JSON::Keys::DATA);
+ if (jsonFieldData == object.end()) return;
+ QStringList redemptionNames;
+ for (const QJsonValue &redemptions : jsonFieldData->toArray())
+ {
+ const QJsonObject objectRedemption=redemptions.toObject();
+ auto jsonFieldRedemptionName=objectRedemption.find("title");
+ if (jsonFieldRedemptionName == objectRedemption.end()) continue;
+ redemptionNames.append(jsonFieldRedemptionName->toString());
+ }
+ emit RedemptionList(redemptionNames);
+ },{
+ {QUERY_PARAMETER_BROADCASTER_ID,security.AdministratorID()}
+ },{
+ {NETWORK_HEADER_AUTHORIZATION,security.Bearer(security.OAuthToken())},
+ {NETWORK_HEADER_CLIENT_ID,security.ClientID()}
+ });
+}
+
void Bot::DispatchArrival(const QString &login)
{
if (auto viewer=viewers.find(login); viewer != viewers.end())
@@ -1103,6 +1164,8 @@ void Bot::DispatchShoutout(Command command)
void Bot::DispatchShoutout(const QString &streamer)
{
+ static const char *TWITCH_API_OPERATION_SHOUTOUT="shoutout";
+
Viewer::Remote *profile=new Viewer::Remote(security,streamer);
connect(profile,&Viewer::Remote::Recognized,profile,[this](const Viewer::Local &profile) {
// native Twitch shoutout
diff --git a/bot.h b/bot.h
index d9c4d79..a0b68ed 100644
--- a/bot.h
+++ b/bot.h
@@ -133,6 +133,7 @@ protected:
void AdjustVibeVolume(Command command);
void StreamTitle(const QString &title);
void StreamCategory(const QString &category);
+ void FetchRedemptionList();
signals:
void Print(const QString &message,const QString operation=QString(),const QString subsystem=QString("bot core"));
void ChatMessage(std::shared_ptr<Chat::Message> message);
@@ -160,7 +161,9 @@ signals:
void AnnounceTextWall(const QString &message,const QString &audioPath);
void AnnounceDeniedCommand(const QString &videoPath);
void Welcomed(const QString &user);
+ void RedemptionList(const QStringList &redemptions);
public slots:
+ void Initialize();
void ParseChatMessage(const QString &prefix,const QString &source,const QStringList ¶meters,const QString &message);
void DispatchCommandViaSubsystem(JSON::SignalPayload *response,const QString &name,const QString &login);
void Ping();
diff --git a/main.cpp b/main.cpp
index 89ecd6e..4234385 100644
--- a/main.cpp
+++ b/main.cpp
@@ -250,6 +250,9 @@ int main(int argc,char *argv[])
celeste.connect(&celeste,&Bot::Pulse,&pulsar,QOverload<const QString&,const QString&>::of(&Pulsar::Pulse));
celeste.connect(&celeste,&Bot::Welcomed,&metrics,&UI::Metrics::Dialog::Acknowledged);
celeste.connect(&celeste,&Bot::Panic,&window,&Window::ShowPanicText);
+ celeste.connect(&celeste,&Bot::RedemptionList,&celeste,[](const QStringList &redemptionNames) {
+ UI::Commands::Entry::redemptionNames=redemptionNames;
+ });
celeste.connect(&celeste,&Bot::Panic,&celeste,[&celeste]() {
celeste.disconnect();
});
@@ -300,6 +303,7 @@ int main(int argc,char *argv[])
});
channel->connect(channel,&Channel::Denied,&security,&Security::AuthorizeUser);
security.connect(&security,&Security::Initialized,channel,&Channel::Connect);
+ security.connect(&security,&Security::Initialized,&celeste,&Bot::Initialize);
application.connect(&application,&QApplication::aboutToQuit,[&log,&socket,channel]() {
socket.connect(&socket,&IRCSocket::disconnected,&log,&Log::Archive);
channel->disconnect(); // stops attempting to reconnect by removing all connections to signals
diff --git a/security.cpp b/security.cpp
index 92b65d4..73d2f67 100644
--- a/security.cpp
+++ b/security.cpp
@@ -231,7 +231,7 @@ void Security::ObtainAdministratorProfile()
Viewer::Remote *profile=new Viewer::Remote(*this,settingAdministrator);
connect(profile,&Viewer::Remote::Recognized,profile,[this](Viewer::Local profile) {
administratorID=profile.ID();
- emit Initialize();
+ Initialize();
});
connect(profile,&Viewer::Remote::Unrecognized,this,[this]() {
AuthorizeUser();
diff --git a/security.h b/security.h
index f96024d..71fbd5f 100644
--- a/security.h
+++ b/security.h
@@ -53,6 +53,7 @@ private:
bool tokensInitialized;
QTimer tokenValidationTimer;
bool authorizing;
+ void Initialize();
signals:
void TokenRequestFailed();
void Listening();
@@ -66,5 +67,4 @@ private slots:
void RewireConnected();
void RewireError(QMqttClient::ClientError error);
void RewireMessage(QMqttMessage messasge);
- void Initialize();
};
diff --git a/twitch.h b/twitch.h
index 2692d15..8b65856 100644
--- a/twitch.h
+++ b/twitch.h
@@ -15,6 +15,7 @@ namespace Twitch
inline const char *ENDPOINT_BADGES="chat/badges/global";
inline const char *ENDPOINT_SHOUTOUTS="chat/shoutouts";
inline const char *ENDPOINT_USERS="users";
+ inline const char *ENDPOINT_REDEMPTION_LIST="channel_points/custom_rewards";
inline const char *ENDPOINT_EVENTSUB="eventsub/subscriptions";
inline const char *ENDPOINT_EVENTSUB_SUBSCRIPTIONS="eventsub/subscriptions";
diff --git a/widgets.cpp b/widgets.cpp
index 1a45f06..8785328 100644
--- a/widgets.cpp
+++ b/widgets.cpp
@@ -310,6 +310,8 @@ namespace UI
QDialog::hideEvent(event);
}
+ QStringList Entry::redemptionNames;
+
Entry::Entry(Feedback::Error &errorReport,QWidget *parent) : QWidget(parent),
layout(this),
details(this),
@@ -325,6 +327,7 @@ namespace UI
random(u"Choose Random Media"_s,std::bind_front(&Entry::SetUpRandomCheckBox,this),&details),
duplicates(u"Allow Duplicates"_s,std::bind_front(&Entry::SetUpDuplicatesCheckBox,this),&details),
protect(u"Protect"_s,std::bind_front(&Entry::SetUpProtectCheckBox,this),&details),
+ redemption(u"Redemption"_s,std::bind_front(&Entry::SetUpRedemptionList,this),&details),
message(u"Message"_s,std::bind_front(&Entry::SetUpMessageTextEdit,this),&details),
errorReport(errorReport)
{
@@ -531,6 +534,7 @@ namespace UI
protect.Hide();
duplicates.Hide();
random.Hide();
+ redemption.Hide();
message.Hide();
browse.Hide();
aliases.Hide();
@@ -546,6 +550,7 @@ namespace UI
protect.Show();
duplicates.Show();
random.Show();
+ redemption.Show();
message.Show();
browse.Show();
aliases.Show();
@@ -629,6 +634,14 @@ namespace UI
detailsLayout.addWidget(widget,3,3,1,1);
}
+ void Entry::SetUpRedemptionList(QComboBox *widget)
+ {
+ widget->setEditable(true);
+ widget->lineEdit()->setPlaceholderText("Redemption");
+ widget->addItems(redemptionNames);
+ detailsLayout.addWidget(widget,4,0,1,4);
+ }
+
void Entry::SetUpMessageTextEdit(QTextEdit *widget)
{
widget->setPlaceholderText(u"Message to display in announcement"_s);
@@ -637,7 +650,7 @@ namespace UI
connect(widget,&QTextEdit::textChanged,this,&Entry::ValidateMessage);
connect(widget,&QTextEdit::textChanged,this,&Entry::UpdateMessage);
widget->viewport()->installEventFilter(this);
- detailsLayout.addWidget(widget,4,0,1,4);
+ detailsLayout.addWidget(widget,5,0,1,4);
}
void Entry::SetUpBrowseButton(QPushButton *widget)
diff --git a/widgets.h b/widgets.h
index e1e3f7a..c26967c 100644
--- a/widgets.h
+++ b/widgets.h
@@ -343,6 +343,7 @@ namespace UI
QString Message() const;
bool Protected() const;
void ToggleFold();
+ static QStringList redemptionNames;
protected:
QGridLayout layout;
QFrame details;
@@ -358,6 +359,7 @@ namespace UI
EphemeralWidget<QCheckBox> random;
EphemeralWidget<QCheckBox> duplicates;
EphemeralWidget<QCheckBox> protect;
+ EphemeralWidget<QComboBox> redemption;
EphemeralWidget<QTextEdit> message;
Feedback::Error &errorReport;
void UpdateName();
@@ -380,6 +382,7 @@ namespace UI
void SetUpProtectCheckBox(QCheckBox *widget);
void SetUpRandomCheckBox(QCheckBox *widget);
void SetUpDuplicatesCheckBox(QCheckBox *widget);
+ void SetUpRedemptionList(QComboBox *widget);
void SetUpMessageTextEdit(QTextEdit *widget);
void SetUpBrowseButton(QPushButton *widget);
void SetUpAliasesButton(QPushButton *widget); It appears I already had a POC for this. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add a text field that allows entering the redemption name for commands that are triggered by redemptions.
The text was updated successfully, but these errors were encountered: