replaced all twitter v1 endpoints, added directmessage endpoints

This commit is contained in:
nuclearfog 2022-01-11 13:03:41 +01:00
parent a75783e80c
commit 9c1f1b98f7
No known key found for this signature in database
GPG Key ID: AA0271FBE406DB98
8 changed files with 265 additions and 234 deletions

View File

@ -4,26 +4,11 @@ import static android.os.AsyncTask.Status.RUNNING;
import static android.view.View.GONE; import static android.view.View.GONE;
import static android.view.View.VISIBLE; import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_SHORT; import static android.widget.Toast.LENGTH_SHORT;
import static org.nuclearfog.twidda.activities.MediaViewer.KEY_MEDIA_LINK; import static org.nuclearfog.twidda.activities.MediaViewer.*;
import static org.nuclearfog.twidda.activities.MediaViewer.KEY_MEDIA_TYPE; import static org.nuclearfog.twidda.activities.SearchPage.*;
import static org.nuclearfog.twidda.activities.MediaViewer.MEDIAVIEWER_ANGIF; import static org.nuclearfog.twidda.activities.TweetEditor.*;
import static org.nuclearfog.twidda.activities.MediaViewer.MEDIAVIEWER_IMAGE; import static org.nuclearfog.twidda.activities.UserDetail.*;
import static org.nuclearfog.twidda.activities.MediaViewer.MEDIAVIEWER_VIDEO; import static org.nuclearfog.twidda.fragments.TweetFragment.*;
import static org.nuclearfog.twidda.activities.SearchPage.KEY_SEARCH_QUERY;
import static org.nuclearfog.twidda.activities.TweetEditor.KEY_TWEETPOPUP_REPLYID;
import static org.nuclearfog.twidda.activities.TweetEditor.KEY_TWEETPOPUP_TEXT;
import static org.nuclearfog.twidda.activities.UserDetail.KEY_USERDETAIL_ID;
import static org.nuclearfog.twidda.activities.UserDetail.KEY_USERDETAIL_MODE;
import static org.nuclearfog.twidda.activities.UserDetail.USERLIST_FAVORIT;
import static org.nuclearfog.twidda.activities.UserDetail.USERLIST_RETWEETS;
import static org.nuclearfog.twidda.fragments.TweetFragment.INTENT_TWEET_REMOVED_ID;
import static org.nuclearfog.twidda.fragments.TweetFragment.INTENT_TWEET_UPDATE_DATA;
import static org.nuclearfog.twidda.fragments.TweetFragment.KEY_FRAG_TWEET_ID;
import static org.nuclearfog.twidda.fragments.TweetFragment.KEY_FRAG_TWEET_MODE;
import static org.nuclearfog.twidda.fragments.TweetFragment.KEY_FRAG_TWEET_SEARCH;
import static org.nuclearfog.twidda.fragments.TweetFragment.RETURN_TWEET_NOT_FOUND;
import static org.nuclearfog.twidda.fragments.TweetFragment.RETURN_TWEET_UPDATE;
import static org.nuclearfog.twidda.fragments.TweetFragment.TWEET_FRAG_ANSWER;
import android.app.Dialog; import android.app.Dialog;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
@ -59,7 +44,7 @@ import org.nuclearfog.textviewtool.LinkAndScrollMovement;
import org.nuclearfog.twidda.R; import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.TweetAction; import org.nuclearfog.twidda.backend.TweetAction;
import org.nuclearfog.twidda.backend.TweetAction.Action; import org.nuclearfog.twidda.backend.TweetAction.Action;
import org.nuclearfog.twidda.backend.apiold.EngineException; import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.model.Tweet; import org.nuclearfog.twidda.model.Tweet;
import org.nuclearfog.twidda.backend.utils.AppStyles; import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler; import org.nuclearfog.twidda.backend.utils.ErrorHandler;
@ -650,9 +635,9 @@ public class TweetActivity extends AppCompatActivity implements OnClickListener,
* @param error Error information * @param error Error information
* @param tweetId ID of the tweet from which an error occurred * @param tweetId ID of the tweet from which an error occurred
*/ */
public void onError(@Nullable EngineException error, long tweetId) { public void onError(@Nullable TwitterException error, long tweetId) {
ErrorHandler.handleFailure(this, error); ErrorHandler.handleFailure(this, error);
if (error != null && error.resourceNotFound()) { if (error != null && error.getErrorType() == ErrorHandler.TwitterError.RESOURCE_NOT_FOUND) {
// Mark tweet as removed, so it can be removed from the list // Mark tweet as removed, so it can be removed from the list
Intent returnData = new Intent(); Intent returnData = new Intent();
returnData.putExtra(INTENT_TWEET_REMOVED_ID, tweetId); returnData.putExtra(INTENT_TWEET_REMOVED_ID, tweetId);

View File

@ -5,15 +5,14 @@ import android.os.AsyncTask;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.nuclearfog.twidda.backend.api.Twitter; import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.apiold.EngineException; import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.backend.apiold.TwitterEngine;
import org.nuclearfog.twidda.backend.lists.Directmessages; import org.nuclearfog.twidda.backend.lists.Directmessages;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.database.AppDatabase; import org.nuclearfog.twidda.database.AppDatabase;
import org.nuclearfog.twidda.fragments.MessageFragment; import org.nuclearfog.twidda.fragments.MessageFragment;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
/** /**
* task to download a direct message list from twitter and handle message actions * task to download a direct message list from twitter and handle message actions
* *
@ -41,9 +40,8 @@ public class MessageLoader extends AsyncTask<Long, Void, Directmessages> {
} }
@Nullable @Nullable
private EngineException twException; private TwitterException twException;
private WeakReference<MessageFragment> callback; private WeakReference<MessageFragment> callback;
private TwitterEngine mTwitter;
private Twitter twitter; private Twitter twitter;
private AppDatabase db; private AppDatabase db;
private Action action; private Action action;
@ -59,7 +57,6 @@ public class MessageLoader extends AsyncTask<Long, Void, Directmessages> {
super(); super();
callback = new WeakReference<>(fragment); callback = new WeakReference<>(fragment);
db = new AppDatabase(fragment.getContext()); db = new AppDatabase(fragment.getContext());
mTwitter = TwitterEngine.getInstance(fragment.getContext());
twitter = Twitter.get(fragment.getContext()); twitter = Twitter.get(fragment.getContext());
this.action = action; this.action = action;
this.cursor = cursor; this.cursor = cursor;
@ -87,14 +84,14 @@ public class MessageLoader extends AsyncTask<Long, Void, Directmessages> {
case DEL: case DEL:
messageId = param[0]; messageId = param[0];
mTwitter.deleteMessage(messageId); twitter.deleteDirectmessage(messageId);
db.deleteMessage(messageId); db.deleteMessage(messageId);
removeMsgId = messageId; removeMsgId = messageId;
break; break;
} }
} catch (EngineException twException) { } catch (TwitterException twException) {
this.twException = twException; this.twException = twException;
if (twException.resourceNotFound()) { if (twException.getErrorType() == ErrorHandler.TwitterError.RESOURCE_NOT_FOUND) {
db.deleteMessage(messageId); db.deleteMessage(messageId);
removeMsgId = messageId; removeMsgId = messageId;
} }

View File

@ -5,6 +5,7 @@ import android.os.AsyncTask;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.nuclearfog.twidda.activities.MessageEditor; import org.nuclearfog.twidda.activities.MessageEditor;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.apiold.EngineException; import org.nuclearfog.twidda.backend.apiold.EngineException;
import org.nuclearfog.twidda.backend.apiold.TwitterEngine; import org.nuclearfog.twidda.backend.apiold.TwitterEngine;
@ -21,23 +22,27 @@ public class MessageUpdater extends AsyncTask<String, Void, Boolean> {
private EngineException twException; private EngineException twException;
private WeakReference<MessageEditor> callback; private WeakReference<MessageEditor> callback;
private TwitterEngine mTwitter; private TwitterEngine mTwitter;
private Twitter twitter;
/** /**
* send direct message * send direct message
* *
* @param callback Activity context * @param activity Activity context
*/ */
public MessageUpdater(@NonNull MessageEditor callback) { public MessageUpdater(@NonNull MessageEditor activity) {
super(); super();
mTwitter = TwitterEngine.getInstance(callback); twitter = Twitter.get(activity);
this.callback = new WeakReference<>(callback); mTwitter = TwitterEngine.getInstance(activity);
callback = new WeakReference<>(activity);
} }
@Override @Override
protected Boolean doInBackground(String[] param) { protected Boolean doInBackground(String[] param) {
try { try {
// upload media first if any // first check if user exists
long id = twitter.showUser(param[0]).getId();
// upload media if any
long mediaId = -1; long mediaId = -1;
String mediaPath = param[2]; String mediaPath = param[2];
if (mediaPath != null && !mediaPath.isEmpty()) { if (mediaPath != null && !mediaPath.isEmpty()) {
@ -45,7 +50,7 @@ public class MessageUpdater extends AsyncTask<String, Void, Boolean> {
} }
// upload message and media ID if defined // upload message and media ID if defined
if (!isCancelled()) { if (!isCancelled()) {
mTwitter.sendDirectMessage(param[0], param[1], mediaId); twitter.sendDirectmessage(id, param[1], mediaId);
} }
return true; return true;
} catch (EngineException twException) { } catch (EngineException twException) {

View File

@ -6,14 +6,13 @@ import androidx.annotation.Nullable;
import org.nuclearfog.twidda.activities.TweetActivity; import org.nuclearfog.twidda.activities.TweetActivity;
import org.nuclearfog.twidda.backend.api.Twitter; import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.apiold.EngineException; import org.nuclearfog.twidda.backend.api.TwitterException;
import org.nuclearfog.twidda.backend.apiold.TwitterEngine; import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.model.Tweet; import org.nuclearfog.twidda.model.Tweet;
import org.nuclearfog.twidda.database.AppDatabase; import org.nuclearfog.twidda.database.AppDatabase;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
/** /**
* Background task to download tweet informations and to take actions * Background task to download tweet informations and to take actions
* *
@ -57,8 +56,7 @@ public class TweetAction extends AsyncTask<TweetAction.Action, Tweet, TweetActio
} }
@Nullable @Nullable
private EngineException twException; private TwitterException twException;
private TwitterEngine mTwitter;
private Twitter twitter; private Twitter twitter;
private WeakReference<TweetActivity> callback; private WeakReference<TweetActivity> callback;
private AppDatabase db; private AppDatabase db;
@ -71,7 +69,6 @@ public class TweetAction extends AsyncTask<TweetAction.Action, Tweet, TweetActio
public TweetAction(TweetActivity activity, long tweetId) { public TweetAction(TweetActivity activity, long tweetId) {
super(); super();
db = new AppDatabase(activity); db = new AppDatabase(activity);
mTwitter = TwitterEngine.getInstance(activity);
twitter = Twitter.get(activity); twitter = Twitter.get(activity);
this.callback = new WeakReference<>(activity); this.callback = new WeakReference<>(activity);
this.tweetId = tweetId; this.tweetId = tweetId;
@ -98,8 +95,8 @@ public class TweetAction extends AsyncTask<TweetAction.Action, Tweet, TweetActio
} }
break; break;
case DELETE: case DELETE: //fixme tweet updates may be buggy because of the API
tweet = mTwitter.deleteTweet(tweetId); tweet = twitter.deleteTweet(tweetId);
db.removeStatus(tweetId); db.removeStatus(tweetId);
// removing retweet reference to this tweet // removing retweet reference to this tweet
if (tweet.getMyRetweetId() > 0) if (tweet.getMyRetweetId() > 0)
@ -107,13 +104,13 @@ public class TweetAction extends AsyncTask<TweetAction.Action, Tweet, TweetActio
break; break;
case RETWEET: case RETWEET:
tweet = mTwitter.retweet(tweetId, true); tweet = twitter.retweetTweet(tweetId);
publishProgress(tweet); publishProgress(tweet);
db.updateStatus(tweet); db.updateStatus(tweet);
break; break;
case UNRETWEET: case UNRETWEET:
tweet = mTwitter.retweet(tweetId, false); tweet = twitter.unretweetTweet(tweetId);
publishProgress(tweet); publishProgress(tweet);
db.updateStatus(tweet); db.updateStatus(tweet);
// removing retweet reference to this tweet // removing retweet reference to this tweet
@ -122,21 +119,21 @@ public class TweetAction extends AsyncTask<TweetAction.Action, Tweet, TweetActio
break; break;
case FAVORITE: case FAVORITE:
tweet = mTwitter.favorite(tweetId, true); tweet = twitter.favoriteTweet(tweetId);
publishProgress(tweet); publishProgress(tweet);
db.storeFavorite(tweet); db.storeFavorite(tweet);
break; break;
case UNFAVORITE: case UNFAVORITE:
tweet = mTwitter.favorite(tweetId, false); tweet = twitter.unfavoriteTweet(tweetId);
publishProgress(tweet); publishProgress(tweet);
db.removeFavorite(tweet); db.removeFavorite(tweet);
break; break;
} }
return action[0]; return action[0];
} catch (EngineException twException) { } catch (TwitterException twException) {
this.twException = twException; this.twException = twException;
if (twException.resourceNotFound()) { if (twException.getErrorType() == ErrorHandler.TwitterError.RESOURCE_NOT_FOUND) {
db.removeStatus(tweetId); db.removeStatus(tweetId);
} }
} catch (Exception err) { } catch (Exception err) {

View File

@ -3,6 +3,7 @@ package org.nuclearfog.twidda.backend;
import android.os.AsyncTask; import android.os.AsyncTask;
import org.nuclearfog.twidda.activities.TweetEditor; import org.nuclearfog.twidda.activities.TweetEditor;
import org.nuclearfog.twidda.backend.api.Twitter;
import org.nuclearfog.twidda.backend.apiold.EngineException; import org.nuclearfog.twidda.backend.apiold.EngineException;
import org.nuclearfog.twidda.backend.apiold.TwitterEngine; import org.nuclearfog.twidda.backend.apiold.TwitterEngine;
import org.nuclearfog.twidda.backend.holder.TweetHolder; import org.nuclearfog.twidda.backend.holder.TweetHolder;
@ -19,20 +20,21 @@ public class TweetUpdater extends AsyncTask<Void, Void, Boolean> {
private EngineException twException; private EngineException twException;
private final TwitterEngine mTwitter; private TwitterEngine mTwitter;
private Twitter twitter;
private final WeakReference<TweetEditor> callback; private WeakReference<TweetEditor> callback;
private TweetHolder tweet; private TweetHolder tweet;
/** /**
* initialize task * initialize task
* *
* @param callback Activity context * @param activity Activity context
*/ */
public TweetUpdater(TweetEditor callback, TweetHolder tweet) { public TweetUpdater(TweetEditor activity, TweetHolder tweet) {
super(); super();
mTwitter = TwitterEngine.getInstance(callback); mTwitter = TwitterEngine.getInstance(activity);
this.callback = new WeakReference<>(callback); twitter = Twitter.get(activity);
callback = new WeakReference<>(activity);
this.tweet = tweet; this.tweet = tweet;
} }
@ -61,7 +63,10 @@ public class TweetUpdater extends AsyncTask<Void, Void, Boolean> {
} }
// upload tweet // upload tweet
if (!isCancelled()) { if (!isCancelled()) {
mTwitter.uploadStatus(tweet, mediaIds); double[] coordinates = null;
if (tweet.hasLocation())
coordinates = new double[] {tweet.getLongitude(), tweet.getLatitude()};
twitter.uploadTweet(tweet.getText(), tweet.getReplyId(), mediaIds, coordinates);
} }
return true; return true;
} catch (EngineException twException) { } catch (EngineException twException) {

View File

@ -75,8 +75,14 @@ public class Twitter {
private static final String USER_UNBLOCK = API + "1.1/blocks/destroy.json"; private static final String USER_UNBLOCK = API + "1.1/blocks/destroy.json";
private static final String USER_MUTE = API + "1.1/mutes/users/create.json"; private static final String USER_MUTE = API + "1.1/mutes/users/create.json";
private static final String USER_UNMUTE = API + "1.1/mutes/users/destroy.json"; private static final String USER_UNMUTE = API + "1.1/mutes/users/destroy.json";
private static final String LIST_TWEETS = API + "1.1/lists/statuses.json"; private static final String TWEETS_LIST = API + "1.1/lists/statuses.json";
private static final String TWEET_SEARCH = API + "1.1/search/tweets.json"; private static final String TWEET_SEARCH = API + "1.1/search/tweets.json";
private static final String TWEET_FAVORITE = API + "1.1/favorites/create.json";
private static final String TWEET_UNFAVORITE = API + "1.1/favorites/destroy.json";
private static final String TWEET_RETWEET = API + "1.1/statuses/retweet/";
private static final String TWEET_UNRETWEET = API + "1.1/statuses/unretweet/";
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 TRENDS = API + "1.1/trends/place.json"; private static final String TRENDS = API + "1.1/trends/place.json";
private static final String LOCATIONS = API + "1.1/trends/available.json"; private static final String LOCATIONS = API + "1.1/trends/available.json";
private static final String USERLIST_SHOW = API + "1.1/lists/show.json"; private static final String USERLIST_SHOW = API + "1.1/lists/show.json";
@ -91,6 +97,8 @@ public class Twitter {
private static final String USERLIST_DEL_USER = API + "1.1/lists/members/destroy.json"; private static final String USERLIST_DEL_USER = API + "1.1/lists/members/destroy.json";
private static final String RELATION = API + "1.1/friendships/show.json"; private static final String RELATION = API + "1.1/friendships/show.json";
private static final String DIRECTMESSAGE = API + "1.1/direct_messages/events/list.json"; private static final String DIRECTMESSAGE = API + "1.1/direct_messages/events/list.json";
private static final String DIRECTMESSAGE_CREATE = API + "1.1/direct_messages/events/new.json";
private static final String DIRECTMESSAGE_DELETE = API + "1.1/direct_messages/events/destroy.json";
public static final String REQUEST_URL = AUTHENTICATE + "?oauth_token="; public static final String REQUEST_URL = AUTHENTICATE + "?oauth_token=";
private static Twitter instance; private static Twitter instance;
@ -690,7 +698,7 @@ public class Twitter {
if (maxId > 1) if (maxId > 1)
params.add("max_id=" + maxId); params.add("max_id=" + maxId);
params.add("list_id=" + listId); params.add("list_id=" + listId);
return getTweets1(LIST_TWEETS, params); return getTweets1(TWEETS_LIST, params);
} }
/** /**
@ -727,30 +735,97 @@ public class Twitter {
/** /**
* lookup tweet by ID * lookup tweet by ID
* *
* @param id tweet ID * @param tweetId tweet ID
* @return tweet information * @return tweet information
*/ */
public Tweet showTweet(long id) throws TwitterException { public Tweet showTweet(long tweetId) throws TwitterException {
List<String> params = new ArrayList<>(3); List<String> params = new ArrayList<>(3);
params.add("id=" + id); params.add("id=" + tweetId);
params.add(TweetV1.EXT_MODE); return getTweet(SHOW_TWEET, params);
try {
Response response = get(SHOW_TWEET, params);
if (response.body() != null) {
JSONObject json = new JSONObject(response.body().string());
if (response.code() == 200) {
return new TweetV1(json, settings.getCurrentUserId());
} else {
throw new TwitterException(json);
} }
} else {
throw new TwitterException(response); /**
* favorite specific tweet
*
* @param tweetId Tweet ID
* @return updated tweet
*/
public Tweet favoriteTweet(long tweetId) throws TwitterException {
List<String> params = new ArrayList<>(3);
params.add("id=" + tweetId);
return getTweet(TWEET_FAVORITE, params);
} }
} catch (IOException err) {
throw new TwitterException(err); /**
} catch (JSONException err) { * remove tweet from favorits
throw new TwitterException(err); *
* @param tweetId Tweet ID
* @return updated tweet
*/
public Tweet unfavoriteTweet(long tweetId) throws TwitterException {
List<String> params = new ArrayList<>(3);
params.add("id=" + tweetId);
return getTweet(TWEET_UNFAVORITE, params);
} }
/**
* retweet specific tweet
*
* @param tweetId Tweet ID
* @return updated tweet
*/
public Tweet retweetTweet(long tweetId) throws TwitterException {
return getTweet(TWEET_RETWEET + tweetId + ".json", new ArrayList<>(2));
}
/**
* remove retweet
*
* @param tweetId ID of the retweeted tweet
* @return updated tweet
*/
public Tweet unretweetTweet(long tweetId) throws TwitterException {
return getTweet(TWEET_UNRETWEET + tweetId + ".json", new ArrayList<>(2));
}
/**
* remove tweet of the authenticating user
*
* @param tweetId tweet ID
* @return tweet information
*/
public Tweet deleteTweet(long tweetId) throws TwitterException {
return getTweet(TWEET_DELETE + tweetId + ".json", new ArrayList<>(2));
}
/**
* upload tweet with additional attachment
*
* @param text tweet text
* @param replyId ID of the tweet to reply or -1 if none
* @param mediaIds array of media IDs
* @param coordinates array of longitude/latitude coordinates
* @return information of the uploaded tweet
*/
public Tweet uploadTweet(String text, long replyId, long[] mediaIds, double[] coordinates) throws TwitterException {
List<String> params = new ArrayList<>(2);
params.add("status=" + StringTools.encode(text));
if (replyId > 0)
params.add("in_reply_to_status_id=" + replyId);
if (mediaIds != null && mediaIds.length > 0) {
StringBuilder buf = new StringBuilder();
for (long id : mediaIds)
buf.append(id).append("%2C");
String idStr = buf.substring(0, buf.lastIndexOf("%2C"));
params.add("media_ids=" + idStr);
}
if (coordinates != null) { // fixme not working with coordinates
String lat = Double.toString(coordinates[0]);
String lon = Double.toString(coordinates[1]);
params.add("lat=" + StringTools.encode(lat));
params.add("long=" + StringTools.encode(lon));
}
return getTweet(TWEET_UPLOAD, params);
} }
/** /**
@ -909,6 +984,64 @@ public class Twitter {
sendPost(USERLIST_DEL_USER, params); sendPost(USERLIST_DEL_USER, params);
} }
/**
* send directmessage to user
*
* @param userId ID of the user
* @param message message text
* @param mediaId ID of uploaded media files or -1 if none
*/
public void sendDirectmessage(long userId, String message, long mediaId) throws TwitterException {
try {
JSONObject data = new JSONObject();
JSONObject root = new JSONObject();
JSONObject target = new JSONObject();
JSONObject msg_create = new JSONObject();
JSONObject event = new JSONObject();
target.put("recipient_id", Long.toString(userId));
msg_create.put("target", target);
msg_create.put("message_data", data);
event.put("type", "message_create");
event.put("message_create", msg_create);
root.put("event", event);
data.put("text", message);
if (mediaId > 0) {
JSONObject attachment = new JSONObject();
JSONObject media = new JSONObject();
attachment.put("type", "media");
attachment.put("media", media);
media.put("id", Long.toString(mediaId));
data.put("attachment", attachment);
}
Response response = post(DIRECTMESSAGE_CREATE, new ArrayList<>(0), root);
if (response.code() != 200) {
throw new TwitterException(response);
}
} catch (IOException err) {
throw new TwitterException(err);
} catch (JSONException err) {
throw new TwitterException(err);
}
}
/**
* delete directmessage
*
* @param messageId ID of the message to delete
*/
public void deleteDirectmessage(long messageId) throws TwitterException {
List<String> params = new ArrayList<>(2);
params.add("id=" + messageId);
try {
Response response = delete(DIRECTMESSAGE_DELETE, params);
if (response.code() != 200) {
throw new TwitterException(response);
}
} catch (IOException err) {
throw new TwitterException(err);
}
}
/** /**
*get current user's direct messages *get current user's direct messages
* *
@ -1032,6 +1165,39 @@ public class Twitter {
} }
} }
/**
* return tweet from endpoint
*
* @param endpoint to use
* @param params additional parameter
*/
private Tweet getTweet(String endpoint, List<String> params) throws TwitterException {
try {
params.add(TweetV1.EXT_MODE);
Response response;
if (endpoint.equals(SHOW_TWEET)) {
response = get(endpoint, params);
} else {
response = post(endpoint, params);
}
if (response.body() != null) {
JSONObject json = new JSONObject(response.body().string());
if (response.code() == 200) {
long currentId = settings.getCurrentUserId();
return new TweetV1(json, currentId);
} else {
throw new TwitterException(json);
}
} else {
throw new TwitterException(response);
}
} catch (IOException err) {
throw new TwitterException(err);
} catch (JSONException err) {
throw new TwitterException(err);
}
}
/** /**
* create a list of users using API v 1.1 * create a list of users using API v 1.1
* *
@ -1284,6 +1450,20 @@ public class Twitter {
return client.newCall(request).execute(); return client.newCall(request).execute();
} }
/**
* create and call POST endpoint
*
* @param endpoint endpoint url
* @return http resonse
*/
private Response post(String endpoint, List<String> params, JSONObject json) throws IOException {
String authHeader = buildHeader("POST", endpoint, params);
String url = appendParams(endpoint, params);
RequestBody body = RequestBody.create(MediaType.parse("application/json"), json.toString());
Request request = new Request.Builder().url(url).addHeader("Authorization", authHeader).post(body).build();
return client.newCall(request).execute();
}
/** /**
* create and call GET endpoint * create and call GET endpoint
* *
@ -1297,6 +1477,19 @@ public class Twitter {
return client.newCall(request).execute(); return client.newCall(request).execute();
} }
/**
* create and call GET endpoint
*
* @param endpoint endpoint url
* @return http response
*/
private Response delete(String endpoint, List<String> 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();
return client.newCall(request).execute();
}
/** /**
* create http header with credentials and signature * create http header with credentials and signature
* *

View File

@ -7,12 +7,10 @@ import android.graphics.BitmapFactory;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.nuclearfog.twidda.backend.holder.TweetHolder;
import org.nuclearfog.twidda.backend.utils.ProxySetup; import org.nuclearfog.twidda.backend.utils.ProxySetup;
import org.nuclearfog.twidda.backend.utils.TLSSocketFactory; import org.nuclearfog.twidda.backend.utils.TLSSocketFactory;
import org.nuclearfog.twidda.backend.utils.Tokens; import org.nuclearfog.twidda.backend.utils.Tokens;
import org.nuclearfog.twidda.database.GlobalSettings; import org.nuclearfog.twidda.database.GlobalSettings;
import org.nuclearfog.twidda.model.Tweet;
import org.nuclearfog.twidda.model.User; import org.nuclearfog.twidda.model.User;
import java.io.File; import java.io.File;
@ -26,10 +24,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import twitter4j.GeoLocation;
import twitter4j.IDs; import twitter4j.IDs;
import twitter4j.Status;
import twitter4j.StatusUpdate;
import twitter4j.Twitter; import twitter4j.Twitter;
import twitter4j.TwitterException; import twitter4j.TwitterException;
import twitter4j.TwitterFactory; import twitter4j.TwitterFactory;
@ -142,151 +137,6 @@ public class TwitterEngine {
} }
} }
/**
* send tweet
*
* @param tweet Tweet holder
* @throws EngineException if twitter service is unavailable
*/
public void uploadStatus(TweetHolder tweet, long[] mediaIds) throws EngineException {
try {
StatusUpdate mStatus = new StatusUpdate(tweet.getText());
if (tweet.isReply())
mStatus.setInReplyToStatusId(tweet.getReplyId());
if (tweet.hasLocation())
mStatus.setLocation(new GeoLocation(tweet.getLatitude(), tweet.getLongitude()));
if (mediaIds.length > 0)
mStatus.setMediaIds(mediaIds);
twitter.updateStatus(mStatus);
} catch (Exception err) {
throw new EngineException(err);
}
}
/**
* Retweet Type
*
* @param tweetId Tweet ID
* @param retweet true to retweet this tweet
* @return updated tweet
* @throws EngineException if Access is unavailable
*/
public Tweet retweet(long tweetId, boolean retweet) throws EngineException {
try {
Status tweet = twitter.showStatus(tweetId);
Status embedded = tweet.getRetweetedStatus();
int retweetCount = tweet.getRetweetCount();
int favoriteCount = tweet.getFavoriteCount();
if (embedded != null) {
tweetId = embedded.getId();
retweetCount = embedded.getRetweetCount();
favoriteCount = embedded.getFavoriteCount();
}
if (retweet) {
twitter.retweetStatus(tweetId);
retweetCount++;
} else {
twitter.unRetweetStatus(tweetId);
if (retweetCount > 0)
retweetCount--;
}
return new TweetV1(tweet, twitter.getId(), tweet.getCurrentUserRetweetId(), retweetCount,
retweet, favoriteCount, tweet.isFavorited());
} catch (Exception err) {
throw new EngineException(err);
}
}
/**
* favorite Tweet
*
* @param tweetId Tweet ID
* @param favorite true to favorite this tweet
* @return updated tweet
* @throws EngineException if Access is unavailable
*/
public Tweet favorite(long tweetId, boolean favorite) throws EngineException {
try {
Status tweet = twitter.showStatus(tweetId);
Status embedded = tweet.getRetweetedStatus();
int retweetCount = tweet.getRetweetCount();
int favoriteCount = tweet.getFavoriteCount();
if (embedded != null) {
tweetId = embedded.getId();
retweetCount = embedded.getRetweetCount();
favoriteCount = embedded.getFavoriteCount();
}
if (favorite) {
twitter.createFavorite(tweetId);
favoriteCount++;
} else {
twitter.destroyFavorite(tweetId);
if (favoriteCount > 0)
favoriteCount--;
}
return new TweetV1(tweet, twitter.getId(), tweet.getCurrentUserRetweetId(),
retweetCount, tweet.isRetweeted(), favoriteCount, favorite);
} catch (Exception err) {
throw new EngineException(err);
}
}
/**
* delete tweet
*
* @param tweetId Tweet ID
* @return removed tweet
* @throws EngineException if Access is unavailable
*/
public Tweet deleteTweet(long tweetId) throws EngineException {
try {
// Twitter API returns removed tweet with false information
// so get the tweet first before delete
TweetV1 tweet = new TweetV1(twitter.showStatus(tweetId), twitter.getId());
twitter.destroyStatus(tweetId);
return tweet;
} catch (Exception err) {
throw new EngineException(err);
}
}
/**
* send direct message to an user
*
* @param username screen name of the user
* @param message message text
* @param mediaId media ID referenced by Twitter
* @throws EngineException if access is unavailable
*/
public void sendDirectMessage(String username, String message, long mediaId) throws EngineException {
try {
if (mediaId > 0) {
long userId = twitter.showUser(username).getId();
twitter.sendDirectMessage(userId, message, mediaId);
} else {
twitter.sendDirectMessage(username, message);
}
} catch (Exception err) {
throw new EngineException(err);
}
}
/**
* Delete Direct Message
*
* @param id Message ID
* @throws EngineException if Access is unavailable or message not found
*/
public void deleteMessage(long id) throws EngineException {
try {
twitter.destroyDirectMessage(id);
} catch (Exception err) {
throw new EngineException(err);
}
}
/** /**
* update current users profile * update current users profile
* *

View File

@ -19,7 +19,6 @@ import org.nuclearfog.twidda.activities.UserProfile;
import org.nuclearfog.twidda.adapter.MessageAdapter; import org.nuclearfog.twidda.adapter.MessageAdapter;
import org.nuclearfog.twidda.adapter.MessageAdapter.OnItemSelected; import org.nuclearfog.twidda.adapter.MessageAdapter.OnItemSelected;
import org.nuclearfog.twidda.backend.MessageLoader; import org.nuclearfog.twidda.backend.MessageLoader;
import org.nuclearfog.twidda.backend.apiold.EngineException;
import org.nuclearfog.twidda.backend.lists.Directmessages; import org.nuclearfog.twidda.backend.lists.Directmessages;
import org.nuclearfog.twidda.backend.utils.ErrorHandler; import org.nuclearfog.twidda.backend.utils.ErrorHandler;
import org.nuclearfog.twidda.dialog.ConfirmDialog; import org.nuclearfog.twidda.dialog.ConfirmDialog;
@ -197,7 +196,7 @@ public class MessageFragment extends ListFragment implements OnItemSelected, OnC
* *
* @param error Twitter exception * @param error Twitter exception
*/ */
public void onError(@NonNull EngineException error) { public void onError(@NonNull ErrorHandler.TwitterError error) {
ErrorHandler.handleFailure(requireContext(), error); ErrorHandler.handleFailure(requireContext(), error);
setRefresh(false); setRefresh(false);
} }