Skip to content

Commit

Permalink
Merge pull request #69 from redouane59/develop
Browse files Browse the repository at this point in the history
V1.11
  • Loading branch information
redouane59 authored Sep 13, 2020
2 parents 8efc3d6 + 3916a95 commit e4f8e2d
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 75 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ In your pom.xml, add the following dependency :
<dependency>
<groupId>com.github.redouane59.twitter</groupId>
<artifactId>twittered</artifactId>
<version>1.10</version>
<version>1.11</version>
</dependency>
```
In order to use your own developer credentials, you have several options :
Expand Down
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.github.redouane59.twitter</groupId>
<artifactId>twittered</artifactId>
<version>1.10</version>
<version>1.11</version>

<name>twittered</name>
<description>java client for twitter API</description>
Expand Down Expand Up @@ -177,5 +177,11 @@
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.6</version>
</dependency>

</dependencies>
</project>
28 changes: 28 additions & 0 deletions src/main/java/com/github/redouane59/twitter/ITwitterClientV1.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ public interface ITwitterClientV1 {
*/
Tweet postTweet(String text);

/**
* Post a tweet calling https://api.twitter.com/1.1/statuses/update.json
*
* @param text the tweet text
* @param inReplyToStatusId the id of the tweet to answer. Note: This parameter will be ignored unless the author of the Tweet this parameter
* references is mentioned within the status text. Therefore, you must include @username , where username is the author of the referenced Tweet,
* within the update.
* @return the created tweet
*/
Tweet postTweet(String text, String inReplyToStatusId);

/**
* Delete a tweet calling https://api.twitter.com/1.1/statuses/destroy/:id.json
*
Expand Down Expand Up @@ -172,6 +183,23 @@ public interface ITwitterClientV1 {
*/
RequestToken getOauth1Token();

/**
* Get token and secret token (oAuth1) calling https://api.twitter.com/oauth/request_token
*
* @param oauthCallback the URL you wish your user to be redirected to when they complete the next step ("oob" to show the pincode)
* @return and object containing the oauth token and the oauth token secret
*/
RequestToken getOauth1Token(String oauthCallback);

/**
* Convert the request token into a usable access token calling https://api.twitter.com/oauth/access_token
*
* @param requestToken the token and secret token
* @param pinCode the oauth verifier
* @return the access tokens
*/
RequestToken getOAuth1AccessToken(RequestToken requestToken, String pinCode);

/**
* Get the last 200 mentions from timeline calling https://api.twitter.com/1.1/statuses/mentions_timeline.json
*
Expand Down
51 changes: 30 additions & 21 deletions src/main/java/com/github/redouane59/twitter/TwitterClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,7 @@
import com.github.redouane59.twitter.signature.TwitterCredentials;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Base64;
Expand All @@ -57,8 +54,6 @@
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;

@Getter
@Setter
Expand Down Expand Up @@ -292,9 +287,17 @@ public Tweet retweetTweet(String tweetId) {

@Override
public Tweet postTweet(String text) {
return this.postTweet(text, null);
}

@Override
public Tweet postTweet(String text, String inReplyToStatusId) {
String url = this.getUrlHelper().getPostTweetUrl();
Map<String, String> parameters = new HashMap<>();
parameters.put("status", text);
if (inReplyToStatusId != null) {
parameters.put("in_reply_to_status_id", inReplyToStatusId);
}
return this.getRequestHelper().postRequest(url, parameters, TweetV1.class).orElseThrow(NoSuchElementException::new);
}

Expand Down Expand Up @@ -568,26 +571,32 @@ public String getBearerToken() {

@Override
public RequestToken getOauth1Token() {
String url = URLHelper.GET_OAUTH1_TOKEN_URL;
String stringResponse = this.requestHelper.postRequest(url, new HashMap<>(), String.class)
.orElseThrow(NoSuchElementException::new);
List<NameValuePair> params = null;
try {
params = URLEncodedUtils.parse(new URI("twitter.com?" + stringResponse), StandardCharsets.UTF_8.name());
} catch (URISyntaxException e) {
LOGGER.error(e.getMessage());
}
RequestToken requestToken = new RequestToken();
for (NameValuePair param : params) {
if (param.getName().equals("oauth_token")) {
requestToken.setOauthToken(param.getValue());
} else if (param.getName().equals("oauth_token_secret")) {
requestToken.setOauthTokenSecret(param.getValue());
}
return this.getOauth1Token(null);
}

@Override
public RequestToken getOauth1Token(String oauthCallback) {
String url = URLHelper.GET_OAUTH1_TOKEN_URL;
Map<String, String> parameters = new HashMap<>();
if (oauthCallback != null) {
parameters.put("oauth_callback", oauthCallback);
}
String stringResponse = this.requestHelper.postRequest(url, parameters, String.class).orElseThrow(NoSuchElementException::new);
RequestToken requestToken = new RequestToken(stringResponse);
LOGGER.info("Open the following URL to grant access to your account:");
LOGGER.info("https://twitter.com/oauth/authenticate?oauth_token=" + requestToken.getOauthToken());
return requestToken;
}

@Override
public RequestToken getOAuth1AccessToken(RequestToken requestToken, String pinCode) {
String url = URLHelper.GET_OAUTH1_ACCESS_TOKEN_URL;
Map<String, String> parameters = new HashMap<>();
parameters.put("oauth_verifier", pinCode);
String stringResponse = this.requestHelper.postRequest(url, parameters, String.class).orElseThrow(NoSuchElementException::new);
return new RequestToken(stringResponse);
}

public static TwitterCredentials getAuthentication() {
String credentialPath = System.getProperty("twitter.credentials.file.path");
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,41 @@
package com.github.redouane59.twitter.dto.others;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;

@Getter
@Setter
@NoArgsConstructor
@Slf4j
public class RequestToken {

@JsonProperty("oauth_token")
private String oauthToken;
@JsonProperty("oauth_token_secret")
private String oauthTokenSecret;

public RequestToken(String stringResponse) {
List<NameValuePair> responseParams = null;
try {
responseParams = URLEncodedUtils.parse(new URI("twitter.com?" + stringResponse), StandardCharsets.UTF_8.name());
} catch (URISyntaxException e) {
LOGGER.error(e.getMessage());
}
for (NameValuePair param : responseParams) {
if (param.getName().equals("oauth_token")) {
this.oauthToken = param.getValue();
} else if (param.getName().equals("oauth_token_secret")) {
this.oauthTokenSecret = param.getValue();
}
}
}
}
97 changes: 49 additions & 48 deletions src/main/java/com/github/redouane59/twitter/helpers/URLHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,58 @@
@Slf4j
public class URLHelper {

private static final String ROOT_URL_V1 = "https://api.twitter.com/1.1";
private static final String ROOT_URL_V2 = "https://api.twitter.com/2";
private static final String ROOT_URL_LABS_V2 = "https://api.twitter.com/labs/2";
private static final String IDS_JSON = "/ids.json?";
private static final String SCREEN_NAME = "screen_name";
private static final String ID = "id";
private static final String COUNT = "count";
private static final String LIST_JSON = "/list.json?";
private static final String SHOW_JSON = "/show.json?";
private static final String CREATE_JSON = "/create.json?";
private static final String DESTROY_JSON = "/destroy.json?";
private static final String RETWEETERS = "/retweeters";
private static final String FOLLOWERS = "/followers";
private static final String FRIENDS = "/friends";
private static final String STATUSES = "/statuses";
private static final String FRIENDSHIPS = "/friendships";
private static final String FAVORITES = "/favorites";
private static final String USERS = "/users";
private static final String TWEETS = "/tweets";
private static final String SEARCH = "/search";
private static final String SAMPLE = "/sample";
private static final String STREAM = "/stream";
private static final String THIRTY_DAYS = "/30day";
private static final String FULL_ARCHIVE = "/fullarchive";
private static final String ACCOUNT_ACTIVITY = "/account_activity/all";
private static final String WEBHOOKS = "/webhooks";
private static final String USER_ID = "user_id";
private static final String LOOKUP_JSON = "/lookup.json?";
private static final String USER_TIMELINE = "/user_timeline.json?";
private static final String JSON = ".json";
private static final String TRIM_USER = "trim_user=true";
private static final String EXCLUDE_RTS = "include_rts=false";
private static final String USER_FORMAT_DETAILED = "user.format=detailed";
private static final String TWEET_FORMAT_DETAILED = "tweet.format=detailed";
private static final String EXPANSIONS_RECENT_TWEET = "expansions=most_recent_tweet_id";
private static final int MAX_COUNT = 200;
private static final int RETWEET_MAX_COUNT = 100;
private static final int MAX_LOOKUP = 100;
private static final String ROOT_URL_V1 = "https://api.twitter.com/1.1";
private static final String ROOT_URL_V2 = "https://api.twitter.com/2";
private static final String ROOT_URL_LABS_V2 = "https://api.twitter.com/labs/2";
private static final String IDS_JSON = "/ids.json?";
private static final String SCREEN_NAME = "screen_name";
private static final String ID = "id";
private static final String COUNT = "count";
private static final String LIST_JSON = "/list.json?";
private static final String SHOW_JSON = "/show.json?";
private static final String CREATE_JSON = "/create.json?";
private static final String DESTROY_JSON = "/destroy.json?";
private static final String RETWEETERS = "/retweeters";
private static final String FOLLOWERS = "/followers";
private static final String FRIENDS = "/friends";
private static final String STATUSES = "/statuses";
private static final String FRIENDSHIPS = "/friendships";
private static final String FAVORITES = "/favorites";
private static final String USERS = "/users";
private static final String TWEETS = "/tweets";
private static final String SEARCH = "/search";
private static final String SAMPLE = "/sample";
private static final String STREAM = "/stream";
private static final String THIRTY_DAYS = "/30day";
private static final String FULL_ARCHIVE = "/fullarchive";
private static final String ACCOUNT_ACTIVITY = "/account_activity/all";
private static final String WEBHOOKS = "/webhooks";
private static final String USER_ID = "user_id";
private static final String LOOKUP_JSON = "/lookup.json?";
private static final String USER_TIMELINE = "/user_timeline.json?";
private static final String JSON = ".json";
private static final String TRIM_USER = "trim_user=true";
private static final String EXCLUDE_RTS = "include_rts=false";
private static final String USER_FORMAT_DETAILED = "user.format=detailed";
private static final String TWEET_FORMAT_DETAILED = "tweet.format=detailed";
private static final String EXPANSIONS_RECENT_TWEET = "expansions=most_recent_tweet_id";
private static final int MAX_COUNT = 200;
private static final int RETWEET_MAX_COUNT = 100;
private static final int MAX_LOOKUP = 100;
private static final String
ALL_USER_FIELDS =
ALL_USER_FIELDS =
"user.fields=id,created_at,username,name,location,url,verified,profile_image_url,public_metrics,pinned_tweet_id,description,protected";
private static final String
ALL_TWEET_FIELDS =
ALL_TWEET_FIELDS =
"tweet.fields=attachments,author_id,created_at,entities,geo,id,in_reply_to_user_id,lang,possibly_sensitive,public_metrics,referenced_tweets,source,text,withheld,context_annotations,conversation_id";
public static final String LAST_TWEET_LIST_URL = ROOT_URL_V1 + STATUSES + USER_TIMELINE;
public static final String RATE_LIMIT_URL = ROOT_URL_V1 + "/application/rate_limit_status.json";
;
public static final String SEARCH_TWEET_STANDARD_URL = ROOT_URL_V1 + SEARCH + TWEETS + JSON;
public static final String SEARCH_TWEET_7_DAYS_URL = ROOT_URL_V2 + TWEETS + SEARCH + "/recent";
public static final String GET_BEARER_TOKEN_URL = "https://api.twitter.com/oauth2/token";
public static final String GET_OAUTH1_TOKEN_URL = "https://api.twitter.com/oauth/request_token";
public static final String LAST_TWEET_LIST_URL = ROOT_URL_V1 + STATUSES + USER_TIMELINE;
public static final String RATE_LIMIT_URL = ROOT_URL_V1 + "/application/rate_limit_status.json";
public static final String SEARCH_TWEET_STANDARD_URL = ROOT_URL_V1 + SEARCH + TWEETS + JSON;
public static final String SEARCH_TWEET_7_DAYS_URL = ROOT_URL_V2 + TWEETS + SEARCH + "/recent";
public static final String GET_BEARER_TOKEN_URL = "https://api.twitter.com/oauth2/token";
public static final String GET_OAUTH1_TOKEN_URL = "https://api.twitter.com/oauth/request_token";
public static final String GET_OAUTH1_ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";


public String getSearchTweet30DaysUrl(String envName) {
return ROOT_URL_V1 + TWEETS + SEARCH + THIRTY_DAYS + "/" + envName + JSON;
Expand Down Expand Up @@ -295,7 +296,7 @@ public String getFilteredStreamRulesUrl() {
}

public String getFilteredStreamUrl() {
return ROOT_URL_V2 + TWEETS + SEARCH + STREAM;
return ROOT_URL_V2 + TWEETS + SEARCH + STREAM + "?" + ALL_TWEET_FIELDS + "&" + ALL_USER_FIELDS;
}

public String getSampledStreamUrl() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public Request signRequest(Request request) {
while (!body.exhausted()) {
long keyEnd = body.indexOf((byte) '=');
if (keyEnd == -1) {
throw new IllegalStateException("Key with no value: " + body.readUtf8());
break;//throw new IllegalStateException("Key with no value: " + body.readUtf8());
}
String key = body.readUtf8(keyEnd);
body.skip(1); // Equals.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,15 @@ public void testGetRetweetersId() {
String tweetId = "1078358350000205824";
assertTrue(twitterClient.getRetweetersId(tweetId).size() > 10);
}

@Test
public void testGetOauth1Token() {
TwitterClient.TWITTER_CREDENTIALS.setAccessToken("");
TwitterClient.TWITTER_CREDENTIALS.setAccessTokenSecret("");
RequestToken result = twitterClient.getOauth1Token();
RequestToken result = twitterClient.getOauth1Token("oob");
assertTrue(result.getOauthToken().length() > 1);
assertTrue(result.getOauthTokenSecret().length() > 1);
//twitterClient.getOAuth1AccessToken(result, "12345");
}

@Test
Expand Down Expand Up @@ -142,13 +143,20 @@ public void testPostAndRTandDeleteTweet() {
assertNotNull(resultPost);
assertNotNull(resultPost.getId());
assertEquals(text, resultPost.getText());
Tweet resultPostAnswer = twitterClient.postTweet(text, resultPost.getId());
assertNotNull(resultPostAnswer);
assertNotNull(resultPostAnswer.getId());
assertEquals(resultPostAnswer.getInReplyToStatusId(), resultPost.getId());
Tweet resultRT = twitterClient.retweetTweet(resultPost.getId());
assertNotNull(resultRT);
assertNotNull(resultRT.getId());
assertEquals(resultPost.getAuthorId(), resultRT.getAuthorId());
Tweet resultDelete = twitterClient.deleteTweet(resultPost.getId());
assertNotNull(resultDelete);
assertEquals(resultPost.getId(), resultDelete.getId());
Tweet resultDelete2 = twitterClient.deleteTweet(resultPostAnswer.getId());
assertNotNull(resultDelete2);
assertEquals(resultPostAnswer.getId(), resultDelete2.getId());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,9 @@ public void testRetrieveFilteredStreamRulesUrl() {

@Test
public void testFilteredStreamUrl() {
assertEquals("https://api.twitter.com/2/tweets/search/stream", urlHelper.getFilteredStreamUrl());
assertEquals(
"https://api.twitter.com/2/tweets/search/stream?tweet.fields=attachments,author_id,created_at,entities,geo,id,in_reply_to_user_id,lang,possibly_sensitive,public_metrics,referenced_tweets,source,text,withheld,context_annotations,conversation_id&user.fields=id,created_at,username,name,location,url,verified,profile_image_url,public_metrics,pinned_tweet_id,description,protected",
urlHelper.getFilteredStreamUrl());
}

@Test
Expand Down

0 comments on commit e4f8e2d

Please sign in to comment.