diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/TwitterV1.java b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/TwitterV1.java index 3db8aeba..99422777 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/TwitterV1.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v1/TwitterV1.java @@ -14,15 +14,6 @@ import org.nuclearfog.twidda.backend.api.Connection; import org.nuclearfog.twidda.backend.api.twitter.Tokens; import org.nuclearfog.twidda.backend.api.twitter.TwitterException; import org.nuclearfog.twidda.backend.api.twitter.impl.TwitterNotification; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.LocationV2; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.MediaV2; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.PollV2; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.TweetV2; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.UserV2; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.maps.LocationV2Map; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.maps.MediaV2Map; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.maps.PollV2Map; -import org.nuclearfog.twidda.backend.api.twitter.impl.v2.maps.UserV2Map; import org.nuclearfog.twidda.backend.lists.Messages; import org.nuclearfog.twidda.backend.lists.UserLists; import org.nuclearfog.twidda.backend.lists.Users; @@ -255,7 +246,7 @@ public class TwitterV1 implements Connection { public User showUser(long id) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - return getUser1(USER_LOOKUP, params); + return getUser(USER_LOOKUP, params); } @@ -265,7 +256,7 @@ public class TwitterV1 implements Connection { if (name.startsWith("@")) name = name.substring(1); params.add("screen_name=" + StringTools.encode(name)); - return getUser1(USER_LOOKUP, params); + return getUser(USER_LOOKUP, params); } @@ -278,7 +269,7 @@ public class TwitterV1 implements Connection { List params = new ArrayList<>(); params.add("q=" + StringTools.encode(search)); params.add("page=" + currentPage); - Users result = getUsers1(USERS_SEARCH, params); + Users result = getUsers(USERS_SEARCH, params); // notice that there are no more results // if result size is less than the requested size if (result.size() < settings.getListSize()) @@ -297,7 +288,7 @@ public class TwitterV1 implements Connection { params.add("id=" + tweetId); params.add("count=" + settings.getListSize()); long[] ids = getUserIDs(TWEET_GET_RETWEETERS, params, cursor); - Users result = getUsers1(ids); + Users result = getUsers(ids); result.setPrevCursor(cursor); result.setNextCursor(ids[ids.length - 1]); // Twitter bug: next cursor is always zero! return result; @@ -316,7 +307,7 @@ public class TwitterV1 implements Connection { List params = new ArrayList<>(); params.add("user_id=" + id); params.add("cursor=" + cursor); - return getUsers1(USERS_FOLLOWING, params); + return getUsers(USERS_FOLLOWING, params); } @@ -325,7 +316,7 @@ public class TwitterV1 implements Connection { List params = new ArrayList<>(); params.add("user_id=" + id); params.add("cursor=" + cursor); - return getUsers1(USERS_FOLLOWER, params); + return getUsers(USERS_FOLLOWER, params); } @@ -334,7 +325,7 @@ public class TwitterV1 implements Connection { List params = new ArrayList<>(); params.add("list_id=" + id); params.add("cursor=" + cursor); - Users result = getUsers1(USERS_LIST_MEMBER, params); + Users result = getUsers(USERS_LIST_MEMBER, params); // fix API returns zero previous_cursor when the end of the list is reached // override previous cursor if (cursor == -1L) @@ -350,7 +341,7 @@ public class TwitterV1 implements Connection { List params = new ArrayList<>(); params.add("list_id=" + id); params.add("cursor=" + cursor); - Users result = getUsers1(USERS_LIST_SUBSCRIBER, params); + Users result = getUsers(USERS_LIST_SUBSCRIBER, params); // fix API returns zero previous_cursor when the end of the list is reached // override previous cursor if (cursor == -1L) @@ -365,7 +356,7 @@ public class TwitterV1 implements Connection { public Users getBlockedUsers(long cursor) throws TwitterException { List params = new ArrayList<>(); params.add("cursor=" + cursor); - return getUsers1(USERS_BLOCKED_LIST, params); + return getUsers(USERS_BLOCKED_LIST, params); } @@ -373,21 +364,21 @@ public class TwitterV1 implements Connection { public Users getMutedUsers(long cursor) throws TwitterException { List params = new ArrayList<>(); params.add("cursor=" + cursor); - return getUsers1(USERS_MUTES, params); + return getUsers(USERS_MUTES, params); } @Override public Users getIncomingFollowRequests(long cursor) throws TwitterException { long[] ids = getUserIDs(USERS_FOLLOW_INCOMING, new ArrayList<>(), cursor); - return getUsers1(ids); + return getUsers(ids); } @Override public Users getOutgoingFollowRequests(long cursor) throws TwitterException { long[] ids = getUserIDs(USERS_FOLLOW_OUTGOING, new ArrayList<>(), cursor); - return getUsers1(ids); + return getUsers(ids); } @@ -414,7 +405,7 @@ public class TwitterV1 implements Connection { public void followUser(long id) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - getUser1(USER_FOLLOW, params); + getUser(USER_FOLLOW, params); } @@ -422,7 +413,7 @@ public class TwitterV1 implements Connection { public void unfollowUser(long id) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - getUser1(USER_UNFOLLOW, params); + getUser(USER_UNFOLLOW, params); } @@ -430,7 +421,7 @@ public class TwitterV1 implements Connection { public void blockUser(long id) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - getUser1(USER_BLOCK, params); + getUser(USER_BLOCK, params); } @@ -440,7 +431,7 @@ public class TwitterV1 implements Connection { if (name.startsWith("@")) name = name.substring(1); params.add("screen_name=" + StringTools.encode(name)); - getUser1(USER_BLOCK, params); + getUser(USER_BLOCK, params); } @@ -448,7 +439,7 @@ public class TwitterV1 implements Connection { public void unblockUser(long id) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - getUser1(USER_UNBLOCK, params); + getUser(USER_UNBLOCK, params); } @@ -456,7 +447,7 @@ public class TwitterV1 implements Connection { public void muteUser(long id) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - getUser1(USER_MUTE, params); + getUser(USER_MUTE, params); } @@ -466,7 +457,7 @@ public class TwitterV1 implements Connection { if (name.startsWith("@")) name = name.substring(1); params.add("screen_name=" + StringTools.encode(name)); - getUser1(USER_MUTE, params); + getUser(USER_MUTE, params); } @@ -474,7 +465,7 @@ public class TwitterV1 implements Connection { public void unmuteUser(long id) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - getUser1(USER_UNMUTE, params); + getUser(USER_UNMUTE, params); } @@ -483,7 +474,7 @@ public class TwitterV1 implements Connection { List params = new ArrayList<>(); params.add("q=" + StringTools.encode(search + " +exclude:retweets")); params.add("result_type=recent"); - List result = getTweets1(TWEET_SEARCH, params, minId, maxId); + List result = getTweets(TWEET_SEARCH, params, minId, maxId); if (settings.filterResults()) filterTweets(result); return result; @@ -551,7 +542,7 @@ public class TwitterV1 implements Connection { @Override public List getHomeTimeline(long minId, long maxId) throws TwitterException { - return getTweets1(TWEETS_HOME_TIMELINE, new ArrayList<>(), minId, maxId); + return getTweets(TWEETS_HOME_TIMELINE, new ArrayList<>(), minId, maxId); } @@ -559,7 +550,7 @@ public class TwitterV1 implements Connection { public List getUserTimeline(long id, long minId, long maxId) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - return getTweets1(TWEETS_USER, params, minId, maxId); + return getTweets(TWEETS_USER, params, minId, maxId); } @@ -567,7 +558,7 @@ public class TwitterV1 implements Connection { public List getUserTimeline(String name, long minId, long maxId) throws TwitterException { List params = new ArrayList<>(); params.add("screen_name=" + StringTools.encode(name)); - return getTweets1(TWEETS_USER, params, minId, maxId); + return getTweets(TWEETS_USER, params, minId, maxId); } @@ -575,7 +566,7 @@ public class TwitterV1 implements Connection { public List getUserFavorits(long id, long minId, long maxId) throws TwitterException { List params = new ArrayList<>(); params.add("user_id=" + id); - return getTweets1(TWEETS_USER_FAVORITS, params, minId, maxId); + return getTweets(TWEETS_USER_FAVORITS, params, minId, maxId); } @@ -583,7 +574,7 @@ public class TwitterV1 implements Connection { public List getUserFavorits(String name, long minId, long maxId) throws TwitterException { List params = new ArrayList<>(); params.add("screen_name=" + StringTools.encode(name)); - return getTweets1(TWEETS_USER_FAVORITS, params, minId, maxId); + return getTweets(TWEETS_USER_FAVORITS, params, minId, maxId); } @@ -591,7 +582,7 @@ public class TwitterV1 implements Connection { public List getUserlistStatuses(long id, long minId, long maxId) throws TwitterException { List params = new ArrayList<>(); params.add("list_id=" + id); - return getTweets1(TWEETS_LIST, params, minId, maxId); + return getTweets(TWEETS_LIST, params, minId, maxId); } @@ -604,7 +595,7 @@ public class TwitterV1 implements Connection { replyUsername = replyUsername.substring(1); } params.add("q=" + StringTools.encode("to:" + replyUsername + " -filter:retweets")); - List result = getTweets1(TWEET_SEARCH, params, Math.max(id, minId), maxId); + List result = getTweets(TWEET_SEARCH, params, Math.max(id, minId), maxId); for (Status reply : result) { if (reply.getRepliedStatusId() == id) { replies.add(reply); @@ -621,7 +612,7 @@ public class TwitterV1 implements Connection { public Status showStatus(long id) throws TwitterException { List params = new ArrayList<>(); params.add("id=" + id); - return getTweet1(TWEET_LOOKUP, params); + return getTweet(TWEET_LOOKUP, params); } @@ -629,7 +620,7 @@ public class TwitterV1 implements Connection { public Status favoriteStatus(long id) throws TwitterException { List params = new ArrayList<>(); params.add("id=" + id); - TweetV1 result = getTweet1(TWEET_FAVORITE, params); + TweetV1 result = getTweet(TWEET_FAVORITE, params); result.setFavorite(true); return result; } @@ -639,7 +630,7 @@ public class TwitterV1 implements Connection { public Status unfavoriteStatus(long id) throws TwitterException { List params = new ArrayList<>(); params.add("id=" + id); - TweetV1 result = getTweet1(TWEET_UNFAVORITE, params); + TweetV1 result = getTweet(TWEET_UNFAVORITE, params); result.setFavorite(false); return result; } @@ -647,7 +638,7 @@ public class TwitterV1 implements Connection { @Override public Status repostStatus(long id) throws TwitterException { - TweetV1 result = getTweet1(TWEET_RETWEET + id + JSON, new ArrayList<>()); + TweetV1 result = getTweet(TWEET_RETWEET + id + JSON, new ArrayList<>()); result.setRetweet(true); return result; } @@ -655,7 +646,7 @@ public class TwitterV1 implements Connection { @Override public Status removeRepost(long id) throws TwitterException { - TweetV1 result = getTweet1(TWEET_UNRETWEET + id + JSON, new ArrayList<>()); + TweetV1 result = getTweet(TWEET_UNRETWEET + id + JSON, new ArrayList<>()); result.setRetweet(false); return result; } @@ -674,7 +665,7 @@ public class TwitterV1 implements Connection { @Override public void deleteStatus(long id) throws TwitterException { - getTweet1(TWEET_DELETE + id + JSON, new ArrayList<>()); + getTweet(TWEET_DELETE + id + JSON, new ArrayList<>()); } @@ -697,7 +688,7 @@ public class TwitterV1 implements Connection { params.add("lat=" + StringTools.encode(lat)); params.add("long=" + StringTools.encode(lon)); } - getTweet1(TWEET_UPLOAD, params); + getTweet(TWEET_UPLOAD, params); } @@ -710,7 +701,7 @@ public class TwitterV1 implements Connection { params.add("mode=public"); else params.add("mode=private"); - return getUserlist1(USERLIST_CREATE, params); + return getUserlist(USERLIST_CREATE, params); } @@ -724,7 +715,7 @@ public class TwitterV1 implements Connection { params.add("mode=public"); else params.add("mode=private"); - return getUserlist1(USERLIST_UPDATE, params); + return getUserlist(USERLIST_UPDATE, params); } @@ -732,7 +723,7 @@ public class TwitterV1 implements Connection { public UserList getUserlist(long id) throws TwitterException { List params = new ArrayList<>(); params.add("list_id=" + id); - return getUserlist1(USERLIST_SHOW, params); + return getUserlist(USERLIST_SHOW, params); } @@ -740,7 +731,7 @@ public class TwitterV1 implements Connection { public UserList followUserlist(long id) throws TwitterException { List params = new ArrayList<>(); params.add("list_id=" + id); - UserListV1 result = getUserlist1(USERLIST_FOLLOW, params); + UserListV1 result = getUserlist(USERLIST_FOLLOW, params); result.setFollowing(true); return result; } @@ -750,7 +741,7 @@ public class TwitterV1 implements Connection { public UserList unfollowUserlist(long id) throws TwitterException { List params = new ArrayList<>(); params.add("list_id=" + id); - UserListV1 result = getUserlist1(USERLIST_UNFOLLOW, params); + UserListV1 result = getUserlist(USERLIST_UNFOLLOW, params); result.setFollowing(false); return result; } @@ -760,7 +751,7 @@ public class TwitterV1 implements Connection { public UserList deleteUserlist(long id) throws TwitterException { List params = new ArrayList<>(); params.add("list_id=" + id); - return getUserlist1(USERLIST_DESTROY, params); + return getUserlist(USERLIST_DESTROY, params); } @@ -1041,7 +1032,7 @@ public class TwitterV1 implements Connection { if (update.getBannerImageStream() != null) { updateImage(PROFILE_UPDATE_BANNER, update.getBannerImageStream(), "banner"); } - return getUser1(PROFILE_UPDATE, params); + return getUser(PROFILE_UPDATE, params); } @@ -1074,7 +1065,7 @@ public class TwitterV1 implements Connection { @Override public List getNotifications(long minId, long maxId) throws TwitterException { - List mentions = getTweets1(TWEETS_MENTIONS, new ArrayList<>(), minId, maxId); + List mentions = getTweets(TWEETS_MENTIONS, new ArrayList<>(), minId, maxId); List result = new ArrayList<>(mentions.size()); for (Status status : mentions) { result.add(new TwitterNotification(status)); @@ -1082,44 +1073,6 @@ public class TwitterV1 implements Connection { return result; } - /** - * create a list of users using API v 2 - * - * @param endpoint endpoint url to get the user data from - * @param params additional parameters - * @return user list - */ - protected Users getUsers2(String endpoint, List params) throws TwitterException { - // enable additional user fields - params.add("user.fields=" + UserV2.FIELDS_USER); - try { - Response response = get(endpoint, params); - ResponseBody body = response.body(); - if (body != null && response.code() == 200) { - JSONObject json = new JSONObject(body.string()); - Users users = new Users(0L, 0L); - // check if result is not empty - if (json.has("data")) { - JSONArray array = json.getJSONArray("data"); - long homeId = settings.getLogin().getId(); - for (int i = 0; i < array.length(); i++) { - try { - users.add(new UserV2(array.getJSONObject(i), homeId)); - } catch (JSONException err) { - if (BuildConfig.DEBUG) { - Log.w("user-v2", err); - } - } - } - } - return users; - } - throw new TwitterException(response); - } catch (IOException | JSONException err) { - throw new TwitterException(err); - } - } - /** * get tweets using an endpoint * @@ -1129,7 +1082,7 @@ public class TwitterV1 implements Connection { * @param maxId maximum tweet ID * @return list of tweets */ - private List getTweets1(String endpoint, List params, long minId, long maxId) throws TwitterException { + private List getTweets(String endpoint, List params, long minId, long maxId) throws TwitterException { // enable extended tweet mode params.add(TweetV1.PARAM_EXT_MODE); params.add(TweetV1.PARAM_INCL_RETWEET); @@ -1170,69 +1123,13 @@ public class TwitterV1 implements Connection { } } - /** - * get tweets using an endpoint - * - * @param endpoint endpoint url to fetch the tweets - * @param params additional parameters - * @param minId minimum tweet ID - * @param maxId maximum tweet ID - * @return list of tweets - */ - protected List getTweets2(String endpoint, List params, long minId, long maxId) throws TwitterException { - // enable additional tweet fields - params.add(TweetV2.FIELDS_TWEET); - params.add(TweetV2.FIELDS_EXPANSION); - params.add(UserV2.FIELDS_USER); - params.add(MediaV2.FIELDS_MEDIA); - params.add(PollV2.FIELDS_POLL); - params.add(LocationV2.FIELDS_PLACE); - // set tweet range - if (minId > 0) - params.add("since_id=" + minId); - if (maxId > 1) - params.add("until_id=" + maxId); - params.add("max_results=" + settings.getListSize()); - try { - Response response = get(endpoint, params); - ResponseBody body = response.body(); - if (body != null && response.code() == 200) { - JSONObject json = new JSONObject(body.string()); - JSONArray data = json.optJSONArray("data"); - if (data != null && data.length() > 0) { - List tweets = new ArrayList<>(data.length() + 1); - UserV2Map userMap = new UserV2Map(json, settings.getLogin().getId()); - MediaV2Map mediaMap = new MediaV2Map(json); - PollV2Map pollMap = new PollV2Map(json); - LocationV2Map locationMap = new LocationV2Map(json); - String host = settings.getLogin().getHostname(); - for (int i = 0; i < data.length(); i++) { - try { - Status item = new TweetV2(data.getJSONObject(i), userMap, mediaMap, pollMap, locationMap, host, null); - tweets.add(item); - } catch (JSONException e) { - if (BuildConfig.DEBUG) { - Log.w("tweet", e); - } - } - } - return tweets; - } - return new ArrayList<>(0); - } - throw new TwitterException(response); - } catch (IOException | JSONException err) { - throw new TwitterException(err); - } - } - /** * return tweet from API 1.1 endpoint * * @param endpoint to use * @param params additional parameter */ - private TweetV1 getTweet1(String endpoint, List params) throws TwitterException { + private TweetV1 getTweet(String endpoint, List params) throws TwitterException { // use extended mode and add additional fields params.add(TweetV1.PARAM_EXT_MODE); params.add(TweetV1.PARAM_INCL_RETWEET); @@ -1255,7 +1152,7 @@ public class TwitterV1 implements Connection { if (result.getEmbeddedStatus() != null) { params.clear(); params.add("id=" + result.getEmbeddedStatus().getId()); - Status status = getTweet1(TWEET_LOOKUP, params); + Status status = getTweet(TWEET_LOOKUP, params); result.setEmbeddedTweet(status); } return result; @@ -1304,7 +1201,7 @@ public class TwitterV1 implements Connection { * @param ids User IDs (last entry is ignored) * @return a list of users */ - private Users getUsers1(long[] ids) throws TwitterException { + private Users getUsers(long[] ids) throws TwitterException { List params = new ArrayList<>(); if (ids.length > 1) { StringBuilder idBuf = new StringBuilder("user_id="); @@ -1312,7 +1209,7 @@ public class TwitterV1 implements Connection { idBuf.append(ids[i]).append("%2C"); } params.add(idBuf.substring(0, idBuf.length() - 3)); - return getUsers1(USERS_LOOKUP, params); + return getUsers(USERS_LOOKUP, params); } return new Users(0L, 0L); } @@ -1324,7 +1221,7 @@ public class TwitterV1 implements Connection { * @param params additional parameters * @return user list */ - private Users getUsers1(String endpoint, List params) throws TwitterException { + private Users getUsers(String endpoint, List params) throws TwitterException { try { Response response; if (USERS_LOOKUP.equals(endpoint)) { @@ -1369,7 +1266,7 @@ public class TwitterV1 implements Connection { * @param params additional parameters * @return user information */ - private User getUser1(String endpoint, List params) throws TwitterException { + private User getUser(String endpoint, List params) throws TwitterException { // enable entities/disable pinned status params.add(UserV1.PARAM_SKIP_STATUS); params.add(UserV1.PARAM_INCLUDE_ENTITIES); @@ -1397,7 +1294,7 @@ public class TwitterV1 implements Connection { * @param params additional parameters * @return userlist information */ - private UserListV1 getUserlist1(String endpoint, List params) throws TwitterException { + private UserListV1 getUserlist(String endpoint, List params) throws TwitterException { try { Response response; if (endpoint.equals(USERLIST_SHOW)) @@ -1567,7 +1464,7 @@ public class TwitterV1 implements Connection { * @return http response */ @SuppressWarnings("SameParameterValue") - private Response post(String endpoint, List params, JSONObject json) throws IOException { + protected Response post(String endpoint, List params, JSONObject json) throws IOException { RequestBody body = RequestBody.create(json.toString(), TYPE_JSON); return post(endpoint, params, body); } @@ -1581,7 +1478,7 @@ public class TwitterV1 implements Connection { * @param addToKey key to add the file * @return http response */ - private Response post(String endpoint, List params, InputStream is, String addToKey, boolean enableChunk) throws IOException { + protected Response post(String endpoint, List params, InputStream is, String addToKey, boolean enableChunk) throws IOException { RequestBody data = new RequestBody() { @Override public MediaType contentType() { @@ -1610,7 +1507,7 @@ public class TwitterV1 implements Connection { * @param keys optional oauth keys (consumer key & secret, optional oauth tokens) * @return http response */ - private Response post(String endpoint, List params, RequestBody body, String... keys) throws IOException { + protected Response post(String endpoint, List params, RequestBody body, String... keys) throws IOException { String authHeader; if (keys.length == 2) authHeader = buildHeader("POST", endpoint, params, keys); @@ -1656,7 +1553,7 @@ public class TwitterV1 implements Connection { * @return http response */ @SuppressWarnings("SameParameterValue") - private Response delete(String endpoint, List params) throws IOException { + protected Response delete(String endpoint, List params) throws IOException { String authHeader = buildHeader("DELETE", endpoint, params); String url = appendParams(endpoint, params); Request request = new Request.Builder().url(url).addHeader("Authorization", authHeader).delete().build(); diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v2/TwitterV2.java b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v2/TwitterV2.java index 18e5bd74..e42f0b85 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v2/TwitterV2.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/api/twitter/impl/v2/TwitterV2.java @@ -1,9 +1,12 @@ package org.nuclearfog.twidda.backend.api.twitter.impl.v2; import android.content.Context; +import android.util.Log; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.nuclearfog.twidda.BuildConfig; import org.nuclearfog.twidda.backend.api.twitter.TwitterException; import org.nuclearfog.twidda.backend.api.twitter.impl.v1.TwitterV1; import org.nuclearfog.twidda.backend.api.twitter.impl.v2.maps.LocationV2Map; @@ -56,26 +59,21 @@ public class TwitterV2 extends TwitterV1 { @Override public Status showStatus(long id) throws TwitterException { Status status = super.showStatus(id); - try { - return getTweet2(TWEET2_LOOKUP + id, new ArrayList<>(), status); - } catch (Exception e) { - e.printStackTrace(); - } - return status; + return getTweet(TWEET2_LOOKUP + id, new ArrayList<>(), status); } @Override public Users getRepostingUsers(long tweetId, long cursor) throws TwitterException { String endpoint = TWEET_UNI + tweetId + "/retweeted_by"; - return getUsers2(endpoint, new ArrayList<>()); + return getUsers(endpoint, new ArrayList<>(), cursor); } @Override public Users getFavoritingUsers(long tweetId, long cursor) throws TwitterException { String endpoint = TWEET_UNI + tweetId + "/liking_users"; - return getUsers2(endpoint, new ArrayList<>()); + return getUsers(endpoint, new ArrayList<>(), cursor); } @@ -97,7 +95,7 @@ public class TwitterV2 extends TwitterV1 { List replies = new LinkedList<>(); 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 result = getTweets2(TWEET_SEARCH_2, params, 0, maxId); + List result = getTweets(TWEET_SEARCH_2, params, 0, maxId); // chose only the first tweet of a conversation for (Status reply : result) { if (reply.getRepliedStatusId() == id && reply.getId() > minId) { @@ -134,7 +132,7 @@ public class TwitterV2 extends TwitterV1 { * @param endpoint to use * @param params additional parameter */ - private TweetV2 getTweet2(String endpoint, List params, Status statusCompat) throws TwitterException { + private Status getTweet(String endpoint, List params, Status statusCompat) throws TwitterException { // enable additional tweet fields params.add(TweetV2.FIELDS_EXPANSION); params.add(UserV2.FIELDS_USER); @@ -166,9 +164,106 @@ public class TwitterV2 extends TwitterV1 { return new TweetV2(json, userMap, mediaMap, pollMap, locationMap, host, statusCompat); } throw new TwitterException(response); - } catch ( - IOException | - JSONException err) { + } catch (IOException | JSONException err) { + throw new TwitterException(err); + } + } + + + /** + * get tweets using an endpoint + * + * @param endpoint endpoint url to fetch the tweets + * @param params additional parameters + * @param minId minimum tweet ID + * @param maxId maximum tweet ID + * @return list of tweets + */ + private List getTweets(String endpoint, List params, long minId, long maxId) throws TwitterException { + // enable additional tweet fields + params.add(TweetV2.FIELDS_TWEET); + params.add(TweetV2.FIELDS_EXPANSION); + params.add(UserV2.FIELDS_USER); + params.add(MediaV2.FIELDS_MEDIA); + params.add(PollV2.FIELDS_POLL); + params.add(LocationV2.FIELDS_PLACE); + // set tweet range + if (minId > 0) + params.add("since_id=" + minId); + if (maxId > 1) + params.add("until_id=" + maxId); + params.add("max_results=" + settings.getListSize()); + try { + Response response = get(endpoint, params); + ResponseBody body = response.body(); + if (body != null && response.code() == 200) { + JSONObject json = new JSONObject(body.string()); + JSONArray data = json.optJSONArray("data"); + if (data != null && data.length() > 0) { + List tweets = new ArrayList<>(data.length() + 1); + UserV2Map userMap = new UserV2Map(json, settings.getLogin().getId()); + MediaV2Map mediaMap = new MediaV2Map(json); + PollV2Map pollMap = new PollV2Map(json); + LocationV2Map locationMap = new LocationV2Map(json); + String host = settings.getLogin().getHostname(); + for (int i = 0; i < data.length(); i++) { + try { + Status item = new TweetV2(data.getJSONObject(i), userMap, mediaMap, pollMap, locationMap, host, null); + tweets.add(item); + } catch (JSONException e) { + if (BuildConfig.DEBUG) { + Log.w("tweet-v2", e); + } + } + } + return tweets; + } + return new ArrayList<>(0); + } + throw new TwitterException(response); + } catch (IOException | JSONException err) { + throw new TwitterException(err); + } + } + + + /** + * create a list of users using API v 2 + * + * @param endpoint endpoint url to get the user data from + * @param params additional parameters + * @param cursor cursor to parse multiple pages + * @return user list + */ + private Users getUsers(String endpoint, List params, long cursor) throws TwitterException { + // enable additional user fields + params.add("user.fields=" + UserV2.FIELDS_USER); + params.add("max_results=" + settings.getListSize()); + // todo implement cursor + try { + Response response = get(endpoint, params); + ResponseBody body = response.body(); + if (body != null && response.code() == 200) { + JSONObject json = new JSONObject(body.string()); + Users users = new Users(0L, 0L); + // check if result is not empty + if (json.has("data")) { + JSONArray array = json.getJSONArray("data"); + long homeId = settings.getLogin().getId(); + for (int i = 0; i < array.length(); i++) { + try { + users.add(new UserV2(array.getJSONObject(i), homeId)); + } catch (JSONException err) { + if (BuildConfig.DEBUG) { + Log.w("user-v2", err); + } + } + } + } + return users; + } + throw new TwitterException(response); + } catch (IOException | JSONException err) { throw new TwitterException(err); } } diff --git a/app/src/main/java/org/nuclearfog/twidda/backend/async/ImageSaver.java b/app/src/main/java/org/nuclearfog/twidda/backend/async/ImageSaver.java index 1b1eeda0..5822469b 100644 --- a/app/src/main/java/org/nuclearfog/twidda/backend/async/ImageSaver.java +++ b/app/src/main/java/org/nuclearfog/twidda/backend/async/ImageSaver.java @@ -17,18 +17,18 @@ import java.lang.ref.WeakReference; public class ImageSaver extends AsyncTask { private WeakReference weakRef; - private InputStream mediaStream; - private OutputStream fileStream; + private InputStream inputStream; + private OutputStream outputStream; /** - * @param mediaStream inputstream of a cached image file - * @param fileStream destiny output stream of a file + * @param inputStream inputstream of a cached image file + * @param outputStream destiny output stream of a file */ - public ImageSaver(MediaActivity activity, InputStream mediaStream, OutputStream fileStream) { + public ImageSaver(MediaActivity activity, InputStream inputStream, OutputStream outputStream) { super(); weakRef = new WeakReference<>(activity); - this.mediaStream = mediaStream; - this.fileStream = fileStream; + this.inputStream = inputStream; + this.outputStream = outputStream; } @@ -37,11 +37,11 @@ public class ImageSaver extends AsyncTask { try { int length; byte[] buffer = new byte[4096]; - while ((length = mediaStream.read(buffer)) > 0) { - fileStream.write(buffer, 0, length); + while ((length = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, length); } - mediaStream.close(); - fileStream.close(); + inputStream.close(); + outputStream.close(); return true; } catch (Exception e) { e.printStackTrace(); diff --git a/app/src/main/java/org/nuclearfog/twidda/ui/activities/MediaActivity.java b/app/src/main/java/org/nuclearfog/twidda/ui/activities/MediaActivity.java index 5163d719..35328cd4 100644 --- a/app/src/main/java/org/nuclearfog/twidda/ui/activities/MediaActivity.java +++ b/app/src/main/java/org/nuclearfog/twidda/ui/activities/MediaActivity.java @@ -35,6 +35,10 @@ import android.os.Bundle; import android.os.Environment; import android.widget.Toast; +import androidx.activity.result.ActivityResult; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; @@ -53,7 +57,7 @@ import java.util.Locale; * * @author nuclearfog */ -public abstract class MediaActivity extends AppCompatActivity implements LocationListener { +public abstract class MediaActivity extends AppCompatActivity implements ActivityResultCallback, LocationListener { /** * permission type for location @@ -125,11 +129,17 @@ public abstract class MediaActivity extends AppCompatActivity implements Locatio protected static final int REQUEST_STORE_IMG = 0x58D3; + private ActivityResultLauncher activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this); + @Nullable private ImageSaver imageTask; + @Nullable + private Uri srcMediaUri; + @Nullable + private File destMediaFile; + private boolean locationPending = false; - private Uri selectedImage; - private String imageName; + private int requestCode = 0; @Override @@ -173,10 +183,10 @@ public abstract class MediaActivity extends AppCompatActivity implements Locatio @Override - protected final void onActivityResult(int reqCode, int returnCode, @Nullable Intent intent) { - super.onActivityResult(reqCode, returnCode, intent); - if (returnCode == RESULT_OK && intent != null && intent.getData() != null) { - onMediaFetched(reqCode, intent.getData()); + public final void onActivityResult(ActivityResult result) { + Intent intent = result.getData(); + if (result.getResultCode() == RESULT_OK && intent != null && intent.getData() != null) { + onMediaFetched(requestCode, intent.getData()); } } @@ -210,28 +220,26 @@ public abstract class MediaActivity extends AppCompatActivity implements Locatio @SuppressWarnings("IOStreamConstructor") private void saveImage() { try { - if (imageTask == null || imageTask.getStatus() != RUNNING) { + if ((imageTask == null || imageTask.getStatus() != RUNNING) && destMediaFile != null && srcMediaUri != null) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { // store images directly - File imageFolder = Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES); - File imageFile = new File(imageFolder, imageName); - InputStream src = getContentResolver().openInputStream(selectedImage); - OutputStream dest = new FileOutputStream(imageFile); + InputStream src = getContentResolver().openInputStream(srcMediaUri); + OutputStream dest = new FileOutputStream(destMediaFile); imageTask = new ImageSaver(this, src, dest); imageTask.execute(); } else { // use scoped storage - String ext = selectedImage.getLastPathSegment(); + String ext = srcMediaUri.getLastPathSegment(); ext = ext.substring(ext.indexOf('.') + 1).toLowerCase(Locale.ENGLISH); String mime = "image/" + ext; ContentValues values = new ContentValues(); - values.put(DISPLAY_NAME, imageName); + values.put(DISPLAY_NAME, destMediaFile.getName()); values.put(DATE_TAKEN, System.currentTimeMillis()); values.put(RELATIVE_PATH, DIRECTORY_PICTURES); values.put(MIME_TYPE, mime); Uri imageUri = getContentResolver().insert(EXTERNAL_CONTENT_URI, values); if (imageUri != null) { - InputStream src = getContentResolver().openInputStream(selectedImage); + InputStream src = getContentResolver().openInputStream(srcMediaUri); OutputStream dest = getContentResolver().openOutputStream(imageUri); imageTask = new ImageSaver(this, src, dest); imageTask.execute(); @@ -249,9 +257,9 @@ public abstract class MediaActivity extends AppCompatActivity implements Locatio */ public void onImageSaved() { Toast.makeText(getApplicationContext(), R.string.info_image_saved, LENGTH_SHORT).show(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && destMediaFile != null) { // start media scanner to scan for new image - MediaScannerConnection.scanFile(this, new String[]{imageName}, null, null); + MediaScannerConnection.scanFile(this, new String[]{destMediaFile.getPath()}, null, null); } } @@ -315,8 +323,11 @@ public abstract class MediaActivity extends AppCompatActivity implements Locatio * @param uri Uri of the image */ protected void storeImage(Uri uri) { - selectedImage = uri; - imageName = IMAGE_PREFIX + uri.getLastPathSegment(); + String imageName = IMAGE_PREFIX + uri.getLastPathSegment(); + File imageFolder = Environment.getExternalStoragePublicDirectory(DIRECTORY_PICTURES); + destMediaFile = new File(imageFolder, imageName); + srcMediaUri = uri; + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q || checkSelfPermission(WRITE_EXTERNAL_STORAGE) == PERMISSION_GRANTED) { saveImage(); @@ -370,10 +381,11 @@ public abstract class MediaActivity extends AppCompatActivity implements Locatio break; } try { - // todo replace this - startActivityForResult(mediaSelect, requestCode); + activityResultLauncher.launch(mediaSelect); + this.requestCode = requestCode; } catch (ActivityNotFoundException err) { Toast.makeText(getApplicationContext(), R.string.error_no_media_app, LENGTH_SHORT).show(); + this.requestCode = 0; } }