mirror of https://github.com/tuskyapp/Tusky.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
340 lines
10 KiB
340 lines
10 KiB
/* Copyright 2017 Andrew Dawson |
|
* |
|
* This file is part of Tusky. |
|
* |
|
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU |
|
* General Public License as published by the Free Software Foundation, either version 3 of the |
|
* License, or (at your option) any later version. |
|
* |
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
|
* Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License along with Tusky. If not, see |
|
* <http://www.gnu.org/licenses/>. */ |
|
|
|
package com.keylesspalace.tusky; |
|
|
|
import android.text.Spanned; |
|
|
|
import org.json.JSONArray; |
|
import org.json.JSONException; |
|
import org.json.JSONObject; |
|
|
|
import java.text.ParseException; |
|
import java.text.SimpleDateFormat; |
|
import java.util.ArrayList; |
|
import java.util.Date; |
|
import java.util.List; |
|
|
|
public class Status { |
|
enum Visibility { |
|
PUBLIC, |
|
UNLISTED, |
|
PRIVATE, |
|
} |
|
|
|
private String id; |
|
private String accountId; |
|
private String displayName; |
|
/** the username with the remote domain appended, like @domain.name, if it's a remote account */ |
|
private String username; |
|
/** the main text of the status, marked up with style for links & mentions, etc */ |
|
private Spanned content; |
|
/** the fully-qualified url of the avatar image */ |
|
private String avatar; |
|
private String rebloggedByUsername; |
|
/** when the status was initially created */ |
|
private Date createdAt; |
|
/** whether the authenticated user has reblogged this status */ |
|
private boolean reblogged; |
|
/** whether the authenticated user has favourited this status */ |
|
private boolean favourited; |
|
private boolean sensitive; |
|
private String spoilerText; |
|
private Visibility visibility; |
|
private MediaAttachment[] attachments; |
|
private Mention[] mentions; |
|
|
|
public static final int MAX_MEDIA_ATTACHMENTS = 4; |
|
|
|
public Status(String id, String accountId, String displayName, String username, Spanned content, |
|
String avatar, Date createdAt, boolean reblogged, boolean favourited, |
|
String visibility) { |
|
this.id = id; |
|
this.accountId = accountId; |
|
this.displayName = displayName; |
|
this.username = username; |
|
this.content = content; |
|
this.avatar = avatar; |
|
this.createdAt = createdAt; |
|
this.reblogged = reblogged; |
|
this.favourited = favourited; |
|
this.spoilerText = ""; |
|
this.visibility = Visibility.valueOf(visibility.toUpperCase()); |
|
this.attachments = new MediaAttachment[0]; |
|
this.mentions = new Mention[0]; |
|
} |
|
|
|
public String getId() { |
|
return id; |
|
} |
|
|
|
public String getAccountId() { |
|
return accountId; |
|
} |
|
|
|
public String getDisplayName() { |
|
return displayName; |
|
} |
|
|
|
public String getUsername() { |
|
return username; |
|
} |
|
|
|
public Spanned getContent() { |
|
return content; |
|
} |
|
|
|
public String getAvatar() { |
|
return avatar; |
|
} |
|
|
|
public Date getCreatedAt() { |
|
return createdAt; |
|
} |
|
|
|
public String getRebloggedByUsername() { |
|
return rebloggedByUsername; |
|
} |
|
|
|
public boolean getReblogged() { |
|
return reblogged; |
|
} |
|
|
|
public boolean getFavourited() { |
|
return favourited; |
|
} |
|
|
|
public boolean getSensitive() { |
|
return sensitive; |
|
} |
|
|
|
public String getSpoilerText() { |
|
return spoilerText; |
|
} |
|
|
|
public Visibility getVisibility() { |
|
return visibility; |
|
} |
|
|
|
public MediaAttachment[] getAttachments() { |
|
return attachments; |
|
} |
|
|
|
public Mention[] getMentions() { |
|
return mentions; |
|
} |
|
|
|
public void setRebloggedByUsername(String name) { |
|
rebloggedByUsername = name; |
|
} |
|
|
|
public void setReblogged(boolean reblogged) { |
|
this.reblogged = reblogged; |
|
} |
|
|
|
public void setFavourited(boolean favourited) { |
|
this.favourited = favourited; |
|
} |
|
|
|
public void setSpoilerText(String spoilerText) { |
|
this.spoilerText = spoilerText; |
|
} |
|
|
|
public void setMentions(Mention[] mentions) { |
|
this.mentions = mentions; |
|
} |
|
|
|
public void setAttachments(MediaAttachment[] attachments, boolean sensitive) { |
|
this.attachments = attachments; |
|
this.sensitive = sensitive; |
|
} |
|
|
|
@Override |
|
public int hashCode() { |
|
return id.hashCode(); |
|
} |
|
|
|
@Override |
|
public boolean equals(Object other) { |
|
if (this.id == null) { |
|
return this == other; |
|
} else if (!(other instanceof Status)) { |
|
return false; |
|
} |
|
Status status = (Status) other; |
|
return status.id.equals(this.id); |
|
} |
|
|
|
private static Date parseDate(String dateTime) { |
|
Date date; |
|
String s = dateTime.replace("Z", "+00:00"); |
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); |
|
try { |
|
date = format.parse(s); |
|
} catch (ParseException e) { |
|
e.printStackTrace(); |
|
return null; |
|
} |
|
return date; |
|
} |
|
|
|
public static Status parse(JSONObject object, boolean isReblog) throws JSONException { |
|
String id = object.getString("id"); |
|
String content = object.getString("content"); |
|
Date createdAt = parseDate(object.getString("created_at")); |
|
boolean reblogged = object.getBoolean("reblogged"); |
|
boolean favourited = object.getBoolean("favourited"); |
|
String spoilerText = object.getString("spoiler_text"); |
|
boolean sensitive = object.optBoolean("sensitive"); |
|
String visibility = object.getString("visibility"); |
|
|
|
JSONObject account = object.getJSONObject("account"); |
|
String accountId = account.getString("id"); |
|
String displayName = account.getString("display_name"); |
|
if (displayName.isEmpty()) { |
|
displayName = account.getString("username"); |
|
} |
|
String username = account.getString("acct"); |
|
String avatarUrl = account.getString("avatar"); |
|
String avatar; |
|
if (!avatarUrl.equals("/avatars/original/missing.png")) { |
|
avatar = avatarUrl; |
|
} else { |
|
avatar = ""; |
|
} |
|
|
|
JSONArray mentionsArray = object.getJSONArray("mentions"); |
|
Mention[] mentions = null; |
|
if (mentionsArray != null) { |
|
int n = mentionsArray.length(); |
|
mentions = new Mention[n]; |
|
for (int i = 0; i < n; i++) { |
|
JSONObject mention = mentionsArray.getJSONObject(i); |
|
String url = mention.getString("url"); |
|
String mentionedUsername = mention.getString("acct"); |
|
String mentionedAccountId = mention.getString("id"); |
|
mentions[i] = new Mention(url, mentionedUsername, mentionedAccountId); |
|
} |
|
} |
|
|
|
JSONArray mediaAttachments = object.getJSONArray("media_attachments"); |
|
MediaAttachment[] attachments = null; |
|
if (mediaAttachments != null) { |
|
int n = mediaAttachments.length(); |
|
attachments = new MediaAttachment[n]; |
|
for (int i = 0; i < n; i++) { |
|
JSONObject attachment = mediaAttachments.getJSONObject(i); |
|
String url = attachment.getString("url"); |
|
String previewUrl = attachment.getString("preview_url"); |
|
String type = attachment.getString("type"); |
|
attachments[i] = new MediaAttachment(url, previewUrl, |
|
MediaAttachment.Type.valueOf(type.toUpperCase())); |
|
} |
|
} |
|
|
|
Status reblog = null; |
|
/* This case shouldn't be hit after the first recursion at all. But if this method is |
|
* passed unusual data this check will prevent extra recursion */ |
|
if (!isReblog) { |
|
JSONObject reblogObject = object.optJSONObject("reblog"); |
|
if (reblogObject != null) { |
|
reblog = parse(reblogObject, true); |
|
} |
|
} |
|
|
|
Status status; |
|
if (reblog != null) { |
|
status = reblog; |
|
status.setRebloggedByUsername(username); |
|
} else { |
|
Spanned contentPlus = HtmlUtils.fromHtml(content); |
|
status = new Status( |
|
id, accountId, displayName, username, contentPlus, avatar, createdAt, |
|
reblogged, favourited, visibility); |
|
if (mentions != null) { |
|
status.setMentions(mentions); |
|
} |
|
if (attachments != null) { |
|
status.setAttachments(attachments, sensitive); |
|
} |
|
if (!spoilerText.isEmpty()) { |
|
status.setSpoilerText(spoilerText); |
|
} |
|
} |
|
return status; |
|
} |
|
|
|
public static List<Status> parse(JSONArray array) throws JSONException { |
|
List<Status> statuses = new ArrayList<>(); |
|
for (int i = 0; i < array.length(); i++) { |
|
JSONObject object = array.getJSONObject(i); |
|
statuses.add(parse(object, false)); |
|
} |
|
return statuses; |
|
} |
|
|
|
public static class MediaAttachment { |
|
enum Type { |
|
IMAGE, |
|
VIDEO, |
|
} |
|
|
|
private String url; |
|
private String previewUrl; |
|
private Type type; |
|
|
|
public MediaAttachment(String url, String previewUrl, Type type) { |
|
this.url = url; |
|
this.previewUrl = previewUrl; |
|
this.type = type; |
|
} |
|
|
|
public String getUrl() { |
|
return url; |
|
} |
|
|
|
public String getPreviewUrl() { |
|
return previewUrl; |
|
} |
|
|
|
public Type getType() { |
|
return type; |
|
} |
|
} |
|
|
|
public static class Mention { |
|
private String url; |
|
private String username; |
|
private String id; |
|
|
|
public Mention(String url, String username, String id) { |
|
this.url = url; |
|
this.username = username; |
|
this.id = id; |
|
} |
|
|
|
public String getUrl() { |
|
return url; |
|
} |
|
|
|
public String getUsername() { |
|
return username; |
|
} |
|
|
|
public String getId() { |
|
return id; |
|
} |
|
} |
|
}
|
|
|