prepared migrating to notification, added mastodon image upload & download, bug fix
This commit is contained in:
parent
2eb99730dd
commit
b0c9f0efe2
|
@ -3,7 +3,6 @@ package org.nuclearfog.twidda.adapter;
|
|||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
import static org.nuclearfog.twidda.backend.utils.StringTools.formatCreationTime;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
@ -182,7 +181,7 @@ public class MessageAdapter extends Adapter<ViewHolder> {
|
|||
holder.username.setText(sender.getUsername());
|
||||
holder.screenname.setText(sender.getScreenname());
|
||||
holder.receiver.setText(message.getReceiver().getScreenname());
|
||||
holder.time.setText(formatCreationTime(resources, message.getTimestamp()));
|
||||
holder.time.setText(StringTools.formatCreationTime(resources, message.getTimestamp()));
|
||||
holder.message.setText(text);
|
||||
if (sender.isVerified()) {
|
||||
holder.verifiedIcon.setVisibility(VISIBLE);
|
||||
|
|
|
@ -3,7 +3,6 @@ package org.nuclearfog.twidda.adapter;
|
|||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||
import static org.nuclearfog.twidda.backend.utils.StringTools.formatCreationTime;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
@ -67,6 +66,7 @@ public class UserlistAdapter extends Adapter<ViewHolder> {
|
|||
private UserLists userlists = new UserLists(0L, 0L);
|
||||
private int loadingIndex = NO_LOADING;
|
||||
|
||||
|
||||
/**
|
||||
* @param listener item click listener
|
||||
*/
|
||||
|
@ -153,7 +153,7 @@ public class UserlistAdapter extends Adapter<ViewHolder> {
|
|||
vh.description.setText(item.getDescription());
|
||||
vh.username.setText(owner.getUsername());
|
||||
vh.screenname.setText(owner.getScreenname());
|
||||
vh.date.setText(formatCreationTime(resources, item.getTimestamp()));
|
||||
vh.date.setText(StringTools.formatCreationTime(resources, item.getTimestamp()));
|
||||
vh.member.setText(NUM_FORMAT.format(item.getMemberCount()));
|
||||
vh.subscriber.setText(NUM_FORMAT.format(item.getSubscriberCount()));
|
||||
if (settings.imagesEnabled() && !owner.getImageUrl().isEmpty()) {
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.nuclearfog.twidda.backend.api;
|
|||
import org.nuclearfog.twidda.backend.lists.Messages;
|
||||
import org.nuclearfog.twidda.backend.lists.UserLists;
|
||||
import org.nuclearfog.twidda.backend.lists.Users;
|
||||
import org.nuclearfog.twidda.backend.update.MediaUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.update.ProfileUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.StatusUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.UserListUpdate;
|
||||
|
@ -515,7 +515,7 @@ public interface Connection {
|
|||
* @param link link to the image
|
||||
* @return image bitmap
|
||||
*/
|
||||
MediaUpdate downloadImage(String link) throws ConnectionException;
|
||||
MediaStatus downloadImage(String link) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* updates current user's profile
|
||||
|
@ -545,7 +545,7 @@ public interface Connection {
|
|||
* @param mediaUpdate inputstream with MIME type of the media
|
||||
* @return media ID
|
||||
*/
|
||||
long uploadMedia(MediaUpdate mediaUpdate) throws ConnectionException;
|
||||
long uploadMedia(MediaStatus mediaUpdate) throws ConnectionException;
|
||||
|
||||
/**
|
||||
* get notification of the current user
|
||||
|
|
|
@ -21,7 +21,7 @@ import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonUser;
|
|||
import org.nuclearfog.twidda.backend.lists.Messages;
|
||||
import org.nuclearfog.twidda.backend.lists.UserLists;
|
||||
import org.nuclearfog.twidda.backend.lists.Users;
|
||||
import org.nuclearfog.twidda.backend.update.MediaUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.update.ProfileUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.StatusUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.UserListUpdate;
|
||||
|
@ -44,11 +44,14 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import okio.BufferedSink;
|
||||
import okio.Okio;
|
||||
|
||||
/**
|
||||
* Implementation of the Mastodon API
|
||||
|
@ -90,8 +93,11 @@ public class Mastodon implements Connection {
|
|||
private static final String ENDPOINT_LOOKUP_USER = "/api/v1/accounts/lookup";
|
||||
private static final String ENDPOINT_USERLIST = "/api/v1/lists";
|
||||
private static final String ENDPOINT_NOTIFICATION = "/api/v1/notifications";
|
||||
private static final String ENDPOINT_UPLOAD_MEDIA = "/api/v2/media";
|
||||
private static final String ENDPOINT_MEDIA_STATUS = "/api/v1/media/";
|
||||
|
||||
MediaType TYPE_TEXT = MediaType.parse("text/plain");
|
||||
private static final MediaType TYPE_TEXT = MediaType.parse("text/plain");
|
||||
private static final MediaType TYPE_STREAM = MediaType.parse("application/octet-stream");
|
||||
|
||||
|
||||
private GlobalSettings settings;
|
||||
|
@ -508,6 +514,8 @@ public class Mastodon implements Connection {
|
|||
public void uploadStatus(StatusUpdate update, long[] mediaIds) throws MastodonException {
|
||||
List<String> params = new ArrayList<>();
|
||||
params.add("status=" + StringTools.encode(update.getText()));
|
||||
// add identifier to prevent duplicate posts
|
||||
params.add("Idempotency-Key=" + System.currentTimeMillis() / 5000);
|
||||
params.add("visibility=public");
|
||||
if (update.getReplyId() > 0)
|
||||
params.add("in_reply_to_id=" + update.getReplyId());
|
||||
|
@ -654,8 +662,23 @@ public class Mastodon implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public MediaUpdate downloadImage(String link) throws MastodonException {
|
||||
throw new MastodonException("not implemented!"); // todo add implementation
|
||||
public MediaStatus downloadImage(String link) throws MastodonException {
|
||||
try {
|
||||
Request request = new Request.Builder().url(link).get().build();
|
||||
Response response = client.newCall(request).execute();
|
||||
ResponseBody body = response.body();
|
||||
if (response.code() == 200 && body != null) {
|
||||
MediaType type = body.contentType();
|
||||
if (type != null) {
|
||||
String mime = type.toString();
|
||||
InputStream stream = body.byteStream();
|
||||
return new MediaStatus(stream, mime);
|
||||
}
|
||||
}
|
||||
throw new MastodonException(response);
|
||||
} catch (IOException e) {
|
||||
throw new MastodonException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -678,8 +701,32 @@ public class Mastodon implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public long uploadMedia(MediaUpdate mediaUpdate) throws MastodonException {
|
||||
throw new MastodonException("not implemented!"); // todo add implementation
|
||||
public long uploadMedia(MediaStatus mediaUpdate) throws MastodonException {
|
||||
try {
|
||||
Response response = post(ENDPOINT_UPLOAD_MEDIA, new ArrayList<>(), mediaUpdate.getStream(), "file");
|
||||
ResponseBody body = response.body();
|
||||
if (body != null) {
|
||||
if (response.code() == 200) {
|
||||
JSONObject json = new JSONObject(body.string());
|
||||
return Long.parseLong(json.getString("id"));
|
||||
}
|
||||
// wait until processed
|
||||
else if (response.code() == 202) {
|
||||
int retryCount = 0;
|
||||
JSONObject json = new JSONObject(body.string());
|
||||
long id = Long.parseLong(json.getString("id"));
|
||||
while (retryCount++ < 10) {
|
||||
response = get(ENDPOINT_MEDIA_STATUS + id, new ArrayList<>());
|
||||
if (response.code() == 200)
|
||||
return id;
|
||||
Thread.sleep(2000L);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new MastodonException(response);
|
||||
} catch (IOException | JSONException | NumberFormatException | InterruptedException e) {
|
||||
throw new MastodonException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -951,18 +998,6 @@ public class Mastodon implements Connection {
|
|||
return get(currentLogin.getHostname(), endpoint, currentLogin.getBearerToken(), params);
|
||||
}
|
||||
|
||||
/**
|
||||
* create post response with user bearer token
|
||||
*
|
||||
* @param endpoint endpoint to use
|
||||
* @param params additional parameters
|
||||
* @return POST response
|
||||
*/
|
||||
private Response post(String endpoint, List<String> params) throws IOException {
|
||||
Account currentLogin = settings.getLogin();
|
||||
return post(currentLogin.getHostname(), endpoint, currentLogin.getBearerToken(), params);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a GET response
|
||||
*
|
||||
|
@ -979,6 +1014,18 @@ public class Mastodon implements Connection {
|
|||
return client.newCall(request.build()).execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* create post response with user bearer token
|
||||
*
|
||||
* @param endpoint endpoint to use
|
||||
* @param params additional parameters
|
||||
* @return POST response
|
||||
*/
|
||||
private Response post(String endpoint, List<String> params) throws IOException {
|
||||
Account login = settings.getLogin();
|
||||
return post(login.getHostname(), endpoint, login.getBearerToken(), params);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a POST response
|
||||
*
|
||||
|
@ -988,7 +1035,43 @@ public class Mastodon implements Connection {
|
|||
* @return POST response
|
||||
*/
|
||||
private Response post(String hostname, String endpoint, @Nullable String bearer, List<String> params) throws IOException {
|
||||
RequestBody body = RequestBody.create("", TYPE_TEXT);
|
||||
return post(hostname, endpoint, bearer, params, RequestBody.create("", TYPE_TEXT));
|
||||
}
|
||||
|
||||
/**
|
||||
* send POST request with file and create response
|
||||
*
|
||||
* @param endpoint endpoint url
|
||||
* @param params additional http parameters
|
||||
* @return http response
|
||||
*/
|
||||
private Response post(String endpoint, List<String> params, InputStream is, String addToKey) throws IOException {
|
||||
RequestBody data = new RequestBody() {
|
||||
@Override
|
||||
public MediaType contentType() {
|
||||
return TYPE_STREAM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(@NonNull BufferedSink sink) throws IOException {
|
||||
sink.writeAll(Okio.buffer(Okio.source(is)));
|
||||
}
|
||||
};
|
||||
Account login = settings.getLogin();
|
||||
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart(addToKey, StringTools.getRandomString(), data).build();
|
||||
return post(login.getHostname(), endpoint, login.getBearerToken(), params, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* send POST request
|
||||
*
|
||||
* @param hostname hostname of a Mastodon instance
|
||||
* @param endpoint POST endpoint to use
|
||||
* @param bearer bearer token to authenticate
|
||||
* @param params additional parameters
|
||||
* @return POST response
|
||||
*/
|
||||
private Response post(String hostname, String endpoint, @Nullable String bearer, List<String> params, RequestBody body) throws IOException {
|
||||
Request.Builder request = new Request.Builder().url(buildUrl(hostname, endpoint, params)).post(body);
|
||||
if (bearer != null) {
|
||||
request.addHeader("Authorization", "Bearer " + bearer);
|
||||
|
|
|
@ -44,6 +44,10 @@ public class MastodonException extends ConnectionException {
|
|||
errorCode = RATE_LIMIT_EX;
|
||||
break;
|
||||
|
||||
case 422:
|
||||
errorCode = INVALID_MEDIA;
|
||||
break;
|
||||
|
||||
case 503:
|
||||
errorCode = SERVICE_UNAVAILABLE;
|
||||
break;
|
||||
|
|
|
@ -34,7 +34,7 @@ public class MastodonNotification implements Notification {
|
|||
String typeStr = json.getString("type");
|
||||
JSONObject statusJson = json.optJSONObject("status");
|
||||
JSONObject userJson = json.getJSONObject("account");
|
||||
createdAt = StringTools.getTime2(json.getString("created_at"));
|
||||
createdAt = StringTools.getTime(json.getString("created_at"), StringTools.TIME_MASTODON);
|
||||
user = new MastodonUser(userJson);
|
||||
|
||||
switch (typeStr) {
|
||||
|
|
|
@ -46,7 +46,7 @@ public class MastodonStatus implements Status {
|
|||
String replyUserIdStr = json.optString("in_reply_to_account_id", "0");
|
||||
|
||||
author = new MastodonUser(json.getJSONObject("account"), currentUserId);
|
||||
createdAt = StringTools.getTime2(json.optString("created_at"));
|
||||
createdAt = StringTools.getTime(json.optString("created_at"), StringTools.TIME_MASTODON);
|
||||
replyCount = json.optInt("replies_count");
|
||||
reblogCount = json.optInt("reblogs_count");
|
||||
favoriteCount = json.optInt("favourites_count");
|
||||
|
|
|
@ -44,7 +44,7 @@ public class MastodonUser implements User {
|
|||
String idStr = json.getString("id");
|
||||
screenname = json.optString("acct", "");
|
||||
username = json.optString("display_name");
|
||||
createdAt = StringTools.getTime2(json.optString("created_at", ""));
|
||||
createdAt = StringTools.getTime(json.optString("created_at", ""), StringTools.TIME_MASTODON);
|
||||
profileUrl = json.optString("avatar");
|
||||
bannerUrl = json.optString("banner");
|
||||
description = json.optString("note");
|
||||
|
|
|
@ -19,13 +19,14 @@ import org.nuclearfog.twidda.backend.api.twitter.impl.RelationV1;
|
|||
import org.nuclearfog.twidda.backend.api.twitter.impl.TrendV1;
|
||||
import org.nuclearfog.twidda.backend.api.twitter.impl.TweetV1;
|
||||
import org.nuclearfog.twidda.backend.api.twitter.impl.TwitterAccount;
|
||||
import org.nuclearfog.twidda.backend.api.twitter.impl.TwitterNotification;
|
||||
import org.nuclearfog.twidda.backend.api.twitter.impl.UserListV1;
|
||||
import org.nuclearfog.twidda.backend.api.twitter.impl.UserV1;
|
||||
import org.nuclearfog.twidda.backend.api.twitter.impl.UserV2;
|
||||
import org.nuclearfog.twidda.backend.lists.Messages;
|
||||
import org.nuclearfog.twidda.backend.lists.UserLists;
|
||||
import org.nuclearfog.twidda.backend.lists.Users;
|
||||
import org.nuclearfog.twidda.backend.update.MediaUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.update.ProfileUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.StatusUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.UserListUpdate;
|
||||
|
@ -972,7 +973,7 @@ public class Twitter implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public long uploadMedia(MediaUpdate mediaUpdate) throws TwitterException {
|
||||
public long uploadMedia(MediaStatus mediaUpdate) throws TwitterException {
|
||||
List<String> params = new ArrayList<>();
|
||||
String state;
|
||||
boolean enableChunk;
|
||||
|
@ -1056,7 +1057,7 @@ public class Twitter implements Connection {
|
|||
|
||||
|
||||
@Override
|
||||
public MediaUpdate downloadImage(String link) throws TwitterException {
|
||||
public MediaStatus downloadImage(String link) throws TwitterException {
|
||||
try {
|
||||
// this type of link requires authentication
|
||||
if (link.startsWith(DOWNLOAD)) {
|
||||
|
@ -1067,7 +1068,7 @@ public class Twitter implements Connection {
|
|||
if (type != null) {
|
||||
String mime = type.toString();
|
||||
InputStream stream = body.byteStream();
|
||||
return new MediaUpdate(stream, mime);
|
||||
return new MediaStatus(stream, mime);
|
||||
}
|
||||
}
|
||||
throw new TwitterException(response);
|
||||
|
@ -1082,7 +1083,7 @@ public class Twitter implements Connection {
|
|||
if (type != null) {
|
||||
String mime = type.toString();
|
||||
InputStream stream = body.byteStream();
|
||||
return new MediaUpdate(stream, mime);
|
||||
return new MediaStatus(stream, mime);
|
||||
}
|
||||
}
|
||||
throw new TwitterException(response);
|
||||
|
@ -1145,7 +1146,12 @@ public class Twitter implements Connection {
|
|||
|
||||
@Override
|
||||
public List<Notification> getNotifications(long minId, long maxId) throws ConnectionException {
|
||||
throw new TwitterException("not supported!");
|
||||
List<Status> mentions = getMentionTimeline(minId, maxId);
|
||||
List<Notification> result = new ArrayList<>(mentions.size());
|
||||
for (Status status : mentions) {
|
||||
result.add(new TwitterNotification(status));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1595,6 +1601,7 @@ public class Twitter implements Connection {
|
|||
* @param endpoint endpoint url
|
||||
* @param params additional http parameters
|
||||
* @param enableChunk true to enable file chunk
|
||||
* @param addToKey key to add the file
|
||||
* @return http response
|
||||
*/
|
||||
private Response post(String endpoint, List<String> params, InputStream is, String addToKey, boolean enableChunk) throws IOException {
|
||||
|
|
|
@ -96,7 +96,7 @@ public class TweetV1 implements Status {
|
|||
isFavorited = json.optBoolean("favorited");
|
||||
isRetweeted = json.optBoolean("retweeted");
|
||||
isSensitive = json.optBoolean("possibly_sensitive");
|
||||
timestamp = StringTools.getTime1(json.optString("created_at", ""));
|
||||
timestamp = StringTools.getTime(json.optString("created_at", ""), StringTools.TIME_TWITTER_V1);
|
||||
coordinates = getLocation(json);
|
||||
mediaLinks = addMedia(json);
|
||||
userMentions = StringTools.getUserMentions(text, author.getScreenname());
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package org.nuclearfog.twidda.backend.api.twitter.impl;
|
||||
|
||||
import org.nuclearfog.twidda.model.Notification;
|
||||
import org.nuclearfog.twidda.model.Status;
|
||||
import org.nuclearfog.twidda.model.User;
|
||||
|
||||
/**
|
||||
* Twitter implementation of a notification
|
||||
* Twitter currently only supports mentions as notification
|
||||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class TwitterNotification implements Notification {
|
||||
|
||||
private static final long serialVersionUID = -2434138376220697796L;
|
||||
|
||||
private Status status;
|
||||
|
||||
|
||||
public TwitterNotification(Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
return status.getId();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return TYPE_MENTION;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long createdAt() {
|
||||
return status.getTimestamp();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public User getUser() {
|
||||
return status.getAuthor();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ public class UserListV1 implements UserList {
|
|||
String idStr = json.getString("id_str");
|
||||
|
||||
owner = new UserV1(json.getJSONObject("user"), currentId);
|
||||
createdAt = StringTools.getTime1(json.optString("created_at", ""));
|
||||
createdAt = StringTools.getTime(json.optString("created_at", ""), StringTools.TIME_TWITTER_V1);
|
||||
title = json.optString("name", "");
|
||||
description = json.optString("description", "");
|
||||
memberCount = json.optInt("member_count");
|
||||
|
|
|
@ -66,7 +66,7 @@ public class UserV1 implements User {
|
|||
favoriteCount = json.optInt("favourites_count");
|
||||
followReqSent = json.optBoolean("follow_request_sent");
|
||||
defaultImage = json.optBoolean("default_profile_image");
|
||||
created = StringTools.getTime1(json.optString("created_at", ""));
|
||||
created = StringTools.getTime(json.optString("created_at", ""), StringTools.TIME_TWITTER_V1);
|
||||
description = getDescription(json);
|
||||
url = getUrl(json);
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ public class UserV2 implements User {
|
|||
location = json.optString("location", "");
|
||||
isVerified = json.optBoolean("verified");
|
||||
profileBannerUrl = json.optString("profile_banner_url", "");
|
||||
created = StringTools.getTime2(json.optString("created_at", ""));
|
||||
created = StringTools.getTime(json.optString("created_at", ""), StringTools.TIME_TWITTER_V2);
|
||||
defaultImage = profileImageUrl.contains("default_profile_images");
|
||||
|
||||
url = getUrl(json);
|
||||
|
|
|
@ -8,7 +8,7 @@ import androidx.annotation.Nullable;
|
|||
import org.nuclearfog.twidda.backend.api.Connection;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionManager;
|
||||
import org.nuclearfog.twidda.backend.update.MediaUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.utils.StringTools;
|
||||
import org.nuclearfog.twidda.ui.activities.ImageViewer;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class ImageLoader extends AsyncTask<Uri, Uri, Boolean> {
|
|||
// download imaged to a local cache folder
|
||||
for (Uri link : links) {
|
||||
// get input stream
|
||||
MediaUpdate mediaUpdate = connection.downloadImage(link.toString());
|
||||
MediaStatus mediaUpdate = connection.downloadImage(link.toString());
|
||||
InputStream input = mediaUpdate.getStream();
|
||||
String mimeType = mediaUpdate.getMimeType();
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import android.os.AsyncTask;
|
|||
import org.nuclearfog.twidda.backend.api.Connection;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionException;
|
||||
import org.nuclearfog.twidda.backend.api.ConnectionManager;
|
||||
import org.nuclearfog.twidda.backend.update.MediaUpdate;
|
||||
import org.nuclearfog.twidda.backend.update.MediaStatus;
|
||||
import org.nuclearfog.twidda.backend.update.StatusUpdate;
|
||||
import org.nuclearfog.twidda.ui.activities.StatusEditor;
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class StatusUpdater extends AsyncTask<StatusUpdate, Void, Void> {
|
|||
StatusUpdate statusUpdate = statusUpdates[0];
|
||||
try {
|
||||
// upload media first
|
||||
MediaUpdate[] mediaUpdates = statusUpdate.getMediaUpdates();
|
||||
MediaStatus[] mediaUpdates = statusUpdate.getMediaUpdates();
|
||||
long[] mediaIds = new long[mediaUpdates.length];
|
||||
for (int pos = 0; pos < mediaUpdates.length; pos++) {
|
||||
// upload media file and save media ID
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.io.InputStream;
|
|||
*
|
||||
* @author nuclearfog
|
||||
*/
|
||||
public class MediaUpdate {
|
||||
public class MediaStatus {
|
||||
|
||||
private InputStream inputStream;
|
||||
private String mimeType;
|
||||
|
@ -19,7 +19,7 @@ public class MediaUpdate {
|
|||
* @param inputStream stream of the media (local or online)
|
||||
* @param mimeType MIME type e.g. image/jpeg
|
||||
*/
|
||||
public MediaUpdate(InputStream inputStream, String mimeType) {
|
||||
public MediaStatus(InputStream inputStream, String mimeType) {
|
||||
this.inputStream = inputStream;
|
||||
this.mimeType = mimeType;
|
||||
}
|
|
@ -19,7 +19,7 @@ import java.io.InputStream;
|
|||
public class MessageUpdate {
|
||||
|
||||
private Uri uri;
|
||||
private MediaUpdate mediaUpdate;
|
||||
private MediaStatus mediaUpdate;
|
||||
private String name = "";
|
||||
private String text = "";
|
||||
|
||||
|
@ -62,7 +62,7 @@ public class MessageUpdate {
|
|||
* @return input stream
|
||||
*/
|
||||
@Nullable
|
||||
public MediaUpdate getMediaUpdate() {
|
||||
public MediaStatus getMediaUpdate() {
|
||||
return mediaUpdate;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ public class MessageUpdate {
|
|||
String mimeType = resolver.getType(uri);
|
||||
InputStream fileStream = resolver.openInputStream(uri);
|
||||
if (fileStream != null && mimeType != null && fileStream.available() > 0) {
|
||||
mediaUpdate = new MediaUpdate(fileStream, mimeType);
|
||||
mediaUpdate = new MediaStatus(fileStream, mimeType);
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -25,7 +25,7 @@ public class StatusUpdate {
|
|||
private double latitude;
|
||||
|
||||
private List<Uri> mediaUris = new ArrayList<>(5);
|
||||
private MediaUpdate[] mediaUpdates = {};
|
||||
private MediaStatus[] mediaUpdates = {};
|
||||
private boolean hasLocation = false;
|
||||
|
||||
/**
|
||||
|
@ -93,7 +93,7 @@ public class StatusUpdate {
|
|||
*
|
||||
* @return list of media updates
|
||||
*/
|
||||
public MediaUpdate[] getMediaUpdates() {
|
||||
public MediaStatus[] getMediaUpdates() {
|
||||
return mediaUpdates;
|
||||
}
|
||||
|
||||
|
@ -152,13 +152,13 @@ public class StatusUpdate {
|
|||
return true;
|
||||
try {
|
||||
// open input streams
|
||||
mediaUpdates = new MediaUpdate[mediaUris.size()];
|
||||
mediaUpdates = new MediaStatus[mediaUris.size()];
|
||||
for (int i = 0; i < mediaUpdates.length; i++) {
|
||||
InputStream is = resolver.openInputStream(mediaUris.get(i));
|
||||
String mime = resolver.getType(mediaUris.get(i));
|
||||
// check if stream is valid
|
||||
if (is != null && mime != null && is.available() > 0) {
|
||||
mediaUpdates[i] = new MediaUpdate(is, mime);
|
||||
mediaUpdates[i] = new MediaStatus(is, mime);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -174,7 +174,7 @@ public class StatusUpdate {
|
|||
* close all open streams
|
||||
*/
|
||||
public void close() {
|
||||
for (MediaUpdate mediaUpdate : mediaUpdates) {
|
||||
for (MediaStatus mediaUpdate : mediaUpdates) {
|
||||
mediaUpdate.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Date;
|
|||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -51,11 +52,17 @@ public final class StringTools {
|
|||
*/
|
||||
private static final SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
|
||||
|
||||
private static final TimeZone TIME_ZONE = TimeZone.getDefault();
|
||||
|
||||
/**
|
||||
* fallback date if parsing failed
|
||||
*/
|
||||
private static final long DEFAULT_TIME = 0x61D99F64;
|
||||
|
||||
public static final int TIME_TWITTER_V1 = 0xE16A;
|
||||
public static final int TIME_TWITTER_V2 = 0x3F5C;
|
||||
public static final int TIME_MASTODON = 0x5105;
|
||||
|
||||
/**
|
||||
* random generator used to generate random strings
|
||||
*/
|
||||
|
@ -184,33 +191,33 @@ public final class StringTools {
|
|||
}
|
||||
|
||||
/**
|
||||
* convert Twitter API 1.1 date time to long format
|
||||
* convert time strings from different APIs to the local format
|
||||
*
|
||||
* @param timeStr Twitter time string
|
||||
* @param timeStr Twitter time string
|
||||
* @param timeFormat API format to use {@link #TIME_TWITTER_V1,#TIME_TWITTER_V2,#TIME_MASTODON}
|
||||
* @return date time
|
||||
*/
|
||||
public static long getTime1(String timeStr) {
|
||||
public static long getTime(String timeStr, int timeFormat) {
|
||||
try {
|
||||
Date date = dateFormat1.parse(timeStr);
|
||||
if (date != null)
|
||||
return date.getTime();
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return DEFAULT_TIME;
|
||||
}
|
||||
switch (timeFormat) {
|
||||
case TIME_TWITTER_V1:
|
||||
Date result = dateFormat1.parse(timeStr);
|
||||
if (result != null)
|
||||
return result.getTime();
|
||||
break;
|
||||
|
||||
/**
|
||||
* convert Twitter API 2 date time to long format
|
||||
*
|
||||
* @param timeStr Twitter time string
|
||||
* @return date time
|
||||
*/
|
||||
public static long getTime2(String timeStr) {
|
||||
try {
|
||||
Date date = dateFormat2.parse(timeStr);
|
||||
if (date != null)
|
||||
return date.getTime();
|
||||
case TIME_TWITTER_V2:
|
||||
result = dateFormat2.parse(timeStr);
|
||||
if (result != null)
|
||||
return result.getTime();
|
||||
break;
|
||||
|
||||
case TIME_MASTODON:
|
||||
result = dateFormat2.parse(timeStr);
|
||||
if (result != null) // temporary fix: Mastodon time depends on timezone
|
||||
return result.getTime() + TIME_ZONE.getOffset(new Date().getTime());
|
||||
break;
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue