Skip to content
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

Update @adamint's changes to make our JSONAPI responses more easily traversible #7

Merged
merged 35 commits into from
Oct 27, 2017

Conversation

21echoes
Copy link
Contributor

#4 was super awesome, but needed some help getting over the finish line.

In total, this PR moves away from the sad world of:

JSONObject userResponse = apiClient.fetchUser();
JSONObject user = userResponse.getJSONObject("data");
JSONArray included = userResponse.getJSONArray("included");
JSONObject pledge = null;
JSONObject campaign = null;
if (included != null) {
    for (int i = 0; i < included.length(); i++) {
        JSONObject object = included.getJSONObject(i);
        if (object.getString("type").equals("pledge") && object.getJSONObject("relationships").getJSONObject("creator").getJSONObject("data").getString("id").equals(creatorID)) {
            pledge = object;
            break;
        }
    }
    for (int i = 0; i < included.length(); i++) {
        JSONObject object = included.getJSONObject(i);
        if (object.getString("type").equals("campaign") && object.getJSONObject("relationships").getJSONObject("creator").getJSONObject("data").getString("id").equals(creatorID)) {
            campaign = object;
            break;
        }
    }
}

into the happy world of:

JSONAPIDocument<User> userResponse = apiClient.fetchUser();
User user = userResponse.get();

List<Pledge> pledges = user.getPledges()
if (pledges != null && pledges.size() > 0) {
    Pledge pledge = pledges.get(0);
}

Copy link
Contributor

@jrsun jrsun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewed by @kennydo and me

README.md Outdated
@@ -13,60 +13,52 @@ Get the artifact from [Maven](http://search.maven.org/#search|ga|1|g%3A%22com.pa

Step 1. Get your client_id and client_secret
---
Visit the [OAuth Documentation Page](https://www.patreon.com/oauth2/documentation)
Visit the [Patreon OAuth Platform Documentation Page](https://www.patreon.com/platform)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the docs refer to https://docs.patreon.com, we should call this the Patreon Platform Page or something. Also, this link should be https://www.patreon.com/portal or similar.

README.md Outdated
4. visit https://oss.sonatype.org/#stagingRepositories, find the latest repository, close it, then release it
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: capitalize visit

*/
public JSONAPIDocument<List<Campaign>> fetchCampaigns() throws IOException {
return converter.readDocumentCollection(
getDataStream("current_user/campaigns?include=rewards,creator,goals"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe allow passing custom include and/or fields?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

definitely want to do that, but i think it's out of scope for this PR 👍

* @return JSONAPIDocument<List<Pledge>> containing pledges & associated data
* @throws IOException Thrown when the GET request failed
*/
public JSONAPIDocument<List<Pledge>> fetchPageOfPledges(String campaignId, int pageSize, String pageCursor) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like this interface requires users who want pagination to parse out cursors from the next link, and pass back in to this method. could we hide that logic and provide an iterable interface?

it would be nice to still expose a startCursor to allow users to start iteration from a certain point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 agreed that a helper method to get the link out would be nice (it's what python does, for instance)

connection.setRequestProperty("Authorization", "Bearer ".concat(this.accessToken));
return connection.getInputStream();
} catch (IOException e) {
System.out.println(e.getMessage());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use SLF4J? ping @kennydo for example

}

public String getDefaultOauthUrl(String redirectUri) {
return "https://www.patreon.com/oauth2/authorize?response_type=code&client_id=" + clientID + "&redirect_uri=" + redirectUri;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for PatreonAPI.java urls?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be nice to use URIBuilder to construct the oauth flow urls as well, and then pass the result into Jsoup.connect

private String scope;
private String token_type;

public Token(String access_token, String refresh_token, int expires_in, String scope, String token_type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, that's what I use for parsing most PatreonAPI stuff. how are you recommending we use that here?

JSONAPIDocument<List<Campaign>> campaignResponse = api.fetchCampaigns();
Assert.assertEquals(1, campaignResponse.get().size());
Campaign campaign = campaignResponse.get().get(0);
Assert.assertEquals("70261", campaign.getId());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pull expected campaign data into constant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 there's more extensive stuff to do rewriting all tests -- right now they require you to add a real access_token, rather than mocking network

@@ -0,0 +1,26 @@
package com.patreon;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this file incomplete?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this and the other test are both placeholders

@21echoes 21echoes requested a review from jrsun October 26, 2017 22:00

private InputStream getDataStream(String suffix) {
try {
String prefix = "https://api.patreon.com/oauth2/api/";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry for missing this, but i believe we encourage patreon.com/api over api.patreon.com because it saves an OPTIONS request

Copy link
Contributor Author

@21echoes 21echoes Oct 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when you're not in a browser, there's no OPTIONS request, and this library is never used in a browser

* @throws IOException Thrown when the GET request failed
*/
public JSONAPIDocument<List<Pledge>> fetchPageOfPledges(String campaignId, int pageSize, String pageCursor) throws IOException {
String url = String.format("campaigns/%s/pledges?page%%5Bcount%%5D=%s", campaignId, pageSize);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can this be new URIBuilder().setPath(blah).addParameter('page%5Bcount%5D', pageSize)

if (pageCursor != null) {
try {
String escapedCursor = URLEncoder.encode(pageCursor, "UTF-8");
url.concat(String.format("&page%%5Bcursor%%5D=%s", escapedCursor));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

@21echoes 21echoes requested a review from jrsun October 27, 2017 00:32
Copy link
Contributor

@jrsun jrsun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥇

return null;
}

public List<Pledge> fetchAllPledges(String campaignId) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is bomb!!

);
}

public String getCursorFromPledgesResponse(JSONAPIDocument<List<Pledge>> pledgesResponse) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥇

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

optional, possibly in a later PR: it would be really cool to make this resource-independent.


private InputStream getDataStream(String suffix) throws IOException {
try {
String prefix = "https://api.patreon.com/oauth2/api/";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

think this should be www.patreon.com/api

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd really love to keep our platform API at api.patreon.com and have www.patreon.com/api be an in-house implementation detail for our js clients

@21echoes 21echoes merged commit c84328d into master Oct 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants