This commit is contained in:
nuclearfog 2022-12-21 16:41:14 +01:00
parent 201d3d7624
commit 54d10eb768
No known key found for this signature in database
GPG Key ID: 03488A185C476379
5 changed files with 103 additions and 93 deletions

View File

@ -298,13 +298,12 @@ public interface Connection {
/**
* get replies of a status
*
* @param name screen name of the status author
* @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
* @return list of statuses
*/
List<Status> getStatusReplies(String name, long id, long minId, long maxId) throws ConnectionException;
List<Status> getStatusReplies(long id, long minId, long maxId) throws ConnectionException;
/**
* lookup status by ID

View File

@ -425,7 +425,7 @@ public class Mastodon implements Connection {
@Override
public List<Status> getStatusReplies(String name, long id, long minId, long maxId) {
public List<Status> getStatusReplies(long id, long minId, long maxId) {
return new ArrayList<>(0); // todo add implementation
}

View File

@ -628,25 +628,22 @@ public class Twitter implements Connection {
@Override
public List<Status> getStatusReplies(String name, long id, long minId, long maxId) throws TwitterException {
public List<Status> getStatusReplies(long id, long minId, long maxId) throws TwitterException {
List<String> params = new ArrayList<>();
if (minId > 0)
params.add("since_id=" + minId);
else
params.add("since_id=" + id);
if (maxId > 1)
params.add("max_id=" + maxId);
if (name.startsWith("@"))
name = name.substring(1);
params.add("until_id=" + maxId);
params.add("query=conversation_id:" + id);
List<Status> result = getTweets2(TWEET_SEARCH_2, params);
List<Status> replies = new LinkedList<>();
// chose only the first tweet of a conversation
for (Status reply : result) {
if (reply.getRepliedStatusId() == id) {
replies.add(reply);
}
}
if (settings.filterResults())
if (settings.filterResults() && !replies.isEmpty())
filterTweets(replies);
return replies;
}
@ -1180,23 +1177,31 @@ public class Twitter implements Connection {
params.add(TweetV2.FIELDS_TWEET);
params.add(TweetV2.FIELDS_EXPANSION);
params.add(UserV2.USER_FIELDS);
params.add(MediaV2.FIELDS_MEDIA);
params.add(PollV2.FIELDS_POLL);
params.add(LocationV2.FIELDS_PLACE);
params.add("max_results=" + settings.getListSize());
Response response = get(endpoint, params);
ResponseBody body = response.body();
if (body != null && response.code() == 200) {
JSONArray array = new JSONObject(body.string()).getJSONArray("data");
long homeId = settings.getLogin().getId();
List<Status> tweets = new ArrayList<>(array.length() + 1);
for (int i = 0; i < array.length(); i++) {/*
try {
tweets.add(new TweetV2(array.getJSONObject(i), homeId));
} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.w("tweet", e);
JSONObject json = new JSONObject(body.string());
JSONArray data = json.optJSONArray("data");
if (data != null && data.length() > 0) {
List<Status> tweets = new ArrayList<>(data.length() + 1);
UserV2Map userMap = new UserV2Map(json, settings.getLogin().getId());
for (int i = 0; i < data.length(); i++) {
try {
Status item = new TweetV2(data.getJSONObject(i), userMap);
tweets.add(item);
} catch (JSONException e) {
if (BuildConfig.DEBUG) {
Log.w("tweet", e);
}
}
}*/
}
return tweets;
}
return tweets;
return new ArrayList<>(0);
}
throw new TwitterException(response);
} catch (IOException | JSONException err) {
@ -1256,7 +1261,6 @@ public class Twitter implements Connection {
params.add(TweetV2.FIELDS_TWEET_PRIVATE);
else
params.add(TweetV2.FIELDS_TWEET);
params.add(TweetV2.FIELDS_EXPANSION);
params.add(UserV2.USER_FIELDS);
params.add(MediaV2.FIELDS_MEDIA);
@ -1270,11 +1274,12 @@ public class Twitter implements Connection {
ResponseBody body = response.body();
if (body != null && response.code() == 200) {
JSONObject json = new JSONObject(body.string());
JSONObject data = json.getJSONObject("data");
UserV2Map userMap = new UserV2Map(json, settings.getLogin().getId());
MediaV2Map mediaMap = new MediaV2Map(json);
PollV2Map pollMap = new PollV2Map(json);
LocationV2Map locationMap = new LocationV2Map(json);
return new TweetV2(json, userMap, mediaMap, pollMap, locationMap, statusCompat);
return new TweetV2(data, userMap, mediaMap, pollMap, locationMap, statusCompat);
}
throw new TwitterException(response);
} catch (IOException | JSONException err) {

View File

@ -78,41 +78,39 @@ public class TweetV2 implements Status {
/**
*/
public TweetV2(JSONObject json, UserV2Map userMap, MediaV2Map mediaMap, PollV2Map pollMap, LocationV2Map locationMap) throws JSONException {
this(json, userMap, mediaMap, pollMap, locationMap, null);
public TweetV2(JSONObject json, UserV2Map userMap) throws JSONException {
this(json, userMap, null, null, null, null);
}
/**
* @param json Tweet v2 json
* @param tweetCompat Tweet containing base informations
*/
public TweetV2(JSONObject json, UserV2Map userMap, MediaV2Map mediaMap, PollV2Map pollMap, LocationV2Map locationMap, @Nullable Status tweetCompat) throws JSONException {
JSONObject dataJson = json.getJSONObject("data");
JSONObject publicMetrics = dataJson.getJSONObject("public_metrics");
JSONObject nonPublicMetrics = dataJson.optJSONObject("non_public_metrics");
JSONObject entities = dataJson.getJSONObject("entities");
JSONObject geoJson = dataJson.optJSONObject("geo");
JSONObject attachments = dataJson.getJSONObject("attachments");
JSONArray mentionsJson = entities.optJSONArray("mentions");
JSONArray tweetReferences = dataJson.optJSONArray("referenced_tweets");
JSONArray pollIds = attachments.optJSONArray("poll_ids");
JSONArray mediaKeys = attachments.optJSONArray("media_keys");
JSONArray urls = entities.optJSONArray("urls");
String idStr = dataJson.getString("id");
String textStr = dataJson.optString("text", "");
String timeStr = dataJson.optString("created_at", "");
String replyUserIdStr = dataJson.optString("in_reply_to_user_id", "-1");
String conversationIdStr = dataJson.optString("conversation_id", "-1");
String authorId = dataJson.getString("author_id");
public TweetV2(JSONObject json, @NonNull UserV2Map userMap, @Nullable MediaV2Map mediaMap, @Nullable PollV2Map pollMap, @Nullable LocationV2Map locationMap, @Nullable Status tweetCompat) throws JSONException {
JSONObject publicMetrics = json.getJSONObject("public_metrics");
JSONObject nonPublicMetrics = json.optJSONObject("non_public_metrics");
JSONObject entities = json.optJSONObject("entities");
JSONObject geoJson = json.optJSONObject("geo");
JSONObject attachments = json.optJSONObject("attachments");
JSONArray tweetReferences = json.optJSONArray("referenced_tweets");
String idStr = json.getString("id");
String textStr = json.optString("text", "");
String timeStr = json.optString("created_at", "");
String replyUserIdStr = json.optString("in_reply_to_user_id", "-1");
String conversationIdStr = json.optString("conversation_id", "-1");
String authorId = json.getString("author_id");
// string to long conversion
try {
id = Long.parseLong(idStr);
replyUserId = Long.parseLong(replyUserIdStr);
author = userMap.get(Long.parseLong(authorId));
if (pollIds != null && pollIds.length() > 0)
poll = pollMap.get(Long.parseLong(pollIds.getString(0)));
if (geoJson != null) {
if (attachments != null) {
JSONArray pollIds = attachments.optJSONArray("poll_ids");
if (pollMap != null && pollIds != null && pollIds.length() > 0)
poll = pollMap.get(Long.parseLong(pollIds.getString(0)));
}
if (locationMap != null && geoJson != null) {
String locIdStr = geoJson.getString("place_id");
location = locationMap.get(Long.parseUnsignedLong(locIdStr, 16));
}
@ -121,14 +119,13 @@ public class TweetV2 implements Status {
} catch (NumberFormatException e) {
throw new JSONException("Bad IDs: " + conversationIdStr + "," + idStr + "," + replyUserIdStr + "," + authorId);
}
replyCount = publicMetrics.getInt("reply_count");
retweetCount = publicMetrics.getInt("retweet_count");
favoriteCount = publicMetrics.getInt("like_count");
timestamp = StringTools.getTime(timeStr, StringTools.TIME_TWITTER_V2);
source = dataJson.optString("source", "unknown");
sensitive = dataJson.optBoolean("possibly_sensitive", false);
// add attributes missing from API V2.0
source = json.optString("source", "unknown");
sensitive = json.optBoolean("possibly_sensitive", false);
// add missing attributes using API v1.1
if (tweetCompat != null) {
replyName = tweetCompat.getReplyName();
embedded = tweetCompat.getEmbeddedStatus();
@ -137,57 +134,66 @@ public class TweetV2 implements Status {
source = tweetCompat.getSource(); // fix for any reason Twitter doesn't return source information anymore
}
// add media
if (mediaKeys != null && mediaKeys.length() > 0) {
medias = new Media[mediaKeys.length()];
for (int i = 0 ; i < mediaKeys.length() ; i++) {
medias[i] = mediaMap.get(mediaKeys.getString(i));
if (attachments != null) {
JSONArray mediaKeys = attachments.optJSONArray("media_keys");
if (mediaMap != null && mediaKeys != null && mediaKeys.length() > 0) {
medias = new Media[mediaKeys.length()];
for (int i = 0; i < mediaKeys.length(); i++) {
medias[i] = mediaMap.get(mediaKeys.getString(i));
}
}
}
// add metrics
if (nonPublicMetrics != null) {
metrics = new MetricsV2(publicMetrics, nonPublicMetrics);
}
// add mentioned usernames
if (mentionsJson != null && mentionsJson.length() > 0) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < mentionsJson.length(); i++) {
JSONObject mentionJson = mentionsJson.getJSONObject(i);
builder.append('@').append(mentionJson.getString("username")).append(' ');
if (entities != null) {
JSONArray mentionsJson = entities.optJSONArray("mentions");
JSONArray urls = entities.optJSONArray("urls");
// add mentioned usernames
if (mentionsJson != null && mentionsJson.length() > 0) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < mentionsJson.length(); i++) {
JSONObject mentionJson = mentionsJson.getJSONObject(i);
builder.append('@').append(mentionJson.getString("username")).append(' ');
}
mentions = builder.toString();
}
mentions = builder.toString();
}
// expand urls
if (urls != null) {
// check for shortened urls and replace them with full urls
StringBuilder builder = new StringBuilder(textStr);
List<Card> cardsList = new LinkedList<>();
for (int i = urls.length() - 1; i >= 0; i--) {
// expand shortened links
JSONObject entry = urls.getJSONObject(i);
String expandedUrl = entry.getString("expanded_url");
String displayUrl = entry.getString("display_url");
String mediaKey = entry.optString("media_key", "");
int start = entry.optInt("start", -1);
int end = entry.optInt("end", -1);
if (start >= 0 && end > start) {
int offset = StringTools.calculateIndexOffset(textStr, start);
// replace shortened link
if (!displayUrl.contains("pic.twitter.com")) {
builder.replace(start + offset, end + offset, expandedUrl);
// expand urls
if (urls != null) {
// check for shortened urls and replace them with full urls
StringBuilder builder = new StringBuilder(textStr);
List<Card> cardsList = new LinkedList<>();
for (int i = urls.length() - 1; i >= 0; i--) {
// expand shortened links
JSONObject entry = urls.getJSONObject(i);
String expandedUrl = entry.getString("expanded_url");
String displayUrl = entry.getString("display_url");
String mediaKey = entry.optString("media_key", "");
int start = entry.optInt("start", -1);
int end = entry.optInt("end", -1);
if (start >= 0 && end > start) {
int offset = StringTools.calculateIndexOffset(textStr, start);
// replace shortened link
if (!displayUrl.contains("pic.twitter.com")) {
builder.replace(start + offset, end + offset, expandedUrl);
}
// remove shortened link if it is a media link
else {
builder.delete(start + offset, end + offset);
}
}
// remove shortened link if it is a media link
else {
builder.delete(start + offset, end + offset);
// create Twitter card if link is not a media link
if (mediaKey.isEmpty()) {
TwitterCard item = new TwitterCard(urls.getJSONObject(i));
cardsList.add(item);
}
}
// create Twitter card if link is not a media link
if (mediaKey.isEmpty()) {
TwitterCard item = new TwitterCard(urls.getJSONObject(i));
cardsList.add(item);
}
tweetText = StringTools.unescapeString(builder.toString());
cards = cardsList.toArray(cards);
} else {
tweetText = StringTools.unescapeString(textStr);
}
tweetText = StringTools.unescapeString(builder.toString());
cards = cardsList.toArray(cards);
} else {
tweetText = StringTools.unescapeString(textStr);
}

View File

@ -159,18 +159,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(search, id, sinceId, maxId);
statuses = connection.getStatusReplies(id, sinceId, maxId);
if (!statuses.isEmpty() && db.containsStatus(id)) {
db.saveReplyTimeline(statuses);
}
}
} else if (sinceId > 0) {
statuses = connection.getStatusReplies(search, id, sinceId, maxId);
statuses = connection.getStatusReplies(id, sinceId, maxId);
if (!statuses.isEmpty() && db.containsStatus(id)) {
db.saveReplyTimeline(statuses);
}
} else if (maxId > 1) {
statuses = connection.getStatusReplies(search, id, sinceId, maxId);
statuses = connection.getStatusReplies(id, sinceId, maxId);
}
break;