Migrated follow and unfollow methods to Helix API (#2306)

This commit is contained in:
Paweł 2020-12-22 09:55:58 +01:00 committed by GitHub
parent 89c74e03d6
commit 2f5df3db4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 118 additions and 87 deletions

View file

@ -62,6 +62,7 @@
- Bugfix: Fix a crash bug that occurred when moving splits across windows and closing the "parent tab" (#2249, #2259) - Bugfix: Fix a crash bug that occurred when moving splits across windows and closing the "parent tab" (#2249, #2259)
- Dev: Updated minimum required Qt framework version to 5.12. (#2210) - Dev: Updated minimum required Qt framework version to 5.12. (#2210)
- Dev: Migrated `Kraken::getUser` to Helix (#2260) - Dev: Migrated `Kraken::getUser` to Helix (#2260)
- Dev: Migrated `TwitchAccount::(un)followUser` from Kraken to Helix and moved it to `Helix::(un)followUser`. (#2306)
## 2.2.2 ## 2.2.2

View file

@ -313,29 +313,39 @@ void CommandController::initialize(Settings &, Paths &paths)
channel->addMessage(makeSystemMessage("Usage: /follow [user]")); channel->addMessage(makeSystemMessage("Usage: /follow [user]"));
return ""; return "";
} }
auto app = getApp();
auto user = app->accounts->twitch.getCurrent(); auto currentUser = getApp()->accounts->twitch.getCurrent();
auto target = words.at(1);
if (user->isAnon()) if (currentUser->isAnon())
{ {
channel->addMessage( channel->addMessage(
makeSystemMessage("You must be logged in to follow someone")); makeSystemMessage("You must be logged in to follow someone"));
return ""; return "";
} }
auto target = words.at(1);
getHelix()->getUserByName( getHelix()->getUserByName(
target, target,
[user, channel, target](const auto &targetUser) { [currentUser, channel, target](const auto &targetUser) {
user->followUser(targetUser.id, [channel, target]() { getHelix()->followUser(
currentUser->getUserId(), targetUser.id,
[channel, target]() {
channel->addMessage(makeSystemMessage( channel->addMessage(makeSystemMessage(
"You successfully followed " + target)); "You successfully followed " + target));
},
[channel, target]() {
channel->addMessage(makeSystemMessage(
QString("User %1 could not be followed, an unknown "
"error occured!")
.arg(target)));
}); });
}, },
[channel, target] { [channel, target] {
channel->addMessage(makeSystemMessage( channel->addMessage(
"User " + target + " could not be followed!")); makeSystemMessage(QString("User %1 could not be followed, "
"no user with that name found!")
.arg(target)));
}); });
return ""; return "";
@ -347,29 +357,35 @@ void CommandController::initialize(Settings &, Paths &paths)
channel->addMessage(makeSystemMessage("Usage: /unfollow [user]")); channel->addMessage(makeSystemMessage("Usage: /unfollow [user]"));
return ""; return "";
} }
auto app = getApp();
auto user = app->accounts->twitch.getCurrent(); auto currentUser = getApp()->accounts->twitch.getCurrent();
auto target = words.at(1);
if (user->isAnon()) if (currentUser->isAnon())
{ {
channel->addMessage( channel->addMessage(
makeSystemMessage("You must be logged in to follow someone")); makeSystemMessage("You must be logged in to follow someone"));
return ""; return "";
} }
auto target = words.at(1);
getHelix()->getUserByName( getHelix()->getUserByName(
target, target,
[user, channel, target](const auto &targetUser) { [currentUser, channel, target](const auto &targetUser) {
user->unfollowUser(targetUser.id, [channel, target]() { getHelix()->unfollowUser(
currentUser->getUserId(), targetUser.id,
[channel, target]() {
channel->addMessage(makeSystemMessage( channel->addMessage(makeSystemMessage(
"You successfully unfollowed " + target)); "You successfully unfollowed " + target));
},
[channel, target]() {
channel->addMessage(makeSystemMessage(
"An error occurred while unfollowing " + target));
}); });
}, },
[channel, target] { [channel, target] {
channel->addMessage(makeSystemMessage( channel->addMessage(makeSystemMessage(
"User " + target + " could not be followed!")); QString("User %1 could not be followed!").arg(target)));
}); });
return ""; return "";

View file

@ -290,47 +290,6 @@ void TwitchAccount::checkFollow(const QString targetUserID,
[] {}); [] {});
} }
void TwitchAccount::followUser(const QString userID,
std::function<void()> successCallback)
{
QUrl requestUrl("https://api.twitch.tv/kraken/users/" + this->getUserId() +
"/follows/channels/" + userID);
NetworkRequest(requestUrl, NetworkRequestType::Put)
.authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken())
.onSuccess([successCallback](auto result) -> Outcome {
// TODO: Properly check result of follow request
successCallback();
return Success;
})
.execute();
}
void TwitchAccount::unfollowUser(const QString userID,
std::function<void()> successCallback)
{
QUrl requestUrl("https://api.twitch.tv/kraken/users/" + this->getUserId() +
"/follows/channels/" + userID);
NetworkRequest(requestUrl, NetworkRequestType::Delete)
.authorizeTwitchV5(this->getOAuthClient(), this->getOAuthToken())
.onError([successCallback](NetworkResult result) {
if (result.status() >= 200 && result.status() <= 299)
{
successCallback();
}
})
.onSuccess([successCallback](const auto &document) -> Outcome {
successCallback();
return Success;
})
.execute();
}
std::set<TwitchUser> TwitchAccount::getIgnores() const std::set<TwitchUser> TwitchAccount::getIgnores() const
{ {
std::lock_guard<std::mutex> lock(this->ignoresMutex_); std::lock_guard<std::mutex> lock(this->ignoresMutex_);

View file

@ -98,10 +98,6 @@ public:
void checkFollow(const QString targetUserID, void checkFollow(const QString targetUserID,
std::function<void(FollowResult)> onFinished); std::function<void(FollowResult)> onFinished);
void followUser(const QString userID,
std::function<void()> successCallback);
void unfollowUser(const QString userID,
std::function<void()> successCallback);
std::set<TwitchUser> getIgnores() const; std::set<TwitchUser> getIgnores() const;

View file

@ -315,6 +315,50 @@ void Helix::getGameById(QString gameId,
failureCallback); failureCallback);
} }
void Helix::followUser(QString userId, QString targetId,
std::function<void()> successCallback,
HelixFailureCallback failureCallback)
{
QUrlQuery urlQuery;
urlQuery.addQueryItem("from_id", userId);
urlQuery.addQueryItem("to_id", targetId);
this->makeRequest("users/follows", urlQuery)
.type(NetworkRequestType::Post)
.onSuccess([successCallback](auto result) -> Outcome {
successCallback();
return Success;
})
.onError([failureCallback](auto result) {
// TODO: make better xd
failureCallback();
})
.execute();
}
void Helix::unfollowUser(QString userId, QString targetId,
std::function<void()> successCallback,
HelixFailureCallback failureCallback)
{
QUrlQuery urlQuery;
urlQuery.addQueryItem("from_id", userId);
urlQuery.addQueryItem("to_id", targetId);
this->makeRequest("users/follows", urlQuery)
.type(NetworkRequestType::Delete)
.onSuccess([successCallback](auto result) -> Outcome {
successCallback();
return Success;
})
.onError([failureCallback](auto result) {
// TODO: make better xd
failureCallback();
})
.execute();
}
NetworkRequest Helix::makeRequest(QString url, QUrlQuery urlQuery) NetworkRequest Helix::makeRequest(QString url, QUrlQuery urlQuery)
{ {
assert(!url.startsWith("/")); assert(!url.startsWith("/"));

View file

@ -184,6 +184,14 @@ public:
void getGameById(QString gameId, ResultCallback<HelixGame> successCallback, void getGameById(QString gameId, ResultCallback<HelixGame> successCallback,
HelixFailureCallback failureCallback); HelixFailureCallback failureCallback);
void followUser(QString userId, QString targetId,
std::function<void()> successCallback,
HelixFailureCallback failureCallback);
void unfollowUser(QString userId, QString targetlId,
std::function<void()> successCallback,
HelixFailureCallback failureCallback);
void update(QString clientId, QString oauthToken); void update(QString clientId, QString oauthToken);
static void initialize(); static void initialize();

View file

@ -13,23 +13,6 @@ Migration path: **Unknown**
Used in: Used in:
* `TwitchChannel::refreshTitle` to check the current stream title/game of offline channels * `TwitchChannel::refreshTitle` to check the current stream title/game of offline channels
### Follow Channel
URL: https://dev.twitch.tv/docs/v5/reference/users#follow-channel
Requires `user_follows_edit` scope
Migration path: **Unknown**
* We implement this API in `providers/twitch/TwitchAccount.cpp followUser`
### Unfollow Channel
URL: https://dev.twitch.tv/docs/v5/reference/users#unfollow-channel
Requires `user_follows_edit` scope
Migration path: **Unknown**
* We implement this API in `providers/twitch/TwitchAccount.cpp unfollowUser`
### Get Cheermotes ### Get Cheermotes
URL: https://dev.twitch.tv/docs/v5/reference/bits#get-cheermotes URL: https://dev.twitch.tv/docs/v5/reference/bits#get-cheermotes
@ -106,6 +89,24 @@ URL: https://dev.twitch.tv/docs/api/reference#get-streams
* `TwitchChannel` to get live status, game, title, and viewer count of a channel * `TwitchChannel` to get live status, game, title, and viewer count of a channel
* `NotificationController` to provide notifications for channels you might not have open in Chatterino, but are still interested in getting notifications for * `NotificationController` to provide notifications for channels you might not have open in Chatterino, but are still interested in getting notifications for
### Follow User
URL: https://dev.twitch.tv/docs/api/reference#create-user-follows
Requires `user:edit:follows` scope
* We implement this in `providers/twitch/api/Helix.cpp followUser`
Used in:
* `widgets/dialogs/UserInfoPopup.cpp` to follow a user by ticking follow checkbox in usercard
* `controllers/commands/CommandController.cpp` in /follow command
### Unfollow User
URL: https://dev.twitch.tv/docs/api/reference#delete-user-follows
Requires `user:edit:follows` scope
* We implement this in `providers/twitch/api/Helix.cpp unfollowUser`
Used in:
* `widgets/dialogs/UserInfoPopup.cpp` to unfollow a user by unticking follow checkbox in usercard
* `controllers/commands/CommandController.cpp` in /unfollow command
## TMI ## TMI
The TMI api is undocumented. The TMI api is undocumented.

View file

@ -386,8 +386,11 @@ void UserInfoPopup::installEvents()
{ {
case Qt::CheckState::Unchecked: { case Qt::CheckState::Unchecked: {
this->ui_.follow->setEnabled(false); this->ui_.follow->setEnabled(false);
currentUser->unfollowUser(this->userId_, getHelix()->unfollowUser(currentUser->getUserId(),
reenableFollowCheckbox); this->userId_,
reenableFollowCheckbox, [] {
//
});
} }
break; break;
@ -398,8 +401,11 @@ void UserInfoPopup::installEvents()
case Qt::CheckState::Checked: { case Qt::CheckState::Checked: {
this->ui_.follow->setEnabled(false); this->ui_.follow->setEnabled(false);
currentUser->followUser(this->userId_, getHelix()->followUser(currentUser->getUserId(),
reenableFollowCheckbox); this->userId_,
reenableFollowCheckbox, [] {
//
});
} }
break; break;
} }