| package de.danoeh.antennapod.core.gpoddernet; |
| |
| import android.support.annotation.NonNull; |
| |
| import com.squareup.okhttp.Credentials; |
| import com.squareup.okhttp.MediaType; |
| import com.squareup.okhttp.OkHttpClient; |
| import com.squareup.okhttp.Request; |
| import com.squareup.okhttp.RequestBody; |
| import com.squareup.okhttp.Response; |
| import com.squareup.okhttp.ResponseBody; |
| |
| import org.json.JSONArray; |
| import org.json.JSONException; |
| import org.json.JSONObject; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.HttpURLConnection; |
| import java.net.MalformedURLException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import de.danoeh.antennapod.core.ClientConfig; |
| import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice; |
| import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction; |
| import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeActionGetResponse; |
| import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeActionPostResponse; |
| import de.danoeh.antennapod.core.gpoddernet.model.GpodnetPodcast; |
| import de.danoeh.antennapod.core.gpoddernet.model.GpodnetSubscriptionChange; |
| import de.danoeh.antennapod.core.gpoddernet.model.GpodnetTag; |
| import de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse; |
| import de.danoeh.antennapod.core.preferences.GpodnetPreferences; |
| import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; |
| |
| /** |
| * Communicates with the gpodder.net service. |
| */ |
| public class GpodnetService { |
| |
| private static final String TAG = "GpodnetService"; |
| |
| private static final String BASE_SCHEME = "https"; |
| |
| public static final String DEFAULT_BASE_HOST = "gpodder.net"; |
| private final String BASE_HOST; |
| |
| private static final MediaType TEXT = MediaType.parse("plain/text; charset=utf-8"); |
| private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); |
| |
| private final OkHttpClient httpClient; |
| |
| |
| public GpodnetService() { |
| httpClient = AntennapodHttpClient.getHttpClient(); |
| BASE_HOST = GpodnetPreferences.getHostname(); |
| } |
| |
| /** |
| * Returns the [count] most used tags. |
| */ |
| public List<GpodnetTag> getTopTags(int count) |
| throws GpodnetServiceException { |
| URL url; |
| try { |
| url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/api/2/tags/%d.json", count), null).toURL(); |
| } catch (MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| |
| Request.Builder request = new Request.Builder().url(url); |
| String response = executeRequest(request); |
| try { |
| JSONArray jsonTagList = new JSONArray(response); |
| List<GpodnetTag> tagList = new ArrayList<GpodnetTag>( |
| jsonTagList.length()); |
| for (int i = 0; i < jsonTagList.length(); i++) { |
| JSONObject jObj = jsonTagList.getJSONObject(i); |
| String title = jObj.getString("title"); |
| String tag = jObj.getString("tag"); |
| int usage = jObj.getInt("usage"); |
| tagList.add(new GpodnetTag(title, tag, usage)); |
| } |
| return tagList; |
| } catch (JSONException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| /** |
| * Returns the [count] most subscribed podcasts for the given tag. |
| * |
| * @throws IllegalArgumentException if tag is null |
| */ |
| public List<GpodnetPodcast> getPodcastsForTag(@NonNull GpodnetTag tag, |
| int count) |
| throws GpodnetServiceException { |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/api/2/tag/%s/%d.json", tag.getTag(), count), null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| String response = executeRequest(request); |
| |
| JSONArray jsonArray = new JSONArray(response); |
| return readPodcastListFromJSONArray(jsonArray); |
| |
| } catch (JSONException | MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| /** |
| * Returns the toplist of podcast. |
| * |
| * @param count of elements that should be returned. Must be in range 1..100. |
| * @throws IllegalArgumentException if count is out of range. |
| */ |
| public List<GpodnetPodcast> getPodcastToplist(int count) |
| throws GpodnetServiceException { |
| if(count < 1 || count > 100) { |
| throw new IllegalArgumentException("Count must be in range 1..100"); |
| } |
| |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/toplist/%d.json", count), null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| String response = executeRequest(request); |
| |
| JSONArray jsonArray = new JSONArray(response); |
| return readPodcastListFromJSONArray(jsonArray); |
| |
| } catch (JSONException | MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| /** |
| * Returns a list of suggested podcasts for the user that is currently |
| * logged in. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param count The |
| * number of elements that should be returned. Must be in range |
| * 1..100. |
| * @throws IllegalArgumentException if count is out of range. |
| * @throws GpodnetServiceAuthenticationException If there is an authentication error. |
| */ |
| public List<GpodnetPodcast> getSuggestions(int count) throws GpodnetServiceException { |
| if(count < 1 || count > 100) { |
| throw new IllegalArgumentException("Count must be in range 1..100"); |
| } |
| |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/suggestions/%d.json", count), null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| String response = executeRequest(request); |
| |
| JSONArray jsonArray = new JSONArray(response); |
| return readPodcastListFromJSONArray(jsonArray); |
| } catch (JSONException | MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| /** |
| * Searches the podcast directory for a given string. |
| * |
| * @param query The search query |
| * @param scaledLogoSize The size of the logos that are returned by the search query. |
| * Must be in range 1..256. If the value is out of range, the |
| * default value defined by the gpodder.net API will be used. |
| */ |
| public List<GpodnetPodcast> searchPodcasts(String query, int scaledLogoSize) |
| throws GpodnetServiceException { |
| String parameters = (scaledLogoSize > 0 && scaledLogoSize <= 256) ? String |
| .format("q=%s&scale_logo=%d", query, scaledLogoSize) : String |
| .format("q=%s", query); |
| try { |
| URL url = new URI(BASE_SCHEME, null, BASE_HOST, -1, "/search.json", |
| parameters, null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| String response = executeRequest(request); |
| |
| JSONArray jsonArray = new JSONArray(response); |
| return readPodcastListFromJSONArray(jsonArray); |
| |
| } catch (JSONException | MalformedURLException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } catch (URISyntaxException e) { |
| e.printStackTrace(); |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| /** |
| * Returns all devices of a given user. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param username The username. Must be the same user as the one which is |
| * currently logged in. |
| * @throws IllegalArgumentException If username is null. |
| * @throws GpodnetServiceAuthenticationException If there is an authentication error. |
| */ |
| public List<GpodnetDevice> getDevices(@NonNull String username) |
| throws GpodnetServiceException { |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/api/2/devices/%s.json", username), null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| String response = executeRequest(request); |
| JSONArray devicesArray = new JSONArray(response); |
| return readDeviceListFromJSONArray(devicesArray); |
| } catch (JSONException | MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| /** |
| * Configures the device of a given user. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param username The username. Must be the same user as the one which is |
| * currently logged in. |
| * @param deviceId The ID of the device that should be configured. |
| * @throws IllegalArgumentException If username or deviceId is null. |
| * @throws GpodnetServiceAuthenticationException If there is an authentication error. |
| */ |
| public void configureDevice(@NonNull String username, |
| @NonNull String deviceId, |
| String caption, |
| GpodnetDevice.DeviceType type) |
| throws GpodnetServiceException { |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/api/2/devices/%s/%s.json", username, deviceId), null).toURL(); |
| String content; |
| if (caption != null || type != null) { |
| JSONObject jsonContent = new JSONObject(); |
| if (caption != null) { |
| jsonContent.put("caption", caption); |
| } |
| if (type != null) { |
| jsonContent.put("type", type.toString()); |
| } |
| content = jsonContent.toString(); |
| } else { |
| content = ""; |
| } |
| RequestBody body = RequestBody.create(JSON, content); |
| Request.Builder request = new Request.Builder().post(body).url(url); |
| executeRequest(request); |
| } catch (JSONException | MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| /** |
| * Returns the subscriptions of a specific device. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param username The username. Must be the same user as the one which is |
| * currently logged in. |
| * @param deviceId The ID of the device whose subscriptions should be returned. |
| * @return A list of subscriptions in OPML format. |
| * @throws IllegalArgumentException If username or deviceId is null. |
| * @throws GpodnetServiceAuthenticationException If there is an authentication error. |
| */ |
| public String getSubscriptionsOfDevice(@NonNull String username, |
| @NonNull String deviceId) |
| throws GpodnetServiceException { |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/subscriptions/%s/%s.opml", username, deviceId), null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| return executeRequest(request); |
| } catch (MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| /** |
| * Returns all subscriptions of a specific user. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param username The username. Must be the same user as the one which is |
| * currently logged in. |
| * @return A list of subscriptions in OPML format. |
| * @throws IllegalArgumentException If username is null. |
| * @throws GpodnetServiceAuthenticationException If there is an authentication error. |
| */ |
| public String getSubscriptionsOfUser(@NonNull String username) |
| throws GpodnetServiceException { |
| |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/subscriptions/%s.opml", username), null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| String response = executeRequest(request); |
| return response; |
| } catch (MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| /** |
| * Uploads the subscriptions of a specific device. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param username The username. Must be the same user as the one which is |
| * currently logged in. |
| * @param deviceId The ID of the device whose subscriptions should be updated. |
| * @param subscriptions A list of feed URLs containing all subscriptions of the |
| * device. |
| * @throws IllegalArgumentException If username, deviceId or subscriptions is null. |
| * @throws GpodnetServiceAuthenticationException If there is an authentication error. |
| */ |
| public void uploadSubscriptions(@NonNull String username, |
| @NonNull String deviceId, |
| @NonNull List<String> subscriptions) |
| throws GpodnetServiceException { |
| |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/subscriptions/%s/%s.txt", username, deviceId), null).toURL(); |
| StringBuilder builder = new StringBuilder(); |
| for (String s : subscriptions) { |
| builder.append(s); |
| builder.append("\n"); |
| } |
| RequestBody body = RequestBody.create(TEXT, builder.toString()); |
| Request.Builder request = new Request.Builder().put(body).url(url); |
| executeRequest(request); |
| } catch (MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| |
| } |
| |
| /** |
| * Updates the subscription list of a specific device. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param username The username. Must be the same user as the one which is |
| * currently logged in. |
| * @param deviceId The ID of the device whose subscriptions should be updated. |
| * @param added Collection of feed URLs of added feeds. This Collection MUST NOT contain any duplicates |
| * @param removed Collection of feed URLs of removed feeds. This Collection MUST NOT contain any duplicates |
| * @return a GpodnetUploadChangesResponse. See {@link de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse} |
| * for details. |
| * @throws java.lang.IllegalArgumentException if username, deviceId, added or removed is null. |
| * @throws de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException if added or removed contain duplicates or if there |
| * is an authentication error. |
| */ |
| public GpodnetUploadChangesResponse uploadChanges(@NonNull String username, |
| @NonNull String deviceId, |
| @NonNull Collection<String> added, |
| @NonNull Collection<String> removed) |
| throws GpodnetServiceException { |
| |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/api/2/subscriptions/%s/%s.json", username, deviceId), null).toURL(); |
| |
| final JSONObject requestObject = new JSONObject(); |
| requestObject.put("add", new JSONArray(added)); |
| requestObject.put("remove", new JSONArray(removed)); |
| |
| RequestBody body = RequestBody.create(JSON, requestObject.toString()); |
| Request.Builder request = new Request.Builder().post(body).url(url); |
| |
| final String response = executeRequest(request); |
| return GpodnetUploadChangesResponse.fromJSONObject(response); |
| } catch (JSONException | MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| |
| } |
| |
| /** |
| * Returns all subscription changes of a specific device. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param username The username. Must be the same user as the one which is |
| * currently logged in. |
| * @param deviceId The ID of the device whose subscription changes should be |
| * downloaded. |
| * @param timestamp A timestamp that can be used to receive all changes since a |
| * specific point in time. |
| * @throws IllegalArgumentException If username or deviceId is null. |
| * @throws GpodnetServiceAuthenticationException If there is an authentication error. |
| */ |
| public GpodnetSubscriptionChange getSubscriptionChanges(@NonNull String username, |
| @NonNull String deviceId, |
| long timestamp) throws GpodnetServiceException { |
| |
| String params = String.format("since=%d", timestamp); |
| String path = String.format("/api/2/subscriptions/%s/%s.json", |
| username, deviceId); |
| try { |
| URL url = new URI(BASE_SCHEME, null, BASE_HOST, -1, path, params, |
| null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| |
| String response = executeRequest(request); |
| JSONObject changes = new JSONObject(response); |
| return readSubscriptionChangesFromJSONObject(changes); |
| } catch (URISyntaxException e) { |
| e.printStackTrace(); |
| throw new IllegalStateException(e); |
| } catch (JSONException | MalformedURLException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| |
| } |
| |
| /** |
| * Updates the episode actions |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param episodeActions Collection of episode actions. |
| * @return a GpodnetUploadChangesResponse. See {@link de.danoeh.antennapod.core.gpoddernet.model.GpodnetUploadChangesResponse} |
| * for details. |
| * @throws java.lang.IllegalArgumentException if username, deviceId, added or removed is null. |
| * @throws de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException if added or removed contain duplicates or if there |
| * is an authentication error. |
| */ |
| public GpodnetEpisodeActionPostResponse uploadEpisodeActions(@NonNull Collection<GpodnetEpisodeAction> episodeActions) |
| throws GpodnetServiceException { |
| |
| String username = GpodnetPreferences.getUsername(); |
| |
| try { |
| URL url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/api/2/episodes/%s.json", username), null).toURL(); |
| |
| final JSONArray list = new JSONArray(); |
| for(GpodnetEpisodeAction episodeAction : episodeActions) { |
| JSONObject obj = episodeAction.writeToJSONObject(); |
| if(obj != null) { |
| list.put(obj); |
| } |
| } |
| |
| RequestBody body = RequestBody.create(JSON, list.toString()); |
| Request.Builder request = new Request.Builder().post(body).url(url); |
| |
| final String response = executeRequest(request); |
| return GpodnetEpisodeActionPostResponse.fromJSONObject(response); |
| } catch (JSONException | MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| |
| } |
| |
| /** |
| * Returns all subscription changes of a specific device. |
| * <p/> |
| * This method requires authentication. |
| * |
| * @param timestamp A timestamp that can be used to receive all changes since a |
| * specific point in time. |
| * @throws IllegalArgumentException If username or deviceId is null. |
| * @throws GpodnetServiceAuthenticationException If there is an authentication error. |
| */ |
| public GpodnetEpisodeActionGetResponse getEpisodeChanges(long timestamp) throws GpodnetServiceException { |
| |
| String username = GpodnetPreferences.getUsername(); |
| |
| String params = String.format("since=%d", timestamp); |
| String path = String.format("/api/2/episodes/%s.json", |
| username); |
| try { |
| URL url = new URI(BASE_SCHEME, null, BASE_HOST, -1, path, params, |
| null).toURL(); |
| Request.Builder request = new Request.Builder().url(url); |
| |
| String response = executeRequest(request); |
| JSONObject json = new JSONObject(response); |
| return readEpisodeActionsFromJSONObject(json); |
| } catch (URISyntaxException e) { |
| e.printStackTrace(); |
| throw new IllegalStateException(e); |
| } catch (JSONException | MalformedURLException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| |
| } |
| |
| |
| /** |
| * Logs in a specific user. This method must be called if any of the methods |
| * that require authentication is used. |
| * |
| * @throws IllegalArgumentException If username or password is null. |
| */ |
| public void authenticate(@NonNull String username, |
| @NonNull String password) |
| throws GpodnetServiceException { |
| URL url; |
| try { |
| url = new URI(BASE_SCHEME, BASE_HOST, String.format( |
| "/api/2/auth/%s/login.json", username), null).toURL(); |
| } catch (MalformedURLException | URISyntaxException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| RequestBody body = RequestBody.create(TEXT, ""); |
| Request.Builder request = new Request.Builder().url(url).post(body); |
| executeRequestWithAuthentication(request, username, password); |
| } |
| |
| /** |
| * Shuts down the GpodnetService's HTTP client. The service will be shut down in a separate thread to avoid |
| * NetworkOnMainThreadExceptions. |
| */ |
| public void shutdown() { |
| new Thread() { |
| @Override |
| public void run() { |
| AntennapodHttpClient.cleanup(); |
| } |
| }.start(); |
| } |
| |
| private String executeRequest(@NonNull Request.Builder requestB) |
| throws GpodnetServiceException { |
| Request request = requestB.header("User-Agent", ClientConfig.USER_AGENT).build(); |
| String responseString = null; |
| Response response = null; |
| ResponseBody body = null; |
| try { |
| |
| response = httpClient.newCall(request).execute(); |
| checkStatusCode(response); |
| body = response.body(); |
| responseString = getStringFromResponseBody(body); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } finally { |
| if (response != null && body != null) { |
| try { |
| body.close(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| |
| } |
| return responseString; |
| } |
| |
| private String executeRequestWithAuthentication(Request.Builder requestB, |
| String username, String password) throws GpodnetServiceException { |
| if (requestB == null || username == null || password == null) { |
| throw new IllegalArgumentException( |
| "request and credentials must not be null"); |
| } |
| |
| Request request = requestB.header("User-Agent", ClientConfig.USER_AGENT).build(); |
| String result = null; |
| ResponseBody body = null; |
| try { |
| String credential = Credentials.basic(username, password); |
| Request authRequest = request.newBuilder().header("Authorization", credential).build(); |
| Response response = httpClient.newCall(authRequest).execute(); |
| checkStatusCode(response); |
| body = response.body(); |
| result = getStringFromResponseBody(body); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } finally { |
| if (body != null) { |
| try { |
| body.close(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| } |
| } |
| return result; |
| } |
| |
| private String getStringFromResponseBody(@NonNull ResponseBody body) |
| throws GpodnetServiceException { |
| ByteArrayOutputStream outputStream; |
| int contentLength = 0; |
| try { |
| contentLength = (int) body.contentLength(); |
| } catch (IOException ignore) { |
| // ignore |
| } |
| if (contentLength > 0) { |
| outputStream = new ByteArrayOutputStream(contentLength); |
| } else { |
| outputStream = new ByteArrayOutputStream(); |
| } |
| try { |
| byte[] buffer = new byte[8 * 1024]; |
| InputStream in = body.byteStream(); |
| int count; |
| while ((count = in.read(buffer)) > 0) { |
| outputStream.write(buffer, 0, count); |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| throw new GpodnetServiceException(e); |
| } |
| return outputStream.toString(); |
| } |
| |
| private void checkStatusCode(@NonNull Response response) |
| throws GpodnetServiceException { |
| int responseCode = response.code(); |
| if (responseCode != HttpURLConnection.HTTP_OK) { |
| if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) { |
| throw new GpodnetServiceAuthenticationException("Wrong username or password"); |
| } else { |
| throw new GpodnetServiceBadStatusCodeException("Bad response code: " |
| + responseCode, responseCode); |
| } |
| } |
| } |
| |
| private List<GpodnetPodcast> readPodcastListFromJSONArray(@NonNull JSONArray array) |
| throws JSONException { |
| List<GpodnetPodcast> result = new ArrayList<GpodnetPodcast>( |
| array.length()); |
| for (int i = 0; i < array.length(); i++) { |
| result.add(readPodcastFromJSONObject(array.getJSONObject(i))); |
| } |
| return result; |
| } |
| |
| private GpodnetPodcast readPodcastFromJSONObject(JSONObject object) |
| throws JSONException { |
| String url = object.getString("url"); |
| |
| String title; |
| Object titleObj = object.opt("title"); |
| if (titleObj != null && titleObj instanceof String) { |
| title = (String) titleObj; |
| } else { |
| title = url; |
| } |
| |
| String description; |
| Object descriptionObj = object.opt("description"); |
| if (descriptionObj != null && descriptionObj instanceof String) { |
| description = (String) descriptionObj; |
| } else { |
| description = ""; |
| } |
| |
| int subscribers = object.getInt("subscribers"); |
| |
| Object logoUrlObj = object.opt("logo_url"); |
| String logoUrl = (logoUrlObj instanceof String) ? (String) logoUrlObj |
| : null; |
| if (logoUrl == null) { |
| Object scaledLogoUrl = object.opt("scaled_logo_url"); |
| if (scaledLogoUrl != null && scaledLogoUrl instanceof String) { |
| logoUrl = (String) scaledLogoUrl; |
| } |
| } |
| |
| String website = null; |
| Object websiteObj = object.opt("website"); |
| if (websiteObj != null && websiteObj instanceof String) { |
| website = (String) websiteObj; |
| } |
| String mygpoLink = object.getString("mygpo_link"); |
| return new GpodnetPodcast(url, title, description, subscribers, |
| logoUrl, website, mygpoLink); |
| } |
| |
| private List<GpodnetDevice> readDeviceListFromJSONArray(@NonNull JSONArray array) |
| throws JSONException { |
| List<GpodnetDevice> result = new ArrayList<GpodnetDevice>( |
| array.length()); |
| for (int i = 0; i < array.length(); i++) { |
| result.add(readDeviceFromJSONObject(array.getJSONObject(i))); |
| } |
| return result; |
| } |
| |
| private GpodnetDevice readDeviceFromJSONObject(JSONObject object) |
| throws JSONException { |
| String id = object.getString("id"); |
| String caption = object.getString("caption"); |
| String type = object.getString("type"); |
| int subscriptions = object.getInt("subscriptions"); |
| return new GpodnetDevice(id, caption, type, subscriptions); |
| } |
| |
| private GpodnetSubscriptionChange readSubscriptionChangesFromJSONObject( |
| @NonNull JSONObject object) throws JSONException { |
| |
| List<String> added = new LinkedList<String>(); |
| JSONArray jsonAdded = object.getJSONArray("add"); |
| for (int i = 0; i < jsonAdded.length(); i++) { |
| String addedUrl = jsonAdded.getString(i); |
| // gpodder escapes colons unnecessarily |
| addedUrl = addedUrl.replace("%3A", ":"); |
| added.add(addedUrl); |
| } |
| |
| List<String> removed = new LinkedList<String>(); |
| JSONArray jsonRemoved = object.getJSONArray("remove"); |
| for (int i = 0; i < jsonRemoved.length(); i++) { |
| String removedUrl = jsonRemoved.getString(i); |
| // gpodder escapes colons unnecessarily |
| removedUrl = removedUrl.replace("%3A", ":"); |
| removed.add(removedUrl); |
| } |
| |
| long timestamp = object.getLong("timestamp"); |
| return new GpodnetSubscriptionChange(added, removed, timestamp); |
| } |
| |
| private GpodnetEpisodeActionGetResponse readEpisodeActionsFromJSONObject( |
| @NonNull JSONObject object) throws JSONException { |
| |
| List<GpodnetEpisodeAction> episodeActions = new ArrayList<GpodnetEpisodeAction>(); |
| |
| long timestamp = object.getLong("timestamp"); |
| JSONArray jsonActions = object.getJSONArray("actions"); |
| for(int i=0; i < jsonActions.length(); i++) { |
| JSONObject jsonAction = jsonActions.getJSONObject(i); |
| GpodnetEpisodeAction episodeAction = GpodnetEpisodeAction.readFromJSONObject(jsonAction); |
| if(episodeAction != null) { |
| episodeActions.add(episodeAction); |
| } |
| } |
| return new GpodnetEpisodeActionGetResponse(episodeActions, timestamp); |
| } |
| |
| } |