summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2021-04-24 16:18:02 +0200
committerByteHamster <info@bytehamster.com>2021-04-24 17:05:59 +0200
commite30533a810efa59bba6c101dd1405e776e1b451e (patch)
treecbeed0877116c02d04257dbc1380287bd0e3eb4b /core
parent7b5f29e090f34c0aae60c5e3d7a1c9288a7eda7a (diff)
downloadAntennaPod-e30533a810efa59bba6c101dd1405e776e1b451e.zip
Moved synchronization to its own module
Diffstat (limited to 'core')
-rw-r--r--core/build.gradle2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java18
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java826
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceAuthenticationException.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceException.java15
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetDevice.java73
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java49
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetPodcast.java72
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetTag.java66
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetUploadChangesResponse.java53
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java260
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java34
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/ISyncService.java20
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/SubscriptionChanges.java39
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/SyncServiceException.java13
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/model/UploadChangesResponse.java13
20 files changed, 15 insertions, 1565 deletions
diff --git a/core/build.gradle b/core/build.gradle
index e5ab13bcd..f9c09c7bc 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -75,6 +75,8 @@ android {
dependencies {
implementation project(':model')
implementation project(':net:ssl')
+ implementation project(':net:sync:gpoddernet')
+ implementation project(':net:sync:model')
implementation project(':ui:app-start-intent')
implementation project(':ui:common')
implementation project(':ui:png-icons')
diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java
index 209558b19..e338e0d01 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java
@@ -6,7 +6,7 @@ import android.util.Log;
import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.sync.SyncService;
-import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService;
+import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService;
/**
* Manages preferences for accessing gpodder.net service
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
index 2d0efd22a..8c9035621 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java
@@ -19,7 +19,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.sync.SyncService;
-import de.danoeh.antennapod.core.sync.model.EpisodeAction;
+import de.danoeh.antennapod.net.sync.model.EpisodeAction;
import org.greenrobot.eventbus.EventBus;
/**
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index cf3983910..3231c3779 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -8,7 +8,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import de.danoeh.antennapod.core.sync.SyncService;
-import de.danoeh.antennapod.core.sync.model.EpisodeAction;
+import de.danoeh.antennapod.net.sync.model.EpisodeAction;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
index 21b217e66..4736a2c33 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
@@ -32,17 +32,17 @@ import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
-import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.core.sync.model.EpisodeAction;
-import de.danoeh.antennapod.core.sync.model.EpisodeActionChanges;
-import de.danoeh.antennapod.core.sync.model.ISyncService;
-import de.danoeh.antennapod.core.sync.model.SubscriptionChanges;
-import de.danoeh.antennapod.core.sync.model.SyncServiceException;
-import de.danoeh.antennapod.core.sync.model.UploadChangesResponse;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.URLChecker;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
+import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService;
+import de.danoeh.antennapod.net.sync.model.EpisodeAction;
+import de.danoeh.antennapod.net.sync.model.EpisodeActionChanges;
+import de.danoeh.antennapod.net.sync.model.ISyncService;
+import de.danoeh.antennapod.net.sync.model.SubscriptionChanges;
+import de.danoeh.antennapod.net.sync.model.SyncServiceException;
+import de.danoeh.antennapod.net.sync.model.UploadChangesResponse;
import io.reactivex.Completable;
import io.reactivex.schedulers.Schedulers;
import org.apache.commons.lang3.StringUtils;
@@ -81,7 +81,9 @@ public class SyncService extends Worker {
if (!GpodnetPreferences.loggedIn()) {
return Result.success();
}
- syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHosturl());
+ syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(),
+ GpodnetPreferences.getHosturl(), GpodnetPreferences.getDeviceID(),
+ GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword());
SharedPreferences.Editor prefs = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
.edit();
prefs.putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, System.currentTimeMillis()).apply();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
deleted file mode 100644
index cd0fc93ea..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
+++ /dev/null
@@ -1,826 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet;
-
-import android.util.Log;
-import androidx.annotation.NonNull;
-import de.danoeh.antennapod.core.BuildConfig;
-import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
-import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetDevice;
-import de.danoeh.antennapod.core.sync.model.EpisodeAction;
-import de.danoeh.antennapod.core.sync.model.EpisodeActionChanges;
-import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetEpisodeActionPostResponse;
-import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast;
-import de.danoeh.antennapod.core.sync.model.ISyncService;
-import de.danoeh.antennapod.core.sync.model.SubscriptionChanges;
-import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetTag;
-import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetUploadChangesResponse;
-import de.danoeh.antennapod.core.sync.model.SyncServiceException;
-import de.danoeh.antennapod.core.sync.model.UploadChangesResponse;
-import okhttp3.Credentials;
-import okhttp3.MediaType;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.RequestBody;
-import okhttp3.Response;
-import okhttp3.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.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Communicates with the gpodder.net service.
- */
-public class GpodnetService implements ISyncService {
- public static final String TAG = "GpodnetService";
- public static final String DEFAULT_BASE_HOST = "gpodder.net";
- private static final int UPLOAD_BULK_SIZE = 30;
- 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 String baseScheme;
- private String baseHost;
- private int basePort;
-
- private final OkHttpClient httpClient;
- private String username = null;
-
- // split into schema, host and port - missing parts are null
- private static Pattern urlsplit_regex = Pattern.compile("(?:(https?)://)?([^:]+)(?::(\\d+))?");
-
- public GpodnetService(OkHttpClient httpClient, String baseHosturl) {
- this.httpClient = httpClient;
-
- Matcher m = urlsplit_regex.matcher(baseHosturl);
- if (m.matches()) {
- this.baseScheme = m.group(1);
- this.baseHost = m.group(2);
- if (m.group(3) == null) {
- this.basePort = -1;
- } else {
- this.basePort = Integer.parseInt(m.group(3)); // regex -> can only be digits
- }
- } else {
- // URL does not match regex: use it anyway -> this will cause an exception on connect
- this.baseScheme = "https";
- this.baseHost = baseHosturl;
- this.basePort = 443;
- }
-
- if (this.baseScheme == null) { // assume https
- this.baseScheme = "https";
- }
-
- if (this.baseScheme.equals("https") && this.basePort == -1) {
- this.basePort = 443;
- }
-
- if (this.baseScheme.equals("http") && this.basePort == -1) {
- this.basePort = 80;
- }
- }
-
- private void requireLoggedIn() {
- if (username == null) {
- throw new IllegalStateException("Not logged in");
- }
- }
-
- /**
- * Returns the [count] most used tags.
- */
- public List<GpodnetTag> getTopTags(int count) throws GpodnetServiceException {
- URL url;
- try {
- url = new URI(baseScheme, null, baseHost, basePort,
- String.format(Locale.US, "/api/2/tags/%d.json", count), null, 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<>(jsonTagList.length());
- for (int i = 0; i < jsonTagList.length(); i++) {
- JSONObject jsonObject = jsonTagList.getJSONObject(i);
- String title = jsonObject.getString("title");
- String tag = jsonObject.getString("tag");
- int usage = jsonObject.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(baseScheme, null, baseHost, basePort,
- String.format(Locale.US, "/api/2/tag/%s/%d.json", tag.getTag(), count), null, 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(baseScheme, null, baseHost, basePort,
- String.format(Locale.US, "/toplist/%d.json", count), null, 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(baseScheme, null, baseHost, basePort,
- String.format(Locale.US, "/suggestions/%d.json", count), null, 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(Locale.US, "q=%s&scale_logo=%d", query, scaledLogoSize) : String
- .format("q=%s", query);
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort, "/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.
- *
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public List<GpodnetDevice> getDevices() throws GpodnetServiceException {
- requireLoggedIn();
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/api/2/devices/%s.json", username), null, 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);
- }
- }
-
- /**
- * Returns synchronization status of devices.
- * <p/>
- * This method requires authentication.
- *
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public List<List<String>> getSynchronizedDevices() throws GpodnetServiceException {
- requireLoggedIn();
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/api/2/sync-devices/%s.json", username), null, null).toURL();
- Request.Builder request = new Request.Builder().url(url);
- String response = executeRequest(request);
- JSONObject syncStatus = new JSONObject(response);
- List<List<String>> result = new ArrayList<>();
-
- JSONArray synchronizedDevices = syncStatus.getJSONArray("synchronized");
- for (int i = 0; i < synchronizedDevices.length(); i++) {
- JSONArray groupDevices = synchronizedDevices.getJSONArray(i);
- List<String> group = new ArrayList<>();
- for (int j = 0; j < groupDevices.length(); j++) {
- group.add(groupDevices.getString(j));
- }
- result.add(group);
- }
-
- JSONArray notSynchronizedDevices = syncStatus.getJSONArray("not-synchronized");
- for (int i = 0; i < notSynchronizedDevices.length(); i++) {
- result.add(Collections.singletonList(notSynchronizedDevices.getString(i)));
- }
-
- return result;
- } catch (JSONException | MalformedURLException | URISyntaxException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- /**
- * Configures the device of a given user.
- * <p/>
- * This method requires authentication.
- *
- * @param deviceId The ID of the device that should be configured.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public void configureDevice(@NonNull String deviceId, String caption, GpodnetDevice.DeviceType type)
- throws GpodnetServiceException {
- requireLoggedIn();
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/api/2/devices/%s/%s.json", username, deviceId), null, 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);
- }
- }
-
- /**
- * Links devices for synchronization.
- * <p/>
- * This method requires authentication.
- *
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public void linkDevices(@NonNull List<String> deviceIds) throws GpodnetServiceException {
- requireLoggedIn();
- try {
- final URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/api/2/sync-devices/%s.json", username), null, null).toURL();
- JSONObject jsonContent = new JSONObject();
- JSONArray group = new JSONArray();
- for (String deviceId : deviceIds) {
- group.put(deviceId);
- }
-
- JSONArray synchronizedGroups = new JSONArray();
- synchronizedGroups.put(group);
- jsonContent.put("synchronize", synchronizedGroups);
- jsonContent.put("stop-synchronize", new JSONArray());
-
- Log.d("aaaa", jsonContent.toString());
- RequestBody body = RequestBody.create(JSON, jsonContent.toString());
- 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 deviceId The ID of the device whose subscriptions should be returned.
- * @return A list of subscriptions in OPML format.
- * @throws GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public String getSubscriptionsOfDevice(@NonNull String deviceId) throws GpodnetServiceException {
- requireLoggedIn();
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/subscriptions/%s/%s.opml", username, deviceId), null, 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.
- *
- * @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() throws GpodnetServiceException {
- requireLoggedIn();
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/subscriptions/%s.opml", username), null, null).toURL();
- Request.Builder request = new Request.Builder().url(url);
- return executeRequest(request);
- } catch (MalformedURLException | URISyntaxException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- /**
- * Uploads the subscriptions of a specific device.
- * <p/>
- * This method requires authentication.
- *
- * @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 deviceId, @NonNull List<String> subscriptions)
- throws GpodnetServiceException {
- requireLoggedIn();
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/subscriptions/%s/%s.txt", username, deviceId), null, 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 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 GpodnetUploadChangesResponse}
- * for details.
- * @throws GpodnetServiceException if added or removed contain duplicates or if there
- * is an authentication error.
- */
- public GpodnetUploadChangesResponse uploadChanges(@NonNull String deviceId, @NonNull Collection<String> added,
- @NonNull Collection<String> removed) throws GpodnetServiceException {
- requireLoggedIn();
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/api/2/subscriptions/%s/%s.json", username, deviceId), null, 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 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 GpodnetServiceAuthenticationException If there is an authentication error.
- */
- public SubscriptionChanges getSubscriptionChanges(@NonNull String deviceId, long timestamp)
- throws GpodnetServiceException {
- requireLoggedIn();
- String params = String.format(Locale.US, "since=%d", timestamp);
- String path = String.format("/api/2/subscriptions/%s/%s.json", username, deviceId);
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort, 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 GpodnetUploadChangesResponse}
- * for details.
- * @throws GpodnetServiceException if added or removed contain duplicates or if there
- * is an authentication error.
- */
- @Override
- public UploadChangesResponse uploadEpisodeActions(List<EpisodeAction> episodeActions) throws SyncServiceException {
- requireLoggedIn();
- UploadChangesResponse response = null;
- for (int i = 0; i < episodeActions.size(); i += UPLOAD_BULK_SIZE) {
- response = uploadEpisodeActionsPartial(episodeActions,
- i, Math.min(episodeActions.size(), i + UPLOAD_BULK_SIZE));
- }
- return response;
- }
-
- private UploadChangesResponse uploadEpisodeActionsPartial(List<EpisodeAction> episodeActions, int from, int to)
- throws SyncServiceException {
- try {
- Log.d(TAG, "Uploading partial actions " + from + " to " + to + " of " + episodeActions.size());
- URL url = new URI(baseScheme, null, baseHost, basePort,
- String.format("/api/2/episodes/%s.json", username), null, null).toURL();
-
- final JSONArray list = new JSONArray();
- for (int i = from; i < to; i++) {
- EpisodeAction episodeAction = episodeActions.get(i);
- JSONObject obj = episodeAction.writeToJsonObject();
- if (obj != null) {
- obj.put("device", GpodnetPreferences.getDeviceID());
- 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 SyncServiceException(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 SyncServiceException If there is an authentication error.
- */
- @Override
- public EpisodeActionChanges getEpisodeActionChanges(long timestamp) throws SyncServiceException {
- requireLoggedIn();
- String params = String.format(Locale.US, "since=%d", timestamp);
- String path = String.format("/api/2/episodes/%s.json", username);
- try {
- URL url = new URI(baseScheme, null, baseHost, basePort, 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 SyncServiceException(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(baseScheme, null, baseHost, basePort,
- String.format("/api/2/auth/%s/login.json", username), null, null).toURL();
- } catch (MalformedURLException | URISyntaxException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- RequestBody requestBody = RequestBody.create(TEXT, "");
- Request request = new Request.Builder().url(url).post(requestBody).build();
- try {
- String credential = Credentials.basic(username, password, Charset.forName("UTF-8"));
- Request authRequest = request.newBuilder().header("Authorization", credential).build();
- Response response = httpClient.newCall(authRequest).execute();
- checkStatusCode(response);
- response.body().close();
- this.username = username;
- } catch (Exception e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- private String executeRequest(@NonNull Request.Builder requestB) throws GpodnetServiceException {
- Request request = requestB.build();
- String responseString;
- Response response;
- 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 (body != null) {
- body.close();
- }
- }
- return responseString;
- }
-
- private String getStringFromResponseBody(@NonNull ResponseBody body) throws GpodnetServiceException {
- ByteArrayOutputStream outputStream;
- int contentLength = (int) body.contentLength();
- 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);
- }
- return outputStream.toString("UTF-8");
- } catch (IOException e) {
- e.printStackTrace();
- throw new GpodnetServiceException(e);
- }
- }
-
- 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 {
- if (BuildConfig.DEBUG) {
- try {
- Log.d(TAG, response.body().string());
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- throw new GpodnetServiceBadStatusCodeException("Bad response code: " + responseCode, responseCode);
- }
- }
- }
-
- private List<GpodnetPodcast> readPodcastListFromJsonArray(@NonNull JSONArray array) throws JSONException {
- List<GpodnetPodcast> result = new ArrayList<>(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 instanceof String) {
- title = (String) titleObj;
- } else {
- title = url;
- }
-
- String description;
- Object descriptionObj = object.opt("description");
- if (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 instanceof String) {
- logoUrl = (String) scaledLogoUrl;
- }
- }
-
- String website = null;
- Object websiteObj = object.opt("website");
- if (websiteObj instanceof String) {
- website = (String) websiteObj;
- }
- String mygpoLink = object.getString("mygpo_link");
-
- String author = null;
- Object authorObj = object.opt("author");
- if (authorObj instanceof String) {
- author = (String) authorObj;
- }
- return new GpodnetPodcast(url, title, description, subscribers, logoUrl, website, mygpoLink, author);
- }
-
- private List<GpodnetDevice> readDeviceListFromJsonArray(@NonNull JSONArray array) throws JSONException {
- List<GpodnetDevice> result = new ArrayList<>(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 SubscriptionChanges readSubscriptionChangesFromJsonObject(@NonNull JSONObject object)
- throws JSONException {
-
- List<String> added = new LinkedList<>();
- 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<>();
- 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 SubscriptionChanges(added, removed, timestamp);
- }
-
- private EpisodeActionChanges readEpisodeActionsFromJsonObject(@NonNull JSONObject object)
- throws JSONException {
-
- List<EpisodeAction> episodeActions = new ArrayList<>();
-
- long timestamp = object.getLong("timestamp");
- JSONArray jsonActions = object.getJSONArray("actions");
- for (int i = 0; i < jsonActions.length(); i++) {
- JSONObject jsonAction = jsonActions.getJSONObject(i);
- EpisodeAction episodeAction = EpisodeAction.readFromJsonObject(jsonAction);
- if (episodeAction != null) {
- episodeActions.add(episodeAction);
- }
- }
- return new EpisodeActionChanges(episodeActions, timestamp);
- }
-
- @Override
- public void login() throws GpodnetServiceException {
- authenticate(GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword());
- }
-
- @Override
- public SubscriptionChanges getSubscriptionChanges(long lastSync) throws GpodnetServiceException {
- return getSubscriptionChanges(GpodnetPreferences.getDeviceID(), lastSync);
- }
-
- @Override
- public UploadChangesResponse uploadSubscriptionChanges(List<String> addedFeeds, List<String> removedFeeds)
- throws GpodnetServiceException {
- return uploadChanges(GpodnetPreferences.getDeviceID(), addedFeeds, removedFeeds);
- }
-
- @Override
- public void logout() {
-
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceAuthenticationException.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceAuthenticationException.java
deleted file mode 100644
index 0aec8e97e..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceAuthenticationException.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet;
-
-public class GpodnetServiceAuthenticationException extends GpodnetServiceException {
- private static final long serialVersionUID = 1L;
-
- public GpodnetServiceAuthenticationException(String message) {
- super(message);
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java
deleted file mode 100644
index c24b5fc0a..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet;
-
-class GpodnetServiceBadStatusCodeException extends GpodnetServiceException {
- private static final long serialVersionUID = 1L;
-
- private final int statusCode;
-
- public GpodnetServiceBadStatusCodeException(String message, int statusCode) {
- super(message);
- this.statusCode = statusCode;
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceException.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceException.java
deleted file mode 100644
index 10c4fdc11..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceException.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet;
-
-import de.danoeh.antennapod.core.sync.model.SyncServiceException;
-
-public class GpodnetServiceException extends SyncServiceException {
- private static final long serialVersionUID = 1L;
-
- public GpodnetServiceException(String message) {
- super(message);
- }
-
- public GpodnetServiceException(Throwable e) {
- super(e);
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetDevice.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetDevice.java
deleted file mode 100644
index 454b3301d..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetDevice.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet.model;
-
-import androidx.annotation.NonNull;
-
-public class GpodnetDevice {
-
- private final String id;
- private final String caption;
- private final DeviceType type;
- private final int subscriptions;
-
- public GpodnetDevice(@NonNull String id,
- String caption,
- String type,
- int subscriptions) {
- this.id = id;
- this.caption = caption;
- this.type = DeviceType.fromString(type);
- this.subscriptions = subscriptions;
- }
-
- @Override
- public String toString() {
- return "GpodnetDevice [id=" + id + ", caption=" + caption + ", type="
- + type + ", subscriptions=" + subscriptions + "]";
- }
-
- public enum DeviceType {
- DESKTOP, LAPTOP, MOBILE, SERVER, OTHER;
-
- static DeviceType fromString(String s) {
- if (s == null) {
- return OTHER;
- }
-
- switch (s) {
- case "desktop":
- return DESKTOP;
- case "laptop":
- return LAPTOP;
- case "mobile":
- return MOBILE;
- case "server":
- return SERVER;
- default:
- return OTHER;
- }
- }
-
- @Override
- public String toString() {
- return super.toString().toLowerCase();
- }
-
- }
-
- public String getId() {
- return id;
- }
-
- public String getCaption() {
- return caption;
- }
-
- public DeviceType getType() {
- return type;
- }
-
- public int getSubscriptions() {
- return subscriptions;
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java
deleted file mode 100644
index ae9ab9d70..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet.model;
-
-import androidx.collection.ArrayMap;
-
-import de.danoeh.antennapod.core.sync.model.UploadChangesResponse;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.Map;
-
-public class GpodnetEpisodeActionPostResponse extends UploadChangesResponse {
- /**
- * URLs that should be updated. The key of the map is the original URL, the value of the map
- * is the sanitized URL.
- */
- private final Map<String, String> updatedUrls;
-
- private GpodnetEpisodeActionPostResponse(long timestamp, Map<String, String> updatedUrls) {
- super(timestamp);
- this.updatedUrls = updatedUrls;
- }
-
- /**
- * Creates a new GpodnetUploadChangesResponse-object from a JSON object that was
- * returned by an uploadChanges call.
- *
- * @throws org.json.JSONException If the method could not parse the JSONObject.
- */
- public static GpodnetEpisodeActionPostResponse fromJSONObject(String objectString) throws JSONException {
- final JSONObject object = new JSONObject(objectString);
- final long timestamp = object.getLong("timestamp");
- JSONArray urls = object.getJSONArray("update_urls");
- Map<String, String> updatedUrls = new ArrayMap<>(urls.length());
- for (int i = 0; i < urls.length(); i++) {
- JSONArray urlPair = urls.getJSONArray(i);
- updatedUrls.put(urlPair.getString(0), urlPair.getString(1));
- }
- return new GpodnetEpisodeActionPostResponse(timestamp, updatedUrls);
- }
-
- @Override
- public String toString() {
- return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
- }
-}
-
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetPodcast.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetPodcast.java
deleted file mode 100644
index bc4969758..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetPodcast.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet.model;
-
-import androidx.annotation.NonNull;
-
-public class GpodnetPodcast {
- private final String url;
- private final String title;
- private final String description;
- private final int subscribers;
- private final String logoUrl;
- private final String website;
- private final String mygpoLink;
- private final String author;
-
- public GpodnetPodcast(@NonNull String url,
- @NonNull String title,
- @NonNull String description,
- int subscribers,
- String logoUrl,
- String website,
- String mygpoLink,
- String author
- ) {
- this.url = url;
- this.title = title;
- this.description = description;
- this.subscribers = subscribers;
- this.logoUrl = logoUrl;
- this.website = website;
- this.mygpoLink = mygpoLink;
- this.author = author;
- }
-
- @Override
- public String toString() {
- return "GpodnetPodcast [url=" + url + ", title=" + title
- + ", description=" + description + ", subscribers="
- + subscribers + ", logoUrl=" + logoUrl + ", website=" + website
- + ", mygpoLink=" + mygpoLink + "]";
- }
-
- public String getUrl() {
- return url;
- }
-
- public String getTitle() {
- return title;
- }
-
- public String getDescription() {
- return description;
- }
-
- public int getSubscribers() {
- return subscribers;
- }
-
- public String getLogoUrl() {
- return logoUrl;
- }
-
- public String getWebsite() {
- return website;
- }
-
- public String getAuthor() { return author; }
-
- public String getMygpoLink() {
- return mygpoLink;
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetTag.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetTag.java
deleted file mode 100644
index 93abf4688..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetTag.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet.model;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import androidx.annotation.NonNull;
-
-public class GpodnetTag implements Parcelable {
-
- private final String title;
- private final String tag;
- private final int usage;
-
- public GpodnetTag(@NonNull String title, @NonNull String tag, int usage) {
- this.title = title;
- this.tag = tag;
- this.usage = usage;
- }
-
- private GpodnetTag(Parcel in) {
- title = in.readString();
- tag = in.readString();
- usage = in.readInt();
- }
-
- @Override
- public String toString() {
- return "GpodnetTag [title="+title+", tag=" + tag + ", usage=" + usage + "]";
- }
-
- public String getTitle() {
- return title;
- }
-
- public String getTag() {
- return tag;
- }
-
- public int getUsage() {
- return usage;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(title);
- dest.writeString(tag);
- dest.writeInt(usage);
- }
-
- public static final Creator<GpodnetTag> CREATOR = new Creator<GpodnetTag>() {
- @Override
- public GpodnetTag createFromParcel(Parcel in) {
- return new GpodnetTag(in);
- }
-
- @Override
- public GpodnetTag[] newArray(int size) {
- return new GpodnetTag[size];
- }
- };
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetUploadChangesResponse.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetUploadChangesResponse.java
deleted file mode 100644
index 790ba547f..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetUploadChangesResponse.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package de.danoeh.antennapod.core.sync.gpoddernet.model;
-
-import androidx.collection.ArrayMap;
-
-import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService;
-import de.danoeh.antennapod.core.sync.model.UploadChangesResponse;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.Map;
-
-/**
- * Object returned by {@link GpodnetService} in uploadChanges method.
- */
-public class GpodnetUploadChangesResponse extends UploadChangesResponse {
- /**
- * URLs that should be updated. The key of the map is the original URL, the value of the map
- * is the sanitized URL.
- */
- public final Map<String, String> updatedUrls;
-
- public GpodnetUploadChangesResponse(long timestamp, Map<String, String> updatedUrls) {
- super(timestamp);
- this.updatedUrls = updatedUrls;
- }
-
- /**
- * Creates a new GpodnetUploadChangesResponse-object from a JSON object that was
- * returned by an uploadChanges call.
- *
- * @throws org.json.JSONException If the method could not parse the JSONObject.
- */
- public static GpodnetUploadChangesResponse fromJSONObject(String objectString) throws JSONException {
- final JSONObject object = new JSONObject(objectString);
- final long timestamp = object.getLong("timestamp");
- Map<String, String> updatedUrls = new ArrayMap<>();
- JSONArray urls = object.getJSONArray("update_urls");
- for (int i = 0; i < urls.length(); i++) {
- JSONArray urlPair = urls.getJSONArray(i);
- updatedUrls.put(urlPair.getString(0), urlPair.getString(1));
- }
- return new GpodnetUploadChangesResponse(timestamp, updatedUrls);
- }
-
- @Override
- public String toString() {
- return "GpodnetUploadChangesResponse{" +
- "timestamp=" + timestamp +
- ", updatedUrls=" + updatedUrls +
- '}';
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java
deleted file mode 100644
index 7a97b7755..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java
+++ /dev/null
@@ -1,260 +0,0 @@
-package de.danoeh.antennapod.core.sync.model;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.core.util.ObjectsCompat;
-import de.danoeh.antennapod.model.feed.FeedItem;
-import de.danoeh.antennapod.core.util.DateUtils;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
-public class EpisodeAction {
- private static final String TAG = "EpisodeAction";
- public static final Action NEW = Action.NEW;
- public static final Action DOWNLOAD = Action.DOWNLOAD;
- public static final Action PLAY = Action.PLAY;
- public static final Action DELETE = Action.DELETE;
-
- private final String podcast;
- private final String episode;
- private final Action action;
- private final Date timestamp;
- private final int started;
- private final int position;
- private final int total;
-
- private EpisodeAction(Builder builder) {
- this.podcast = builder.podcast;
- this.episode = builder.episode;
- this.action = builder.action;
- this.timestamp = builder.timestamp;
- this.started = builder.started;
- this.position = builder.position;
- this.total = builder.total;
- }
-
- /**
- * Create an episode action object from JSON representation. Mandatory fields are "podcast",
- * "episode" and "action".
- *
- * @param object JSON representation
- * @return episode action object, or null if mandatory values are missing
- */
- public static EpisodeAction readFromJsonObject(JSONObject object) {
- String podcast = object.optString("podcast", null);
- String episode = object.optString("episode", null);
- String actionString = object.optString("action", null);
- if (TextUtils.isEmpty(podcast) || TextUtils.isEmpty(episode) || TextUtils.isEmpty(actionString)) {
- return null;
- }
- EpisodeAction.Action action;
- try {
- action = EpisodeAction.Action.valueOf(actionString.toUpperCase());
- } catch (IllegalArgumentException e) {
- return null;
- }
- EpisodeAction.Builder builder = new EpisodeAction.Builder(podcast, episode, action);
- String utcTimestamp = object.optString("timestamp", null);
- if (!TextUtils.isEmpty(utcTimestamp)) {
- builder.timestamp(DateUtils.parse(utcTimestamp));
- }
- if (action == EpisodeAction.Action.PLAY) {
- int started = object.optInt("started", -1);
- int position = object.optInt("position", -1);
- int total = object.optInt("total", -1);
- if (started >= 0 && position > 0 && total > 0) {
- builder
- .started(started)
- .position(position)
- .total(total);
- }
- }
- return builder.build();
- }
-
- public String getPodcast() {
- return this.podcast;
- }
-
- public String getEpisode() {
- return this.episode;
- }
-
- public Action getAction() {
- return this.action;
- }
-
- private String getActionString() {
- return this.action.name().toLowerCase();
- }
-
- public Date getTimestamp() {
- return this.timestamp;
- }
-
- /**
- * Returns the position (in seconds) at which the client started playback.
- *
- * @return start position (in seconds)
- */
- public int getStarted() {
- return this.started;
- }
-
- /**
- * Returns the position (in seconds) at which the client stopped playback.
- *
- * @return stop position (in seconds)
- */
- public int getPosition() {
- return this.position;
- }
-
- /**
- * Returns the total length of the file in seconds.
- *
- * @return total length in seconds
- */
- public int getTotal() {
- return this.total;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof EpisodeAction)) {
- return false;
- }
-
- EpisodeAction that = (EpisodeAction) o;
- return started == that.started && position == that.position && total == that.total && action != that.action
- && ObjectsCompat.equals(podcast, that.podcast)
- && ObjectsCompat.equals(episode, that.episode)
- && ObjectsCompat.equals(timestamp, that.timestamp);
- }
-
- @Override
- public int hashCode() {
- int result = podcast != null ? podcast.hashCode() : 0;
- result = 31 * result + (episode != null ? episode.hashCode() : 0);
- result = 31 * result + (action != null ? action.hashCode() : 0);
- result = 31 * result + (timestamp != null ? timestamp.hashCode() : 0);
- result = 31 * result + started;
- result = 31 * result + position;
- result = 31 * result + total;
- return result;
- }
-
- /**
- * Returns a JSON object representation of this object.
- *
- * @return JSON object representation, or null if the object is invalid
- */
- public JSONObject writeToJsonObject() {
- JSONObject obj = new JSONObject();
- try {
- obj.putOpt("podcast", this.podcast);
- obj.putOpt("episode", this.episode);
- obj.put("action", this.getActionString());
- SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
- formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
- obj.put("timestamp", formatter.format(this.timestamp));
- if (this.getAction() == Action.PLAY) {
- obj.put("started", this.started);
- obj.put("position", this.position);
- obj.put("total", this.total);
- }
- } catch (JSONException e) {
- Log.e(TAG, "writeToJSONObject(): " + e.getMessage());
- return null;
- }
- return obj;
- }
-
- @NonNull
- @Override
- public String toString() {
- return "EpisodeAction{"
- + "podcast='" + podcast + '\''
- + ", episode='" + episode + '\''
- + ", action=" + action
- + ", timestamp=" + timestamp
- + ", started=" + started
- + ", position=" + position
- + ", total=" + total
- + '}';
- }
-
- public enum Action {
- NEW, DOWNLOAD, PLAY, DELETE
- }
-
- public static class Builder {
-
- // mandatory
- private final String podcast;
- private final String episode;
- private final Action action;
-
- // optional
- private Date timestamp;
- private int started = -1;
- private int position = -1;
- private int total = -1;
-
- public Builder(FeedItem item, Action action) {
- this(item.getFeed().getDownload_url(), item.getMedia().getDownload_url(), action);
- }
-
- public Builder(String podcast, String episode, Action action) {
- this.podcast = podcast;
- this.episode = episode;
- this.action = action;
- }
-
- public Builder timestamp(Date timestamp) {
- this.timestamp = timestamp;
- return this;
- }
-
- public Builder currentTimestamp() {
- return timestamp(new Date());
- }
-
- public Builder started(int seconds) {
- if (action == Action.PLAY) {
- this.started = seconds;
- }
- return this;
- }
-
- public Builder position(int seconds) {
- if (action == Action.PLAY) {
- this.position = seconds;
- }
- return this;
- }
-
- public Builder total(int seconds) {
- if (action == Action.PLAY) {
- this.total = seconds;
- }
- return this;
- }
-
- public EpisodeAction build() {
- return new EpisodeAction(this);
- }
-
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java
deleted file mode 100644
index 90af585af..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package de.danoeh.antennapod.core.sync.model;
-
-
-import androidx.annotation.NonNull;
-
-import java.util.List;
-
-public class EpisodeActionChanges {
-
- private final List<EpisodeAction> episodeActions;
- private final long timestamp;
-
- public EpisodeActionChanges(@NonNull List<EpisodeAction> episodeActions, long timestamp) {
- this.episodeActions = episodeActions;
- this.timestamp = timestamp;
- }
-
- public List<EpisodeAction> getEpisodeActions() {
- return this.episodeActions;
- }
-
- public long getTimestamp() {
- return this.timestamp;
- }
-
- @NonNull
- @Override
- public String toString() {
- return "EpisodeActionGetResponse{"
- + "episodeActions=" + episodeActions
- + ", timestamp=" + timestamp
- + '}';
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/ISyncService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/ISyncService.java
deleted file mode 100644
index 473072b97..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/ISyncService.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package de.danoeh.antennapod.core.sync.model;
-
-import java.util.List;
-
-public interface ISyncService {
-
- void login() throws SyncServiceException;
-
- SubscriptionChanges getSubscriptionChanges(long lastSync) throws SyncServiceException;
-
- UploadChangesResponse uploadSubscriptionChanges(
- List<String> addedFeeds, List<String> removedFeeds) throws SyncServiceException;
-
- EpisodeActionChanges getEpisodeActionChanges(long lastSync) throws SyncServiceException;
-
- UploadChangesResponse uploadEpisodeActions(List<EpisodeAction> queuedEpisodeActions)
- throws SyncServiceException;
-
- void logout() throws SyncServiceException;
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/SubscriptionChanges.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/SubscriptionChanges.java
deleted file mode 100644
index 51f2ed10d..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/SubscriptionChanges.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package de.danoeh.antennapod.core.sync.model;
-
-import androidx.annotation.NonNull;
-
-import java.util.List;
-
-public class SubscriptionChanges {
- private final List<String> added;
- private final List<String> removed;
- private final long timestamp;
-
- public SubscriptionChanges(@NonNull List<String> added,
- @NonNull List<String> removed,
- long timestamp) {
- this.added = added;
- this.removed = removed;
- this.timestamp = timestamp;
- }
-
- @Override
- public String toString() {
- return "SubscriptionChange [added=" + added.toString()
- + ", removed=" + removed.toString() + ", timestamp="
- + timestamp + "]";
- }
-
- public List<String> getAdded() {
- return added;
- }
-
- public List<String> getRemoved() {
- return removed;
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/SyncServiceException.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/SyncServiceException.java
deleted file mode 100644
index d7e999b45..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/SyncServiceException.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package de.danoeh.antennapod.core.sync.model;
-
-public class SyncServiceException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public SyncServiceException(String message) {
- super(message);
- }
-
- public SyncServiceException(Throwable cause) {
- super(cause);
- }
-}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/UploadChangesResponse.java b/core/src/main/java/de/danoeh/antennapod/core/sync/model/UploadChangesResponse.java
deleted file mode 100644
index 44850bb03..000000000
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/UploadChangesResponse.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package de.danoeh.antennapod.core.sync.model;
-
-public abstract class UploadChangesResponse {
-
- /**
- * timestamp/ID that can be used for requesting changes since this upload.
- */
- public final long timestamp;
-
- public UploadChangesResponse(long timestamp) {
- this.timestamp = timestamp;
- }
-}