package app.fedilab.android.client; /* Copyright 2017 Thomas Schneider * * This file is a part of Fedilab * * This program 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. * * Fedilab 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 Fedilab; if not, * see . */ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.os.Build; import android.os.Bundle; import android.text.Html; import android.text.SpannableString; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.preference.PreferenceManager; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; import java.net.URLEncoder; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; import app.fedilab.android.R; import app.fedilab.android.activities.MainActivity; import app.fedilab.android.asynctasks.UpdateAccountInfoAsyncTask; import app.fedilab.android.client.Entities.Account; import app.fedilab.android.client.Entities.AccountAdmin; import app.fedilab.android.client.Entities.AccountCreation; import app.fedilab.android.client.Entities.AdminAction; import app.fedilab.android.client.Entities.Announcement; import app.fedilab.android.client.Entities.Application; import app.fedilab.android.client.Entities.Attachment; import app.fedilab.android.client.Entities.Card; import app.fedilab.android.client.Entities.Conversation; import app.fedilab.android.client.Entities.Emojis; import app.fedilab.android.client.Entities.Error; import app.fedilab.android.client.Entities.Filters; import app.fedilab.android.client.Entities.HowToVideo; import app.fedilab.android.client.Entities.IdentityProof; import app.fedilab.android.client.Entities.Instance; import app.fedilab.android.client.Entities.InstanceNodeInfo; import app.fedilab.android.client.Entities.InstanceReg; import app.fedilab.android.client.Entities.InstanceSocial; import app.fedilab.android.client.Entities.Mention; import app.fedilab.android.client.Entities.NodeInfo; import app.fedilab.android.client.Entities.Notification; import app.fedilab.android.client.Entities.Peertube; import app.fedilab.android.client.Entities.Poll; import app.fedilab.android.client.Entities.PollOptions; import app.fedilab.android.client.Entities.PushSubscription; import app.fedilab.android.client.Entities.Reaction; import app.fedilab.android.client.Entities.Relationship; import app.fedilab.android.client.Entities.Report; import app.fedilab.android.client.Entities.Results; import app.fedilab.android.client.Entities.Schedule; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.client.Entities.StoredStatus; import app.fedilab.android.client.Entities.Tag; import app.fedilab.android.client.Entities.Trends; import app.fedilab.android.client.Entities.TrendsHistory; import app.fedilab.android.fragments.DisplayNotificationsFragment; import app.fedilab.android.helper.ECDH; import app.fedilab.android.helper.Helper; import app.fedilab.android.sqlite.AccountDAO; import app.fedilab.android.sqlite.Sqlite; import app.fedilab.android.sqlite.TimelineCacheDAO; import static app.fedilab.android.helper.ECDH.kp_private; import static app.fedilab.android.helper.ECDH.kp_public; import static app.fedilab.android.helper.ECDH.newPair; /** * Created by Thomas on 23/04/2017. * Manage Calls to the REST API * Modify the 16/11/2017 with httpsurlconnection */ public class API { private Account account; private final Context context; private Results results; private Attachment attachment; private List accounts; private List statuses; private int tootPerPage, accountPerPage, notificationPerPage; private int actionCode; private String instance; private String prefKeyOauthTokenT; private APIResponse apiResponse; private Error APIError; private List domains; public API(Context context) { this.context = context; if (context == null) { APIError = new Error(); return; } SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); tootPerPage = sharedpreferences.getInt(Helper.SET_TOOT_PER_PAGE, Helper.TOOTS_PER_PAGE); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED && tootPerPage > 20) { tootPerPage = 20; } accountPerPage = Helper.ACCOUNTS_PER_PAGE; notificationPerPage = Helper.NOTIFICATIONS_PER_PAGE; this.prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); if (Helper.getLiveInstance(context) != null) this.instance = Helper.getLiveInstance(context); else { SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(context)); Account account = new AccountDAO(context, db).getUniqAccount(userId, instance); if (account == null) { APIError = new Error(); APIError.setError(context.getString(R.string.toast_error)); return; } this.instance = account.getInstance().trim(); } apiResponse = new APIResponse(); APIError = null; } public API(Context context, String instance, String token) { this.context = context; if (context == null) { apiResponse = new APIResponse(); APIError = new Error(); return; } SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); tootPerPage = sharedpreferences.getInt(Helper.SET_TOOT_PER_PAGE, Helper.TOOTS_PER_PAGE); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED && tootPerPage > 20) { tootPerPage = 20; } accountPerPage = Helper.ACCOUNTS_PER_PAGE; notificationPerPage = Helper.NOTIFICATIONS_PER_PAGE; if (instance != null) this.instance = instance; else this.instance = Helper.getLiveInstance(context); if (token != null) this.prefKeyOauthTokenT = token; else this.prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); apiResponse = new APIResponse(); APIError = null; } /** * Parse json response an unique Car * * @param resobj JSONObject * @return Card */ private static Card parseCardResponse(JSONObject resobj) { Card card = new Card(); try { card.setUrl(resobj.getString("url")); card.setTitle(resobj.getString("title")); card.setDescription(resobj.getString("description")); card.setImage(resobj.getString("image")); card.setType(resobj.getString("type")); try { card.setAuthor_name(resobj.getString("author_name")); } catch (Exception e) { card.setAuthor_name(null); } try { card.setAuthor_url(resobj.getString("author_url")); } catch (Exception e) { card.setAuthor_url(null); } try { card.setHtml(resobj.getString("html")); } catch (Exception e) { card.setHtml(null); } try { card.setEmbed_url(resobj.getString("embed_url")); } catch (Exception e) { card.setEmbed_url(null); } try { card.setProvider_name(resobj.getString("provider_name")); } catch (Exception e) { card.setProvider_name(null); } try { card.setProvider_url(resobj.getString("provider_url")); } catch (Exception e) { card.setProvider_url(null); } try { card.setHeight(resobj.getInt("height")); } catch (Exception e) { card.setHeight(0); } try { card.setWidth(resobj.getInt("width")); } catch (Exception e) { card.setWidth(0); } } catch (JSONException e) { card = null; } return card; } /** * Parse json response an unique instance social result * * @param resobj JSONObject * @return InstanceSocial */ public static InstanceSocial parseInstanceSocialResponse(JSONObject resobj) { InstanceSocial instanceSocial = new InstanceSocial(); try { instanceSocial.setUptime(Float.parseFloat(resobj.getString("uptime"))); instanceSocial.setUp(resobj.getBoolean("up")); instanceSocial.setConnections(Long.parseLong(resobj.getString("connections"))); instanceSocial.setDead(resobj.getBoolean("dead")); instanceSocial.setId(resobj.getString("id")); instanceSocial.setInfo(resobj.getString("info")); instanceSocial.setVersion(resobj.getString("version")); instanceSocial.setName(resobj.getString("name")); instanceSocial.setObs_rank(resobj.getString("obs_rank")); instanceSocial.setThumbnail(resobj.getString("thumbnail")); instanceSocial.setIpv6(resobj.getBoolean("ipv6")); instanceSocial.setObs_score(resobj.getInt("obs_score")); instanceSocial.setOpen_registrations(resobj.getBoolean("open_registrations")); instanceSocial.setUsers(Long.parseLong(resobj.getString("users"))); instanceSocial.setStatuses(Long.parseLong(resobj.getString("statuses"))); instanceSocial.setHttps_rank(resobj.getString("https_rank")); instanceSocial.setHttps_score(resobj.getInt("https_score")); if (!resobj.isNull("added_at")) { instanceSocial.setAdded_at(Helper.mstStringToDate(resobj.getString("added_at"))); } instanceSocial.setChecked_at(Helper.mstStringToDate(resobj.getString("checked_at"))); instanceSocial.setUpdated_at(Helper.mstStringToDate(resobj.getString("updated_at"))); } catch (Exception e) { e.printStackTrace(); } return instanceSocial; } /** * Parse json response for unique how to * * @param resobj JSONObject * @return Peertube */ public static Peertube parsePeertube(String instance, JSONObject resobj) { Peertube peertube = new Peertube(); try { peertube.setId(resobj.getString("id")); peertube.setCache(resobj); peertube.setUuid(resobj.getString("uuid")); peertube.setName(resobj.getString("name")); peertube.setDescription(resobj.getString("description")); peertube.setEmbedPath(resobj.getString("embedPath")); peertube.setPreviewPath(resobj.getString("previewPath")); peertube.setThumbnailPath(resobj.getString("thumbnailPath")); peertube.setAccount(parseAccountResponsePeertube(instance, resobj.getJSONObject("account"))); peertube.setInstance(instance); peertube.setView(resobj.getInt("views")); peertube.setLike(resobj.getInt("likes")); peertube.setDislike(resobj.getInt("dislikes")); peertube.setDuration(resobj.getInt("duration")); try { peertube.setCreated_at(Helper.mstStringToDate(resobj.getString("createdAt"))); } catch (ParseException e) { e.printStackTrace(); } } catch (JSONException e) { e.printStackTrace(); } return peertube; } /** * Parse json response for unique how to * * @param resobj JSONObject * @return Peertube */ private static Peertube parseSinglePeertube(String instance, JSONObject resobj) { Peertube peertube = new Peertube(); try { peertube.setId(resobj.getString("id")); peertube.setUuid(resobj.getString("uuid")); peertube.setName(resobj.getString("name")); peertube.setCache(resobj); peertube.setInstance(instance); peertube.setHost(resobj.getJSONObject("account").getString("host")); peertube.setDescription(resobj.getString("description")); peertube.setEmbedPath(resobj.getString("embedPath")); peertube.setPreviewPath(resobj.getString("previewPath")); peertube.setThumbnailPath(resobj.getString("thumbnailPath")); peertube.setView(resobj.getInt("views")); peertube.setLike(resobj.getInt("likes")); peertube.setCommentsEnabled(resobj.getBoolean("commentsEnabled")); peertube.setDislike(resobj.getInt("dislikes")); peertube.setDuration(resobj.getInt("duration")); peertube.setAccount(parseAccountResponsePeertube(instance, resobj.getJSONObject("account"))); try { peertube.setCreated_at(Helper.mstStringToDate(resobj.getString("createdAt"))); } catch (ParseException e) { e.printStackTrace(); } ArrayList resolutions = new ArrayList<>(); if (resobj.has("streamingPlaylists") && resobj.getJSONArray("streamingPlaylists").length() > 0) { JSONArray files = resobj.getJSONArray("streamingPlaylists").getJSONObject(0).getJSONArray("files"); for (int j = 0; j < files.length(); j++) { JSONObject attObj = files.getJSONObject(j); resolutions.add(attObj.getJSONObject("resolution").getString("id")); } peertube.setResolution(resolutions); peertube.setStreamService(true); } else { JSONArray files = resobj.getJSONArray("files"); for (int j = 0; j < files.length(); j++) { JSONObject attObj = files.getJSONObject(j); resolutions.add(attObj.getJSONObject("resolution").getString("id")); } peertube.setResolution(resolutions); peertube.setStreamService(false); } } catch (JSONException e) { e.printStackTrace(); } return peertube; } /** * Parse json response for peertube comments * * @param resobj JSONObject * @return Peertube */ private static List parseSinglePeertubeComments(Context context, String instance, JSONObject resobj) { List statuses = new ArrayList<>(); try { JSONArray jsonArray = resobj.getJSONArray("data"); int i = 0; while (i < jsonArray.length()) { Status status = new Status(); JSONObject comment = jsonArray.getJSONObject(i); status.setId(comment.getString("id")); status.setUri(comment.getString("url")); status.setUrl(comment.getString("url")); status.setSensitive(false); status.setSpoiler_text(""); status.setContent(context, comment.getString("text")); status.setIn_reply_to_id(comment.getString("inReplyToCommentId")); status.setAccount(parseAccountResponsePeertube(instance, comment.getJSONObject("account"))); status.setCreated_at(Helper.mstStringToDate(comment.getString("createdAt"))); status.setMentions(new ArrayList<>()); status.setEmojis(new ArrayList<>()); status.setMedia_attachments(new ArrayList<>()); status.setVisibility("public"); status.setViewType(context); SpannableString spannableString; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) spannableString = new SpannableString(Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_LEGACY)); else spannableString = new SpannableString(Html.fromHtml(status.getContent())); status.setContentSpan(new SpannableString(spannableString)); i++; statuses.add(status); } } catch (JSONException | ParseException e) { e.printStackTrace(); } return statuses; } /** * Parse json response for unique how to * * @param resobj JSONObject * @return HowToVideo */ private static HowToVideo parseHowTo(JSONObject resobj) { HowToVideo howToVideo = new HowToVideo(); try { howToVideo.setId(resobj.getString("id")); howToVideo.setUuid(resobj.getString("uuid")); howToVideo.setName(resobj.getString("name")); howToVideo.setDescription(resobj.getString("description")); howToVideo.setEmbedPath(resobj.getString("embedPath")); howToVideo.setPreviewPath(resobj.getString("previewPath")); howToVideo.setThumbnailPath(resobj.getString("thumbnailPath")); } catch (JSONException e) { e.printStackTrace(); } return howToVideo; } /** * Parse json response for several scheduled toots * * @param jsonObject JSONObject * @return List */ private static Schedule parseSimpleSchedule(Context context, JSONObject jsonObject) { Schedule schedule = new Schedule(); try { JSONObject resobj = jsonObject.getJSONObject("params"); Status status = parseSchedule(context, resobj); List attachements = parseAttachmentResponse(jsonObject.getJSONArray("media_attachments")); status.setMedia_attachments((ArrayList) attachements); schedule.setStatus(status); schedule.setAttachmentList(attachements); schedule.setId(jsonObject.getString("id")); schedule.setScheduled_at(Helper.mstStringToDate(jsonObject.getString("scheduled_at"))); } catch (JSONException | ParseException e) { e.printStackTrace(); } return schedule; } /** * Parse json response for several scheduled toots * * @param jsonArray JSONArray * @return List */ private static List parseSchedule(Context context, JSONArray jsonArray) { List schedules = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { Schedule schedule = new Schedule(); JSONObject resobj = jsonArray.getJSONObject(i).getJSONObject("params"); Status status = parseSchedule(context, resobj); List attachements = parseAttachmentResponse(jsonArray.getJSONObject(i).getJSONArray("media_attachments")); status.setMedia_attachments((ArrayList) attachements); schedule.setStatus(status); schedule.setAttachmentList(attachements); schedules.add(schedule); schedule.setId(jsonArray.getJSONObject(i).getString("id")); schedule.setScheduled_at(Helper.mstStringToDate(jsonArray.getJSONObject(i).getString("scheduled_at"))); i++; } } catch (JSONException | ParseException e) { e.printStackTrace(); } return schedules; } /** * Parse json response for several status * * @param jsonArray JSONArray * @return List */ private static List parseStatuses(Context context, JSONArray jsonArray) { List statuses = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Status status = parseStatuses(context, resobj); i++; statuses.add(status); } } catch (JSONException e) { e.printStackTrace(); } return statuses; } /** * Parse json response for several reactions * * @param jsonArray JSONArray * @return List */ private static List parseReaction(JSONArray jsonArray) { List reactions = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Reaction reaction = parseReaction(resobj); i++; reactions.add(reaction); } } catch (JSONException e) { e.printStackTrace(); } return reactions; } /** * Parse a push notification * * @param resobj JSONObject * @return PushSubscription */ private static PushSubscription parsePushNotifications(JSONObject resobj) { PushSubscription pushSubscription = new PushSubscription(); try { pushSubscription.setId(resobj.getString("id")); pushSubscription.setEndpoint(resobj.getString("endpoint")); pushSubscription.setServer_key(resobj.getString("server_key")); JSONObject alertsObject = resobj.getJSONObject("alerts"); Iterator iter = alertsObject.keys(); HashMap alertsList = new HashMap<>(); while (iter.hasNext()) { String key = iter.next(); boolean value = (boolean) alertsObject.get(key); alertsList.put(key, value); } pushSubscription.setAlertsList(alertsList); } catch (JSONException e) { e.printStackTrace(); } return pushSubscription; } /** * Parse a reaction * * @param resobj JSONObject * @return Reaction */ private static Reaction parseReaction(JSONObject resobj) { Reaction reaction = new Reaction(); try { reaction.setName(resobj.getString("name")); reaction.setCount(resobj.getInt("count")); reaction.setMe(resobj.getBoolean("me")); if (resobj.has("url")) { reaction.setUrl(resobj.getString("url")); } } catch (JSONException e) { e.printStackTrace(); } return reaction; } /** * Parse json response for several announcements * * @param jsonArray JSONArray * @return List */ private static List parseAnnouncement(Context context, JSONArray jsonArray) { List announcements = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Announcement announcement = parseAnnouncement(context, resobj); i++; announcements.add(announcement); } } catch (JSONException e) { e.printStackTrace(); } return announcements; } /** * Parse an annoucement * * @param context Context * @param resobj JSONObject * @return Announcement */ private static Announcement parseAnnouncement(Context context, JSONObject resobj) { Announcement announcement = new Announcement(); try { Account account = new Account(); account.setBot(false); account.setUsername("admin"); account.setUuid("admin"); account.setId("admin"); account.setDisplay_name("admin"); announcement.setMedia_attachments(new ArrayList<>()); announcement.setAccount(account); announcement.setId(resobj.getString("id")); announcement.setContent(context, resobj.getString("content")); if (resobj.getString("published_at").compareTo("null") != 0) { announcement.setCreated_at(Helper.mstStringToDate(resobj.getString("published_at"))); } if (resobj.getString("updated_at").compareTo("null") != 0) { announcement.setUpdatedAt(Helper.mstStringToDate(resobj.getString("updated_at"))); } if (resobj.getString("starts_at").compareTo("null") != 0) { announcement.setStartAt(Helper.mstStringToDate(resobj.getString("starts_at"))); } if (resobj.getString("ends_at").compareTo("null") != 0) { announcement.setEndAt(Helper.mstStringToDate(resobj.getString("ends_at"))); } announcement.setRead(resobj.getBoolean("read")); announcement.setReactions(parseReaction(resobj.getJSONArray("reactions"))); List tags = new ArrayList<>(); JSONArray arrayTag = resobj.getJSONArray("tags"); for (int j = 0; j < arrayTag.length(); j++) { JSONObject tagObj = arrayTag.getJSONObject(j); Tag tag = new Tag(); tag.setName(tagObj.getString("name")); tag.setUrl(tagObj.getString("url")); tags.add(tag); } announcement.setTags(tags); List emojiList = new ArrayList<>(); try { JSONArray emojisTag = resobj.getJSONArray("emojis"); for (int j = 0; j < emojisTag.length(); j++) { JSONObject emojisObj = emojisTag.getJSONObject(j); Emojis emojis = parseEmojis(emojisObj); emojiList.add(emojis); } announcement.setEmojis(emojiList); } catch (Exception e) { announcement.setEmojis(new ArrayList<>()); } List mentions = new ArrayList<>(); try { JSONArray arrayMention = resobj.getJSONArray("mentions"); for (int j = 0; j < arrayMention.length(); j++) { JSONObject menObj = arrayMention.getJSONObject(j); Mention mention = new Mention(); mention.setId(menObj.getString("id")); mention.setUrl(menObj.getString("url")); mention.setAcct(menObj.getString("acct")); mention.setUsername(menObj.getString("username")); mentions.add(mention); } announcement.setMentions(mentions); } catch (Exception e) { announcement.setMentions(new ArrayList<>()); } } catch (JSONException | ParseException e) { e.printStackTrace(); } Status.fillSpan(new WeakReference<>(context), announcement); return announcement; } /** * Parse a poll * * @param resobj JSONObject * @return Poll */ private static Poll parsePoll(JSONObject resobj) { Poll poll = new Poll(); try { poll.setId(resobj.getString("id")); poll.setExpires_at(Helper.mstStringToDate(resobj.getString("expires_at"))); poll.setExpired(resobj.getBoolean("expired")); poll.setMultiple(resobj.getBoolean("multiple")); poll.setVotes_count(resobj.getInt("votes_count")); if (resobj.has("voters_count")) { poll.setVoters_count(resobj.getInt("voters_count")); } else { poll.setVoters_count(resobj.getInt("votes_count")); } List emojiList = new ArrayList<>(); try { JSONArray emojisPoll = resobj.getJSONArray("emojis"); for (int j = 0; j < emojisPoll.length(); j++) { JSONObject emojisObj = emojisPoll.getJSONObject(j); Emojis emojis = parseEmojis(emojisObj); emojiList.add(emojis); } poll.setEmojis(emojiList); } catch (Exception e) { poll.setEmojis(new ArrayList<>()); } poll.setVoted(resobj.getBoolean("voted")); JSONArray options = resobj.getJSONArray("options"); List pollOptions = new ArrayList<>(); for (int i = 0; i < options.length(); i++) { JSONObject option = options.getJSONObject(i); PollOptions pollOption = new PollOptions(); pollOption.setTitle(option.getString("title")); pollOption.setVotes_count(option.getInt("votes_count")); pollOptions.add(pollOption); } poll.setOptionsList(pollOptions); JSONArray own_votes = resobj.getJSONArray("own_votes"); List own_votes_list = new ArrayList<>(); for (int i = 0; i < own_votes.length(); i++) { int own_vote = own_votes.getInt(i); own_votes_list.add(own_vote); } poll.setOwn_votes(own_votes_list); } catch (JSONException | ParseException e) { e.printStackTrace(); } return poll; } /** * Parse json response for unique status * * @param resobj JSONObject * @return Status */ public static Status parseStatuses(Context context, JSONObject resobj) { return parseStatuses(context, resobj, true); } /** * Parse json response for unique status * * @param context Context * @param resobj JSONObject * @param recursive boolean * @return Status */ private static Status parseStatuses(Context context, JSONObject resobj, boolean recursive) { Status status = new Status(); try { status.setId(resobj.getString("id")); if (resobj.has("uri")) { status.setUri(resobj.getString("uri")); } else { status.setUri(resobj.getString("id")); } if (resobj.has("created_at")) { status.setCreated_at(Helper.mstStringToDate(resobj.getString("created_at"))); } else { status.setCreated_at(new Date()); } if (!resobj.isNull("in_reply_to_id")) { status.setIn_reply_to_id(resobj.getString("in_reply_to_id")); } if (!resobj.isNull("in_reply_to_account_id")) { status.setIn_reply_to_account_id(resobj.getString("in_reply_to_account_id")); } if (resobj.has("sensitive")) { status.setSensitive(resobj.getBoolean("sensitive")); } else { status.setSensitive(false); } if (resobj.has("spoiler_text")) { status.setSpoiler_text(resobj.getString("spoiler_text")); } try { status.setVisibility(resobj.getString("visibility")); } catch (Exception e) { status.setVisibility("public"); } try { status.setLanguage(resobj.getString("language")); } catch (Exception e) { status.setLanguage("ja"); } List reactions = new ArrayList<>(); if (resobj.has("pleroma") && resobj.getJSONObject("pleroma").has("emoji_reactions")) { try { reactions = parseReaction(resobj.getJSONObject("pleroma").getJSONArray("emoji_reactions")); } catch (Exception ignored) { } } status.setReactions(reactions); if (resobj.has("url")) { status.setUrl(resobj.getString("url")); } ArrayList attachments = new ArrayList<>(); //Retrieves attachments if (resobj.has("media_attachments")) { JSONArray arrayAttachement = resobj.getJSONArray("media_attachments"); for (int j = 0; j < arrayAttachement.length(); j++) { JSONObject attObj = arrayAttachement.getJSONObject(j); Attachment attachment = new Attachment(); attachment.setId(attObj.getString("id")); attachment.setPreview_url(attObj.getString("preview_url")); attachment.setRemote_url(attObj.getString("remote_url")); attachment.setType(attObj.getString("type")); attachment.setText_url(attObj.getString("text_url")); attachment.setUrl(attObj.getString("url")); try { attachment.setDescription(attObj.getString("description")); } catch (JSONException ignore) { } attachments.add(attachment); } } try { status.setCard(parseCardResponse(resobj.getJSONObject("card"))); } catch (Exception e) { status.setCard(null); } status.setMedia_attachments(attachments); //Retrieves mentions List mentions = new ArrayList<>(); if (resobj.has("mentions")) { JSONArray arrayMention = resobj.getJSONArray("mentions"); for (int j = 0; j < arrayMention.length(); j++) { JSONObject menObj = arrayMention.getJSONObject(j); Mention mention = new Mention(); mention.setId(menObj.getString("id")); mention.setUrl(menObj.getString("url")); mention.setAcct(menObj.getString("acct")); mention.setUsername(menObj.getString("username")); mentions.add(mention); } } status.setMentions(mentions); //Retrieves tags List tags = new ArrayList<>(); if (resobj.has("tags")) { JSONArray arrayTag = resobj.getJSONArray("tags"); for (int j = 0; j < arrayTag.length(); j++) { JSONObject tagObj = arrayTag.getJSONObject(j); Tag tag = new Tag(); tag.setName(tagObj.getString("name")); tag.setUrl(tagObj.getString("url")); tags.add(tag); } } status.setTags(tags); //Retrieves emjis List emojiList = new ArrayList<>(); if (resobj.has("emojis")) { try { JSONArray emojisTag = resobj.getJSONArray("emojis"); for (int j = 0; j < emojisTag.length(); j++) { JSONObject emojisObj = emojisTag.getJSONObject(j); Emojis emojis = parseEmojis(emojisObj); emojiList.add(emojis); } } catch (Exception ignored) { } } status.setEmojis(emojiList); //Retrieve Application Application application = new Application(); try { resobj.getJSONObject("application"); application.setName(resobj.getJSONObject("application").getString("name")); application.setWebsite(resobj.getJSONObject("application").getString("website")); } catch (Exception e) { application = new Application(); } status.setApplication(application); status.setAccount(parseAccountResponse(resobj.getJSONObject("account"))); status.setContent(context, resobj.getString("content")); if (!resobj.isNull("favourites_count")) { status.setFavourites_count(resobj.getInt("favourites_count")); } else { status.setFavourites_count(0); } if (!resobj.isNull("reblogs_count")) { status.setReblogs_count(resobj.getInt("reblogs_count")); } else { status.setReblogs_count(0); } try { status.setReplies_count(resobj.getInt("replies_count")); } catch (Exception e) { status.setReplies_count(-1); } try { status.setReblogged(resobj.getBoolean("reblogged")); } catch (Exception e) { status.setReblogged(false); } try { status.setFavourited(resobj.getBoolean("favourited")); } catch (Exception e) { status.setFavourited(false); } try { status.setMuted(resobj.getBoolean("muted")); } catch (Exception e) { status.setMuted(false); } try { status.setPinned(resobj.getBoolean("pinned")); } catch (JSONException e) { status.setPinned(false); } try { if (recursive) { status.setReblog(parseStatuses(context, resobj.getJSONObject("reblog"), false)); } } catch (Exception ignored) { } if (resobj.has("poll") && !resobj.isNull("poll")) { Poll poll = parsePoll(resobj.getJSONObject("poll")); status.setPoll(poll); } } catch (JSONException | ParseException e) { e.printStackTrace(); } status.setViewType(context); Status.fillSpan(new WeakReference<>(context), status); return status; } /** * Parse json response for unique schedule * * @param resobj JSONObject * @return Status */ private static Status parseSchedule(Context context, JSONObject resobj) { Status status = new Status(); try { status.setIn_reply_to_id(resobj.getString("in_reply_to_id")); if (!resobj.isNull("sensitive")) { status.setSensitive(resobj.getBoolean("sensitive")); } else { status.setSensitive(false); } status.setSpoiler_text(resobj.getString("spoiler_text")); try { status.setVisibility(resobj.getString("visibility")); } catch (Exception e) { status.setVisibility("public"); } status.setContent(context, resobj.getString("text")); } catch (JSONException ignored) { } return status; } /** * Parse json response for several notes (Misskey) * * @param jsonArray JSONArray * @return List */ private static List parseNotes(Context context, String instance, JSONArray jsonArray) { List statuses = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Status status = parseNotes(context, instance, resobj); i++; statuses.add(status); } } catch (JSONException e) { e.printStackTrace(); } return statuses; } /** * Parse json response for unique note (misskey) * * @param resobj JSONObject * @return Status */ private static Status parseNotes(Context context, String instance, JSONObject resobj) { Status status = new Status(); try { status.setId(resobj.getString("id")); status.setUri("https://" + instance + "/notes/" + resobj.getString("id")); status.setCreated_at(Helper.mstStringToDate(resobj.getString("createdAt"))); status.setIn_reply_to_id(resobj.getString("replyId")); status.setSensitive(false); resobj.get("cw"); if (!resobj.getString("cw").equals("null")) status.setSpoiler_text(resobj.getString("cw")); try { status.setVisibility(resobj.getString("visibility")); } catch (Exception e) { status.setVisibility("public"); e.printStackTrace(); } status.setUrl("https://" + instance + "/notes/" + resobj.getString("id")); //Retrieves attachments if (resobj.has("media")) { JSONArray arrayAttachement = resobj.getJSONArray("media"); ArrayList attachments = new ArrayList<>(); for (int j = 0; j < arrayAttachement.length(); j++) { JSONObject attObj = arrayAttachement.getJSONObject(j); Attachment attachment = new Attachment(); attachment.setId(attObj.getString("id")); attachment.setPreview_url(attObj.getString("thumbnailUrl")); attachment.setRemote_url(attObj.getString("url")); if (attObj.getString("type").contains("/")) { attachment.setType(attObj.getString("type").split("/")[0]); } else attachment.setType(attObj.getString("type")); attachment.setText_url(attObj.getString("url")); attachment.setUrl(attObj.getString("url")); if (attObj.getString("isSensitive").equals("true")) { status.setSensitive(true); } try { attachment.setDescription(attObj.getString("comment")); } catch (JSONException e) { e.printStackTrace(); } attachments.add(attachment); } status.setMedia_attachments(attachments); } else { status.setMedia_attachments(new ArrayList<>()); } try { status.setCard(parseCardResponse(resobj.getJSONObject("card"))); } catch (Exception e) { status.setCard(null); } //Retrieves mentions List mentions = new ArrayList<>(); status.setAccount(parseMisskeyAccountResponse(instance, resobj.getJSONObject("user"))); status.setContent(context, resobj.getString("text")); try { status.setReplies_count(resobj.getInt("repliesCount")); } catch (Exception e) { status.setReplies_count(-1); } try { status.setFavourited(resobj.getBoolean("isFavorited")); } catch (Exception e) { status.setFavourited(false); } status.setBookmarked(resobj.has("bookmarked") && !resobj.isNull("bookmarked")); try { resobj.getJSONObject("renoteId"); if (!resobj.getJSONObject("renoteId").toString().equals("null")) status.setReblog(parseStatuses(context, resobj.getJSONObject("renote"))); } catch (Exception ignored) { } status.setMentions(mentions); //Retrieves tags List tags = new ArrayList<>(); if (resobj.has("tags")) { JSONArray arrayTag = resobj.getJSONArray("tags"); for (int j = 0; j < arrayTag.length(); j++) { JSONObject tagObj = arrayTag.getJSONObject(j); Tag tag = new Tag(); tag.setName(tagObj.getString("name")); tag.setUrl(tagObj.getString("url")); tags.add(tag); } } status.setTags(tags); //Retrieves emjis List emojiList = new ArrayList<>(); if (resobj.has("emojis")) { JSONArray emojisTag = resobj.getJSONArray("emojis"); for (int j = 0; j < emojisTag.length(); j++) { JSONObject emojisObj = emojisTag.getJSONObject(j); Emojis emojis = parseMisskeyEmojis(emojisObj); emojiList.add(emojis); } status.setEmojis(emojiList); } status.setEmojis(emojiList); //Retrieve Application Application application = new Application(); try { resobj.getJSONObject("application"); application.setName(resobj.getJSONObject("application").getString("name")); application.setWebsite(resobj.getJSONObject("application").getString("website")); } catch (Exception e) { application = new Application(); } status.setApplication(application); } catch (JSONException ignored) { } catch (ParseException e) { e.printStackTrace(); } Status.fillSpan(new WeakReference<>(context), status); return status; } /** * Parse json response for emoji * * @param resobj JSONObject * @return Emojis */ private static Emojis parseEmojis(JSONObject resobj) { Emojis emojis = new Emojis(); try { emojis.setShortcode(resobj.getString("shortcode")); emojis.setStatic_url(resobj.getString("static_url")); emojis.setUrl(resobj.getString("url")); try { emojis.setVisible_in_picker((resobj.getBoolean("visible_in_picker"))); } catch (Exception e) { emojis.setVisible_in_picker(true); } } catch (Exception ignored) { } return emojis; } /** * Parse json response for emoji * * @param resobj JSONObject * @return Emojis */ private static Emojis parseMisskeyEmojis(JSONObject resobj) { Emojis emojis = new Emojis(); try { emojis.setShortcode(resobj.getString("name")); emojis.setStatic_url(resobj.getString("url")); emojis.setUrl(resobj.getString("url")); } catch (Exception ignored) { } return emojis; } /** * Parse json response for emoji * * @param resobj JSONObject * @return Emojis */ private static app.fedilab.android.client.Entities.List parseList(JSONObject resobj) { app.fedilab.android.client.Entities.List list = new app.fedilab.android.client.Entities.List(); try { list.setId(resobj.getString("id")); list.setTitle(resobj.getString("title")); } catch (Exception ignored) { } return list; } /** * Parse json response an unique peertube account * * @param resobj JSONObject * @return Account */ private static Account parseAccountResponsePeertube(String instance, JSONObject resobj) { Account account = new Account(); try { account.setId(resobj.getString("id")); account.setUsername(resobj.getString("name")); account.setAcct(resobj.getString("name") + "@" + resobj.getString("host")); account.setDisplay_name(resobj.getString("displayName")); account.setHost(resobj.getString("host")); if (resobj.has("createdAt")) account.setCreated_at(Helper.mstStringToDate(resobj.getString("createdAt"))); else account.setCreated_at(new Date()); if (resobj.has("followersCount")) account.setFollowers_count(resobj.getInt("followersCount")); else account.setFollowers_count(0); if (resobj.has("followingCount")) account.setFollowing_count(resobj.getInt("followingCount")); else account.setFollowing_count(0); account.setStatuses_count(0); if (resobj.has("description")) account.setNote(resobj.getString("description")); else account.setNote(""); account.setUrl(resobj.getString("url")); account.setSocial("PEERTUBE"); if (resobj.has("avatar") && !resobj.getString("avatar").equals("null")) { account.setAvatar("https://" + instance + resobj.getJSONObject("avatar").get("path")); account.setAvatar_static("https://" + instance + resobj.getJSONObject("avatar").get("path")); } else account.setAvatar(null); account.setAvatar_static(resobj.getString("avatar")); } catch (JSONException ignored) { } catch (ParseException e) { e.printStackTrace(); } return account; } /** * Parse json response an unique report for admins * * @param resobj JSONObject * @return AccountAdmin */ private static Report parseReportAdminResponse(Context context, JSONObject resobj) { Report report = new Report(); try { report.setId(resobj.getString("id")); if (!resobj.isNull("action_taken")) { report.setAction_taken(resobj.getBoolean("action_taken")); } else if (!resobj.isNull("state")) { report.setAction_taken(!resobj.getString("state").equals("open")); } if (!resobj.isNull("comment")) { report.setComment(resobj.getString("comment")); } else if (!resobj.isNull("content")) { report.setComment(resobj.getString("content")); } report.setCreated_at(Helper.mstStringToDate(resobj.getString("created_at"))); if (!resobj.isNull("updated_at")) { report.setUpdated_at(Helper.mstStringToDate(resobj.getString("updated_at"))); } if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { if (!resobj.isNull("account")) { report.setAccount(parseAccountAdminResponse(resobj.getJSONObject("account"))); } if (!resobj.isNull("target_account")) { report.setTarget_account(parseAccountAdminResponse(resobj.getJSONObject("target_account"))); } if (!resobj.isNull("assigned_account")) { report.setAssigned_account(parseAccountAdminResponse(resobj.getJSONObject("assigned_account"))); } } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { if (!resobj.isNull("account")) { Account account = parseAccountResponse(resobj.getJSONObject("account")); AccountAdmin accountAdmin = new AccountAdmin(); accountAdmin.setId(account.getId()); accountAdmin.setUsername(account.getAcct()); accountAdmin.setAccount(account); report.setTarget_account(accountAdmin); } if (!resobj.isNull("actor")) { Account account = parseAccountResponse(resobj.getJSONObject("actor")); AccountAdmin accountAdmin = new AccountAdmin(); accountAdmin.setId(account.getId()); accountAdmin.setUsername(account.getAcct()); accountAdmin.setAccount(account); report.setAccount(accountAdmin); } } if (!resobj.isNull("action_taken_by_account")) { report.setAction_taken_by_account(parseAccountAdminResponse(resobj.getJSONObject("action_taken_by_account"))); } report.setStatuses(parseStatuses(context, resobj.getJSONArray("statuses"))); } catch (Exception e) { e.printStackTrace(); } return report; } /** * Parse json response an unique account for admins * * @param resobj JSONObject * @return Account */ private static AccountAdmin parseAccountAdminResponse(JSONObject resobj) { AccountAdmin accountAdmin = new AccountAdmin(); try { accountAdmin.setId(resobj.getString("id")); if (!resobj.isNull("username")) { accountAdmin.setUsername(resobj.getString("username")); } if (!resobj.isNull("nickname")) { accountAdmin.setUsername(resobj.getString("nickname")); } if (!resobj.isNull("created_at")) { accountAdmin.setCreated_at(Helper.mstStringToDate(resobj.getString("created_at"))); } if (!resobj.isNull("email")) { accountAdmin.setEmail(resobj.getString("email")); } if (!resobj.isNull("role")) { accountAdmin.setRole(resobj.getString("role")); } if (!resobj.isNull("roles")) { if (resobj.getJSONObject("roles").getBoolean("admin")) { accountAdmin.setRole("admin"); } else if (resobj.getJSONObject("roles").getBoolean("moderator")) { accountAdmin.setRole("moderator"); } else { accountAdmin.setRole("user"); } } if (!resobj.isNull("ip")) { accountAdmin.setIp(resobj.getString("ip")); } if (!resobj.isNull("domain")) { accountAdmin.setDomain(resobj.getString("domain")); } if (!resobj.isNull("account")) { accountAdmin.setAccount(parseAccountResponse(resobj.getJSONObject("account"))); } else { Account account = new Account(); account.setId(accountAdmin.getId()); account.setAcct(accountAdmin.getUsername()); account.setDisplay_name(accountAdmin.getUsername()); accountAdmin.setAccount(account); } if (!resobj.isNull("confirmed")) { accountAdmin.setConfirmed(resobj.getBoolean("confirmed")); } else { accountAdmin.setConfirmed(true); } if (!resobj.isNull("suspended")) { accountAdmin.setSuspended(resobj.getBoolean("suspended")); } else { accountAdmin.setSuspended(false); } if (!resobj.isNull("silenced")) { accountAdmin.setSilenced(resobj.getBoolean("silenced")); } else { accountAdmin.setSilenced(false); } if (!resobj.isNull("disabled")) { accountAdmin.setDisabled(resobj.getBoolean("disabled")); } else { if (!resobj.isNull("deactivated")) { accountAdmin.setDisabled(resobj.getBoolean("deactivated")); } else { accountAdmin.setDisabled(false); } } if (!resobj.isNull("approved")) { accountAdmin.setApproved(resobj.getBoolean("approved")); } else { accountAdmin.setApproved(true); } } catch (Exception e) { e.printStackTrace(); } return accountAdmin; } /** * Parse json response an unique account * * @param resobj JSONObject * @return Account */ private static Account parseAccountResponse(JSONObject resobj) { return parseAccountResponse(resobj, true); } /** * Parse json response an unique account * * @param resobj JSONObject * @return Account */ private static Account parseAccountPixelfedSearchResponse(JSONObject resobj) { Account account = new Account(); try { account.setId(resobj.getJSONObject("entity").getString("id")); account.setFollowing(resobj.getJSONObject("entity").getBoolean("following")); account.setAvatar(resobj.getString("avatar")); account.setAvatar_static(resobj.getString("avatar")); account.setDisplay_name(resobj.getString("name")); account.setUsername(resobj.getString("value")); account.setNote(""); account.setAcct(resobj.getString("value")); account.setUrl(resobj.getString("url")); account.setStatuses_count(resobj.getJSONObject("entity").getInt("post_count")); } catch (Exception ignored) { } return account; } /** * Parse json response an unique account * * @param resobj JSONObject * @param recursive boolean * @return Account */ private static Account parseAccountResponse(JSONObject resobj, boolean recursive) { Account account = new Account(); try { account.setId(resobj.getString("id")); account.setUuid(resobj.getString("id")); account.setUsername(resobj.getString("username")); account.setAcct(resobj.getString("acct")); account.setDisplay_name(resobj.getString("display_name")); if (account.getDisplay_name() == null || account.getDisplay_name().compareTo("") == 0) { account.setDisplay_name(resobj.getString("username")); } account.setLocked(resobj.getBoolean("locked")); if (resobj.has("created_at") && !resobj.isNull("created_at")) { account.setCreated_at(Helper.mstStringToDate(resobj.getString("created_at"))); } else { account.setCreated_at(new Date()); } if (!resobj.isNull("followers_count")) { account.setFollowers_count(resobj.getInt("followers_count")); } else { account.setFollowers_count(0); } if (!resobj.isNull("following_count")) { account.setFollowing_count(resobj.getInt("following_count")); } else { account.setFollowing_count(0); } if (!resobj.isNull("statuses_count")) { account.setStatuses_count(resobj.getInt("statuses_count")); } else { account.setStatuses_count(0); } account.setNote(resobj.getString("note")); try { account.setBot(resobj.getBoolean("bot")); } catch (Exception e) { account.setBot(false); } try { if (recursive) { account.setMoved_to_account(parseAccountResponse(resobj.getJSONObject("moved"), false)); } } catch (Exception ignored) { account.setMoved_to_account(null); } account.setUrl(resobj.getString("url")); account.setAvatar(resobj.getString("avatar")); if (resobj.has("avatar_static")) account.setAvatar_static(resobj.getString("avatar_static")); else account.setAvatar_static(resobj.getString("avatar")); if (resobj.has("header")) account.setHeader(resobj.getString("header")); if (resobj.has("header_static")) account.setHeader_static(resobj.getString("header_static")); try { if (resobj.has("pleroma")) { account.setSocial("PLEROMA"); try { account.setModerator(resobj.getJSONObject("pleroma").getBoolean("is_moderator")); account.setAdmin(resobj.getJSONObject("pleroma").getBoolean("is_admin")); } catch (Exception ignored) { account.setModerator(false); account.setAdmin(false); } } } catch (Exception e) { e.printStackTrace(); } try { if (resobj.has("fields") && resobj.get("fields") instanceof JSONArray) { JSONArray fields = resobj.getJSONArray("fields"); LinkedHashMap fieldsMap = new LinkedHashMap<>(); LinkedHashMap fieldsMapVerified = new LinkedHashMap<>(); for (int j = 0; j < fields.length(); j++) { fieldsMap.put(fields.getJSONObject(j).getString("name"), fields.getJSONObject(j).getString("value")); try { fields.getJSONObject(j).getString("verified_at"); fieldsMapVerified.put(fields.getJSONObject(j).getString("name"), !fields.getJSONObject(j).getString("verified_at").equals("null")); } catch (Exception e) { fieldsMapVerified.put(fields.getJSONObject(j).getString("name"), false); } } account.setFields(fieldsMap); account.setFieldsVerified(fieldsMapVerified); } } catch (Exception e) { e.printStackTrace(); } //Retrieves emjis List emojiList = new ArrayList<>(); if (resobj.has("emojis")) { try { JSONArray emojisTag = resobj.getJSONArray("emojis"); for (int j = 0; j < emojisTag.length(); j++) { JSONObject emojisObj = emojisTag.getJSONObject(j); Emojis emojis = parseEmojis(emojisObj); emojiList.add(emojis); } account.setEmojis(emojiList); } catch (Exception e) { account.setEmojis(new ArrayList<>()); e.printStackTrace(); } } else { account.setEmojis(new ArrayList<>()); } if (resobj.has("source")) { JSONObject source = resobj.getJSONObject("source"); try { if (source.has("privacy")) { account.setPrivacy(source.getString("privacy")); } else { account.setPrivacy("public"); } if (source.has("sensitive")) { account.setSensitive(source.getBoolean("sensitive")); } else { account.setSensitive(false); } } catch (Exception e) { account.setPrivacy("public"); account.setSensitive(false); e.printStackTrace(); } } } catch (JSONException | ParseException e) { e.printStackTrace(); } return account; } /** * Parse json response an unique account * * @param resobj JSONObject * @return Account */ private static Account parseMisskeyAccountResponse(String instance, JSONObject resobj) { Account account = new Account(); try { account.setId(resobj.getString("id")); account.setUsername(resobj.getString("username")); String host; String acct; if (resobj.isNull("host")) { acct = resobj.getString("username"); } else { host = resobj.getString("host"); acct = resobj.getString("username") + "@" + host; } account.setAcct(acct); account.setDisplay_name(resobj.getString("name")); account.setCreated_at(new Date()); account.setUrl("https://" + instance + "/@" + account.getUsername()); account.setAvatar(resobj.getString("avatarUrl")); account.setAvatar_static(resobj.getString("avatarUrl")); try { account.setBot(resobj.getBoolean("isBot")); } catch (Exception e) { account.setBot(false); } //Retrieves emjis List emojiList = new ArrayList<>(); if (resobj.has("emojis")) { JSONArray emojisTag = resobj.getJSONArray("emojis"); for (int j = 0; j < emojisTag.length(); j++) { JSONObject emojisObj = emojisTag.getJSONObject(j); Emojis emojis = parseEmojis(emojisObj); emojiList.add(emojis); } } account.setEmojis(emojiList); } catch (JSONException e) { e.printStackTrace(); } return account; } /** * Parse json response for list of relationship * * @param jsonArray JSONArray * @return List */ private static List parseAttachmentResponse(JSONArray jsonArray) { List attachments = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Attachment attachment = parseAttachmentResponse(resobj); attachments.add(attachment); i++; } } catch (JSONException ignored) { } return attachments; } /** * Parse json response an unique attachment * * @param resobj JSONObject * @return Relationship */ public static Attachment parseAttachmentResponse(JSONObject resobj) { Attachment attachment = new Attachment(); try { attachment.setId(resobj.getString("id")); attachment.setType(resobj.getString("type")); attachment.setUrl(resobj.getString("url")); try { attachment.setDescription(resobj.getString("description")); } catch (JSONException ignore) { } try { attachment.setRemote_url(resobj.getString("remote_url")); } catch (JSONException ignore) { } if (attachment.getRemote_url() != null && attachment.getRemote_url().toLowerCase().compareTo("null") == 0) { attachment.setRemote_url(null); } try { attachment.setPreview_url(resobj.getString("preview_url")); } catch (JSONException ignore) { } if (attachment.getPreview_url() != null && attachment.getPreview_url().toLowerCase().compareTo("null") == 0) { attachment.setPreview_url(null); } try { attachment.setMeta(resobj.getString("meta")); } catch (JSONException ignore) { } if (attachment.getMeta() != null && attachment.getMeta().toLowerCase().compareTo("null") == 0) { attachment.setMeta(null); } try { attachment.setText_url(resobj.getString("text_url")); } catch (JSONException ignore) { } if (attachment.getText_url() != null && attachment.getText_url().toLowerCase().compareTo("null") == 0) { attachment.setText_url(null); } try { attachment.setMime(resobj.getString("mime")); } catch (JSONException ignore) { } if (attachment.getMime() != null && attachment.getMime().toLowerCase().compareTo("null") == 0) { attachment.setMime(null); } try { attachment.setFilter_class(resobj.getString("filter_class")); } catch (JSONException ignore) { } if (attachment.getFilter_class() != null && attachment.getFilter_class().toLowerCase().compareTo("null") == 0) { attachment.setFilter_class(null); } try { attachment.setFilter_name(resobj.getString("filter_name")); } catch (JSONException ignore) { } if (attachment.getFilter_name() != null && attachment.getFilter_name().toLowerCase().compareTo("null") == 0) { attachment.setFilter_name(null); } try { attachment.setLicense(resobj.getString("license")); } catch (JSONException ignore) { } if (attachment.getLicense() != null && attachment.getLicense().toLowerCase().compareTo("null") == 0) { attachment.setLicense(null); } try { attachment.setOrientation(resobj.getString("orientation")); } catch (JSONException ignore) { } if (attachment.getOrientation() != null && attachment.getOrientation().toLowerCase().compareTo("null") == 0) { attachment.setOrientation(null); } } catch (JSONException ignored) { } return attachment; } /** * Parse json response an unique notification * * @param resobj JSONObject * @return Account */ public static Notification parseNotificationResponse(Context context, JSONObject resobj) { Notification notification = new Notification(); try { notification.setId(resobj.getString("id")); notification.setType(resobj.getString("type")); notification.setCreated_at(Helper.mstStringToDate(resobj.getString("created_at"))); notification.setAccount(parseAccountResponse(resobj.getJSONObject("account"))); if (resobj.has("status")) { try { notification.setStatus(parseStatuses(context, resobj.getJSONObject("status"), false)); } catch (Exception ignored) { } } notification.setCreated_at(Helper.mstStringToDate(resobj.getString("created_at"))); } catch (JSONException ignored) { } catch (ParseException e) { e.printStackTrace(); } return notification; } /** * Parse xml response for Nitter * * @param xml String * @return List */ private List parseNitter(String xml) { final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String nitterHost = sharedpreferences.getString(Helper.SET_NITTER_HOST, Helper.DEFAULT_NITTER_HOST).toLowerCase(); List statuses = new ArrayList<>(); try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); xpp.setInput(new StringReader(xml)); int eventType = xpp.getEventType(); Account account = null; Status status = null; HashMap mappedProfile = new HashMap<>(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { if (xpp.getName().compareTo("item") == 0) { status = new Status(); status.setReplies_count(0); status.setFavourites_count(0); status.setReblogs_count(0); status.setFavourited(false); status.setReblogged(false); status.setEmojiFound(true); status.setPollEmojiFound(true); status.setEmojiTranslateFound(true); status.setMedia_attachments(new ArrayList<>()); account = new Account(); } else if (xpp.getName().compareTo("creator") == 0) { eventType = xpp.next(); if (eventType == XmlPullParser.TEXT) { if (account != null) { account.setAcct(xpp.getText().replace("@", "") + "@" + nitterHost); account.setDisplay_name(xpp.getText().replace("@", "")); account.setUsername(xpp.getText().replace("@", "")); account.setId("https://" + nitterHost + "/" + xpp.getText()); account.setUuid("https://" + nitterHost + "/" + xpp.getText()); account.setUrl("https://" + nitterHost + "/" + xpp.getText()); if (!mappedProfile.containsKey(xpp.getText())) { HttpsConnection httpsConnection = new HttpsConnection(context, nitterHost); try { String response = httpsConnection.get("https://" + nitterHost + "/" + xpp.getText() + "/rss", 10, null, null); XmlPullParserFactory factory2 = XmlPullParserFactory.newInstance(); factory2.setNamespaceAware(true); XmlPullParser xpp2 = factory2.newPullParser(); xpp2.setInput(new StringReader(response)); int eventType2 = xpp2.getEventType(); while (eventType2 != XmlPullParser.END_DOCUMENT) { if (eventType2 == XmlPullParser.START_TAG) { if (xpp2.getName().compareTo("url") == 0) { eventType2 = xpp2.next(); if (eventType2 == XmlPullParser.TEXT) { mappedProfile.put(xpp.getText(), xpp2.getText()); } break; } } eventType2 = xpp2.next(); } } catch (NoSuchAlgorithmException | KeyManagementException | HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); } } account.setAvatar(mappedProfile.get(xpp.getText())); account.setAvatar_static(mappedProfile.get(xpp.getText())); } } } else if (xpp.getName().compareTo("pubDate") == 0) { eventType = xpp.next(); if (eventType == XmlPullParser.TEXT && status != null) { if (xpp.getText() != null) { try { DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH); Date date = formatter.parse(xpp.getText()); status.setCreated_at(date); } catch (ParseException e) { status.setCreated_at(new Date()); } } } } else if (xpp.getName().compareTo("description") == 0) { eventType = xpp.next(); if (eventType == XmlPullParser.TEXT && status != null) { if (xpp.getText() != null) { String description = xpp.getText(); Pattern imgPattern = Pattern.compile("]*src=\"([^\"]+)\"[^>]*>"); Matcher matcher = imgPattern.matcher(description); ArrayList attachments = new ArrayList<>(); while (matcher.find()) { description = description.replaceAll(Pattern.quote(matcher.group()), ""); Attachment attachment = new Attachment(); attachment.setType("image"); attachment.setDescription(""); attachment.setUrl(matcher.group(1)); attachment.setPreview_url(matcher.group(1)); attachment.setId(matcher.group(1)); attachments.add(attachment); } status.setMedia_attachments(attachments); status.setContent(context, description); } } } else if (xpp.getName().compareTo("guid") == 0) { eventType = xpp.next(); if (eventType == XmlPullParser.TEXT && status != null) { if (xpp.getText() != null) { status.setUri(xpp.getText()); Pattern idPattern = Pattern.compile("([0-9])+"); Matcher matcher = idPattern.matcher(xpp.getText()); while (matcher.find()) { status.setId(matcher.group(0)); } } } } else if (xpp.getName().compareTo("link") == 0) { eventType = xpp.next(); if (eventType == XmlPullParser.TEXT && status != null) { if (xpp.getText() != null) { status.setUrl(xpp.getText()); } } } } else if (eventType == XmlPullParser.END_TAG) { if (xpp.getName().compareTo("item") == 0) { if (status != null) { status.setAccount(account); Status.fillSpan(new WeakReference<>(context), status); statuses.add(status); } account = null; status = null; } } eventType = xpp.next(); } } catch (XmlPullParserException | IOException e) { e.printStackTrace(); } return statuses; } private List parseIdentityProof(JSONArray jsonArray) { List identityProofs = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); IdentityProof identityProof = parseIdentityProof(resobj); i++; identityProofs.add(identityProof); } } catch (JSONException e) { e.printStackTrace(); } return identityProofs; } private IdentityProof parseIdentityProof(JSONObject jsonObject) { IdentityProof identityProof = new IdentityProof(); try { identityProof.setProfile_url(jsonObject.getString("profile_url")); identityProof.setProof_url(jsonObject.getString("proof_url")); identityProof.setProvider(jsonObject.getString("provider")); identityProof.setProvider_username(jsonObject.getString("provider_username")); identityProof.setUpdated_at(Helper.mstStringToDate(jsonObject.getString("updated_at"))); } catch (JSONException | ParseException e) { e.printStackTrace(); } return identityProof; } /** * Execute admin get actions * * @param action type of the action * @param id String can for an account or a status * @return APIResponse */ public APIResponse adminGet(adminAction action, String id, AdminAction adminAction) { apiResponse = new APIResponse(); HashMap params = null; String endpoint = null; String url_action = null; switch (action) { case GET_ACCOUNTS: params = new HashMap<>(); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { if (adminAction.isLocal()) params.put("local", String.valueOf(adminAction.isLocal())); if (adminAction.isRemote()) params.put("remote", String.valueOf(adminAction.isRemote())); if (adminAction.isActive()) params.put("active", String.valueOf(adminAction.isActive())); if (adminAction.isPending()) params.put("pending", String.valueOf(adminAction.isPending())); if (adminAction.isDisabled()) params.put("disabled", String.valueOf(adminAction.isDisabled())); if (adminAction.isSilenced()) params.put("silenced", String.valueOf(adminAction.isSilenced())); if (adminAction.isSuspended()) params.put("suspended", String.valueOf(adminAction.isSuspended())); endpoint = "/admin/accounts"; } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { if (adminAction.isLocal()) params.put("filters", "local"); if (adminAction.isRemote()) params.put("filters", "external"); if (adminAction.isActive()) params.put("filters", "active"); if (adminAction.isDisabled()) params.put("filters", "deactivated"); endpoint = "/admin/users"; } break; case GET_ONE_ACCOUNT: if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { endpoint = String.format("/admin/accounts/%s", id); } else { try { id = URLEncoder.encode(id, "UTF-8"); } catch (UnsupportedEncodingException ignored) { } params = new HashMap<>(); params.put("query", id); endpoint = "/admin/users"; } break; case GET_REPORTS: endpoint = "/admin/reports"; if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { if (!adminAction.isUnresolved()) { params = new HashMap<>(); params.put("resolved", "present"); } } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { if (adminAction.isUnresolved()) { params = new HashMap<>(); params.put("state", "open"); } else { params = new HashMap<>(); params.put("state", "resolved"); } } break; case GET_ONE_REPORT: endpoint = String.format("/admin/reports/%s", id); break; } if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { url_action = getAbsoluteUrl(endpoint); } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { url_action = Helper.instanceWithProtocol(this.context, this.instance) + "/api/pleroma" + endpoint; } if (url_action == null) { apiResponse = new APIResponse(); APIError = new Error(); APIError.setError(context.getString(R.string.toast_error)); apiResponse.setError(APIError); return apiResponse; } try { String response = new HttpsConnection(context, this.instance).get(url_action, 10, params, prefKeyOauthTokenT); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { if (new JSONObject(response).has("users")) { response = new JSONArray(new JSONObject(response).getJSONArray("users").toString()).toString(); } else if (new JSONObject(response).has("reports")) { response = new JSONArray(new JSONObject(response).getJSONArray("reports").toString()).toString(); } } switch (action) { case GET_ACCOUNTS: List accountAdmins = parseAccountAdminResponse(new JSONArray(response)); apiResponse.setAccountAdmins(accountAdmins); break; case GET_ONE_ACCOUNT: if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { accountAdmins = parseAccountAdminResponse(new JSONArray(response)); if (accountAdmins.size() > 0) { Account accountpleroma = getAccount(accountAdmins.get(0).getId()); if (accountpleroma != null) { accountAdmins.get(0).setAccount(accountpleroma); } } } else { AccountAdmin accountAdmin = parseAccountAdminResponse(new JSONObject(response)); accountAdmins = new ArrayList<>(); accountAdmins.add(accountAdmin); } apiResponse.setAccountAdmins(accountAdmins); break; case GET_REPORTS: List reports = parseReportAdminResponse(new JSONArray(response)); apiResponse.setReports(reports); break; case GET_ONE_REPORT: reports = new ArrayList<>(); Report report = parseReportAdminResponse(context, new JSONObject(response)); reports.add(report); apiResponse.setReports(reports); break; } } catch (IOException | NoSuchAlgorithmException | KeyManagementException | JSONException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } return apiResponse; } /** * Execute admin post actions * * @param action type of the action * @param id String can for an account or a status * @return APIResponse */ public APIResponse adminDo(adminAction action, String id, AdminAction adminAction) { apiResponse = new APIResponse(); String http_action = "POST"; String endpoint = null; String url_action = null; HashMap params = null; switch (action) { case ENABLE: if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { endpoint = String.format("/admin/accounts/%s/enable", id); } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { http_action = "PATCH"; endpoint = String.format("/admin/users/%s/toggle_activation", id); } break; case APPROVE: endpoint = String.format("/admin/accounts/%s/approve", id); break; case REJECT: endpoint = String.format("/admin/accounts/%s/reject", id); break; case UNSILENCE: endpoint = String.format("/admin/accounts/%s/unsilence", id); break; case UNSUSPEND: endpoint = String.format("/admin/accounts/%s/unsuspend", id); break; case ASSIGN_TO_SELF: endpoint = String.format("/admin/reports/%s/assign_to_self", id); break; case UNASSIGN: endpoint = String.format("/admin/reports/%s/unassign", id); break; case REOPEN: if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { endpoint = String.format("/admin/reports/%s/reopen", id); } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { endpoint = String.format("/admin/reports/%s", id); params = new HashMap<>(); params.put("state", "open"); http_action = "PUT"; } break; case RESOLVE: if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { endpoint = String.format("/admin/reports/%s/resolve", id); } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { endpoint = String.format("/admin/reports/%s", id); params = new HashMap<>(); params.put("state", "resolved"); http_action = "PUT"; } break; case NONE: params = new HashMap<>(); params.put("type", "none"); endpoint = String.format("/admin/accounts/%s/action", id); params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification())); if (adminAction.getText() != null) { params.put("text", adminAction.getText()); } break; case DISABLE: if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { params = new HashMap<>(); params.put("type", "disable"); endpoint = String.format("/admin/accounts/%s/action", id); params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification())); if (adminAction.getText() != null) { params.put("text", adminAction.getText()); } } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { http_action = "PATCH"; endpoint = String.format("/admin/users/%s/toggle_activation", id); } break; case SILENCE: params = new HashMap<>(); params.put("type", "silence"); endpoint = String.format("/admin/accounts/%s/action", id); params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification())); if (adminAction.getText() != null) { params.put("text", adminAction.getText()); } break; case SUSPEND: if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { params = new HashMap<>(); params.put("type", "suspend"); endpoint = String.format("/admin/accounts/%s/action", id); params.put("send_email_notification", String.valueOf(adminAction.isSend_email_notification())); if (adminAction.getText() != null) { params.put("text", adminAction.getText()); } } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { http_action = "DELETE"; endpoint = "/admin/users"; params = new HashMap<>(); params.put("nickname", id); } break; } if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) { url_action = getAbsoluteUrl(endpoint); } else if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { url_action = Helper.instanceWithProtocol(this.context, this.instance) + "/api/pleroma" + endpoint; } try { String response = null; switch (http_action) { case "POST": assert url_action != null; response = new HttpsConnection(context, this.instance).post(url_action, 10, params, prefKeyOauthTokenT); break; case "PATCH": assert url_action != null; response = new HttpsConnection(context, this.instance).patch(url_action, 10, null, null, null, null, null, prefKeyOauthTokenT); break; case "PUT": assert url_action != null; response = new HttpsConnection(context, this.instance).put(url_action, 10, params, prefKeyOauthTokenT); break; case "DELETE": assert url_action != null; new HttpsConnection(context, this.instance).delete(url_action, 10, params, prefKeyOauthTokenT); break; } switch (action) { case ENABLE: case APPROVE: case REJECT: case UNSILENCE: // case UNDISABLE: case UNSUSPEND: List accountAdmins = null; try { AccountAdmin accountAdmin = parseAccountAdminResponse(new JSONObject(response)); accountAdmin.setAction(action); accountAdmins = new ArrayList<>(); accountAdmins.add(accountAdmin); } catch (JSONException e) { e.printStackTrace(); } apiResponse.setAccountAdmins(accountAdmins); break; case ASSIGN_TO_SELF: case UNASSIGN: case REOPEN: case RESOLVE: List reports = null; Report report; try { reports = new ArrayList<>(); report = parseReportAdminResponse(context, new JSONObject(response)); reports.add(report); } catch (JSONException e) { e.printStackTrace(); } apiResponse.setReports(reports); break; case NONE: accountAdmins = new ArrayList<>(); AccountAdmin accountAdmin = new AccountAdmin(); accountAdmin.setAction(action); accountAdmins.add(accountAdmin); apiResponse.setAccountAdmins(accountAdmins); break; case DISABLE: accountAdmins = new ArrayList<>(); accountAdmin = new AccountAdmin(); accountAdmin.setDisabled(true); accountAdmin.setAction(action); accountAdmins.add(accountAdmin); apiResponse.setAccountAdmins(accountAdmins); break; case SILENCE: accountAdmins = new ArrayList<>(); accountAdmin = new AccountAdmin(); accountAdmin.setSilenced(true); accountAdmin.setAction(action); accountAdmins.add(accountAdmin); apiResponse.setAccountAdmins(accountAdmins); break; case SUSPEND: accountAdmins = new ArrayList<>(); accountAdmin = new AccountAdmin(); accountAdmin.setSuspended(true); accountAdmin.setAction(action); accountAdmins.add(accountAdmin); apiResponse.setAccountAdmins(accountAdmins); break; } } catch (IOException | NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } return apiResponse; } public InstanceNodeInfo displayNodeInfo(String domain) { if (domain == null) { return null; } String response; InstanceNodeInfo instanceNodeInfo = new InstanceNodeInfo(); if (domain.startsWith("http://")) { domain = domain.replace("http://", ""); } if (domain.startsWith("https://")) { domain = domain.replace("https://", ""); } try { response = new HttpsConnection(context, domain).get("https://" + domain + "/.well-known/nodeinfo", 30, null, null); JSONArray jsonArray = new JSONObject(response).getJSONArray("links"); ArrayList nodeInfos = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); NodeInfo nodeInfo = new NodeInfo(); nodeInfo.setHref(resobj.getString("href")); nodeInfo.setRel(resobj.getString("rel")); i++; nodeInfos.add(nodeInfo); } if (nodeInfos.size() > 0) { NodeInfo nodeInfo = nodeInfos.get(nodeInfos.size() - 1); response = new HttpsConnection(context, this.instance).get(nodeInfo.getHref(), 30, null, null); JSONObject resobj = new JSONObject(response); JSONObject jsonObject = resobj.getJSONObject("software"); String name = jsonObject.getString("name").toUpperCase(); if (name.compareTo("CORGIDON") == 0) { name = "MASTODON"; } instanceNodeInfo.setName(name); instanceNodeInfo.setVersion(jsonObject.getString("version")); instanceNodeInfo.setOpenRegistrations(resobj.getBoolean("openRegistrations")); } } catch (JSONException e) { e.printStackTrace(); } } catch (IOException | JSONException | NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); try { response = new HttpsConnection(context, this.instance).get("https://" + domain + "/api/v1/instance", 30, null, null); JSONObject jsonObject = new JSONObject(response); instanceNodeInfo.setName("MASTODON"); instanceNodeInfo.setVersion(jsonObject.getString("version")); instanceNodeInfo.setOpenRegistrations(true); } catch (IOException e1) { instanceNodeInfo.setConnectionError(true); e1.printStackTrace(); } catch (NoSuchAlgorithmException | JSONException | KeyManagementException e1) { e1.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e1) { if (e1.getStatusCode() == 404 || e1.getStatusCode() == 501) { instanceNodeInfo.setName("GNU"); instanceNodeInfo.setVersion("unknown"); instanceNodeInfo.setOpenRegistrations(true); e1.printStackTrace(); } else { instanceNodeInfo.setName("MASTODON"); instanceNodeInfo.setVersion("3.0"); instanceNodeInfo.setOpenRegistrations(false); } } } catch (HttpsConnection.HttpsConnectionException e) { try { response = new HttpsConnection(context, this.instance).get("https://" + domain + "/api/v1/instance", 30, null, null); JSONObject jsonObject = new JSONObject(response); instanceNodeInfo.setName("MASTODON"); instanceNodeInfo.setVersion(jsonObject.getString("version")); instanceNodeInfo.setOpenRegistrations(true); } catch (IOException e1) { instanceNodeInfo.setConnectionError(true); e1.printStackTrace(); } catch (NoSuchAlgorithmException | JSONException | KeyManagementException e1) { e1.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e1) { if (e1.getStatusCode() == 404 || e1.getStatusCode() == 501) { instanceNodeInfo.setName("GNU"); instanceNodeInfo.setVersion("unknown"); instanceNodeInfo.setOpenRegistrations(true); e1.printStackTrace(); } else { instanceNodeInfo.setName("MASTODON"); instanceNodeInfo.setVersion("3.0"); instanceNodeInfo.setOpenRegistrations(false); } } e.printStackTrace(); } return instanceNodeInfo; } public InstanceNodeInfo instanceInfo(String domain) { String response; InstanceNodeInfo instanceNodeInfo = null; try { response = new HttpsConnection(context, domain).get("https://" + domain + "/.well-known/nodeinfo", 30, null, null); JSONArray jsonArray = new JSONObject(response).getJSONArray("links"); ArrayList nodeInfos = new ArrayList<>(); try { instanceNodeInfo = new InstanceNodeInfo(); int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); NodeInfo nodeInfo = new NodeInfo(); nodeInfo.setHref(resobj.getString("href")); nodeInfo.setRel(resobj.getString("rel")); i++; nodeInfos.add(nodeInfo); } if (nodeInfos.size() > 0) { NodeInfo nodeInfo = nodeInfos.get(nodeInfos.size() - 1); response = new HttpsConnection(context, this.instance).get(nodeInfo.getHref(), 30, null, null); JSONObject resobj = new JSONObject(response); JSONObject jsonObject = resobj.getJSONObject("software"); String name; name = jsonObject.getString("name").toUpperCase(); instanceNodeInfo.setName(name); instanceNodeInfo.setVersion(jsonObject.getString("version")); instanceNodeInfo.setOpenRegistrations(resobj.getBoolean("openRegistrations")); if (name.trim().toUpperCase().compareTo("MASTODON") == 0 || name.trim().toUpperCase().compareTo("PLEROMA") == 0 || name.trim().toUpperCase().compareTo("PIXELFED") == 0) { APIResponse apiResponse = getInstance(domain); Instance instanceNode = apiResponse.getInstance(); instanceNodeInfo.setNodeDescription(instanceNode.getDescription()); instanceNodeInfo.setNumberOfUsers(instanceNode.getUserCount()); instanceNodeInfo.setNumberOfPosts(instanceNode.getStatusCount()); instanceNodeInfo.setNumberOfInstance(instanceNode.getDomainCount()); instanceNodeInfo.setStaffAccount(instanceNode.getContactAccount()); instanceNodeInfo.setNodeName(instanceNode.getTitle()); instanceNodeInfo.setThumbnail(instanceNode.getThumbnail()); instanceNodeInfo.setVersion(instanceNode.getVersion()); } if (resobj.has("metadata")) { JSONObject metadata = resobj.getJSONObject("metadata"); if (metadata.has("staffAccounts")) { instanceNodeInfo.setStaffAccountStr(metadata.getString("staffAccounts")); } if (metadata.has("nodeName")) { instanceNodeInfo.setNodeName(metadata.getString("nodeName")); } } if (resobj.has("usage")) { JSONObject usage = resobj.getJSONObject("usage"); if (usage.has("users") && usage.getJSONObject("users").has("total")) { instanceNodeInfo.setNumberOfUsers(usage.getJSONObject("users").getInt("total")); } if (usage.has("localPosts")) { instanceNodeInfo.setNumberOfPosts(usage.getInt("localPosts")); } } if (instanceNodeInfo.getStaffAccountStr() != null && instanceNodeInfo.getStaffAccount() == null) { APIResponse search = searchAccounts(instanceNodeInfo.getStaffAccountStr(), 1); if (search != null && search.getAccounts() != null && search.getAccounts().size() > 0) { instanceNodeInfo.setStaffAccount(search.getAccounts().get(0)); } } } } catch (JSONException e) { setDefaultError(e); } } catch (IOException | JSONException | NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { APIResponse apiResponse = getInstance(domain); instanceNodeInfo = new InstanceNodeInfo(); instanceNodeInfo.setName("MASTODON"); Instance instanceNode = apiResponse.getInstance(); instanceNodeInfo.setNodeDescription(instanceNode.getDescription()); instanceNodeInfo.setNumberOfUsers(instanceNode.getUserCount()); instanceNodeInfo.setNumberOfPosts(instanceNode.getStatusCount()); instanceNodeInfo.setNumberOfInstance(instanceNode.getDomainCount()); instanceNodeInfo.setStaffAccount(instanceNode.getContactAccount()); instanceNodeInfo.setNodeName(instanceNode.getTitle()); instanceNodeInfo.setThumbnail(instanceNode.getThumbnail()); instanceNodeInfo.setVersion(instanceNode.getVersion()); } return instanceNodeInfo; } /*** * Get info on the current Instance *synchronously* * @return APIResponse */ public APIResponse getInstance(String instance) { try { String response = new HttpsConnection(context, this.instance).get("https://" + instance + "/api/v1/instance", 30, null, prefKeyOauthTokenT); Instance instanceEntity = parseInstance(new JSONObject(response)); apiResponse.setInstance(instanceEntity); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return apiResponse; } /*** * Get info on the current Instance *synchronously* * @return APIResponse */ public APIResponse getInstance() { try { String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/instance"), 30, null, prefKeyOauthTokenT); Instance instanceEntity = parseInstance(new JSONObject(response)); apiResponse.setInstance(instanceEntity); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return apiResponse; } /*** * Get instance for registering an account *synchronously* * @return APIResponse */ public APIResponse getInstanceReg(String category) { apiResponse = new APIResponse(); try { String response = new HttpsConnection(context, null).get(String.format("https://api.joinmastodon.org/servers?category=%s", category)); List instanceRegs = parseInstanceReg(new JSONArray(response)); apiResponse.setInstanceRegs(instanceRegs); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return apiResponse; } /*** * Update credential of the authenticated user *synchronously* * @return APIResponse */ public APIResponse updateCredential(String display_name, String note, ByteArrayInputStream avatar, String avatarName, ByteArrayInputStream header, String headerName, accountPrivacy privacy, HashMap customFields, boolean sensitive) { HashMap requestParams = new HashMap<>(); if (display_name != null) try { requestParams.put("display_name", URLEncoder.encode(display_name, "UTF-8")); } catch (UnsupportedEncodingException e) { requestParams.put("display_name", display_name); } if (note != null && MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) try { requestParams.put("note", URLEncoder.encode(note, "UTF-8")); } catch (UnsupportedEncodingException e) { requestParams.put("note", note); } if (privacy != null) requestParams.put("locked", privacy == accountPrivacy.LOCKED ? "true" : "false"); int i = 0; if (customFields != null && customFields.size() > 0) { Iterator> it = customFields.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = it.next(); requestParams.put("fields_attributes[" + i + "][name]", pair.getKey()); requestParams.put("fields_attributes[" + i + "][value]", pair.getValue()); it.remove(); i++; } } requestParams.put("source[sensitive]", String.valueOf(sensitive)); try { new HttpsConnection(context, this.instance).patch(getAbsoluteUrl("/accounts/update_credentials"), 10, requestParams, avatar, avatarName, header, headerName, prefKeyOauthTokenT); } catch (HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return apiResponse; } /*** * Verifiy credential of the authenticated user *synchronously* * @return Account */ public Account verifyCredentials() { account = new Account(); InstanceNodeInfo nodeinfo = displayNodeInfo(instance); String social = null; if (nodeinfo != null) { social = nodeinfo.getName(); } try { if (context == null) { setError(500, new Throwable("An error occured!")); return null; } String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/accounts/verify_credentials"), 10, null, prefKeyOauthTokenT); account = parseAccountResponse(new JSONObject(response)); if (social != null) { account.setSocial(social.toUpperCase()); } if (account != null && account.getSocial() != null && account.getSocial().equals("PLEROMA")) { isPleromaAdmin(account.getAcct()); } } catch (HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return account; } /*** * Verifiy credential of the authenticated user *synchronously* */ public void refreshToken(Account account) { HashMap params = new HashMap<>(); params.put("grant_type", "refresh_token"); params.put("client_id", account.getClient_id()); params.put("client_secret", account.getClient_secret()); params.put("refresh_token", account.getRefresh_token()); SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); try { String response; if (account.getSocial().compareTo("PEERTUBE") == 0) { response = new HttpsConnection(context, instance).post(getAbsoluteUrl("/users/token"), 60, params, null); } else { response = new HttpsConnection(context, instance).post("https://" + instance + "/oauth/token", 60, params, null); } JSONObject resobj = new JSONObject(response); String newToken = resobj.getString("access_token"); String newRefreshToken = resobj.getString("refresh_token"); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, newToken); editor.apply(); if (account.getSocial().compareTo("PEERTUBE") == 0) { response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/users/me"), 60, null, newToken); JSONObject accountObject = new JSONObject(response).getJSONObject("account"); account = parseAccountResponsePeertube(instance, accountObject); } else { response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/accounts/verify_credentials"), 10, null, newToken); account = parseAccountResponse(new JSONObject(response)); } account.setRefresh_token(newRefreshToken); account.setToken(newToken); if (account.getHeader() == null) { account.setHeader(""); account.setHeader_static(""); } account.setInstance(instance); new AccountDAO(context, db).updateAccount(account); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } } public APIResponse createAccount(AccountCreation accountCreation) { apiResponse = new APIResponse(); try { HashMap params = new HashMap<>(); params.put(Helper.CLIENT_NAME, Helper.CLIENT_NAME_VALUE); params.put(Helper.REDIRECT_URIS, Helper.REDIRECT_CONTENT); params.put(Helper.SCOPES, Helper.OAUTH_SCOPES); params.put(Helper.WEBSITE, Helper.WEBSITE_VALUE); String response = new HttpsConnection(context, this.instance).post(getAbsoluteUrl("/apps"), 30, params, null); JSONObject resobj = new JSONObject(response); String client_id = resobj.getString("client_id"); String client_secret = resobj.getString("client_secret"); params = new HashMap<>(); params.put("grant_type", "client_credentials"); params.put("client_id", client_id); params.put("client_secret", client_secret); params.put("scope", "read write"); response = new HttpsConnection(context, this.instance).post("https://" + this.instance + "/oauth/token", 30, params, null); JSONObject res = new JSONObject(response); String app_token = res.getString("access_token"); params = new HashMap<>(); params.put("username", accountCreation.getUsername()); params.put("email", accountCreation.getEmail()); params.put("password", accountCreation.getPassword()); params.put("agreement", "true"); params.put("locale", Locale.getDefault().getLanguage()); new HttpsConnection(context, this.instance).post(getAbsoluteUrl("/accounts"), 30, params, app_token); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } return apiResponse; } /** * Returns an account * * @param accountId String account fetched * @return Account entity */ public Account getAccount(String accountId) { account = new Account(); try { String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl(String.format("/accounts/%s", accountId)), 10, null, prefKeyOauthTokenT); account = parseAccountResponse(new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return account; } /** * Returns a relationship between the authenticated account and an account * * @param accountId String account fetched * @return Relationship entity */ public Relationship getRelationship(String accountId) { List relationships; Relationship relationship = null; HashMap params = new HashMap<>(); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) params.put("id[]", accountId); else params.put("id", accountId); try { String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/accounts/relationships"), 10, params, prefKeyOauthTokenT); relationships = parseRelationshipResponse(new JSONArray(response)); if (relationships.size() > 0) relationship = relationships.get(0); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return relationship; } /** * Returns a relationship between the authenticated account and an account * * @param accounts ArrayList accounts fetched * @return Relationship entity */ public APIResponse getRelationship(List accounts) { HashMap params = new HashMap<>(); if (accounts != null && accounts.size() > 0) { StringBuilder parameters = new StringBuilder(); for (Account account : accounts) parameters.append("id[]=").append(account.getId()).append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(5)); params.put("id[]", parameters.toString()); List relationships = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/accounts/relationships"), 10, params, prefKeyOauthTokenT); relationships = parseRelationshipResponse(new JSONArray(response)); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setRelationships(relationships); } return apiResponse; } /** * Retrieves status for the account *synchronously* * * @param accountId String Id of the account * @return APIResponse */ public APIResponse getStatus(String accountId) { return getStatus(accountId, false, false, false, null, null, tootPerPage); } /** * Retrieves status for the account *synchronously* * * @param accountId String Id of the account * @param max_id String id max * @return APIResponse */ public APIResponse getStatus(String accountId, String max_id) { return getStatus(accountId, false, false, false, max_id, null, tootPerPage); } /** * Retrieves status with media for the account *synchronously* * * @param accountId String Id of the account * @param max_id String id max * @return APIResponse */ public APIResponse getStatusWithMedia(String accountId, String max_id) { return getStatus(accountId, true, false, false, max_id, null, tootPerPage); } /** * Retrieves pinned status(es) *synchronously* * * @param accountId String Id of the account * @param max_id String id max * @return APIResponse */ public APIResponse getPinnedStatuses(String accountId, String max_id) { return getStatus(accountId, false, true, false, max_id, null, tootPerPage); } /** * Retrieves replies status(es) *synchronously* * * @param accountId String Id of the account * @param max_id String id max * @return APIResponse */ public APIResponse getAccountTLStatuses(String accountId, String max_id, boolean exclude_replies) { return getStatus(accountId, false, false, exclude_replies, max_id, null, tootPerPage); } /** * Retrieves status for the account *synchronously* * * @param accountId String Id of the account * @param onlyMedia boolean only with media * @param exclude_replies boolean excludes replies * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getStatus(String accountId, boolean onlyMedia, boolean pinned, boolean exclude_replies, String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 40) limit = 40; if (pinned) params.put("pinned", Boolean.toString(true)); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { params.put("only_media", Boolean.toString(true)); if (max_id == null) { params.put("min_id", "1"); } } else { if (onlyMedia) params.put("only_media", Boolean.toString(true)); } params.put("exclude_replies", Boolean.toString(exclude_replies)); params.put("limit", String.valueOf(limit)); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String tag = sharedpreferences.getString(Helper.SET_FEATURED_TAG_ACTION, null); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON && tag != null) { params.put("tagged", tag.toLowerCase()); } statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/accounts/%s/statuses", accountId)), 10, params, prefKeyOauthTokenT); statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); setDefaultError(e); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves accounts that reblogged the status *synchronously* * * @param statusId String Id of the status * @param max_id String id max * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getRebloggedBy(String statusId, String max_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); params.put("limit", "80"); accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s/reblogged_by", statusId)), 10, params, prefKeyOauthTokenT); accounts = parseAccountResponse(new JSONArray(response)); setAccountsMaxId(httpsConnection, accounts); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Retrieves accounts that favourited the status *synchronously* * * @param statusId String Id of the status * @param max_id String id max * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getFavouritedBy(String statusId, String max_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); params.put("limit", "80"); accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s/favourited_by", statusId)), 10, params, prefKeyOauthTokenT); accounts = parseAccountResponse(new JSONArray(response)); setAccountsMaxId(httpsConnection, accounts); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Retrieves one status *synchronously* * * @param statusId String Id of the status * @return APIResponse */ public APIResponse getStatusbyId(String statusId) { statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s", statusId)), 10, null, prefKeyOauthTokenT); Status status = parseStatuses(context, new JSONObject(response)); statuses.add(status); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves one status *synchronously* * * @param statusId String Id of the status * @return APIResponse */ public APIResponse getStatusbyIdAndCache(String statusId) { statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s", statusId)), 10, null, prefKeyOauthTokenT); Status status = parseStatuses(context, new JSONObject(response)); SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT); new TimelineCacheDAO(context, db).update(status.getId(), response, account.getId(), account.getInstance()); statuses.add(status); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves the context of status with replies *synchronously* * * @param statusId Id of the status * @return List */ public app.fedilab.android.client.Entities.Context getStatusContext(String userId, String statusId) { app.fedilab.android.client.Entities.Context statusContext = new app.fedilab.android.client.Entities.Context(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response; if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s/context", statusId)), 10, null, prefKeyOauthTokenT); } else { response = httpsConnection.get(getAbsoluteUr2l(String.format("/comments/%s/status/%s", userId, statusId)), 10, null, prefKeyOauthTokenT); } statusContext = parseContext(new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return statusContext; } public APIResponse getReplies(String statusId, String max_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); params.put("limit", String.valueOf(30)); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUr2l(String.format("/status/%s/replies", statusId)), 10, params, prefKeyOauthTokenT); statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves direct timeline for the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getDirectTimeline(String max_id) { return getDirectTimeline(max_id, null, tootPerPage); } /** * Retrieves conversation timeline for the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getConversationTimeline(String max_id) { return getConversationTimeline(max_id, null, tootPerPage); } /** * Retrieves direct timeline for the account since an Id value *synchronously* * * @return APIResponse */ public APIResponse getConversationTimelineSinceId(String since_id) { return getConversationTimeline(null, since_id, tootPerPage); } /** * Retrieves conversation timeline for the account *synchronously* * * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ private APIResponse getConversationTimeline(String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 80) limit = 80; params.put("limit", String.valueOf(limit)); List conversations = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/conversations"), 10, params, prefKeyOauthTokenT); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); conversations = parseConversations(new JSONArray(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setConversations(conversations); return apiResponse; } /** * Retrieves direct timeline for the account since an Id value *synchronously* * * @return APIResponse */ public APIResponse getDirectTimelineSinceId(String since_id) { return getDirectTimeline(null, since_id, tootPerPage); } /** * Retrieves direct timeline for the account *synchronously* * * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ private APIResponse getDirectTimeline(String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 80) limit = 80; params.put("limit", String.valueOf(limit)); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/timelines/direct"), 10, params, prefKeyOauthTokenT); statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves home timeline for the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getHomeTimeline(String max_id) { return getHomeTimeline(max_id, null, null, tootPerPage); } /** * Retrieves home timeline for the account since an Id value *synchronously* * * @return APIResponse */ public APIResponse getHomeTimelineSinceId(String since_id) { return getHomeTimeline(null, since_id, null, tootPerPage); } /** * Retrieves home timeline from cache the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getHomeTimelineCache(String max_id) { SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); statuses = new TimelineCacheDAO(context, db).get(max_id); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean remember_position_home = sharedpreferences.getBoolean(Helper.SET_REMEMBER_POSITION_HOME, true); if (remember_position_home) { if (statuses != null) { Iterator i = statuses.iterator(); List ids = new ArrayList<>(); while (i.hasNext()) { Status s = i.next(); if (ids.contains(s.getId())) { i.remove(); new TimelineCacheDAO(context, db).remove(s.getId()); } else { ids.add(s.getId()); } } } if (statuses == null || statuses.size() <= 1) { return getHomeTimeline(max_id); } else { if (statuses.get(0).getId().matches("\\d+")) { apiResponse.setSince_id(String.valueOf(statuses.get(0).getId())); } else { apiResponse.setSince_id(statuses.get(0).getId()); } apiResponse.setMax_id(statuses.get(statuses.size() - 1).getId()); apiResponse.setStatuses(statuses); return apiResponse; } } else { return getHomeTimeline(max_id); } } /** * Retrieves home timeline for the account *synchronously* * * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getHomeTimeline(String max_id, String since_id, String min_id, int limit) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (min_id != null) params.put("min_id", min_id); if (0 > limit || limit > 80) limit = 80; params.put("limit", String.valueOf(limit)); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/timelines/home"), 10, params, prefKeyOauthTokenT); if (since_id == null) { statuses = parseStatusesForCache(context, new JSONArray(response)); } else { statuses = parseStatuses(context, new JSONArray(response)); } setStatusesMaxId(httpsConnection, statuses); } catch (UnknownHostException e) { if (since_id == null) { getHomeTimelineCache(max_id); } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } if (apiResponse == null) apiResponse = new APIResponse(); apiResponse.setStatuses(statuses); return apiResponse; } /** * Get identy proof for an account *synchronously* * * @param userId user_id String * @return APIResponse */ public APIResponse getIdentityProof(String userId) { List identityProofs = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/accounts/%s/identity_proofs", userId)), 10, null, prefKeyOauthTokenT); identityProofs = parseIdentityProof(new JSONArray(response)); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } if (apiResponse == null) apiResponse = new APIResponse(); apiResponse.setIdentityProofs(identityProofs); return apiResponse; } /** * Retrieves public GNU timeline for the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getGNUTimeline(String remoteInstance, String max_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get("https://" + remoteInstance + "/api/statuses/public_timeline.json", 10, params, prefKeyOauthTokenT); statuses = GNUAPI.parseStatuses(context, new JSONArray(response)); if (statuses.size() > 0) { if (statuses.get(0).getId() != null && statuses.get(0).getId().matches("-?\\d+(\\.\\d+)?")) { apiResponse.setSince_id(String.valueOf(statuses.get(0).getId())); apiResponse.setMax_id(String.valueOf(statuses.get(statuses.size() - 1).getId())); } else { apiResponse.setSince_id(statuses.get(0).getId()); apiResponse.setMax_id(statuses.get(statuses.size() - 1).getId()); } } } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException | HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves public pixelfed timeline for the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getPixelfedTimeline(String remoteInstance, String max_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("page", max_id); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrlRemote(remoteInstance, "/timelines/public/"), 10, params, prefKeyOauthTokenT); statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException | HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } private void setStatusesMaxId(HttpsConnection httpsConnection, List statuses) { if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); } else { if (statuses.size() > 0) { if (statuses.get(0).getId() != null && statuses.get(0).getId().matches("-?\\d+(\\.\\d+)?")) { apiResponse.setSince_id(String.valueOf(statuses.get(0).getId())); apiResponse.setMax_id(String.valueOf(statuses.get(statuses.size() - 1).getId())); } else { apiResponse.setSince_id(statuses.get(0).getId()); apiResponse.setMax_id(statuses.get(statuses.size() - 1).getId()); } if (statuses.size() < tootPerPage) { apiResponse.setSince_id(null); apiResponse.setMax_id(null); } } } } private void setNotificationsMaxId(HttpsConnection httpsConnection, List notifications) { if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); } else { if (notifications.size() > 0) { if (notifications.get(0).getId() != null && notifications.get(0).getId().matches("-?\\d+(\\.\\d+)?")) { apiResponse.setSince_id(String.valueOf(notifications.get(0).getId())); apiResponse.setMax_id(String.valueOf(notifications.get(notifications.size() - 1).getId())); } else { apiResponse.setSince_id(notifications.get(0).getId()); apiResponse.setMax_id(notifications.get(notifications.size() - 1).getId()); } } if (notifications.size() < tootPerPage) { apiResponse.setSince_id(null); apiResponse.setMax_id(null); } } } private void setAccountsMaxId(HttpsConnection httpsConnection, List accounts) { if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); } else { if (accounts.size() > 0) { if (accounts.get(0).getId() != null && accounts.get(0).getId().matches("-?\\d+(\\.\\d+)?")) { apiResponse.setSince_id(String.valueOf(accounts.get(0).getId())); apiResponse.setMax_id(String.valueOf(accounts.get(accounts.size() - 1).getId())); } else { apiResponse.setSince_id(accounts.get(0).getId()); apiResponse.setMax_id(accounts.get(accounts.size() - 1).getId()); } if (accounts.size() < tootPerPage) { apiResponse.setSince_id(null); apiResponse.setMax_id(null); } } } } /** * Retrieves Peertube videos from an instance *synchronously* * * @return APIResponse */ public APIResponse getPeertubeChannel(String instance, String name) { List accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(String.format("https://" + instance + "/api/v1/accounts/%s/video-channels", name), 10, null, null); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); accounts = parseAccountResponsePeertube(instance, jsonArray); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Retrieves Peertube videos from an instance *synchronously* * * @return APIResponse */ public APIResponse getPeertubeChannelVideos(String instance, String name) { List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(String.format("https://" + instance + "/api/v1/video-channels/%s/videos", name), 10, null, null); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(instance, jsonArray); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPeertubes(peertubes); return apiResponse; } /** * Retrieves Peertube videos from an instance *synchronously* * * @return APIResponse */ public APIResponse getPeertube(String instance, String max_id) { List peertubes = new ArrayList<>(); HashMap params = new HashMap<>(); if (max_id == null) max_id = "0"; params.put("start", max_id); params.put("filter", "local"); params.put("sort", "-publishedAt"); params.put("count", "20"); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get("https://" + instance + "/api/v1/videos", 10, params, null); if (response == null) { apiResponse.setPeertubes(peertubes); return apiResponse; } JSONObject jsonObject = new JSONObject(response); if (jsonObject.has("data")) { JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(instance, jsonArray); } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPeertubes(peertubes); return apiResponse; } /** * Retrieves Peertube videos from an instance *synchronously* * * @return APIResponse */ public APIResponse getSinglePeertube(String instance, String videoId) { Peertube peertube = null; try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(String.format("https://" + instance + "/api/v1/videos/%s", videoId), 10, null, null); JSONObject jsonObject = new JSONObject(response); peertube = parseSinglePeertube(instance, jsonObject); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } List peertubes = new ArrayList<>(); peertubes.add(peertube); apiResponse.setPeertubes(peertubes); return apiResponse; } /** * Retrieves peertube search *synchronously* * * @param query String search * @return APIResponse */ public APIResponse searchPeertube(String instance, String query) { HashMap params = new HashMap<>(); params.put("count", "50"); if (query == null) return null; try { params.put("search", URLEncoder.encode(query, "UTF-8")); } catch (UnsupportedEncodingException e) { params.put("search", query); } List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get("https://" + instance + "/api/v1/search/videos", 10, params, null); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(instance, jsonArray); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPeertubes(peertubes); return apiResponse; } /** * Retrieves Peertube videos from an instance *synchronously* * * @return APIResponse */ public APIResponse getSinglePeertubeComments(String instance, String videoId) { statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(String.format("https://" + instance + "/api/v1/videos/%s/comment-threads", videoId), 10, null, null); JSONObject jsonObject = new JSONObject(response); statuses = parseSinglePeertubeComments(context, instance, jsonObject); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves home timeline for the account *synchronously* * * @return APIResponse */ public APIResponse getHowTo() { List howToVideos = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get("https://peertube.fedilab.app/api/v1/video-channels/fedilab_channel/videos", 10, null, null); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); howToVideos = parseHowTos(jsonArray); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setHowToVideos(howToVideos); return apiResponse; } /** * Retrieves Nitter timeline from accounts *synchronously* * * @return APIResponse */ public APIResponse getNitter(String instance, String max_id) { final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String nitterHost = sharedpreferences.getString(Helper.SET_NITTER_HOST, Helper.DEFAULT_NITTER_HOST).toLowerCase(); String[] usernames = instance.split(" "); if (usernames.length == 0) { Error error = new Error(); error.setError(context.getString(R.string.toast_error)); error.setStatusCode(404); apiResponse.setError(error); return apiResponse; } StringBuilder urlparams = new StringBuilder(); { int i = 0; while (i < usernames.length) { String username = usernames[i].trim(); urlparams.append(username); if (i != usernames.length - 1) urlparams.append(","); i++; } } String url = "https://" + nitterHost + "/" + urlparams + "/rss"; if (max_id != null) { url += "?max_position=" + max_id; } try { statuses = new ArrayList<>(); HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(url, 30, null, null); apiResponse.setMax_id(httpsConnection.getMax_id()); statuses = parseNitter(response); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves Misskey timeline from an instance *synchronously* * * @return APIResponse */ public APIResponse getMisskey(String instance, String max_id) { JSONObject params = new JSONObject(); try { params.put("file", false); if (max_id != null) params.put("untilId", max_id); params.put("local", true); params.put("poll", false); params.put("renote", false); params.put("reply", false); } catch (JSONException e) { e.printStackTrace(); } try { statuses = new ArrayList<>(); HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.postMisskey("https://" + instance + "/api/notes", 10, params, null); statuses = parseNotes(context, instance, new JSONArray(response)); if (statuses.size() > 0) { apiResponse.setSince_id(statuses.get(0).getId()); apiResponse.setMax_id(statuses.get(statuses.size() - 1).getId()); } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves public timeline for the account *synchronously* * * @param local boolean only local timeline * @param max_id String id max * @return APIResponse */ public APIResponse getPublicTimeline(String instanceName, boolean local, String max_id) { return getPublicTimeline(local, instanceName, max_id, null, tootPerPage); } /** * Retrieves public timeline for the account *synchronously* * * @param local boolean only local timeline * @param max_id String id max * @return APIResponse */ public APIResponse getPublicTimeline(boolean local, String max_id) { return getPublicTimeline(local, null, max_id, null, tootPerPage); } /** * Retrieves public timeline for the account since an Id value *synchronously* * * @param local boolean only local timeline * @param since_id String id since * @return APIResponse */ public APIResponse getPublicTimelineSinceId(boolean local, String since_id) { return getPublicTimeline(local, null, null, since_id, tootPerPage); } /** * Retrieves instance timeline since an Id value *synchronously* * * @param instanceName String instance name * @param since_id String id since * @return APIResponse */ public APIResponse getInstanceTimelineSinceId(String instanceName, String since_id) { return getPublicTimeline(true, instanceName, null, since_id, tootPerPage); } /** * Retrieves public timeline for the account *synchronously* * * @param local boolean only local timeline * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ private APIResponse getPublicTimeline(boolean local, String instanceName, String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (local) params.put("local", Boolean.toString(true)); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 40) limit = 40; params.put("limit", String.valueOf(limit)); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String url; if (instanceName == null) url = getAbsoluteUrl("/timelines/public"); else url = getAbsoluteUrlRemoteInstance(instanceName); String response = httpsConnection.get(url, 10, params, prefKeyOauthTokenT); statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves news coming from Fedilab's account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getNews(String max_id) { HashMap params = null; if (max_id != null) { params = new HashMap<>(); params.put("max_id", max_id); } statuses = new ArrayList<>(); apiResponse = new APIResponse(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get("https://toot.fedilab.app/api/v1/timelines/tag/fedilab", 10, params, prefKeyOauthTokenT); List tmp_status = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, tmp_status); if (tmp_status.size() > 0) { for (Status status : tmp_status) { if (status.getAccount().getAcct().equals("apps")) { statuses.add(status); } } } } catch (IOException | NoSuchAlgorithmException | KeyManagementException | HttpsConnection.HttpsConnectionException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves discover timeline for the account *synchronously* * * @param local boolean only local timeline * @param max_id String id max * @return APIResponse */ public APIResponse getDiscoverTimeline(boolean local, String max_id) { return getDiscoverTimeline(local, max_id, null, tootPerPage); } /** * Retrieves discover timeline for the account *synchronously* * * @param local boolean only local timeline * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getDiscoverTimeline(boolean local, String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (local) params.put("local", Boolean.toString(true)); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 40) limit = 40; params.put("limit", String.valueOf(limit)); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String url; url = getAbsoluteUr2l("/discover/posts"); String response = httpsConnection.get(url, 10, params, prefKeyOauthTokenT); statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } public APIResponse getCustomArtTimeline(boolean local, String tag, String max_id, List any, List all, List none) { return getArtTimeline(local, tag, max_id, null, any, all, none); } public APIResponse getArtTimeline(boolean local, String max_id, List any, List all, List none) { return getArtTimeline(local, null, max_id, null, any, all, none); } public APIResponse getCustomArtTimelineSinceId(boolean local, String tag, String since_id, List any, List all, List none) { return getArtTimeline(local, tag, null, since_id, any, all, none); } public APIResponse getArtTimelineSinceId(boolean local, String since_id, List any, List all, List none) { return getArtTimeline(local, null, null, since_id, any, all, none); } /** * Retrieves art timeline * * @param local boolean only local timeline * @param max_id String id max * @return APIResponse */ private APIResponse getArtTimeline(boolean local, String tag, String max_id, String since_id, List any, List all, List none) { if (tag == null) tag = "mastoart"; APIResponse apiResponse = getPublicTimelineTag(tag, local, true, max_id, since_id, tootPerPage, any, all, none, null); APIResponse apiResponseReply = new APIResponse(); if (apiResponse != null) { apiResponseReply.setMax_id(apiResponse.getMax_id()); apiResponseReply.setSince_id(apiResponse.getSince_id()); apiResponseReply.setStatuses(new ArrayList<>()); if (apiResponse.getStatuses() != null && apiResponse.getStatuses().size() > 0) { for (Status status : apiResponse.getStatuses()) { if (status.getMedia_attachments() != null) { try { String statusSerialized = Helper.statusToStringStorage(status); for (Attachment attachment : status.getMedia_attachments()) { Status newStatus = Helper.restoreStatusFromString(statusSerialized); if (newStatus == null) break; newStatus.setArt_attachment(attachment); apiResponseReply.getStatuses().add(newStatus); } } catch (Exception ignored) { } } } } } return apiResponseReply; } /** * Retrieves public tag timeline *synchronously* * * @param tag String * @param local boolean only local timeline * @param max_id String id max * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getPublicTimelineTag(String tag, boolean local, String max_id, List any, List all, List none) { return getPublicTimelineTag(tag, local, false, max_id, null, tootPerPage, any, all, none, null); } /** * Retrieves public tag timeline *synchronously* * * @param tag String * @param local boolean only local timeline * @param max_id String id max * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getPublicTimelineTag(String tag, boolean local, String max_id, String instance) { return getPublicTimelineTag(tag, local, false, max_id, null, tootPerPage, null, null, null, instance); } /** * Retrieves public tag timeline *synchronously* * * @param tag String * @param local boolean only local timeline * @param since_id String since id * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getPublicTimelineTagSinceId(String tag, boolean local, String since_id, List any, List all, List none) { return getPublicTimelineTag(tag, local, false, null, since_id, tootPerPage, any, all, none, null); } /** * Retrieves public tag timeline *synchronously* * * @param tag String * @param local boolean only local timeline * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getPublicTimelineTag(String tag, boolean local, boolean onlymedia, String max_id, String since_id, int limit, List any, List all, List none, String instance) { HashMap params = new HashMap<>(); if (local) params.put("local", Boolean.toString(true)); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 40) limit = 40; if (onlymedia) params.put("only_media", Boolean.toString(true)); if (any != null && any.size() > 0) { StringBuilder parameters = new StringBuilder(); for (String a : any) { try { a = URLEncoder.encode(a, "UTF-8"); } catch (UnsupportedEncodingException ignored) { } parameters.append("any[]=").append(a).append("&"); } parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(6)); params.put("any[]", parameters.toString()); } if (all != null && all.size() > 0) { StringBuilder parameters = new StringBuilder(); for (String a : all) { try { a = URLEncoder.encode(a, "UTF-8"); } catch (UnsupportedEncodingException ignored) { } parameters.append("all[]=").append(a).append("&"); } parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(6)); params.put("all[]", parameters.toString()); } if (none != null && none.size() > 0) { StringBuilder parameters = new StringBuilder(); for (String a : none) { try { a = URLEncoder.encode(a, "UTF-8"); } catch (UnsupportedEncodingException ignored) { } parameters.append("none[]=").append(a).append("&"); } parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(7)); params.put("none[]", parameters.toString()); } params.put("limit", String.valueOf(limit)); statuses = new ArrayList<>(); if (tag == null) return null; try { String query = tag.trim(); HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) try { query = URLEncoder.encode(query, "UTF-8"); } catch (UnsupportedEncodingException ignored) { } String response; if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { if (instance == null) response = httpsConnection.get(getAbsoluteUrl(String.format("/timelines/tag/%s", query)), 10, params, prefKeyOauthTokenT); else response = httpsConnection.get(getAbsoluteUrlRemote(instance, String.format("/timelines/tag/%s", query)), 10, params, null); statuses = parseStatuses(context, new JSONArray(response)); } else { //Parse for pixelfed params = new HashMap<>(); params.put("hashtag", tag); response = httpsConnection.get(getAbsoluteUr2l("/discover/tag"), 10, params, null); JSONArray tags = new JSONObject(response).getJSONArray("tags"); statuses = new ArrayList<>(); for (int i = 0; i < tags.length(); i++) { Status status = parseStatuses(context, tags.getJSONObject(i).getJSONObject("status")); statuses.add(status); } } setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves muted users by the authenticated account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getMuted(String max_id) { return getAccounts("/mutes", max_id, null, accountPerPage); } /** * Retrieves blocked users by the authenticated account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getBlocks(String max_id) { return getAccounts("/blocks", max_id, null, accountPerPage); } /** * Retrieves following for the account specified by targetedId *synchronously* * * @param targetedId String targetedId * @param max_id String id max * @return APIResponse */ public APIResponse getFollowing(String targetedId, String max_id) { return getAccounts(String.format("/accounts/%s/following", targetedId), max_id, null, accountPerPage); } /** * Retrieves followers for the account specified by targetedId *synchronously* * * @param targetedId String targetedId * @param max_id String id max * @return APIResponse */ public APIResponse getFollowers(String targetedId, String max_id) { return getAccounts(String.format("/accounts/%s/followers", targetedId), max_id, null, accountPerPage); } /** * Retrieves blocked users by the authenticated account *synchronously* * * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getAccounts(String action, String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 40) limit = 40; params.put("limit", String.valueOf(limit)); accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(action), 10, params, prefKeyOauthTokenT); accounts = parseAccountResponse(new JSONArray(response)); setAccountsMaxId(httpsConnection, accounts); if (accounts.size() == 1) { if (accounts.get(0).getAcct() == null) { Throwable error = new Throwable(context.getString(R.string.toast_error)); setError(500, error); } } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Retrieves blocked domains for the authenticated account *synchronously* * * @param max_id String id max * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getBlockedDomain(String max_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); params.put("limit", "80"); domains = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/domain_blocks"), 10, params, prefKeyOauthTokenT); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); domains = parseDomains(new JSONArray(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setDomains(domains); return apiResponse; } /** * Delete a blocked domains for the authenticated account *synchronously* * * @param domain String domain name */ @SuppressWarnings("SameParameterValue") public int deleteBlockedDomain(String domain) { HashMap params = new HashMap<>(); params.put("domain", domain); domains = new ArrayList<>(); HttpsConnection httpsConnection; try { httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.delete(getAbsoluteUrl("/domain_blocks"), 10, params, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return actionCode; } /** * Retrieves follow requests for the authenticated account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getFollowRequest(String max_id) { return getFollowRequest(max_id, null, accountPerPage); } /** * Retrieves follow requests for the authenticated account *synchronously* * * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getFollowRequest(String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 40) limit = 40; params.put("limit", String.valueOf(limit)); accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/follow_requests"), 10, params, prefKeyOauthTokenT); accounts = parseAccountResponse(new JSONArray(response)); setAccountsMaxId(httpsConnection, accounts); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Retrieves favourited status for the authenticated account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getFavourites(String max_id) { return getFavourites(max_id, null, tootPerPage); } /** * Retrieves favourited status for the authenticated account *synchronously* * * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getFavourites(String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 40) limit = 40; params.put("limit", String.valueOf(limit)); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/favourites"), 10, params, prefKeyOauthTokenT); statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves announcements for the authenticated account *synchronously* * * @return APIResponse */ public APIResponse getAnnouncements() { List announcements = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/announcements"), 10, null, prefKeyOauthTokenT); announcements = parseAnnouncement(context, new JSONArray(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAnnouncements(announcements); return apiResponse; } /** * Retrieves bookmarked status for the authenticated account *synchronously* * * @param max_id String id max * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getBookmarks(String max_id) { HashMap params = new HashMap<>(); statuses = new ArrayList<>(); try { String response; HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { if (max_id != null) params.put("max_id", max_id); params.put("limit", "40"); response = httpsConnection.get(getAbsoluteUrl("/bookmarks"), 10, params, prefKeyOauthTokenT); } else { params.put("max_id", max_id); params.put("limit", String.valueOf(tootPerPage)); response = httpsConnection.get(Helper.instanceWithProtocol(this.context, this.instance) + "/api/local/bookmarks", 10, params, prefKeyOauthTokenT); } statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Makes the post action for a status * * @param statusAction Enum * @param targetedId String id of the targeted Id *can be this of a status or an account* * @return in status code - Should be equal to 200 when action is done */ public int postAction(StatusAction statusAction, String targetedId) { return postAction(statusAction, targetedId, null, null); } /** * Makes the post action for a status * * @param statusAction Enum * @param targetedId String id of the targeted Id *can be this of a status or an account* * @return in status code - Should be equal to 200 when action is done */ public int postAction(StatusAction statusAction, String targetedId, String comment) { return postAction(statusAction, targetedId, null, comment); } /** * Makes the post action for a status * * @param targetedId String id of the targeted Id *can be this of a status or an account* * @param muteNotifications - boolean - notifications should be also muted * @return in status code - Should be equal to 200 when action is done */ public int muteNotifications(String targetedId, boolean muteNotifications) { HashMap params = new HashMap<>(); params.put("notifications", Boolean.toString(muteNotifications)); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.post(getAbsoluteUrl(String.format("/accounts/%s/mute", targetedId)), 10, params, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return actionCode; } //Pleroma admin calls /** * Makes the post action * * @param status Status object related to the status * @param comment String comment for the report * @return in status code - Should be equal to 200 when action is done */ public int reportAction(Status status, String comment) { return postAction(API.StatusAction.REPORT, null, status, comment); } /** * Makes the post action * * @param targetedId targeted account * @param comment String comment for the report * @return in status code - Should be equal to 200 when action is done */ public int reportAction(String targetedId, String comment) { return postAction(API.StatusAction.REPORT, targetedId, null, comment); } public int statusAction(Status status) { return postAction(StatusAction.CREATESTATUS, null, status, null); } /** * Makes the post action * * @param statusAction Enum * @param targetedId String id of the targeted Id *can be this of a status or an account* * @param status Status object related to the status * @param comment String comment for the report * @return in status code - Should be equal to 200 when action is done */ private int postAction(StatusAction statusAction, String targetedId, Status status, String comment) { String action; HashMap params = null; switch (statusAction) { case FAVOURITE: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/statuses/%s/favourite", targetedId); } else { action = "/i/like"; params = new HashMap<>(); params.put("item", targetedId); } break; case UNFAVOURITE: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/statuses/%s/unfavourite", targetedId); } else { action = "/i/like"; params = new HashMap<>(); params.put("item", targetedId); } break; case BOOKMARK: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/statuses/%s/bookmark", targetedId); } else { action = "/i/bookmark"; params = new HashMap<>(); params.put("item", targetedId); } break; case UNBOOKMARK: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/statuses/%s/unbookmark", targetedId); } else { action = "/i/bookmark"; params = new HashMap<>(); params.put("item", targetedId); } break; case REBLOG: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/statuses/%s/reblog", targetedId); } else { action = "/i/share"; params = new HashMap<>(); params.put("item", targetedId); } break; case UNREBLOG: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/statuses/%s/unreblog", targetedId); } else { action = "/i/share"; params = new HashMap<>(); params.put("item", targetedId); } break; case FOLLOW: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/accounts/%s/follow", targetedId); } else { action = "/i/follow"; params = new HashMap<>(); params.put("item", targetedId); } break; case NOTIFY_FOR_ACCOUNT: params = new HashMap<>(); params.put("notify", "true"); action = String.format("/accounts/%s/follow", targetedId); break; case UNNOTIFY_FOR_ACCOUNT: params = new HashMap<>(); params.put("notify", "false"); action = String.format("/accounts/%s/follow", targetedId); break; case REMOTE_FOLLOW: action = "/follows"; params = new HashMap<>(); params.put("uri", targetedId); break; case UNFOLLOW: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/accounts/%s/unfollow", targetedId); } else { action = "/i/follow"; params = new HashMap<>(); params.put("item", targetedId); } break; case BLOCK: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/accounts/%s/block", targetedId); } else { action = "/i/block"; params = new HashMap<>(); params.put("item", targetedId); } break; case BLOCK_DOMAIN: action = "/domain_blocks"; params = new HashMap<>(); params.put("domain", targetedId); break; case UNBLOCK: action = String.format("/accounts/%s/unblock", targetedId); break; case MUTE: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/accounts/%s/mute", targetedId); } else { action = "/i/mute"; params = new HashMap<>(); params.put("item", targetedId); params.put("type", "user"); } break; case UNMUTE: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/accounts/%s/unmute", targetedId); } else { action = "/i/unmute"; params = new HashMap<>(); params.put("item", targetedId); params.put("type", "user"); } break; case MUTE_CONVERSATION: action = String.format("/statuses/%s/mute", targetedId); break; case UNMUTE_CONVERSATION: action = String.format("/statuses/%s/unmute", targetedId); break; case PIN: action = String.format("/statuses/%s/pin", targetedId); break; case UNPIN: action = String.format("/statuses/%s/unpin", targetedId); break; case REACT: action = String.format("/pleroma/statuses/%s/react_with_emoji", targetedId); break; case UNREACT: action = String.format("/pleroma/statuses/%s/unreact_with_emoji", targetedId); break; case ENDORSE: action = String.format("/accounts/%s/pin", targetedId); break; case UNENDORSE: action = String.format("/accounts/%s/unpin", targetedId); break; case SHOW_BOOST: params = new HashMap<>(); params.put("reblogs", "true"); action = String.format("/accounts/%s/follow", targetedId); break; case HIDE_BOOST: params = new HashMap<>(); params.put("reblogs", "false"); action = String.format("/accounts/%s/follow", targetedId); break; case UNSTATUS: if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { action = String.format("/statuses/%s", targetedId); } else { action = "/i/delete"; params = new HashMap<>(); params.put("item", targetedId); params.put("type", "status"); } break; case REMOVE_REACTION: case ADD_REACTION: action = String.format("/announcements/%s/reactions/%s", targetedId, comment); break; case REMOVE_PLEROMA_REACTION: case ADD_PLEROMA_REACTION: action = String.format("/pleroma/statuses/%s/reactions/%s", targetedId, comment); break; case DISMISS_ANNOUNCEMENT: action = String.format("/announcements/%s/dismiss", targetedId); break; case AUTHORIZE: action = String.format("/follow_requests/%s/authorize", targetedId); break; case REJECT: action = String.format("/follow_requests/%s/reject", targetedId); break; case REPORT: action = "/reports"; params = new HashMap<>(); if (status != null) params.put("account_id", status.getAccount().getId()); else params.put("account_id", targetedId); params.put("comment", comment); if (status != null) { params.put("status_ids[]", status.getId()); } break; case CREATESTATUS: params = new HashMap<>(); action = "/statuses"; try { params.put("status", URLEncoder.encode(status.getContent(), "UTF-8")); } catch (UnsupportedEncodingException e) { params.put("status", status.getContent()); } if (status.getScheduled_at() != null) params.put("scheduled_at", status.getScheduled_at()); if (status.getIn_reply_to_id() != null) params.put("in_reply_to_id", status.getIn_reply_to_id()); if (status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0) { StringBuilder parameters = new StringBuilder(); for (Attachment attachment : status.getMedia_attachments()) parameters.append("media_ids[]=").append(attachment.getId()).append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(12)); params.put("media_ids[]", parameters.toString()); } if (status.isSensitive()) params.put("sensitive", Boolean.toString(status.isSensitive())); if (status.getSpoiler_text() != null) try { params.put("spoiler_text", URLEncoder.encode(status.getSpoiler_text(), "UTF-8")); } catch (UnsupportedEncodingException e) { params.put("spoiler_text", status.getSpoiler_text()); } params.put("visibility", status.getVisibility()); break; default: return -1; } if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED || (statusAction != StatusAction.UNSTATUS && statusAction != StatusAction.ADD_REACTION && statusAction != StatusAction.REMOVE_REACTION && statusAction != StatusAction.ADD_PLEROMA_REACTION && statusAction != StatusAction.REMOVE_PLEROMA_REACTION)) { try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String url; if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { url = getAbsoluteUrl(action); } else { url = "https://" + Helper.getLiveInstance(context) + action; } String resp = httpsConnection.post(url, 10, params, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); Bundle b = new Bundle(); try { Status status1 = parseStatuses(context, new JSONObject(resp)); b.putParcelable("status", status1); } catch (JSONException ignored) { } Intent intentBC = new Intent(Helper.RECEIVE_ACTION); intentBC.putExtras(b); LocalBroadcastManager.getInstance(context).sendBroadcast(intentBC); SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT); Status indb = new TimelineCacheDAO(context, db).getSingle(targetedId); if (indb != null && MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { String response = httpsConnection.get(getAbsoluteUrl(String.format("/statuses/%s", targetedId)), 10, null, prefKeyOauthTokenT); new TimelineCacheDAO(context, db).update(targetedId, response, account.getId(), account.getInstance()); } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } } else if (statusAction == StatusAction.ADD_REACTION || statusAction == StatusAction.ADD_PLEROMA_REACTION) { try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.put(getAbsoluteUrl(action), 10, null, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } } else { try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.delete(getAbsoluteUrl(action), 10, null, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); //Delete a status (Mastodon or Pleroma) if (statusAction != StatusAction.REMOVE_REACTION && statusAction != StatusAction.REMOVE_PLEROMA_REACTION) { SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); new TimelineCacheDAO(context, db).remove(targetedId); } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } } return actionCode; } public int reportStatus(List statuses, String comment, boolean forward) { String action; HashMap params; action = "/reports"; params = new HashMap<>(); params.put("account_id", statuses.get(0).getAccount().getId()); params.put("comment", comment); StringBuilder parameters = new StringBuilder(); for (Status val : statuses) parameters.append("status_ids[]=").append(val).append("&"); if (parameters.length() > 0) { parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(13)); params.put("status_ids[]", parameters.toString()); } params.put("forward", String.valueOf(forward)); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.post(getAbsoluteUrl(action), 10, params, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return actionCode; } /** * scheduled action for a status * * @param status Status object related to the status * @return APIResponse */ public APIResponse scheduledAction(String call, Status status, String max_id, String targetedId) { HashMap params = new HashMap<>(); if (call.equals("PUT")) { if (status.getScheduled_at() != null) params.put("scheduled_at", status.getScheduled_at()); } else if (call.equals("GET")) { if (max_id != null) params.put("max_id", max_id); } List storedStatus = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = null; switch (call) { case "GET": response = httpsConnection.get(getAbsoluteUrl("/scheduled_statuses/"), 10, null, prefKeyOauthTokenT); break; case "PUT": response = httpsConnection.put(getAbsoluteUrl(String.format("/scheduled_statuses/%s", targetedId)), 10, params, prefKeyOauthTokenT); break; case "DELETE": httpsConnection.delete(getAbsoluteUrl(String.format("/scheduled_statuses/%s", targetedId)), 10, null, prefKeyOauthTokenT); break; } if (call.equals("GET")) { apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); } if (response != null && call.equals("PUT")) { Schedule schedule = parseSimpleSchedule(context, new JSONObject(response)); StoredStatus st = new StoredStatus(); st.setCreation_date(status.getCreated_at()); st.setId(-1); st.setJobId(-1); st.setScheduled_date(schedule.getScheduled_at()); st.setStatusReply(null); st.setSent_date(null); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); st.setUserId(userId); st.setStatus(schedule.getStatus()); storedStatus.add(st); } else if (response != null) { List scheduleList = parseSchedule(context, new JSONArray(response)); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); for (Schedule schedule : scheduleList) { StoredStatus st = new StoredStatus(); st.setCreation_date(null); st.setScheduledServerdId(schedule.getId()); st.setJobId(-1); st.setScheduled_date(schedule.getScheduled_at()); st.setStatusReply(null); st.setSent_date(null); st.setUserId(userId); st.setStatus(schedule.getStatus()); storedStatus.add(st); } } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStoredStatuses(storedStatus); return apiResponse; } /** * Public api call to submit a vote * * @param pollId String * @param choices int[] * @return Poll */ public Poll submiteVote(String pollId, int[] choices) { JsonObject jsonObject = new JsonObject(); JsonArray jchoices = new JsonArray(); for (int choice : choices) { jchoices.add(choice); } jsonObject.add("choices", jchoices); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.postJson(getAbsoluteUrl(String.format("/polls/%s/votes", pollId)), 10, jsonObject, prefKeyOauthTokenT); return parsePoll(new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return null; } /** * Public api call to refresh a poll * * @param status Status * @return Poll */ public Poll getPoll(Status status) { try { Poll _p = (status.getReblog() != null) ? status.getReblog().getPoll() : status.getPoll(); HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/polls/%s", _p.getId())), 10, null, prefKeyOauthTokenT); Poll poll = parsePoll(new JSONObject(response)); Bundle b = new Bundle(); status.setPoll(poll); b.putParcelable("status", status); Intent intentBC = new Intent(Helper.RECEIVE_ACTION); intentBC.putExtras(b); SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); Status alreadyCached = new TimelineCacheDAO(context, db).getSingle(status.getId()); Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT); if (alreadyCached != null) { poll = parsePoll(new JSONObject(response)); status.setPoll(poll); new TimelineCacheDAO(context, db).update(status.getId(), Helper.statusToStringStorage(status), account.getId(), account.getInstance()); } LocalBroadcastManager.getInstance(context).sendBroadcast(intentBC); return poll; } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return null; } /** * Posts a status * * @param status Status object related to the status * @return APIResponse */ public APIResponse postStatusAction(Status status) { JsonObject jsonObject = new JsonObject(); String url; url = getAbsoluteUrl("/statuses"); if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { jsonObject.addProperty("status", status.getContent()); if (status.getContentType() != null) jsonObject.addProperty("content_type", status.getContentType()); if (status.getIn_reply_to_id() != null) jsonObject.addProperty("in_reply_to_id", status.getIn_reply_to_id()); if (status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0) { JsonArray mediaArray = new JsonArray(); for (Attachment attachment : status.getMedia_attachments()) mediaArray.add(attachment.getId()); jsonObject.add("media_ids", mediaArray); } if (status.getScheduled_at() != null) jsonObject.addProperty("scheduled_at", status.getScheduled_at()); if (status.isSensitive()) jsonObject.addProperty("sensitive", status.isSensitive()); if (status.getSpoiler_text() != null) jsonObject.addProperty("spoiler_text", status.getSpoiler_text()); if (status.getPoll() != null) { JsonObject poll = new JsonObject(); JsonArray options = new JsonArray(); for (PollOptions option : status.getPoll().getOptionsList()) { if (!option.getTitle().isEmpty()) options.add(option.getTitle()); } poll.add("options", options); poll.addProperty("expires_in", status.getPoll().getExpires_in()); poll.addProperty("multiple", status.getPoll().isMultiple()); jsonObject.add("poll", poll); } jsonObject.addProperty("visibility", status.getVisibility()); } else { if (status.getIn_reply_to_id() != null) { url = "https://" + Helper.getLiveInstance(context) + "/i/comment"; jsonObject.addProperty("comment", status.getContent()); jsonObject.addProperty("item", status.getIn_reply_to_id()); jsonObject.addProperty("sensitive", status.isSensitive()); } else { url = "https://" + Helper.getLiveInstance(context) + "/api/compose/v0/publish"; jsonObject.addProperty("caption", status.getContent()); jsonObject.addProperty("comments_disabled", false); jsonObject.addProperty("cw", status.isSensitive()); jsonObject.addProperty("visibility", status.getVisibility()); String attachments = new GsonBuilder().serializeNulls().create().toJson(status.getMedia_attachments()); jsonObject.addProperty("place", false); JsonParser parser = new JsonParser(); JsonArray jsonArrayTags = parser.parse("[]").getAsJsonArray(); jsonObject.add("tagged", jsonArrayTags); JsonArray jsonArrayMedia = parser.parse(attachments).getAsJsonArray(); jsonObject.add("media", jsonArrayMedia); } } statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.postJson(url, 10, jsonObject, prefKeyOauthTokenT); if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { Status statusreturned = parseStatuses(context, new JSONObject(response)); statuses.add(statusreturned); } else { final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(context)); Account account = new AccountDAO(context, db).getUniqAccount(userId, instance); status.setAccount(account); statuses.add(status); } setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); setDefaultError(e); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Posts a status * * @param notificationId String, the current notification id, if null all notifications are deleted * @return APIResponse */ public APIResponse postNoticationAction(String notificationId) { String action; HashMap params = new HashMap<>(); if (notificationId == null) action = "/notifications/clear"; else { action = "/notifications/" + notificationId + "/dismiss"; } try { new HttpsConnection(context, this.instance).post(getAbsoluteUrl(action), 10, params, prefKeyOauthTokenT); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return apiResponse; } /** * Retrieves notifications for the authenticated account since an id*synchronously* * * @param since_id String since max * @return APIResponse */ public APIResponse getNotificationsSince(DisplayNotificationsFragment.Type type, String since_id, boolean display) { return getNotifications(type, null, since_id, notificationPerPage, display); } /** * Retrieves notifications for the authenticated account since an id*synchronously* * * @param since_id String since max * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getNotificationsSince(DisplayNotificationsFragment.Type type, String since_id, int notificationPerPage, boolean display) { return getNotifications(type, null, since_id, notificationPerPage, display); } /** * Retrieves notifications for the authenticated account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getNotifications(DisplayNotificationsFragment.Type type, String max_id, boolean display) { return getNotifications(type, max_id, null, notificationPerPage, display); } /** * Retrieves notifications for the authenticated account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getNotifications(String max_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); params.put("limit", "30"); if (context == null) { apiResponse = new APIResponse(); Error error = new Error(); apiResponse.setError(error); return apiResponse; } List notifications = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/notifications"), 15, params, prefKeyOauthTokenT); notifications = parseNotificationResponse(new JSONArray(response)); setNotificationsMaxId(httpsConnection, notifications); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setNotifications(notifications); return apiResponse; } /** * Retrieves notifications for the authenticated account *synchronously* * * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ private APIResponse getNotifications(DisplayNotificationsFragment.Type type, String max_id, String since_id, int limit, boolean display) { HashMap params = new HashMap<>(); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { params.put("pg", "true"); params.put("page", max_id); } else { if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 30) limit = 30; params.put("limit", String.valueOf(limit)); } if (context == null) { apiResponse = new APIResponse(); Error error = new Error(); apiResponse.setError(error); return apiResponse; } final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean notif_follow, notif_add, notif_mention, notif_share, notif_poll, notif_status; StringBuilder parameters = new StringBuilder(); //TODO: If pixelfed supports exclude_types this condition needs to be changed if (type == DisplayNotificationsFragment.Type.ALL && MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { if (display) { notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW_FILTER, true); notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD_FILTER, true); notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION_FILTER, true); notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE_FILTER, true); notif_poll = sharedpreferences.getBoolean(Helper.SET_NOTIF_POLL_FILTER, true); notif_status = sharedpreferences.getBoolean(Helper.SET_NOTIF_STATUS_FILTER, true); } else { notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true); notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true); notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true); notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true); notif_poll = sharedpreferences.getBoolean(Helper.SET_NOTIF_POLL, true); notif_status = sharedpreferences.getBoolean(Helper.SET_NOTIF_STATUS, true); } if (!notif_follow) { parameters.append("exclude_types[]=").append("follow").append("&"); parameters.append("exclude_types[]=").append("follow_request").append("&"); } if (!notif_add) parameters.append("exclude_types[]=").append("favourite").append("&"); if (!notif_share) parameters.append("exclude_types[]=").append("reblog").append("&"); if (!notif_status) parameters.append("exclude_types[]=").append("status").append("&"); if (!notif_mention) parameters.append("exclude_types[]=").append("mention").append("&"); if (!notif_poll) parameters.append("exclude_types[]=").append("poll").append("&"); if (parameters.length() > 0) { parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(16)); params.put("exclude_types[]", parameters.toString()); } } else if (type == DisplayNotificationsFragment.Type.MENTION) { parameters.append("exclude_types[]=").append("follow").append("&"); parameters.append("exclude_types[]=").append("follow_request").append("&"); parameters.append("exclude_types[]=").append("favourite").append("&"); parameters.append("exclude_types[]=").append("reblog").append("&"); parameters.append("exclude_types[]=").append("status").append("&"); parameters.append("exclude_types[]=").append("poll").append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(16)); params.put("exclude_types[]", parameters.toString()); } else if (type == DisplayNotificationsFragment.Type.FAVORITE) { parameters.append("exclude_types[]=").append("follow").append("&"); parameters.append("exclude_types[]=").append("follow_request").append("&"); parameters.append("exclude_types[]=").append("mention").append("&"); parameters.append("exclude_types[]=").append("status").append("&"); parameters.append("exclude_types[]=").append("reblog").append("&"); parameters.append("exclude_types[]=").append("poll").append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(16)); params.put("exclude_types[]", parameters.toString()); } else if (type == DisplayNotificationsFragment.Type.BOOST) { parameters.append("exclude_types[]=").append("follow").append("&"); parameters.append("exclude_types[]=").append("follow_request").append("&"); parameters.append("exclude_types[]=").append("status").append("&"); parameters.append("exclude_types[]=").append("mention").append("&"); parameters.append("exclude_types[]=").append("favourite").append("&"); parameters.append("exclude_types[]=").append("poll").append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(16)); params.put("exclude_types[]", parameters.toString()); } else if (type == DisplayNotificationsFragment.Type.POLL) { parameters.append("exclude_types[]=").append("reblog").append("&"); parameters.append("exclude_types[]=").append("follow").append("&"); parameters.append("exclude_types[]=").append("status").append("&"); parameters.append("exclude_types[]=").append("follow_request").append("&"); parameters.append("exclude_types[]=").append("mention").append("&"); parameters.append("exclude_types[]=").append("favourite").append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(16)); params.put("exclude_types[]", parameters.toString()); } else if (type == DisplayNotificationsFragment.Type.FOLLOW) { parameters.append("exclude_types[]=").append("status").append("&"); parameters.append("exclude_types[]=").append("reblog").append("&"); parameters.append("exclude_types[]=").append("mention").append("&"); parameters.append("exclude_types[]=").append("favourite").append("&"); parameters.append("exclude_types[]=").append("poll").append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(16)); params.put("exclude_types[]", parameters.toString()); } else if (type == DisplayNotificationsFragment.Type.STATUS) { parameters.append("exclude_types[]=").append("follow").append("&"); parameters.append("exclude_types[]=").append("reblog").append("&"); parameters.append("exclude_types[]=").append("mention").append("&"); parameters.append("exclude_types[]=").append("favourite").append("&"); parameters.append("exclude_types[]=").append("poll").append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(16)); params.put("exclude_types[]", parameters.toString()); } List notifications = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/notifications"), 10, params, prefKeyOauthTokenT); notifications = parseNotificationResponse(new JSONArray(response)); setNotificationsMaxId(httpsConnection, notifications); } catch (HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } if (apiResponse != null) { apiResponse.setNotifications(notifications); } return apiResponse; } /** * Changes media description * * @param mediaId String * @param description String * @return Attachment */ public Attachment updateDescription(String mediaId, String description) { HashMap params = new HashMap<>(); try { params.put("description", URLEncoder.encode(description, "UTF-8")); } catch (UnsupportedEncodingException e) { params.put("description", description); } try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.put(getAbsoluteUrl(String.format("/media/%s", mediaId)), 240, params, prefKeyOauthTokenT); attachment = parseAttachmentResponse(new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return attachment; } /** * Retrieves Accounts and feeds when searching *synchronously* * * @param query String search * @return Results */ public APIResponse search(String query) { HashMap params = new HashMap<>(); apiResponse = new APIResponse(); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) params.put("q", query); else try { params.put("q", URLEncoder.encode(query, "UTF-8")); } catch (UnsupportedEncodingException e) { params.put("q", query); } params.put("resolve", "true"); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUr2l("/search"), 10, params, prefKeyOauthTokenT); results = parseResultsResponse(new JSONObject(response)); apiResponse.setResults(results); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return apiResponse; } /** * Retrieves trends for Mastodon *synchronously* * * @return APIResponse */ public APIResponse getTrends() { List trends; apiResponse = new APIResponse(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/trends"), 10, null, null); trends = parseTrends(new JSONArray(response)); apiResponse.setTrends(trends); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return apiResponse; } /** * Retrieves Accounts and feeds when searching *synchronously* * * @param query String search * @return Results */ public APIResponse search2(String query, searchType type, String offset) { apiResponse = new APIResponse(); HashMap params = new HashMap<>(); if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) params.put("q", query); else try { params.put("q", URLEncoder.encode(query, "UTF-8")); } catch (UnsupportedEncodingException e) { params.put("q", query); } if (offset != null) params.put("offset", offset); if (type != null) { switch (type) { case TAGS: params.put("type", "hashtags"); break; case ACCOUNTS: params.put("type", "accounts"); break; case STATUSES: params.put("type", "statuses"); break; } } params.put("limit", "20"); params.put("resolve", "true"); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response; if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { response = httpsConnection.get(getAbsoluteUr2l("/search"), 10, params, prefKeyOauthTokenT); } else { String searchPixelfed; try { searchPixelfed = "q=" + URLEncoder.encode(query, "UTF-8"); } catch (UnsupportedEncodingException e) { searchPixelfed = "q=" + query; } response = httpsConnection.get(Helper.getLiveInstanceWithProtocol(context) + "/api/search?" + searchPixelfed + "&src=metro&v=2&scope=all", 10, null, prefKeyOauthTokenT); } results = parseResultsResponse(new JSONObject(response)); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); apiResponse.setResults(results); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return apiResponse; } /** * Retrieves Accounts when searching (ie: via @...) *synchronously* * Not limited to following * * @param query String search * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse searchAccounts(String query, int count) { return searchAccounts(query, count, false); } /** * Retrieves Accounts when searching (ie: via @...) *synchronously* * * @param query String search * @param count int limit * @param following boolean following only * @return APIResponse */ public APIResponse searchAccounts(String query, int count, boolean following) { HashMap params = new HashMap<>(); params.put("q", query); if (count < 5) count = 5; if (count > 40) count = 40; if (following) params.put("following", Boolean.toString(true)); params.put("limit", String.valueOf(count)); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/accounts/search"), 10, params, prefKeyOauthTokenT); accounts = parseAccountResponse(new JSONArray(response)); setAccountsMaxId(httpsConnection, accounts); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Retrieves Accounts when searching (ie: via @...) *synchronously* * * @return APIResponse */ public APIResponse getCustomEmoji() { List emojis = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/custom_emojis"), 30, null, prefKeyOauthTokenT); emojis = parseEmojis(new JSONArray(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } //Add custom emoji for Pleroma /*if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PLEROMA) { APIResponse apiResponsePleroma = getCustomPleromaEmoji(); if (apiResponsePleroma != null && apiResponsePleroma.getEmojis() != null && apiResponsePleroma.getEmojis().size() > 0) emojis.addAll(apiResponsePleroma.getEmojis()); }*/ apiResponse.setEmojis(emojis); return apiResponse; } /** * Check if it's a Pleroma admin account and change in settings *synchronously* */ private void isPleromaAdmin(String nickname) { SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean isAdmin; try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.get(String.format(Helper.getLiveInstanceWithProtocol(context) + "/api/pleroma/admin/permission_group/%s/admin", nickname), 10, null, prefKeyOauthTokenT); //Call didn't return a 404, so the account is admin isAdmin = true; } catch (Exception e) { isAdmin = false; } SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putBoolean(Helper.PREF_IS_ADMINISTRATOR, isAdmin); editor.apply(); } /** * Get filters for the user * * @return APIResponse */ public APIResponse getFilters() { List filters = null; try { String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/filters"), 10, null, prefKeyOauthTokenT); if (response == null) { apiResponse.setFilters(new ArrayList<>()); return apiResponse; } filters = parseFilters(new JSONArray(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setFilters(filters); return apiResponse; } /** * Get a Filter by its id * * @return APIResponse */ public APIResponse getFilters(String filterId) { List filters = new ArrayList<>(); Filters filter; try { String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl(String.format("/filters/%s", filterId)), 10, null, prefKeyOauthTokenT); filter = parseFilter(new JSONObject(response)); filters.add(filter); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setFilters(filters); return apiResponse; } /** * Create a filter * * @param filter Filter * @return APIResponse */ public APIResponse addFilters(Filters filter) { HashMap params = new HashMap<>(); params.put("phrase", filter.getPhrase()); StringBuilder parameters = new StringBuilder(); for (String context : filter.getContext()) parameters.append("context[]=").append(context).append("&"); if (parameters.length() > 0) { parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(10)); params.put("context[]", parameters.toString()); } params.put("irreversible", String.valueOf(filter.isIrreversible())); params.put("whole_word", String.valueOf(filter.isWhole_word())); params.put("expires_in", String.valueOf(filter.getExpires_in())); ArrayList filters = new ArrayList<>(); try { String response = new HttpsConnection(context, this.instance).post(getAbsoluteUrl("/filters"), 10, params, prefKeyOauthTokenT); Filters resfilter = parseFilter(new JSONObject(response)); filters.add(resfilter); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setFilters(filters); return apiResponse; } /** * Delete a filter * * @param filter Filter * @return APIResponse */ public int deleteFilters(Filters filter) { try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.delete(getAbsoluteUrl(String.format("/filters/%s", filter.getId())), 10, null, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return actionCode; } /** * Delete a filter * * @param filter Filter * @return APIResponse */ public APIResponse updateFilters(Filters filter) { HashMap params = new HashMap<>(); params.put("phrase", filter.getPhrase()); StringBuilder parameters = new StringBuilder(); for (String context : filter.getContext()) parameters.append("context[]=").append(context).append("&"); if (parameters.length() > 0) { parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(10)); params.put("context[]", parameters.toString()); } params.put("irreversible", String.valueOf(filter.isIrreversible())); params.put("whole_word", String.valueOf(filter.isWhole_word())); params.put("expires_in", String.valueOf(filter.getExpires_in())); ArrayList filters = new ArrayList<>(); try { String response = new HttpsConnection(context, this.instance).put(getAbsoluteUrl(String.format("/filters/%s", filter.getId())), 10, params, prefKeyOauthTokenT); Filters resfilter = parseFilter(new JSONObject(response)); filters.add(resfilter); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setFilters(filters); return apiResponse; } /** * Get lists for the user * * @return APIResponse */ public APIResponse getLists() { apiResponse = new APIResponse(); List lists = new ArrayList<>(); try { String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/lists"), 5, null, prefKeyOauthTokenT); lists = parseLists(new JSONArray(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setLists(lists); return apiResponse; } /** * Retrieves list timeline *synchronously* * * @param list_id String id of the list * @param max_id String id max * @param since_id String since the id * @param limit int limit - max value 40 * @return APIResponse */ public APIResponse getListTimeline(String list_id, String max_id, String since_id, int limit) { HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); if (since_id != null) params.put("since_id", since_id); if (0 > limit || limit > 80) limit = 80; params.put("limit", String.valueOf(limit)); statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/timelines/list/%s", list_id)), 10, params, prefKeyOauthTokenT); statuses = parseStatuses(context, new JSONArray(response)); setStatusesMaxId(httpsConnection, statuses); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Get accounts in a list for a user * * @param listId String, id of the list * @param limit int, limit of results * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getAccountsInList(String listId, int limit) { HashMap params = new HashMap<>(); if (limit < 0) limit = 0; if (limit > 50) limit = 50; params.put("limit", String.valueOf(limit)); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/lists/%s/accounts", listId)), 10, params, prefKeyOauthTokenT); accounts = parseAccountResponse(new JSONArray(response)); setAccountsMaxId(httpsConnection, accounts); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Add an account in a list * * @param id String, id of the list * @param account_ids String, account to add * @return APIResponse */ public APIResponse addAccountToList(String id, String[] account_ids) { HashMap params = new HashMap<>(); StringBuilder parameters = new StringBuilder(); for (String val : account_ids) parameters.append("account_ids[]=").append(val).append("&"); if (parameters.length() > 0) { parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(14)); params.put("account_ids[]", parameters.toString()); } try { new HttpsConnection(context, this.instance).post(getAbsoluteUrl(String.format("/lists/%s/accounts", id)), 10, params, prefKeyOauthTokenT); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return apiResponse; } /** * Delete an account from a list * * @param id String, the id of the list * @return APIResponse */ public int deleteAccountFromList(String id, String[] account_ids) { try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); StringBuilder parameters = new StringBuilder(); HashMap params = new HashMap<>(); for (String val : account_ids) parameters.append("account_ids[]=").append(val).append("&"); if (parameters.length() > 0) { parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(14)); params.put("account_ids[]", parameters.toString()); } httpsConnection.delete(getAbsoluteUrl(String.format("/lists/%s/accounts", id)), 10, params, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | KeyManagementException | IOException e) { e.printStackTrace(); } return actionCode; } /** * Posts a list * * @param title String, the title of the list * @return APIResponse */ public APIResponse createList(String title) { HashMap params = new HashMap<>(); params.put("title", title); List lists = new ArrayList<>(); app.fedilab.android.client.Entities.List list; try { String response = new HttpsConnection(context, this.instance).post(getAbsoluteUrl("/lists"), 10, params, prefKeyOauthTokenT); list = parseList(new JSONObject(response)); lists.add(list); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setLists(lists); return apiResponse; } /** * Get subscribed push notifications * * @return APIResponse */ public APIResponse getPushSubscription() { PushSubscription pushSubscription = null; try { String response = new HttpsConnection(context, this.instance).get(getAbsoluteUrl("/push/subscription"), 10, null, prefKeyOauthTokenT); pushSubscription = parsePushNotifications(new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPushSubscription(pushSubscription); return apiResponse; } /** * Update subscribed push notifications * * @return APIResponse */ public APIResponse updatePushSubscription(String endpoint) { PushSubscription pushSubscription = new PushSubscription(); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true); boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true); boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true); boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true); boolean notif_status = sharedpreferences.getBoolean(Helper.SET_NOTIF_STATUS, true); boolean notif_poll = sharedpreferences.getBoolean(Helper.SET_NOTIF_POLL, true); HashMap params = new HashMap<>(); try { endpoint = URLEncoder.encode(endpoint, "UTF-8"); } catch (UnsupportedEncodingException ignored) { } params.put("subscription[endpoint]", endpoint); params.put("data[alerts][follow]", String.valueOf(notif_follow)); params.put("data[alerts][mention]", String.valueOf(notif_mention)); params.put("data[alerts][favourite]", String.valueOf(notif_add)); params.put("data[alerts][reblog]", String.valueOf(notif_share)); params.put("data[alerts][poll]", String.valueOf(notif_poll)); try { String response = new HttpsConnection(context, this.instance).put(getAbsoluteUrl("/push/subscription"), 10, params, prefKeyOauthTokenT); pushSubscription = parsePushNotifications(new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPushSubscription(pushSubscription); return apiResponse; } /** * Subscribe to push notifications * * @return APIResponse */ public APIResponse pushSubscription(String endpoint, Account account) { PushSubscription pushSubscription = new PushSubscription(); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true); boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true); boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true); boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true); boolean notif_status = sharedpreferences.getBoolean(Helper.SET_NOTIF_STATUS, true); boolean notif_poll = sharedpreferences.getBoolean(Helper.SET_NOTIF_POLL, true); SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(context); String strPub = prefs.getString(kp_public, ""); String strPriv = prefs.getString(kp_private, ""); if (strPub.trim().isEmpty() || strPriv.trim().isEmpty()) { newPair(context); } ECDH ecdh = ECDH.getInstance(); String pubKey = ecdh.getPublicKey(context); byte[] randBytes = new byte[16]; new Random().nextBytes(randBytes); String auth = ECDH.base64Encode(randBytes); JSONObject jsonObject = new JSONObject(); try { JSONObject jsonObjectSub = new JSONObject(); jsonObjectSub.put("endpoint", endpoint); JSONObject jsonObjectkey = new JSONObject(); jsonObjectkey.put("p256dh", pubKey); jsonObjectkey.put("auth", auth); jsonObjectSub.put("keys", jsonObjectkey); jsonObject.put("subscription", jsonObjectSub); JSONObject jsonObjectdata = new JSONObject(); JSONObject jsonObjectarlerts = new JSONObject(); jsonObjectarlerts.put("follow", notif_follow); jsonObjectarlerts.put("mention", notif_mention); jsonObjectarlerts.put("favourite", notif_add); jsonObjectarlerts.put("reblog", notif_share); jsonObjectarlerts.put("poll", notif_poll); jsonObjectdata.put("alerts", jsonObjectarlerts); jsonObject.put("data", jsonObjectdata); } catch (JSONException e) { e.printStackTrace(); } try { String response = new HttpsConnection(context, this.instance).postJson(getAbsoluteUrl("/push/subscription"), 10, jsonObject, prefKeyOauthTokenT); pushSubscription = parsePushNotifications(new JSONObject(response)); ecdh.saveServerKey(context, account, pushSubscription.getServer_key()); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPushSubscription(pushSubscription); return apiResponse; } /** * Update a list by its id * * @param id String, the id of the list * @param title String, the title of the list * @return APIResponse */ public APIResponse updateList(String id, String title) { HashMap params = new HashMap<>(); params.put("title", title); List lists = new ArrayList<>(); app.fedilab.android.client.Entities.List list; try { String response = new HttpsConnection(context, this.instance).put(getAbsoluteUrl(String.format("/lists/%s", id)), 10, params, prefKeyOauthTokenT); list = parseList(new JSONObject(response)); lists.add(list); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setLists(lists); return apiResponse; } /** * Delete a list by its id * * @param id String, the id of the list * @return APIResponse */ public int deleteList(String id) { try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.delete(getAbsoluteUrl(String.format("/lists/%s", id)), 10, null, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (Exception e) { setDefaultError(e); } return actionCode; } /** * Retrieves list from Communitywiki *synchronously* * * @return APIResponse */ public ArrayList getCommunitywikiList() { ArrayList list = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrlCommunitywiki("/list"), 10, null, prefKeyOauthTokenT); JSONArray jsonArray = new JSONArray(response); int len = jsonArray.length(); for (int i = 0; i < len; i++) { list.add(jsonArray.get(i).toString()); } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return list; } /** * Retrieves list from Communitywiki *synchronously* * * @return APIResponse */ public ArrayList getCommunitywikiList(String name) { ArrayList list = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrlCommunitywiki(String.format("/list/%s", name)), 10, null, prefKeyOauthTokenT); JSONArray jsonArray = new JSONArray(response); for (int i = 0; i < jsonArray.length(); i++) { try { list.add(jsonArray.getJSONObject(i).getString("acct")); } catch (JSONException ignored) { } } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return list; } /** * Parse json response an unique account * * @param resobj JSONObject * @return Account */ private Results parseResultsResponse(JSONObject resobj) { Results results = new Results(); try { if (resobj.has("accounts")) { results.setAccounts(parseAccountResponse(resobj.getJSONArray("accounts"))); } if (resobj.has("profiles")) { results.setAccounts(parseAccountPixelfedSearchResponse(resobj.getJSONArray("profiles"))); } if (resobj.has("statuses")) { results.setStatuses(parseStatuses(context, resobj.getJSONArray("statuses"))); } results.setTrends(parseTrends(resobj.getJSONArray("hashtags"))); results.setHashtags(parseTags(resobj.getJSONArray("hashtags"))); } catch (JSONException e) { setDefaultError(e); } return results; } /** * Parse Domains * * @param jsonArray JSONArray * @return List of domains */ private List parseDomains(JSONArray jsonArray) { List list_tmp = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { try { list_tmp.add(jsonArray.getString(i)); } catch (JSONException ignored) { } } return list_tmp; } /** * Parse Tags * * @param jsonArray JSONArray * @return List of tags */ private List parseTags(JSONArray jsonArray) { List list_tmp = new ArrayList<>(); for (int i = 0; i < jsonArray.length(); i++) { try { if (jsonArray.get(i) instanceof JSONObject) { if (jsonArray.getJSONObject(i).has("name")) { list_tmp.add(jsonArray.getJSONObject(i).getString("name")); } else if (jsonArray.getJSONObject(i).has("value")) { list_tmp.add(jsonArray.getJSONObject(i).getString("value")); } } else { list_tmp.add(jsonArray.getString(i)); } } catch (JSONException ignored) { } } return list_tmp; } /** * Parse json response for several howto * * @param jsonArray JSONArray * @return List */ private List parseHowTos(JSONArray jsonArray) { List howToVideos = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); HowToVideo howToVideo = parseHowTo(resobj); i++; howToVideos.add(howToVideo); } } catch (JSONException e) { setDefaultError(e); } return howToVideos; } /** * Parse json response for several howto * * @param jsonArray JSONArray * @return List */ private List parsePeertube(String instance, JSONArray jsonArray) { List peertubes = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Peertube peertube = parsePeertube(instance, resobj); i++; peertubes.add(peertube); } } catch (JSONException e) { setDefaultError(e); } return peertubes; } /** * Parse json response for several trends * * @param jsonArray JSONArray * @return List */ private List parseTrends(JSONArray jsonArray) { List trends = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Trends trend = parseTrends(resobj); i++; trends.add(trend); } } catch (JSONException e) { setDefaultError(e); } return trends; } /** * Parse json response for unique trend * * @param resobj JSONObject * @return Trend */ private Trends parseTrends(JSONObject resobj) { Trends trend = new Trends(); try { if (resobj.has("name") && !resobj.isNull("name")) { trend.setName(resobj.getString("name")); } else if (resobj.has("value")) { trend.setName(resobj.getString("value")); } trend.setUrl(resobj.getString("url")); List historyList = new ArrayList<>(); if (resobj.has("history")) { JSONArray histories = resobj.getJSONArray("history"); for (int i = 0; i < histories.length(); i++) { JSONObject hystory = histories.getJSONObject(i); TrendsHistory trendsHistory = new TrendsHistory(); trendsHistory.setDays(hystory.getLong("day")); trendsHistory.setUses(hystory.getInt("uses")); trendsHistory.setAccounts(hystory.getInt("accounts")); historyList.add(trendsHistory); } } trend.setTrendsHistory(historyList); } catch (JSONException ignored) { } return trend; } /** * Parse json response for several conversations * * @param jsonArray JSONArray * @return List */ private List parseConversations(JSONArray jsonArray) { List conversations = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Conversation conversation = parseConversation(context, resobj); i++; conversations.add(conversation); } } catch (JSONException e) { setDefaultError(e); } return conversations; } /** * Parse json response for unique conversation * * @param resobj JSONObject * @return Conversation */ private Conversation parseConversation(Context context, JSONObject resobj) { Conversation conversation = new Conversation(); try { conversation.setId(resobj.getString("id")); conversation.setUnread(resobj.getBoolean("unread")); conversation.setAccounts(parseAccountResponse(resobj.getJSONArray("accounts"))); conversation.setLast_status(parseStatuses(context, resobj.getJSONObject("last_status"))); } catch (JSONException ignored) { } return conversation; } /** * Parse json response for several status * * @param jsonArray JSONArray * @return List */ private List parseStatusesForCache(Context context, JSONArray jsonArray) { SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); Account account = new AccountDAO(context, db).getAccountByToken(prefKeyOauthTokenT); List statuses = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Status status = parseStatuses(context, resobj); Status alreadyCached = new TimelineCacheDAO(context, db).getSingle(status.getId()); if (alreadyCached == null && account != null && account.getId() != null && account.getInstance() != null) { new TimelineCacheDAO(context, db).insert(status.getId(), resobj.toString(), account.getId(), account.getInstance()); } i++; statuses.add(status); } } catch (JSONException e) { e.printStackTrace(); } return statuses; } /** * Parse json response an unique instance * * @param resobj JSONObject * @return Instance */ private Instance parseInstance(JSONObject resobj) { Instance instance = new Instance(); try { instance.setUri(resobj.getString("uri")); instance.setTitle(resobj.getString("title")); instance.setDescription(resobj.getString("description")); instance.setEmail(resobj.getString("email")); instance.setVersion(resobj.getString("version")); if (resobj.has("registrations")) { instance.setRegistration(resobj.getBoolean("registrations")); } else { instance.setRegistration(false); } if (resobj.has("approval_required")) { instance.setApproval_required(resobj.getBoolean("approval_required")); } else { instance.setApproval_required(false); } if (resobj.has("poll_limits")) { HashMap poll_limits = new HashMap<>(); JSONObject polllimits = resobj.getJSONObject("poll_limits"); poll_limits.put("min_expiration", polllimits.getInt("min_expiration")); poll_limits.put("max_options", polllimits.getInt("max_options")); poll_limits.put("max_option_chars", polllimits.getInt("max_option_chars")); poll_limits.put("max_expiration", polllimits.getInt("max_expiration")); instance.setPoll_limits(poll_limits); } if (resobj.has("thumbnail")) { instance.setThumbnail(resobj.getString("thumbnail")); } if (resobj.has("stats")) { JSONObject stats = resobj.getJSONObject("stats"); if (stats.has("user_count")) { instance.setUserCount(stats.getInt("user_count")); } if (stats.has("status_count")) { instance.setStatusCount(stats.getInt("status_count")); } if (stats.has("domain_count")) { instance.setDomainCount(stats.getInt("domain_count")); } } if (resobj.has("contact_account")) { instance.setContactAccount(parseAccountResponse(resobj.getJSONObject("contact_account"))); } } catch (JSONException e) { e.printStackTrace(); } return instance; } /** * Parse json response for several instance reg * * @param jsonArray JSONArray * @return List */ private List parseInstanceReg(JSONArray jsonArray) { List instanceRegs = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); InstanceReg instanceReg = parseInstanceReg(resobj); i++; instanceRegs.add(instanceReg); } } catch (JSONException e) { e.printStackTrace(); } return instanceRegs; } /** * Parse json response an unique instance for registering * * @param resobj JSONObject * @return InstanceReg */ private InstanceReg parseInstanceReg(JSONObject resobj) { InstanceReg instanceReg = new InstanceReg(); try { instanceReg.setDomain(resobj.getString("domain")); instanceReg.setVersion(resobj.getString("version")); instanceReg.setDescription(resobj.getString("description")); instanceReg.setLanguage(resobj.getString("language")); instanceReg.setCategory(resobj.getString("category")); instanceReg.setProxied_thumbnail(resobj.getString("proxied_thumbnail")); instanceReg.setTotal_users(resobj.getInt("total_users")); instanceReg.setLast_week_users(resobj.getInt("last_week_users")); } catch (JSONException e) { e.printStackTrace(); } return instanceReg; } /** * Parse emojis * * @param jsonArray JSONArray * @return List of emojis */ private List parseEmojis(JSONArray jsonArray) { List emojis = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Emojis emojis1 = parseEmojis(resobj); if (emojis1.isVisible_in_picker()) emojis.add(emojis1); i++; } } catch (JSONException e) { setDefaultError(e); } return emojis; } /** * Parse Filters * * @param jsonArray JSONArray * @return List of filters */ private List parseFilters(JSONArray jsonArray) { List filters = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Filters filter = parseFilter(resobj); if (filter != null) filters.add(filter); i++; } } catch (JSONException e) { setDefaultError(e); } return filters; } /** * Parse json response for filter * * @param resobj JSONObject * @return Filter */ private Filters parseFilter(JSONObject resobj) { Filters filter = new Filters(); try { filter.setId(resobj.getString("id")); filter.setPhrase(resobj.getString("phrase")); resobj.get("expires_at"); if (!resobj.getString("expires_at").equals("null")) filter.setSetExpires_at(Helper.mstStringToDate(resobj.getString("expires_at"))); filter.setWhole_word(resobj.getBoolean("whole_word")); filter.setIrreversible(resobj.getBoolean("irreversible")); String contextString = resobj.getString("context"); contextString = contextString.replaceAll("\\[", ""); contextString = contextString.replaceAll("]", ""); contextString = contextString.replaceAll("\"", ""); String[] context = contextString.split(","); if (contextString.length() > 0) { ArrayList finalContext = new ArrayList<>(); for (String c : context) finalContext.add(c.trim()); filter.setContext(finalContext); } return filter; } catch (Exception ignored) { return null; } } /** * Parse Lists * * @param jsonArray JSONArray * @return List of lists */ private List parseLists(JSONArray jsonArray) { List lists = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); app.fedilab.android.client.Entities.List list = parseList(resobj); lists.add(list); i++; } } catch (JSONException e) { setDefaultError(e); } return lists; } private List parseAccountResponsePeertube(String instance, JSONArray jsonArray) { List accounts = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Account account = parseAccountResponsePeertube(instance, resobj); accounts.add(account); i++; } } catch (JSONException e) { setDefaultError(e); } return accounts; } /** * Parse json response for list of reports for admins * * @param jsonArray JSONArray * @return List */ private List parseReportAdminResponse(JSONArray jsonArray) { List reports = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Report report = parseReportAdminResponse(context, resobj); reports.add(report); i++; } } catch (JSONException e) { setDefaultError(e); } return reports; } /** * Parse json response for list of accounts for admins * * @param jsonArray JSONArray * @return List */ private List parseAccountAdminResponse(JSONArray jsonArray) { List accountAdmins = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); AccountAdmin accountAdmin = parseAccountAdminResponse(resobj); accountAdmins.add(accountAdmin); i++; } } catch (JSONException e) { setDefaultError(e); } return accountAdmins; } /** * Parse json response for list of accounts * * @param jsonArray JSONArray * @return List */ private List parseAccountResponse(JSONArray jsonArray) { List accounts = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Account account = parseAccountResponse(resobj); accounts.add(account); i++; } } catch (JSONException e) { setDefaultError(e); } return accounts; } /** * Parse json response for list of accounts * * @param jsonArray JSONArray * @return List */ private List parseAccountPixelfedSearchResponse(JSONArray jsonArray) { List accounts = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Account account = parseAccountPixelfedSearchResponse(resobj); accounts.add(account); i++; } } catch (JSONException e) { setDefaultError(e); } return accounts; } /** * Parse json response an unique relationship * * @param resobj JSONObject * @return Relationship */ private Relationship parseRelationshipResponse(JSONObject resobj) { Relationship relationship = new Relationship(); try { relationship.setId(resobj.getString("id")); relationship.setFollowing(resobj.getBoolean("following")); relationship.setFollowed_by(resobj.getBoolean("followed_by")); relationship.setBlocking(resobj.getBoolean("blocking")); relationship.setMuting(resobj.getBoolean("muting")); try { relationship.setMuting_notifications(resobj.getBoolean("muting_notifications")); } catch (Exception ignored) { relationship.setMuting_notifications(true); } try { relationship.setEndorsed(resobj.getBoolean("endorsed")); } catch (Exception ignored) { relationship.setMuting_notifications(false); } try { relationship.setShowing_reblogs(resobj.getBoolean("showing_reblogs")); } catch (Exception ignored) { relationship.setMuting_notifications(false); } try { relationship.setBlocked_by(resobj.getBoolean("blocked_by")); } catch (Exception ignored) { relationship.setBlocked_by(false); } try { relationship.setDomain_blocking(resobj.getBoolean("domain_blocking")); } catch (Exception ignored) { relationship.setDomain_blocking(false); } if (resobj.has("note")) { relationship.setNote(resobj.getString("note")); } try { relationship.setNotifying(resobj.getBoolean("notifying")); } catch (Exception ignored) { relationship.setNotifying(false); } relationship.setRequested(resobj.getBoolean("requested")); } catch (JSONException e) { setDefaultError(e); } return relationship; } /** * Parse json response for list of relationship * * @param jsonArray JSONArray * @return List */ private List parseRelationshipResponse(JSONArray jsonArray) { List relationships = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Relationship relationship = parseRelationshipResponse(resobj); relationships.add(relationship); i++; } } catch (JSONException e) { setDefaultError(e); } return relationships; } /** * Parse json response for the context * * @param jsonObject JSONObject * @return Context */ private app.fedilab.android.client.Entities.Context parseContext(JSONObject jsonObject) { app.fedilab.android.client.Entities.Context context = new app.fedilab.android.client.Entities.Context(); try { if (MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED) { context.setAncestors(parseStatuses(this.context, jsonObject.getJSONArray("data"))); } else { context.setAncestors(parseStatuses(this.context, jsonObject.getJSONArray("ancestors"))); context.setDescendants(parseStatuses(this.context, jsonObject.getJSONArray("descendants"))); } } catch (JSONException e) { setDefaultError(e); } return context; } /** * Parse json response for list of notifications * * @param jsonArray JSONArray * @return List */ private List parseNotificationResponse(JSONArray jsonArray) { List notifications = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Notification notification = parseNotificationResponse(context, resobj); notifications.add(notification); i++; } } catch (JSONException e) { setDefaultError(e); } return notifications; } /** * Set the error message * * @param statusCode int code * @param error Throwable error */ private void setError(int statusCode, Throwable error) { APIError = new Error(); APIError.setStatusCode(statusCode); String message = statusCode + " - " + error.getMessage(); try { JSONObject jsonObject = new JSONObject(Objects.requireNonNull(error.getMessage())); String errorM = jsonObject.getString("error"); message = "Error " + statusCode + " : " + errorM; } catch (JSONException e) { if (error.getMessage().split(".").length > 0) { String errorM = error.getMessage().split(".")[0]; message = "Error " + statusCode + " : " + errorM; } } APIError.setError(message); apiResponse.setError(APIError); } private void setDefaultError(Exception e) { APIError = new Error(); if (apiResponse == null) { apiResponse = new APIResponse(); } if (e.getLocalizedMessage() != null && e.getLocalizedMessage().trim().length() > 0) APIError.setError(e.getLocalizedMessage()); else if (e.getMessage() != null && e.getMessage().trim().length() > 0) APIError.setError(e.getMessage()); else APIError.setError(context.getString(R.string.toast_error)); apiResponse.setError(APIError); } public Error getError() { return APIError; } private String getAbsoluteUrl(String action) { if (prefKeyOauthTokenT.startsWith("X-XSRF-TOKEN")) { return Helper.instanceWithProtocol(this.context, this.instance) + "/api/pixelfed/v1" + action; } else { return Helper.instanceWithProtocol(this.context, this.instance) + "/api/v1" + action; } } private String getAbsoluteUr2l(String action) { return Helper.instanceWithProtocol(this.context, this.instance) + "/api/v2" + action; } private String getAbsoluteUrlRemote(String remote, String action) { return "https://" + remote + "/api/v1" + action; } private String getAbsoluteUrlRemoteInstance(String instanceName) { return "https://" + instanceName + "/api/v1/timelines/public?local=true"; } private String getAbsoluteUrlCommunitywiki(String action) { return "https://communitywiki.org/trunk/api/v1" + action; } public enum searchType { TAGS, STATUSES, ACCOUNTS } public enum adminAction { ENABLE, APPROVE, REJECT, NONE, SILENCE, DISABLE, UNSILENCE, SUSPEND, UNSUSPEND, ASSIGN_TO_SELF, UNASSIGN, REOPEN, RESOLVE, GET_ACCOUNTS, GET_ONE_ACCOUNT, GET_REPORTS, GET_ONE_REPORT } public enum StatusAction { FAVOURITE, UNFAVOURITE, BOOKMARK, UNBOOKMARK, REBLOG, UNREBLOG, MUTE, MUTE_NOTIFICATIONS, UNMUTE, MUTE_CONVERSATION, UNMUTE_CONVERSATION, BLOCK, UNBLOCK, FOLLOW, UNFOLLOW, NOTIFY_FOR_ACCOUNT, UNNOTIFY_FOR_ACCOUNT, CREATESTATUS, UNSTATUS, AUTHORIZE, REJECT, REPORT, REMOTE_FOLLOW, PIN, UNPIN, REACT, UNREACT, ENDORSE, UNENDORSE, SHOW_BOOST, HIDE_BOOST, BLOCK_DOMAIN, RATEVIDEO, PEERTUBECOMMENT, PEERTUBEREPLY, PEERTUBEDELETECOMMENT, PEERTUBEDELETEVIDEO, UPDATESERVERSCHEDULE, DELETESCHEDULED, REFRESHPOLL, ADD_REACTION, REMOVE_REACTION, ADD_PLEROMA_REACTION, REMOVE_PLEROMA_REACTION, DISMISS_ANNOUNCEMENT } public enum accountPrivacy { PUBLIC, LOCKED } }