package app.fedilab.fedilabtube.client; /* Copyright 2020 Thomas Schneider * * This file is a part of TubeLab * * 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. * * TubeLab 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 TubeLab; if not, * see . */ import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import android.os.Build; import android.text.Html; import android.text.SpannableString; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.text.ParseException; 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 app.fedilab.fedilabtube.BuildConfig; import app.fedilab.fedilabtube.R; import app.fedilab.fedilabtube.client.entities.Account; import app.fedilab.fedilabtube.client.entities.AccountCreation; import app.fedilab.fedilabtube.client.entities.ChannelCreation; import app.fedilab.fedilabtube.client.entities.Error; import app.fedilab.fedilabtube.client.entities.Instance; import app.fedilab.fedilabtube.client.entities.InstanceNodeInfo; import app.fedilab.fedilabtube.client.entities.NodeInfo; import app.fedilab.fedilabtube.client.entities.Peertube; import app.fedilab.fedilabtube.client.entities.PeertubeAccountNotification; import app.fedilab.fedilabtube.client.entities.PeertubeActorFollow; import app.fedilab.fedilabtube.client.entities.PeertubeComment; import app.fedilab.fedilabtube.client.entities.PeertubeInformation; import app.fedilab.fedilabtube.client.entities.PeertubeNotification; import app.fedilab.fedilabtube.client.entities.PeertubeVideoNotification; import app.fedilab.fedilabtube.client.entities.Playlist; import app.fedilab.fedilabtube.client.entities.PlaylistElement; import app.fedilab.fedilabtube.client.entities.Relationship; import app.fedilab.fedilabtube.client.entities.Status; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.sqlite.AccountDAO; import app.fedilab.fedilabtube.sqlite.Sqlite; /** * Created by Thomas on 02/01/2019. * Manage Calls to the Peertube REST API */ public class PeertubeAPI { private Account account; private Context context; private int tootPerPage; private int actionCode; private String instance; private String prefKeyOauthTokenT; private APIResponse apiResponse; private Error APIError; public PeertubeAPI(Context context) { this.context = context; SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); tootPerPage = Helper.VIDEOS_PER_PAGE; Helper.getLiveInstance(context); this.instance = Helper.getLiveInstance(context); this.prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); apiResponse = new APIResponse(); APIError = null; } public PeertubeAPI(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 = Helper.VIDEOS_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 for unique how to * * @param resobj JSONObject * @return Peertube */ private static PeertubeNotification parsePeertubeNotifications(JSONObject resobj) { PeertubeNotification peertubeNotification = new PeertubeNotification(); try { peertubeNotification.setId(resobj.getString("id")); peertubeNotification.setType(resobj.getInt("type")); peertubeNotification.setUpdatedAt(Helper.mstStringToDate(resobj.getString("updatedAt"))); peertubeNotification.setCreatedAt(Helper.mstStringToDate(resobj.getString("createdAt"))); peertubeNotification.setRead(resobj.getBoolean("read")); if (resobj.has("comment")) { PeertubeComment peertubeComment = new PeertubeComment(); JSONObject comment = resobj.getJSONObject("comment"); if (comment.has("account")) { JSONObject account = comment.getJSONObject("account"); PeertubeAccountNotification peertubeAccountNotification = new PeertubeAccountNotification(); peertubeAccountNotification.setDisplayName(account.getString("displayName")); peertubeAccountNotification.setName(account.getString("name")); peertubeAccountNotification.setId(account.getString("id")); if (account.has("host")) { peertubeAccountNotification.setHost(account.getString("host")); } peertubeAccountNotification.setAvatar(account.getJSONObject("avatar").getString("path")); peertubeComment.setPeertubeAccountNotification(peertubeAccountNotification); } if (comment.has("video")) { JSONObject video = comment.getJSONObject("video"); PeertubeVideoNotification peertubeVideoNotification = new PeertubeVideoNotification(); peertubeVideoNotification.setUuid(video.getString("uuid")); peertubeVideoNotification.setName(video.getString("name")); peertubeVideoNotification.setId(video.getString("id")); peertubeComment.setPeertubeVideoNotification(peertubeVideoNotification); } peertubeComment.setId(comment.getString("id")); peertubeComment.setThreadId(comment.getString("threadId")); peertubeNotification.setPeertubeComment(peertubeComment); } if (resobj.has("video")) { PeertubeVideoNotification peertubeVideoNotification = new PeertubeVideoNotification(); JSONObject video = resobj.getJSONObject("video"); peertubeVideoNotification.setUuid(video.getString("uuid")); peertubeVideoNotification.setName(video.getString("name")); peertubeVideoNotification.setId(video.getString("id")); if (video.has("channel")) { PeertubeAccountNotification peertubeAccountNotification = new PeertubeAccountNotification(); JSONObject channel = video.getJSONObject("channel"); peertubeAccountNotification.setDisplayName(channel.getString("displayName")); peertubeAccountNotification.setName(channel.getString("name")); peertubeAccountNotification.setId(channel.getString("id")); peertubeAccountNotification.setHost(channel.getString("host")); if (channel.has("avatar")) { peertubeAccountNotification.setAvatar(channel.getJSONObject("avatar").getString("path")); } peertubeVideoNotification.setPeertubeAccountNotification(peertubeAccountNotification); } peertubeNotification.setPeertubeVideoNotification(peertubeVideoNotification); } if (resobj.has("actorFollow")) { PeertubeActorFollow peertubeActorFollow = new PeertubeActorFollow(); JSONObject actorFollow = resobj.getJSONObject("actorFollow"); JSONObject follower = actorFollow.getJSONObject("follower"); JSONObject following = actorFollow.getJSONObject("following"); PeertubeAccountNotification peertubeAccountNotification = new PeertubeAccountNotification(); peertubeAccountNotification.setDisplayName(follower.getString("displayName")); peertubeAccountNotification.setName(follower.getString("name")); peertubeAccountNotification.setId(follower.getString("id")); if (follower.has("host")) { peertubeAccountNotification.setHost(follower.getString("host")); } if (follower.has("avatar")) { peertubeAccountNotification.setAvatar(follower.getJSONObject("avatar").getString("path")); } peertubeActorFollow.setFollower(peertubeAccountNotification); PeertubeAccountNotification peertubeAccounFollowingNotification = new PeertubeAccountNotification(); peertubeAccounFollowingNotification.setDisplayName(following.getString("displayName")); peertubeAccounFollowingNotification.setName(following.getString("name")); try { peertubeAccounFollowingNotification.setId(following.getString("id")); } catch (Exception ignored) { } if (following.has("avatar")) { peertubeAccounFollowingNotification.setAvatar(following.getJSONObject("avatar").getString("path")); } peertubeActorFollow.setFollowing(peertubeAccounFollowingNotification); peertubeActorFollow.setId(actorFollow.getString("id")); peertubeNotification.setPeertubeActorFollow(peertubeActorFollow); } } catch (JSONException | ParseException e) { e.printStackTrace(); } return peertubeNotification; } /** * Parse json response for unique how to * * @param resobj JSONObject * @return Peertube */ public static Peertube parsePeertube(JSONObject resobj) { Peertube peertube = new Peertube(); if (resobj.has("video") && !resobj.isNull("video")) { try { resobj = resobj.getJSONObject("video"); } catch (JSONException e) { e.printStackTrace(); } } else { if (!resobj.has("name")) { return null; } } try { peertube.setId(resobj.getString("id")); peertube.setCache(resobj); if (resobj.has("uuid")) { 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(resobj.getJSONObject("account"))); try { peertube.setChannel(parseAccountResponsePeertube(resobj.getJSONObject("channel"))); } catch (Exception ignored) { } peertube.setView(resobj.getInt("views")); peertube.setLike(resobj.getInt("likes")); peertube.setDislike(resobj.getInt("dislikes")); peertube.setDuration(resobj.getInt("duration")); peertube.setSensitive(resobj.getBoolean("nsfw")); try { peertube.setCommentsEnabled(resobj.getBoolean("commentsEnabled")); } catch (Exception ignored) { } try { peertube.setCreated_at(Helper.mstStringToDate(resobj.getString("createdAt"))); } catch (ParseException e) { e.printStackTrace(); } try { LinkedHashMap langue = new LinkedHashMap<>(); LinkedHashMap category = new LinkedHashMap<>(); LinkedHashMap license = new LinkedHashMap<>(); LinkedHashMap privacy = new LinkedHashMap<>(); if (!resobj.getJSONObject("category").isNull("id")) { license.put(resobj.getJSONObject("category").getInt("id"), resobj.getJSONObject("category").getString("label")); } else { license.put(1, resobj.getJSONObject("category").getString("label")); } if (!resobj.getJSONObject("licence").isNull("id")) { license.put(resobj.getJSONObject("licence").getInt("id"), resobj.getJSONObject("licence").getString("label")); } else { license.put(1, resobj.getJSONObject("licence").getString("label")); } privacy.put(resobj.getJSONObject("privacy").getInt("id"), resobj.getJSONObject("privacy").getString("label")); langue.put(resobj.getJSONObject("language").getString("id"), resobj.getJSONObject("language").getString("label")); peertube.setCategory(category); peertube.setLicense(license); peertube.setLanguage(langue); peertube.setPrivacy(privacy); } catch (Exception 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(resobj.getJSONObject("account"))); List tags = new ArrayList<>(); try { JSONArray tagsA = resobj.getJSONArray("tags"); for (int i = 0; i < tagsA.length(); i++) { String value = tagsA.getString(i); tags.add(value); } peertube.setTags(tags); } catch (Exception ignored) { } try { peertube.setChannel(parseAccountResponsePeertube(resobj.getJSONObject("channel"))); } catch (Exception ignored) { } peertube.setSensitive(resobj.getBoolean("nsfw")); try { peertube.setCreated_at(Helper.mstStringToDate(resobj.getString("createdAt"))); } catch (ParseException e) { e.printStackTrace(); } 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); } 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); } try { LinkedHashMap langue = new LinkedHashMap<>(); LinkedHashMap category = new LinkedHashMap<>(); LinkedHashMap license = new LinkedHashMap<>(); LinkedHashMap privacy = new LinkedHashMap<>(); if (!resobj.getJSONObject("category").isNull("id")) { license.put(resobj.getJSONObject("category").getInt("id"), resobj.getJSONObject("category").getString("label")); } else { license.put(1, resobj.getJSONObject("category").getString("label")); } if (!resobj.getJSONObject("licence").isNull("id")) { license.put(resobj.getJSONObject("licence").getInt("id"), resobj.getJSONObject("licence").getString("label")); } else { license.put(1, resobj.getJSONObject("licence").getString("label")); } privacy.put(resobj.getJSONObject("privacy").getInt("id"), resobj.getJSONObject("privacy").getString("label")); langue.put(resobj.getJSONObject("language").getString("id"), resobj.getJSONObject("language").get("label").toString()); peertube.setCategory(category); peertube.setLicense(license); peertube.setLanguage(langue); peertube.setPrivacy(privacy); } catch (Exception ignored) { } peertube.setResolution(resolutions); } catch (JSONException e) { e.printStackTrace(); } return peertube; } /** * Parse json response for emoji * * @param resobj JSONObject * @return Emojis */ private static Playlist parsePlaylist(Context context, JSONObject resobj) { Playlist playlist = new Playlist(); try { playlist.setId(resobj.getString("id")); playlist.setUuid(resobj.getString("uuid")); playlist.setCreatedAt(Helper.stringToDate(context, resobj.getString("createdAt"))); playlist.setDescription(resobj.getString("description")); playlist.setDisplayName(resobj.getString("displayName")); playlist.setLocal(resobj.getBoolean("isLocal")); if (resobj.has("videoChannel") && !resobj.isNull("videoChannel")) { playlist.setVideoChannelId(resobj.getJSONObject("videoChannel").getString("id")); } playlist.setThumbnailPath(resobj.getString("thumbnailPath")); playlist.setOwnerAccount(parseAccountResponsePeertube(resobj.getJSONObject("ownerAccount"))); playlist.setVideosLength(resobj.getInt("videosLength")); try { LinkedHashMap type = new LinkedHashMap<>(); LinkedHashMap privacy = new LinkedHashMap<>(); privacy.put(resobj.getJSONObject("privacy").getInt("id"), resobj.getJSONObject("privacy").get("label").toString()); type.put(resobj.getJSONObject("type").getInt("id"), resobj.getJSONObject("type").get("label").toString()); playlist.setType(type); playlist.setPrivacy(privacy); } catch (Exception ignored) { } try { playlist.setUpdatedAt(Helper.stringToDate(context, resobj.getString("updatedAt"))); } catch (Exception ignored) { } } catch (Exception ignored) { } return playlist; } /** * Parse json response an unique peertube account * * @param accountObject JSONObject * @return Account */ private static Account parseAccountResponsePeertube(JSONObject accountObject) { Account account = new Account(); try { account.setId(accountObject.getString("id")); account.setUuid(accountObject.getString("id")); account.setUsername(accountObject.getString("name")); account.setAcct(accountObject.getString("name") + "@" + accountObject.get("host")); account.setDisplay_name(accountObject.get("displayName").toString()); account.setHost(accountObject.getString("host")); account.setSocial("PEERTUBE"); account.setInstance(accountObject.getString("host")); if (accountObject.has("ownerAccount")) { account.setchannelOwner(parseAccountResponsePeertube(accountObject.getJSONObject("ownerAccount"))); } if (accountObject.has("createdAt")) account.setCreated_at(Helper.mstStringToDate(accountObject.getString("createdAt"))); else account.setCreated_at(new Date()); if (accountObject.has("followersCount")) account.setFollowers_count(accountObject.getInt("followersCount")); else account.setFollowers_count(0); if (accountObject.has("followingCount")) account.setFollowing_count(accountObject.getInt("followingCount")); else account.setFollowing_count(0); account.setStatuses_count(0); if (accountObject.has("description")) account.setNote(accountObject.getString("description")); else account.setNote(""); if (accountObject.has("url")) { account.setUrl(accountObject.getString("url")); } if (accountObject.has("avatar") && !accountObject.isNull("avatar")) { account.setAvatar(accountObject.getJSONObject("avatar").getString("path")); account.setAvatar_static(accountObject.getJSONObject("avatar").getString("path")); } else { account.setAvatar("null"); account.setAvatar_static("null"); } account.setHeader("null"); account.setHeader_static("null"); } catch (JSONException | ParseException e) { e.printStackTrace(); } return account; } /** * Parse json response for peertube comments * * @param resobj JSONObject * @return Peertube */ private static List parseSinglePeertubeComments(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.get("id").toString()); status.setUri(comment.get("url").toString()); status.setUrl(comment.get("url").toString()); status.setSensitive(false); status.setContent(comment.get("text").toString()); status.setIn_reply_to_id(comment.get("inReplyToCommentId").toString()); status.setAccount(parseAccountResponsePeertube(instance, comment.getJSONObject("account"))); status.setCreated_at(Helper.mstStringToDate(comment.get("createdAt").toString())); status.setVisibility("public"); 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 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.get("id").toString()); account.setUsername(resobj.get("name").toString()); account.setAcct(resobj.get("name").toString() + "@" + resobj.get("host").toString()); account.setDisplay_name(resobj.get("displayName").toString()); account.setHost(resobj.get("host").toString()); 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; } /*** * Get info on the current Instance *synchronously* * @return APIResponse */ public APIResponse getInstance() { try { String response = new HttpsConnection(context).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; } /** * Update video meta data *synchronously* * * @param peertube Peertube * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse updateVideo(Peertube peertube) { LinkedHashMap params = new LinkedHashMap<>(); params.put("name", peertube.getName()); //Category Map.Entry categoryM = peertube.getCategory().entrySet().iterator().next(); Integer idCategory = categoryM.getKey(); params.put("category", String.valueOf(idCategory)); //License Map.Entry licenseM = peertube.getLicense().entrySet().iterator().next(); Integer idLicense = licenseM.getKey(); params.put("licence", String.valueOf(idLicense)); //language Map.Entry languagesM = peertube.getLanguage().entrySet().iterator().next(); String iDlanguage = languagesM.getKey(); params.put("language", iDlanguage); params.put("support", "null"); params.put("description", peertube.getDescription()); //Channel Map.Entry channelsM = peertube.getChannelForUpdate().entrySet().iterator().next(); String iDChannel = channelsM.getValue(); params.put("channelId", iDChannel); //Privacy Map.Entry privacyM = peertube.getPrivacy().entrySet().iterator().next(); Integer idPrivacy = privacyM.getKey(); params.put("privacy", String.valueOf(idPrivacy)); if (peertube.getTags() != null && peertube.getTags().size() > 0) { StringBuilder parameters = new StringBuilder(); parameters.append("[]&"); for (String tag : peertube.getTags()) parameters.append("tags=").append(tag).append("&"); String strParam = parameters.toString(); strParam = strParam.substring(0, strParam.length() - 1); params.put("tags[]", strParam); } else { params.put("tags", "null"); } params.put("nsfw", String.valueOf(peertube.isSensitive())); params.put("waitTranscoding", "true"); params.put("commentsEnabled", String.valueOf(peertube.isCommentsEnabled())); params.put("scheduleUpdate", "null"); List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); httpsConnection.put(getAbsoluteUrl(String.format("/videos/%s", peertube.getId())), 60, params, prefKeyOauthTokenT); peertubes.add(peertube); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } apiResponse.setPeertubes(peertubes); return apiResponse; } /*** * Verifiy PeertubeInformation of the authenticated user *synchronously* * @return Account */ public PeertubeInformation getPeertubeInformation() throws HttpsConnection.HttpsConnectionException { PeertubeInformation peertubeInformation = new PeertubeInformation(); try { String response = new HttpsConnection(context).get(getAbsoluteUrl("/videos/categories"), 60, null, null); JSONObject categories = new JSONObject(response); LinkedHashMap _pcategories = new LinkedHashMap<>(); for (int i = 1; i <= categories.length(); i++) { _pcategories.put(i, categories.getString(String.valueOf(i))); } peertubeInformation.setCategories(_pcategories); response = new HttpsConnection(context).get(getAbsoluteUrl("/videos/languages"), 60, null, null); JSONObject languages = new JSONObject(response); LinkedHashMap _languages = new LinkedHashMap<>(); Iterator iter = languages.keys(); while (iter.hasNext()) { String key = iter.next(); try { _languages.put(key, (String) languages.get(key)); } catch (JSONException ignored) { } } peertubeInformation.setLanguages(_languages); response = new HttpsConnection(context).get(getAbsoluteUrl("/videos/privacies"), 60, null, null); JSONObject privacies = new JSONObject(response); LinkedHashMap _pprivacies = new LinkedHashMap<>(); for (int i = 1; i <= privacies.length(); i++) { _pprivacies.put(i, privacies.getString(String.valueOf(i))); } peertubeInformation.setPrivacies(_pprivacies); response = new HttpsConnection(context).get(getAbsoluteUrl("/video-playlists/privacies"), 60, null, null); JSONObject plprivacies = new JSONObject(response); LinkedHashMap _plprivacies = new LinkedHashMap<>(); for (int i = 1; i <= plprivacies.length(); i++) { _plprivacies.put(i, plprivacies.getString(String.valueOf(i))); } peertubeInformation.setPlaylistPrivacies(_plprivacies); response = new HttpsConnection(context).get(getAbsoluteUrl("/videos/licences"), 60, null, null); JSONObject licences = new JSONObject(response); LinkedHashMap _plicences = new LinkedHashMap<>(); for (int i = 1; i <= licences.length(); i++) { _plicences.put(i, licences.getString(String.valueOf(i))); } peertubeInformation.setLicences(_plicences); String instance = Helper.getLiveInstance(context); String lang = null; if (PeertubeInformation.langueMapped.containsKey(Locale.getDefault().getLanguage())) lang = PeertubeInformation.langueMapped.get(Locale.getDefault().getLanguage()); if (lang != null) { response = new HttpsConnection(context).get(String.format("https://" + instance + "/client/locales/%s/server.json", lang), 60, null, null); JSONObject translations = new JSONObject(response); LinkedHashMap _translations = new LinkedHashMap<>(); Iterator itertrans = translations.keys(); while (itertrans.hasNext()) { String key = itertrans.next(); try { _translations.put(key, (String) translations.get(key)); } catch (JSONException ignored) { } } peertubeInformation.setTranslations(_translations); } } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return peertubeInformation; } /** * Refresh token and update user data * * @param token String * @param instance String */ public void refreshToken(String token, String instance) { SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); if (token == null) { final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String instanceC = Helper.getLiveInstance(context); Account accountToLogout = new AccountDAO(context, db).getUniqAccount(userId, instanceC); Helper.logoutCurrentUser((Activity) context, accountToLogout); return; } Account targetedAccount = new AccountDAO(context, db).getAccountByToken(token); String newToken = null, newRefreshToken = null; if (targetedAccount != null) { HashMap values = refreshToken(targetedAccount.getClient_id(), targetedAccount.getClient_secret(), targetedAccount.getRefresh_token()); if (values.containsKey("access_token") && values.get("access_token") != null) { SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); //This account is currently logged in, the token is updated if (values.get("access_token") != null) { SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.PREF_KEY_OAUTH_TOKEN, values.get("access_token")); editor.apply(); } } if (values.containsKey("refresh_token") && values.get("refresh_token") != null) { newRefreshToken = values.get("refresh_token"); } if (values.containsKey("access_token") && values.get("access_token") != null) { newToken = values.get("access_token"); } String response; try { response = new HttpsConnection(context).get("https://" + instance + "/api/v1/users/me", 60, null, newToken); JSONObject accountObject = new JSONObject(response).getJSONObject("account"); account = parseAccountResponsePeertube(accountObject); } catch (IOException | NoSuchAlgorithmException | KeyManagementException | JSONException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); //setError(e.getStatusCode(), e); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String instanceC = Helper.getLiveInstance(context); Account accountToLogout = new AccountDAO(context, db).getUniqAccount(userId, instanceC); Helper.logoutCurrentUser((Activity) context, accountToLogout); return; } if (newRefreshToken != null && newToken != null) { account.setRefresh_token(newRefreshToken); account.setToken(newToken); } account.setInstance(instance); new AccountDAO(context, db).updateAccount(account); } } /*** * Verifiy credential of the authenticated user *synchronously* * @return Account */ public Account verifyCredentials(String token, String instance) { account = new Account(); try { String response = new HttpsConnection(context).get("https://" + instance + "/api/v1/users/me", 60, null, token); JSONObject accountObject = new JSONObject(response).getJSONObject("account"); account = parseAccountResponsePeertube(accountObject); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } return account; } public int report(reportType type, String id, String reason) { actionCode = -1; try { HashMap params = new HashMap<>(); switch (type) { case VIDEO: params.put("video", id); break; case ACCOUNT: params.put("account", id); break; case COMMENT: params.put("comment", id); break; } params.put("reason", reason); HttpsConnection httpsConnection = new HttpsConnection(context); httpsConnection.post(getAbsoluteUrl("/abuses"), 30, params, null); actionCode = httpsConnection.getActionCode(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } return actionCode; } public APIResponse createAccount(AccountCreation accountCreation) { apiResponse = new APIResponse(); try { HashMap params = new HashMap<>(); params.put("username", accountCreation.getUsername()); params.put("email", accountCreation.getEmail()); params.put("password", accountCreation.getPassword()); new HttpsConnection(context).post(getAbsoluteUrlForInstance(accountCreation.getInstance(), "/users/register"), 30, params, null); apiResponse.setStringData(accountCreation.getEmail()); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } return apiResponse; } /** * Create a channel fot the authenticated user * * @param channelCreation channelCreation */ public void createChannel(ChannelCreation channelCreation) throws HttpsConnection.HttpsConnectionException { actionCode = -1; try { HashMap params = new HashMap<>(); params.put("displayName", channelCreation.getDisplayName()); params.put("name", channelCreation.getName()); params.put("description", channelCreation.getDescription()); params.put("support", channelCreation.getSupport()); HttpsConnection httpsConnection = new HttpsConnection(context); httpsConnection.post(getAbsoluteUrl("/video-channels"), 30, params, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } } /** * Update a channel fot the authenticated user * * @param acct String * @param channelCreation ChannelCreation */ public void updateChannel(String acct, ChannelCreation channelCreation) throws HttpsConnection.HttpsConnectionException { actionCode = -1; try { HashMap params = new HashMap<>(); params.put("displayName", channelCreation.getDisplayName()); params.put("name", channelCreation.getName()); params.put("description", channelCreation.getDescription()); params.put("support", channelCreation.getSupport()); HttpsConnection httpsConnection = new HttpsConnection(context); httpsConnection.put(getAbsoluteUrl(String.format("/video-channels/%s", acct)), 30, params, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } } /** * Delete a Channel * * @param channelId String, the channel id */ public void deleteChannel(String channelId) throws HttpsConnection.HttpsConnectionException { try { HttpsConnection httpsConnection = new HttpsConnection(context); httpsConnection.delete(getAbsoluteUrl(String.format("/video-channels/%s", channelId)), 60, null, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } } /*** * Verifiy credential of the authenticated user *synchronously* * @return Account */ private HashMap refreshToken(String client_id, String client_secret, String refresh_token) { account = new Account(); HashMap params = new HashMap<>(); HashMap newValues = new HashMap<>(); params.put("grant_type", "refresh_token"); params.put("client_id", client_id); params.put("client_secret", client_secret); params.put("refresh_token", refresh_token); try { String response = new HttpsConnection(context).post(getAbsoluteUrl("/users/token"), 60, params, null); JSONObject resobj = new JSONObject(response); String token = resobj.getString("access_token"); String refresh = resobj.getString("refresh_token"); newValues.put("access_token", token); newValues.put("refresh_token", refresh); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } return newValues; } /** * Returns an account * * @param accountId String account fetched * @return Account entity */ @SuppressWarnings({"unused", "RedundantSuppression"}) public Account getAccount(String accountId) { account = new Account(); try { String response = new HttpsConnection(context).get(getAbsoluteUrl(String.format("/accounts/%s", accountId)), 60, null, prefKeyOauthTokenT); account = parseAccountResponsePeertube(new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return account; } public List isFollowing(String uri) { ArrayList uris = new ArrayList<>(); uris.add(uri); return isFollowing(uris); } /** * Returns a relationship between the authenticated account and an account * * @param uris Array String accounts uri fetched * @return Relationship entity */ public List isFollowing(ArrayList uris) { HashMap params = new HashMap<>(); StringBuilder parameters = new StringBuilder(); for (String uri : uris) parameters.append("uris[]=").append(uri).append("&"); parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(7)); params.put("uris[]", parameters.toString()); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl("/users/me/subscriptions/exist"), 60, params, prefKeyOauthTokenT); return parseRelationShip(uris, new JSONObject(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return null; } /** * Retrieves videos for the account *synchronously* * * @param acct String Id of the account * @param max_id String id max * @return APIResponse */ public APIResponse getVideos(String acct, String max_id) { return getVideos(acct, max_id, null); } /** * Retrieves history for videos for the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getMyHistory(String max_id) { return getMyHistory(max_id, null); } /** * Retrieves history for videos for the account *synchronously* * * @param max_id String id max * @param since_id String since the id * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getMyHistory(String max_id, String since_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); if (since_id != null) params.put("since_id", since_id); params.put("count", String.valueOf(tootPerPage)); List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl("/users/me/history/videos"), 60, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(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 videos for the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getMyVideos(String max_id) { return getMyVideos(max_id, null); } /** * Retrieves status for the account *synchronously* * * @param max_id String id max * @param since_id String since the id * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getMyVideos(String max_id, String since_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); if (since_id != null) params.put("since_id", since_id); params.put("count", String.valueOf(tootPerPage)); List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl("/users/me/videos"), 60, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(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 status for the account *synchronously* * * @param acct String Id of the account * @param max_id String id max * @param since_id String since the id * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getVideos(String acct, String max_id, String since_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); if (since_id != null) params.put("since_id", since_id); params.put("count", String.valueOf(tootPerPage)); List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl(String.format("/accounts/%s/videos", acct)), 60, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(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 notifications for the account *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getNotifications(String max_id) { return getNotifications(max_id, null); } /** * Retrieves Peertube notifications since id for the account *synchronously* * * @param since_id String id since * @return APIResponse */ public APIResponse getNotificationsSince(String since_id) { return getNotifications(null, since_id); } /** * Retrieves Peertube notifications for the account *synchronously* * * @param max_id String id max * @param since_id String since the id * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getNotifications(String max_id, String since_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); if (since_id != null) params.put("since_id", since_id); params.put("count", String.valueOf(tootPerPage)); List peertubeNotifications = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl("/users/me/notifications"), 60, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubeNotifications = parsePeertubeNotifications(jsonArray); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPeertubeNotifications(peertubeNotifications); return apiResponse; } /** * Retrieves videos channel for the account *synchronously* * * @param acct String Id of the account * @param max_id String id max * @return APIResponse */ public APIResponse getVideosChannel(String acct, String max_id) { return getVideosChannel(acct, max_id, null); } /** * Retrieves status for the account *synchronously* * * @param acct String Id of the account * @param max_id String id max * @param since_id String since the id * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getVideosChannel(String acct, String max_id, String since_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); if (since_id != null) params.put("since_id", since_id); params.put("count", String.valueOf(tootPerPage)); List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl(String.format("/video-channels/%s/videos", acct)), 60, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(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 subscription videos *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getSubscriptionsTL(String max_id) { try { return getTL(true, "/users/me/subscriptions/videos", "-publishedAt", null, max_id, null, null); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); return apiResponse; } } /** * Retrieves subscriptions *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getSubscriptionUsers(String max_id) { List accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); params.put("sort", "-createdAt"); String response = httpsConnection.get(getAbsoluteUrl("/users/me/subscriptions"), 10, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); accounts = parseAccountResponsePeertube(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 muted accounts *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getMuted(String max_id) { List accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); params.put("sort", "-createdAt"); String response = httpsConnection.get(getAbsoluteUrl("/users/me/blocklist/accounts"), 10, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); accounts = parseBlockedAccountResponsePeertube(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 overview videos *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getOverviewTL(String max_id) { try { return getTL(false, "/overviews/videos", null, null, max_id, null, null); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); return apiResponse; } } /** * Retrieves most likded videos *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getLikedTL(String max_id) { try { return getTL(false, "/videos/", "-likes", null, max_id, null, null); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); return apiResponse; } } /** * Retrieves trending videos *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getTrendingTL(String max_id) { try { return getTL(false, "/videos/", "-trending", null, max_id, null, null); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); return apiResponse; } } /** * Retrieves trending videos *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getRecentlyAddedTL(String max_id) { try { return getTL(false, "/videos/", "-publishedAt", null, max_id, null, null); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); return apiResponse; } } /** * Retrieves local videos *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getLocalTL(String max_id) { try { return getTL(true, "/videos/", "-publishedAt", "local", max_id, null, null); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); return apiResponse; } } /** * Retrieves public videos *synchronously* * * @param max_id String id max * @return APIResponse */ public APIResponse getPublicTL(String max_id) { try { return getTL(false, "/videos/", "-publishedAt", null, max_id, null, null); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); return apiResponse; } } /** * Retrieves home timeline for the account *synchronously* * * @param max_id String id max * @param since_id String since the id * @return APIResponse */ @SuppressWarnings("SameParameterValue") private APIResponse getTL(boolean needToken, String action, String sort, String filter, String max_id, String since_id, String min_id) throws HttpsConnection.HttpsConnectionException { HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); if (since_id != null) params.put("since_id", since_id); if (min_id != null) params.put("min_id", min_id); params.put("count", String.valueOf(tootPerPage)); if (sort != null) params.put("sort", sort); else params.put("sort", "publishedAt"); if (filter != null) params.put("filter", filter); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean nsfw = sharedpreferences.getBoolean(Helper.SET_VIDEO_NSFW, false); params.put("nsfw", String.valueOf(nsfw)); List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl(action), 60, params, needToken ? prefKeyOauthTokenT : null); if (!action.equals("/overviews/videos")) { JSONArray values = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(values); } else { JSONArray categories = new JSONObject(response).getJSONArray("categories"); JSONArray channels = new JSONObject(response).getJSONArray("channels"); JSONArray tags = new JSONObject(response).getJSONArray("tags"); for (int i = 0; i < categories.length(); i++) { JSONArray categoriesVideos = categories.getJSONObject(i).getJSONArray("videos"); List peertubeCategories = parsePeertube(categoriesVideos); if (peertubeCategories.size() > 0) { peertubeCategories.get(0).setHeaderType("categories"); peertubeCategories.get(0).setHeaderTypeValue(categories.getJSONObject(i).getJSONObject("category").getString("label")); peertubes.addAll(peertubeCategories); } } for (int i = 0; i < channels.length(); i++) { JSONArray channelsVideos = channels.getJSONObject(i).getJSONArray("videos"); List peertubeChannels = parsePeertube(channelsVideos); if (peertubeChannels.size() > 0) { peertubeChannels.get(0).setHeaderType("channels"); peertubeChannels.get(0).setHeaderTypeValue(channels.getJSONObject(i).getJSONObject("channel").getString("displayName")); peertubes.addAll(peertubeChannels); } } for (int i = 0; i < tags.length(); i++) { JSONArray tagsVideos = tags.getJSONObject(i).getJSONArray("videos"); List peertubeTags = parsePeertube(tagsVideos); if (peertubeTags.size() > 0) { peertubeTags.get(0).setHeaderType("tags"); peertubeTags.get(0).setHeaderTypeValue(tags.getJSONObject(i).getString("tag")); peertubes.addAll(peertubeTags); } } } } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPeertubes(peertubes); return apiResponse; } /** * Retrieves Peertube channel from an account *synchronously* * Peertube channels are dealt like accounts * * @return APIResponse */ public APIResponse getPeertubeChannel(String name) { List accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl(String.format("/accounts/%s/video-channels", name)), 60, null, null); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); accounts = parseAccountResponsePeertube(jsonArray); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Retrieves Peertube channel info from an account *synchronously* * Peertube channels are dealt like accounts * * @return APIResponse */ public APIResponse getPeertubeChannelInfo(String name) { List accounts = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl(String.format("/video-channels/%s", name)), 60, null, null); JSONObject jsonObject = new JSONObject(response); Account account = parseAccountResponsePeertube(jsonObject); accounts.add(account); } catch (HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setAccounts(accounts); return apiResponse; } /** * Retrieves Peertube videos from an instance *synchronously* * * @return APIResponse */ public APIResponse getSinglePeertube(String instance, String videoId, String token) { Peertube peertube = null; try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(String.format("https://" + instance + "/api/v1/videos/%s", videoId), 60, null, token); JSONObject jsonObject = new JSONObject(response); peertube = parseSinglePeertube(instance, jsonObject); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } List peertubes = new ArrayList<>(); peertubes.add(peertube); apiResponse.setPeertubes(peertubes); return apiResponse; } /** * Retrieves rating of user on a video *synchronously* * * @param id String id * @return APIResponse */ @SuppressWarnings("SameParameterValue") public String getRating(String id) { try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl(String.format("/users/me/videos/%s/rating", id)), 60, null, prefKeyOauthTokenT); return new JSONObject(response).getString("rating"); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return 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) { return postAction(statusAction, targetedId, null, null); } public int postRating(String targetedId, String actionMore) { return postAction(StatusAction.RATEVIDEO, targetedId, actionMore, null); } public int postComment(String targetedId, String actionMore) { return postAction(StatusAction.PEERTUBECOMMENT, targetedId, actionMore, null); } public int postReply(String targetedId, String actionMore, String targetedComment) { return postAction(StatusAction.PEERTUBEREPLY, targetedId, actionMore, targetedComment); } public int deleteComment(String targetedId, String targetedComment) { return postAction(StatusAction.PEERTUBEDELETECOMMENT, targetedId, null, targetedComment); } public int deleteVideo(String targetedId) { return postAction(StatusAction.PEERTUBEDELETEVIDEO, targetedId, null, 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 actionMore String another action * @param targetedComment String another action * @return in status code - Should be equal to 200 when action is done */ private int postAction(StatusAction statusAction, String targetedId, String actionMore, String targetedComment) { String action; String actionCall = "POST"; HashMap params = null; switch (statusAction) { case FOLLOW: action = "/users/me/subscriptions"; params = new HashMap<>(); params.put("uri", targetedId); break; case UNFOLLOW: action = String.format("/users/me/subscriptions/%s", targetedId); actionCall = "DELETE"; break; case MUTE: action = "/users/me/blocklist/accounts"; params = new HashMap<>(); params.put("accountName", targetedId); break; case UNMUTE: action = String.format("/users/me/blocklist/accounts/%s", targetedId); actionCall = "DELETE"; break; case RATEVIDEO: action = String.format("/videos/%s/rate", targetedId); params = new HashMap<>(); params.put("rating", actionMore); actionCall = "PUT"; break; case PEERTUBECOMMENT: action = String.format("/videos/%s/comment-threads", targetedId); params = new HashMap<>(); params.put("text", actionMore); break; case PEERTUBEDELETECOMMENT: action = String.format("/videos/%s/comments/%s", targetedId, targetedComment); actionCall = "DELETE"; break; case PEERTUBEDELETEVIDEO: action = String.format("/videos/%s", targetedId); actionCall = "DELETE"; break; case PEERTUBEREPLY: action = String.format("/videos/%s/comment/%s", targetedId, targetedComment); params = new HashMap<>(); params.put("text", actionMore); break; default: return -1; } try { HttpsConnection httpsConnection = new HttpsConnection(context); switch (actionCall) { case "POST": httpsConnection.post(getAbsoluteUrl(action), 60, params, prefKeyOauthTokenT); break; case "DELETE": httpsConnection.delete(getAbsoluteUrl(action), 60, null, prefKeyOauthTokenT); break; default: httpsConnection.put(getAbsoluteUrl(action), 60, params, prefKeyOauthTokenT); break; } actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return actionCode; } /** * Video is in play lists * * @return APIResponse */ public APIResponse getPlaylistForVideo(String videoId) { HashMap params = new HashMap<>(); params.put("videoIds", videoId); List ids = new ArrayList<>(); try { String response = new HttpsConnection(context).get(getAbsoluteUrl("/users/me/video-playlists/videos-exist"), 60, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray(videoId); try { int i = 0; while (i < jsonArray.length()) { PlaylistElement playlistElement = new PlaylistElement(); JSONObject resobj = jsonArray.getJSONObject(i); playlistElement.setPlaylistId(resobj.getString("playlistId")); playlistElement.setPlaylistElementId(resobj.getString("playlistElementId")); ids.add(playlistElement); i++; } } catch (JSONException e) { setDefaultError(e); } } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse = new APIResponse(); apiResponse.setPlaylistForVideos(ids); return apiResponse; } /** * Get lists for the user * * @return APIResponse */ public APIResponse getPlayists(String username) { List playlists = new ArrayList<>(); try { String response = new HttpsConnection(context).get(getAbsoluteUrl(String.format("/accounts/%s/video-playlists", username)), 60, null, prefKeyOauthTokenT); playlists = parsePlaylists(context, new JSONObject(response).getJSONArray("data")); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPlaylists(playlists); return apiResponse; } /** * Create a Playlist * * @param playlistElement PlaylistElement, the playlist elements */ public String createPlaylist(PlaylistElement playlistElement) throws HttpsConnection.HttpsConnectionException { String playlistId = "-1"; try { HttpsConnection httpsConnection = new HttpsConnection(context); LinkedHashMap params = new LinkedHashMap<>(); params.put("displayName", playlistElement.getDisplayName()); params.put("privacy", playlistElement.getPrivacy()); params.put("videoChannelId", playlistElement.getVideoChannelId()); params.put("description", playlistElement.getDescription()); String response = httpsConnection.postBoundary(HttpsConnection.boundaryType.POST, getAbsoluteUrl("/video-playlists/"), 60, params, prefKeyOauthTokenT); playlistId = new JSONObject(response).getJSONObject("videoPlaylist").getString("id"); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return playlistId; } /** * Update a Playlist * * @param playlistElement PlaylistElement, the playlist elements */ public void updatePlaylist(PlaylistElement playlistElement) throws HttpsConnection.HttpsConnectionException { try { HttpsConnection httpsConnection = new HttpsConnection(context); LinkedHashMap params = new LinkedHashMap<>(); params.put("displayName", playlistElement.getDisplayName()); params.put("privacy", playlistElement.getPrivacy()); params.put("videoChannelId", playlistElement.getVideoChannelId()); params.put("description", playlistElement.getDescription()); httpsConnection.postBoundary(HttpsConnection.boundaryType.PUT, getAbsoluteUrl(String.format("/video-playlists/%s", playlistElement.getPlaylistId())), 60, params, prefKeyOauthTokenT); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } } /** * Delete a Playlist * * @param playlistId String, the playlist id * @return int */ public int deletePlaylist(String playlistId) { try { HttpsConnection httpsConnection = new HttpsConnection(context); httpsConnection.delete(getAbsoluteUrl(String.format("/video-playlists/%s", playlistId)), 60, null, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return actionCode; } /** * Delete video in a Playlist * * @param playlistId String, the playlist id * @param videoId String, the video id * @return int */ public int deleteVideoPlaylist(String playlistId, String videoId) { try { HttpsConnection httpsConnection = new HttpsConnection(context); httpsConnection.delete(getAbsoluteUrl(String.format("/video-playlists/%s/videos/%s", playlistId, videoId)), 60, null, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } return actionCode; } /** * Add video in a Playlist * * @param playlistId String, the playlist id * @param videoId String, the video id * @return int */ public int addVideoPlaylist(String playlistId, String videoId) { try { HttpsConnection httpsConnection = new HttpsConnection(context); HashMap params = new HashMap<>(); params.put("videoId", videoId); httpsConnection.post(getAbsoluteUrl(String.format("/video-playlists/%s/videos", playlistId)), 60, params, prefKeyOauthTokenT); actionCode = httpsConnection.getActionCode(); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | KeyManagementException | IOException e) { e.printStackTrace(); } return actionCode; } /** * Retrieves status for the account *synchronously* * * @param playlistid String Id of the playlist * @param max_id String id max * @param since_id String since the id * @return APIResponse */ @SuppressWarnings("SameParameterValue") public APIResponse getPlaylistVideos(String playlistid, String max_id, String since_id) { HashMap params = new HashMap<>(); if (max_id != null) params.put("start", max_id); if (since_id != null) params.put("since_id", since_id); params.put("count", String.valueOf(tootPerPage)); params.put("sort", "-updatedAt"); List peertubes = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl(String.format("/video-playlists/%s/videos", playlistid)), 60, params, prefKeyOauthTokenT); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(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) { List statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context); 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(instance, jsonObject); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setStatuses(statuses); return apiResponse; } /** * Retrieves peertube search *synchronously* * * @param query String search * @return APIResponse */ public APIResponse searchPeertube(String query, String max_id) { HashMap params = new HashMap<>(); params.put("count", "50"); if (max_id != null) params.put("start", max_id); 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); String response = httpsConnection.get("https://" + instance + "/api/v1/search/videos", 10, params, null); JSONArray jsonArray = new JSONObject(response).getJSONArray("data"); peertubes = parsePeertube(jsonArray); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPeertubes(peertubes); return apiResponse; } /** * Parse json response for peertube relationship * * @param jsonObject JSONObject * @return List */ private List parseRelationShip(ArrayList uris, JSONObject jsonObject) { List relationships = new ArrayList<>(); try { for (String uri : uris) { Relationship relationship = new Relationship(); relationship.setId(uri); relationship.setFollowing(jsonObject.getBoolean(uri)); relationships.add(relationship); } return relationships; } catch (JSONException e) { setDefaultError(e); } return null; } /** * Parse json response for peertube notifications * * @param jsonArray JSONArray * @return List */ private List parsePeertubeNotifications(JSONArray jsonArray) { List peertubeNotifications = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); PeertubeNotification peertubeNotification = parsePeertubeNotifications(resobj); i++; peertubeNotifications.add(peertubeNotification); } } catch (JSONException e) { setDefaultError(e); } return peertubeNotifications; } /** * Parse json response for several howto * * @param jsonArray JSONArray * @return List */ private List parsePeertube(JSONArray jsonArray) { List peertubes = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Peertube peertube = parsePeertube(resobj); i++; if (!BuildConfig.google_restriction || (peertube != null && (peertube.getName() == null || !peertube.getName().toLowerCase().contains("youtube video downloader")))) { peertubes.add(peertube); } } } catch (JSONException e) { setDefaultError(e); } return peertubes; } /** * 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")); } catch (JSONException e) { setDefaultError(e); } return instance; } /** * Parse Playlists * * @param jsonArray JSONArray * @return List of lists */ private List parsePlaylists(Context context, JSONArray jsonArray) { List playlists = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Playlist playlist = parsePlaylist(context, resobj); playlists.add(playlist); i++; } } catch (JSONException e) { setDefaultError(e); } return playlists; } private List parseBlockedAccountResponsePeertube(JSONArray jsonArray) { List accounts = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { if (jsonArray.getJSONObject(i).has("blockedAccount")) { JSONObject resobj = jsonArray.getJSONObject(i).getJSONObject("blockedAccount"); Account account = parseAccountResponsePeertube(resobj); accounts.add(account); } i++; } } catch (JSONException e) { setDefaultError(e); } return accounts; } private List parseAccountResponsePeertube(JSONArray jsonArray) { List accounts = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); Account account = parseAccountResponsePeertube(resobj); accounts.add(account); i++; } } catch (JSONException e) { setDefaultError(e); } return accounts; } 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).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).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 | HttpsConnection.HttpsConnectionException e) { e.printStackTrace(); } return instanceNodeInfo; } /** * 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() != null && 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 (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) { return Helper.instanceWithProtocol(context) + "/api/v1" + action; } @SuppressWarnings("SameParameterValue") private String getAbsoluteUrlForInstance(String instance, String action) { return "https://" + instance + "/api/v1" + action; } public enum reportType { ACCOUNT, COMMENT, VIDEO } public enum StatusAction { FOLLOW, UNFOLLOW, MUTE, UNMUTE, RATEVIDEO, PEERTUBECOMMENT, PEERTUBEREPLY, PEERTUBEDELETECOMMENT, PEERTUBEDELETEVIDEO, REPORT_ACCOUNT, REPORT_VIDEO } }