mirror of
https://github.com/AntennaPod/AntennaPod.git
synced 2026-03-13 09:25:12 +08:00
Remove fyydlin and connect directly (#8327)
### Description Remove fyydlin and connect directly. JitPack is not reliable. Because the fyydlin library is so simple, we don't really need it and can just connect directly to fyyd. This makes it possible to remove one library hosted on JitPack. Also taking the chance to make `PodcastSearchResult` independent from actual providers, so it becomes more of an interface/model class. ### Checklist <!-- To help us keep the issue tracker clean and work as efficient as possible, please make sure that you have done all of the following. You can tick the boxes below by placing an x inside the brackets like this: [x] --> - [x] I have read the contribution guidelines: https://github.com/AntennaPod/AntennaPod/blob/develop/CONTRIBUTING.md#submit-a-pull-request - [x] I have performed a self-review of my code, going through my changes line by line and carefully considering why this line change is necessary - [x] I have run the automated code checks using `./gradlew checkstyle spotbugsPlayDebug spotbugsDebug :app:lintPlayDebug` - [x] My code follows the style guidelines of the AntennaPod project: https://antennapod.org/contribute/develop/app/code-style - [x] I have mentioned the corresponding issue and the relevant keyword (e.g., "Closes: #xy") in the description (see https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) - [x] If it is a core feature, I have added automated tests
This commit is contained in:
committed by
GitHub
parent
95d3f37d25
commit
57e8ce6fbb
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,3 +29,4 @@ gradle.properties
|
||||
*.p12
|
||||
.vscode
|
||||
.cursor
|
||||
*.hprof
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
# RxJava
|
||||
-keep class io.reactivex.Single
|
||||
|
||||
#### Proguard rules for fyyd client
|
||||
-keep class de.mfietz.fyydlin.** { *; }
|
||||
# Retrofit 2.0
|
||||
-dontwarn retrofit2.**
|
||||
-keep class retrofit2.** { *; }
|
||||
|
||||
@@ -26,8 +26,6 @@ dependencies {
|
||||
|
||||
annotationProcessor "androidx.annotation:annotation:$annotationVersion"
|
||||
|
||||
implementation 'com.github.mfietz:fyydlin:e1d25f347641fe5e26c4c2b9756d4e9001a398dd'
|
||||
|
||||
implementation "io.reactivex.rxjava3:rxandroid:$rxAndroidVersion"
|
||||
implementation "io.reactivex.rxjava3:rxjava:$rxJavaVersion"
|
||||
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
||||
|
||||
@@ -1,35 +1,68 @@
|
||||
package de.danoeh.antennapod.net.discovery;
|
||||
|
||||
import de.danoeh.antennapod.net.common.AntennapodHttpClient;
|
||||
import de.mfietz.fyydlin.FyydClient;
|
||||
import de.mfietz.fyydlin.FyydResponse;
|
||||
import de.mfietz.fyydlin.SearchHit;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.SingleOnSubscribe;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
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.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FyydPodcastSearcher implements PodcastSearcher {
|
||||
private final FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient());
|
||||
private static final String FYYD_API_URL = "https://api.fyyd.de/0.2/search/podcast?title=%s&count=10";
|
||||
|
||||
public Single<List<PodcastSearchResult>> search(String query) {
|
||||
return Single.create((SingleOnSubscribe<List<PodcastSearchResult>>) subscriber -> {
|
||||
FyydResponse response = client.searchPodcasts(query, 10)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.blockingGet();
|
||||
|
||||
ArrayList<PodcastSearchResult> searchResults = new ArrayList<>();
|
||||
|
||||
if (!response.getData().isEmpty()) {
|
||||
for (SearchHit searchHit : response.getData()) {
|
||||
PodcastSearchResult podcast = PodcastSearchResult.fromFyyd(searchHit);
|
||||
searchResults.add(podcast);
|
||||
}
|
||||
String encodedQuery;
|
||||
try {
|
||||
encodedQuery = URLEncoder.encode(query, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
encodedQuery = query;
|
||||
}
|
||||
String formattedUrl = String.format(FYYD_API_URL, encodedQuery);
|
||||
|
||||
OkHttpClient client = AntennapodHttpClient.getHttpClient();
|
||||
Request.Builder httpReq = new Request.Builder().url(formattedUrl);
|
||||
ArrayList<PodcastSearchResult> searchResults = new ArrayList<>();
|
||||
try (Response response = client.newCall(httpReq.build()).execute()) {
|
||||
if (!response.isSuccessful()) {
|
||||
subscriber.onError(new IOException(response.toString()));
|
||||
return;
|
||||
}
|
||||
if (response.body() == null) {
|
||||
subscriber.onError(new IOException("Null response"));
|
||||
return;
|
||||
}
|
||||
String resultString = response.body().string();
|
||||
JSONObject result = new JSONObject(resultString);
|
||||
JSONArray data = result.optJSONArray("data");
|
||||
if (data == null) {
|
||||
subscriber.onError(new IOException("Null response"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < data.length(); i++) {
|
||||
JSONObject podcastJson = data.getJSONObject(i);
|
||||
String title = podcastJson.optString("title", "Unknown");
|
||||
String imageUrl = podcastJson.optString("thumbImageURL", "");
|
||||
String feedUrl = podcastJson.optString("xmlURL", "");
|
||||
String author = podcastJson.optString("author", "Unknown");
|
||||
searchResults.add(new PodcastSearchResult(title, imageUrl, feedUrl, author));
|
||||
}
|
||||
} catch (IOException | JSONException e) {
|
||||
subscriber.onError(e);
|
||||
return;
|
||||
}
|
||||
subscriber.onSuccess(searchResults);
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
@@ -54,10 +54,14 @@ public class ItunesPodcastSearcher implements PodcastSearcher {
|
||||
|
||||
for (int i = 0; i < j.length(); i++) {
|
||||
JSONObject podcastJson = j.getJSONObject(i);
|
||||
PodcastSearchResult podcast = PodcastSearchResult.fromItunes(podcastJson);
|
||||
if (podcast.feedUrl != null) {
|
||||
podcasts.add(podcast);
|
||||
if (!podcastJson.has("feedUrl")) {
|
||||
continue;
|
||||
}
|
||||
String title = podcastJson.optString("collectionName", "Unknown");
|
||||
String imageUrl = podcastJson.optString("artworkUrl100", "");
|
||||
String feedUrl = podcastJson.optString("feedUrl", "");
|
||||
String author = podcastJson.optString("artistName", "Unknown");
|
||||
podcasts.add(new PodcastSearchResult(title, imageUrl, feedUrl, author));
|
||||
}
|
||||
} else {
|
||||
subscriber.onError(new IOException(response.toString()));
|
||||
|
||||
@@ -108,10 +108,32 @@ public class ItunesTopListLoader {
|
||||
List<PodcastSearchResult> results = new ArrayList<>();
|
||||
for (int i = 0; i < entries.length(); i++) {
|
||||
JSONObject json = entries.getJSONObject(i);
|
||||
results.add(PodcastSearchResult.fromItunesToplist(json));
|
||||
results.add(toSearchResult(json));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static PodcastSearchResult toSearchResult(JSONObject json) throws JSONException {
|
||||
String title = json.getJSONObject("im:name").getString("label");
|
||||
String imageUrl = null;
|
||||
JSONArray images = json.getJSONArray("im:image");
|
||||
for (int i = 0; imageUrl == null && i < images.length(); i++) {
|
||||
JSONObject image = images.getJSONObject(i);
|
||||
String height = image.getJSONObject("attributes").getString("height");
|
||||
if (Integer.parseInt(height) >= 100) {
|
||||
imageUrl = image.getString("label");
|
||||
}
|
||||
}
|
||||
String feedUrl = "https://itunes.apple.com/lookup?id="
|
||||
+ json.getJSONObject("id").getJSONObject("attributes").getString("im:id");
|
||||
|
||||
String author = null;
|
||||
try {
|
||||
author = json.getJSONObject("im:artist").getString("label");
|
||||
} catch (Exception e) {
|
||||
// Some feeds have empty artist
|
||||
}
|
||||
return new PodcastSearchResult(title, imageUrl, feedUrl, author);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,10 +54,14 @@ public class PodcastIndexPodcastSearcher implements PodcastSearcher {
|
||||
|
||||
for (int i = 0; i < j.length(); i++) {
|
||||
JSONObject podcastJson = j.getJSONObject(i);
|
||||
PodcastSearchResult podcast = PodcastSearchResult.fromPodcastIndex(podcastJson);
|
||||
if (podcast.feedUrl != null) {
|
||||
podcasts.add(podcast);
|
||||
if (!podcastJson.has("url")) {
|
||||
continue;
|
||||
}
|
||||
String title = podcastJson.optString("title", "Unknown");
|
||||
String imageUrl = podcastJson.optString("image", "");
|
||||
String feedUrl = podcastJson.optString("url", "");
|
||||
String author = podcastJson.optString("author", "Unknown");
|
||||
podcasts.add(new PodcastSearchResult(title, imageUrl, feedUrl, author));
|
||||
}
|
||||
} else {
|
||||
subscriber.onError(new IOException(response.toString()));
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package de.danoeh.antennapod.net.discovery;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import de.mfietz.fyydlin.SearchHit;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class PodcastSearchResult {
|
||||
|
||||
@@ -31,7 +27,7 @@ public class PodcastSearchResult {
|
||||
public final String author;
|
||||
|
||||
|
||||
private PodcastSearchResult(String title, @Nullable String imageUrl, @Nullable String feedUrl, @Nullable String author) {
|
||||
public PodcastSearchResult(String title, @Nullable String imageUrl, @Nullable String feedUrl, @Nullable String author) {
|
||||
this.title = title;
|
||||
this.imageUrl = imageUrl;
|
||||
this.feedUrl = feedUrl;
|
||||
@@ -41,62 +37,4 @@ public class PodcastSearchResult {
|
||||
public static PodcastSearchResult dummy() {
|
||||
return new PodcastSearchResult("", "", "", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Podcast instance from a iTunes search result
|
||||
*
|
||||
* @param json object holding the podcast information
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static PodcastSearchResult fromItunes(JSONObject json) {
|
||||
String title = json.optString("collectionName", "");
|
||||
String imageUrl = json.optString("artworkUrl100", null);
|
||||
String feedUrl = json.optString("feedUrl", null);
|
||||
String author = json.optString("artistName", null);
|
||||
return new PodcastSearchResult(title, imageUrl, feedUrl, author);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Podcast instance from iTunes toplist entry
|
||||
*
|
||||
* @param json object holding the podcast information
|
||||
* @throws JSONException
|
||||
*/
|
||||
public static PodcastSearchResult fromItunesToplist(JSONObject json) throws JSONException {
|
||||
String title = json.getJSONObject("im:name").getString("label");
|
||||
String imageUrl = null;
|
||||
JSONArray images = json.getJSONArray("im:image");
|
||||
for(int i=0; imageUrl == null && i < images.length(); i++) {
|
||||
JSONObject image = images.getJSONObject(i);
|
||||
String height = image.getJSONObject("attributes").getString("height");
|
||||
if(Integer.parseInt(height) >= 100) {
|
||||
imageUrl = image.getString("label");
|
||||
}
|
||||
}
|
||||
String feedUrl = "https://itunes.apple.com/lookup?id=" +
|
||||
json.getJSONObject("id").getJSONObject("attributes").getString("im:id");
|
||||
|
||||
String author = null;
|
||||
try {
|
||||
author = json.getJSONObject("im:artist").getString("label");
|
||||
} catch (Exception e) {
|
||||
// Some feeds have empty artist
|
||||
}
|
||||
return new PodcastSearchResult(title, imageUrl, feedUrl, author);
|
||||
}
|
||||
|
||||
public static PodcastSearchResult fromFyyd(SearchHit searchHit) {
|
||||
return new PodcastSearchResult(searchHit.getTitle(),
|
||||
searchHit.getThumbImageURL(),
|
||||
searchHit.getXmlUrl(),
|
||||
searchHit.getAuthor());
|
||||
}
|
||||
|
||||
public static PodcastSearchResult fromPodcastIndex(JSONObject json) {
|
||||
String title = json.optString("title", "");
|
||||
String imageUrl = json.optString("image", null);
|
||||
String feedUrl = json.optString("url", null);
|
||||
String author = json.optString("author", null);
|
||||
return new PodcastSearchResult(title, imageUrl, feedUrl, author);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +42,6 @@
|
||||
website="https://github.com/google/ExoPlayer"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="fyydlin"
|
||||
author="Martin Fietz"
|
||||
website="https://github.com/mfietz/fyydlin"
|
||||
license="Apache 2.0"
|
||||
licenseText="LICENSE_APACHE-2.0.txt" />
|
||||
<library
|
||||
name="Glide"
|
||||
author="bumptech"
|
||||
|
||||
Reference in New Issue
Block a user