added option to use Twitter API v1.1 only
This commit is contained in:
parent
4d4201a0fb
commit
c127e8ec15
|
@ -70,7 +70,7 @@ public interface Connection {
|
|||
* @param id ID of the status
|
||||
* @return user list
|
||||
*/
|
||||
Users getRepostingUsers(long id) throws ConnectionException;
|
||||
Users getRepostingUsers(long id, long cursor) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* get users liking a status
|
||||
|
@ -78,7 +78,7 @@ public interface Connection {
|
|||
* @param id ID of the status
|
||||
* @return user list
|
||||
*/
|
||||
Users getFavoritingUsers(long id) throws ConnectionException;
|
||||
Users getFavoritingUsers(long id, long cursor) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* create a list of users a specified user is following
|
||||
|
@ -318,9 +318,10 @@ public interface Connection {
|
|||
* @param id Id of the status
|
||||
* @param minId get statuses with ID above the min ID
|
||||
* @param maxId get statuses with ID under the max ID
|
||||
* @param extras additional information like screen name of the status author
|
||||
* @return list of statuses
|
||||
*/
|
||||
List<Status> getStatusReplies(long id, long minId, long maxId) throws ConnectionException;
|
||||
List<Status> getStatusReplies(long id, long minId, long maxId, String... extras) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* lookup status by ID
|
||||
|
|
|
@ -207,13 +207,13 @@ public class Mastodon implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public Users getRepostingUsers(long id) throws MastodonException {
|
||||
public Users getRepostingUsers(long id, long cursor) throws MastodonException {
|
||||
return getUsers(ENDPOINT_STATUS + id + "/reblogged_by", new ArrayList<>());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Users getFavoritingUsers(long id) throws MastodonException {
|
||||
public Users getFavoritingUsers(long id, long cursor) throws MastodonException {
|
||||
return getUsers(ENDPOINT_STATUS + id + "/favourited_by", new ArrayList<>());
|
||||
}
|
||||
|
||||
|
@ -459,7 +459,7 @@ public class Mastodon implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public List<Status> getStatusReplies(long id, long minId, long maxId) throws MastodonException {
|
||||
public List<Status> getStatusReplies(long id, long minId, long maxId, String... extras) throws MastodonException {
|
||||
List<Status> statusThreads = getStatuses(ENDPOINT_STATUS + id + "/context", new ArrayList<>(0), minId, maxId);
|
||||
List<Status> result = new LinkedList<>();
|
||||
for (Status status : statusThreads) {
|
||||
|
|
|
@ -19,17 +19,22 @@ public class Tokens {
|
|||
* false means there are no API keys available
|
||||
* set to true when {@link #CONSUMER_TOKEN} and {@link #TOKEN_SECRET} are set
|
||||
*/
|
||||
public static final boolean USE_DEFAULT_KEYS = false;
|
||||
public static final boolean USE_DEFAULT_KEYS = true;
|
||||
|
||||
/**
|
||||
* for compability mode disable Twitter API version 2.0 (use only version 1.1) if the API access don't support this.
|
||||
*/
|
||||
public static final boolean DISABLE_API_V2 = true;
|
||||
|
||||
/**
|
||||
* add here your consumer token
|
||||
*/
|
||||
private static final String CONSUMER_TOKEN = "xxx";
|
||||
private static final String CONSUMER_TOKEN = "";
|
||||
|
||||
/**
|
||||
* add here your token secret
|
||||
*/
|
||||
private static final String TOKEN_SECRET = "xxx";
|
||||
private static final String TOKEN_SECRET = "";
|
||||
|
||||
|
||||
private static Tokens instance;
|
||||
|
|
|
@ -53,7 +53,6 @@ import org.nuclearfog.twidda.model.UserList;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -130,6 +129,7 @@ public class Twitter implements Connection {
|
|||
private static final String TWEET_UPLOAD = API + "/1.1/statuses/update.json";
|
||||
private static final String TWEET_DELETE = API + "/1.1/statuses/destroy/";
|
||||
private static final String TWEET_SEARCH_2 = API + "/2/tweets/search/recent";
|
||||
private static final String TWEET_GET_RETWEETERS = API + "/1.1/statuses/retweeters/ids.json";
|
||||
private static final String TWEET_UNI = API + "/2/tweets/";
|
||||
|
||||
// userlist endpoints
|
||||
|
@ -308,16 +308,32 @@ public class Twitter implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public Users getRepostingUsers(long tweetId) throws TwitterException {
|
||||
public Users getRepostingUsers(long tweetId, long cursor) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
if (!Tokens.DISABLE_API_V2) {
|
||||
String endpoint = TWEET_UNI + tweetId + "/retweeted_by";
|
||||
return getUsers2(endpoint, new ArrayList<>());
|
||||
return getUsers2(endpoint, params);
|
||||
} else {
|
||||
params.add("id=" + tweetId);
|
||||
params.add("count=" + settings.getListSize());
|
||||
long[] ids = getUserIDs(TWEET_GET_RETWEETERS, params, cursor);
|
||||
Users result = getUsers1(ids);
|
||||
result.setPrevCursor(cursor);
|
||||
result.setNextCursor(ids[ids.length - 1]); // Twitter bug: next cursor is always zero!
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Users getFavoritingUsers(long tweetId) throws TwitterException {
|
||||
public Users getFavoritingUsers(long tweetId, long cursor) throws TwitterException {
|
||||
if (!Tokens.DISABLE_API_V2) {
|
||||
String endpoint = TWEET_UNI + tweetId + "/liking_users";
|
||||
return getUsers2(endpoint, new ArrayList<>());
|
||||
} else {
|
||||
// API v1.1 doesn't support this!
|
||||
return new Users(0L, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -389,17 +405,15 @@ public class Twitter implements Connection {
|
|||
|
||||
@Override
|
||||
public Users getIncomingFollowRequests(long cursor) throws TwitterException {
|
||||
long[] ids = getUserIDs(USERS_FOLLOW_INCOMING, cursor);
|
||||
// remove last array entry (cursor) from ID list
|
||||
return getUsers1(Arrays.copyOf(ids, ids.length - 1));
|
||||
long[] ids = getUserIDs(USERS_FOLLOW_INCOMING, new ArrayList<>(), cursor);
|
||||
return getUsers1(ids);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Users getOutgoingFollowRequests(long cursor) throws TwitterException {
|
||||
long[] ids = getUserIDs(USERS_FOLLOW_OUTGOING, cursor);
|
||||
// remove last array entry (cursor) from ID list
|
||||
return getUsers1(Arrays.copyOf(ids, ids.length - 1));
|
||||
long[] ids = getUserIDs(USERS_FOLLOW_OUTGOING, new ArrayList<>(), cursor);
|
||||
return getUsers1(ids);
|
||||
}
|
||||
|
||||
|
||||
|
@ -608,20 +622,35 @@ public class Twitter implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public List<Status> getStatusReplies(long id, long minId, long maxId) throws TwitterException {
|
||||
public List<Status> getStatusReplies(long id, long minId, long maxId, String... extras) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
List<Status> replies = new LinkedList<>();
|
||||
if (!Tokens.DISABLE_API_V2) {
|
||||
params.add("query=" + StringTools.encode("conversation_id:" + id));
|
||||
// Note: minId disabled! Twitter refuses API request containing minId of a tweet older than one week
|
||||
List<Status> result = getTweets2(TWEET_SEARCH_2, params, 0, maxId);
|
||||
List<Status> replies = new LinkedList<>();
|
||||
// chose only the first tweet of a conversation
|
||||
for (Status reply : result) {
|
||||
if (reply.getRepliedStatusId() == id && reply.getId() > minId) {
|
||||
replies.add(reply);
|
||||
}
|
||||
}
|
||||
if (settings.filterResults() && !replies.isEmpty())
|
||||
} else {
|
||||
String replyUsername = extras[0];
|
||||
if (replyUsername.startsWith("@")) {
|
||||
replyUsername = replyUsername.substring(1);
|
||||
}
|
||||
params.add("q=" + StringTools.encode("to:" + replyUsername + " -filter:retweets"));
|
||||
List<Status> result = getTweets1(TWEET_SEARCH, params, Math.max(id, minId), maxId);
|
||||
for (Status reply : result) {
|
||||
if (reply.getRepliedStatusId() == id) {
|
||||
replies.add(reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (settings.filterResults() && !replies.isEmpty()) {
|
||||
filterTweets(replies);
|
||||
}
|
||||
return replies;
|
||||
}
|
||||
|
||||
|
@ -631,12 +660,14 @@ public class Twitter implements Connection {
|
|||
List<String> params = new ArrayList<>();
|
||||
params.add("id=" + id);
|
||||
Status status = getTweet1(TWEET_LOOKUP, params);
|
||||
if (!Tokens.DISABLE_API_V2) {
|
||||
try {
|
||||
params.clear();
|
||||
return getTweet2(TWEET2_LOOKUP + id, params, status);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1070,7 +1101,7 @@ public class Twitter implements Connection {
|
|||
// add blocked user IDs
|
||||
long cursor = -1;
|
||||
for (int i = 0; i < 10 && cursor != 0; i++) {
|
||||
long[] ids = getUserIDs(IDS_BLOCKED_USERS, cursor);
|
||||
long[] ids = getUserIDs(IDS_BLOCKED_USERS, new ArrayList<>(), cursor);
|
||||
for (int pos = 0; pos < ids.length - 2; pos++) {
|
||||
result.add(ids[pos]);
|
||||
}
|
||||
|
@ -1079,7 +1110,7 @@ public class Twitter implements Connection {
|
|||
// add muted user IDs
|
||||
cursor = -1;
|
||||
for (int i = 0; i < 10 && cursor != 0; i++) {
|
||||
long[] ids = getUserIDs(IDS_MUTED_USERS, cursor);
|
||||
long[] ids = getUserIDs(IDS_MUTED_USERS, new ArrayList<>(), cursor);
|
||||
for (int pos = 0; pos < ids.length - 2; pos++) {
|
||||
result.add(ids[pos]);
|
||||
}
|
||||
|
@ -1295,8 +1326,7 @@ public class Twitter implements Connection {
|
|||
* @param cursor cursor value to parse the ID pages
|
||||
* @return an array of user IDs + the list cursor on the last array index
|
||||
*/
|
||||
private long[] getUserIDs(String endpoint, long cursor) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
private long[] getUserIDs(String endpoint, List<String> params, long cursor) throws TwitterException {
|
||||
params.add("cursor=" + cursor);
|
||||
try {
|
||||
Response response = get(endpoint, params);
|
||||
|
@ -1322,15 +1352,15 @@ public class Twitter implements Connection {
|
|||
/**
|
||||
* lookup a list of user IDs
|
||||
*
|
||||
* @param ids User IDs
|
||||
* @param ids User IDs (last entry is ignored)
|
||||
* @return a list of users
|
||||
*/
|
||||
private Users getUsers1(long[] ids) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
if (ids.length > 0) {
|
||||
StringBuilder idBuf = new StringBuilder("user_id=");
|
||||
for (long id : ids) {
|
||||
idBuf.append(id).append("%2C");
|
||||
for (int i = 0 ; i < ids.length - 1 ; i++) {
|
||||
idBuf.append(ids[i]).append("%2C");
|
||||
}
|
||||
params.add(idBuf.substring(0, idBuf.length() - 3));
|
||||
return getUsers1(USERS_LOOKUP, params);
|
||||
|
|
|
@ -196,8 +196,8 @@ public class TweetV1 implements Status {
|
|||
|
||||
@Override
|
||||
public long getConversationId() {
|
||||
// not implemented in API V1.1
|
||||
return 0;
|
||||
// note: does not show the root tweet of the conversation
|
||||
return replyTweetId;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -165,18 +165,18 @@ public class StatusLoader extends AsyncTask<Long, Void, List<Status>> {
|
|||
if (sinceId == 0 && maxId == 0) {
|
||||
statuses = db.getReplies(id);
|
||||
if (statuses.isEmpty()) {
|
||||
statuses = connection.getStatusReplies(id, sinceId, maxId);
|
||||
statuses = connection.getStatusReplies(id, sinceId, maxId, search);
|
||||
if (!statuses.isEmpty() && db.containsStatus(id)) {
|
||||
db.saveReplyTimeline(statuses);
|
||||
}
|
||||
}
|
||||
} else if (sinceId > 0) {
|
||||
statuses = connection.getStatusReplies(id, sinceId, maxId);
|
||||
statuses = connection.getStatusReplies(id, sinceId, maxId, search);
|
||||
if (!statuses.isEmpty() && db.containsStatus(id)) {
|
||||
db.saveReplyTimeline(statuses);
|
||||
}
|
||||
} else if (maxId > 1) {
|
||||
statuses = connection.getStatusReplies(id, sinceId, maxId);
|
||||
statuses = connection.getStatusReplies(id, sinceId, maxId, search);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -115,10 +115,10 @@ public class UserLoader extends AsyncTask<Long, Void, Users> {
|
|||
return connection.getFollowing(id, cursor);
|
||||
|
||||
case REPOST:
|
||||
return connection.getRepostingUsers(id);
|
||||
return connection.getRepostingUsers(id, cursor);
|
||||
|
||||
case FAVORIT:
|
||||
return connection.getFavoritingUsers(id);
|
||||
return connection.getFavoritingUsers(id, cursor);
|
||||
|
||||
case SEARCH:
|
||||
return connection.searchUsers(search, cursor);
|
||||
|
|
|
@ -15,6 +15,7 @@ import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERS_FAVORIT;
|
|||
import static org.nuclearfog.twidda.ui.activities.UsersActivity.USERS_REPOST;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.KEY_STATUS_FRAGMENT_ID;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.KEY_STATUS_FRAGMENT_MODE;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.KEY_STATUS_FRAGMENT_SEARCH;
|
||||
import static org.nuclearfog.twidda.ui.fragments.StatusFragment.STATUS_FRAGMENT_REPLY;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
|
@ -187,15 +188,18 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
|||
clip = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
|
||||
// get parameter
|
||||
String replyUsername = "";
|
||||
Object data = getIntent().getSerializableExtra(KEY_STATUS_DATA);
|
||||
if (data instanceof Status) {
|
||||
status = (Status) data;
|
||||
Status embedded = status.getEmbeddedStatus();
|
||||
if (embedded != null) {
|
||||
id = embedded.getId();
|
||||
replyUsername = embedded.getAuthor().getScreenname();
|
||||
} else {
|
||||
id = status.getId();
|
||||
hidden = status.isHidden();
|
||||
replyUsername = status.getAuthor().getScreenname();
|
||||
}
|
||||
} else {
|
||||
id = getIntent().getLongExtra(KEY_STATUS_ID, -1);
|
||||
|
@ -204,6 +208,7 @@ public class StatusActivity extends AppCompatActivity implements OnClickListener
|
|||
// create list fragment for status replies
|
||||
Bundle param = new Bundle();
|
||||
param.putInt(KEY_STATUS_FRAGMENT_MODE, STATUS_FRAGMENT_REPLY);
|
||||
param.putString(KEY_STATUS_FRAGMENT_SEARCH, replyUsername);
|
||||
param.putLong(KEY_STATUS_FRAGMENT_ID, id);
|
||||
|
||||
// insert fragment into view
|
||||
|
|
Loading…
Reference in New Issue