Skip to content

Commit 78141cb

Browse files
committed
With media client APIs migrated to retrofit (commons-app#2998)
* With media client APIs migrated to retrofit * Add test cases and java docs * Fix test * Fix build * Fix build and other minor issues * Fix tests
1 parent 828b5a3 commit 78141cb

17 files changed

+252
-92
lines changed

app/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ dependencies {
3131
implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.1.1'
3232
implementation 'com.facebook.fresco:fresco:1.13.0'
3333
implementation 'com.drewnoakes:metadata-extractor:2.11.0'
34-
implementation 'com.dmitrybrant:wikimedia-android-data-client:0.0.18'
3534
implementation 'org.apache.commons:commons-lang3:3.8.1'
35+
implementation 'com.dmitrybrant:wikimedia-android-data-client:0.0.23'
3636

3737
// UI
3838
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar'

app/src/main/java/fr/free/nrw/commons/Media.java

+11-10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import android.os.Parcel;
55
import android.os.Parcelable;
66

7+
import androidx.annotation.NonNull;
8+
import androidx.annotation.Nullable;
9+
710
import org.apache.commons.lang3.StringUtils;
811
import org.wikipedia.dataclient.mwapi.MwQueryPage;
912
import org.wikipedia.gallery.ExtMetadata;
@@ -20,8 +23,6 @@
2023
import java.util.Locale;
2124
import java.util.Map;
2225

23-
import androidx.annotation.NonNull;
24-
import androidx.annotation.Nullable;
2526
import fr.free.nrw.commons.location.LatLng;
2627
import fr.free.nrw.commons.utils.CommonsDateUtil;
2728
import fr.free.nrw.commons.utils.MediaDataExtractorUtil;
@@ -156,9 +157,9 @@ public static Media from(MwQueryPage page) {
156157
page.title(),
157158
"",
158159
0,
159-
safeParseDate(metadata.dateTimeOriginal().value()),
160-
safeParseDate(metadata.dateTime().value()),
161-
StringUtil.fromHtml(metadata.artist().value()).toString()
160+
safeParseDate(metadata.dateTime()),
161+
safeParseDate(metadata.dateTime()),
162+
StringUtil.fromHtml(metadata.artist()).toString()
162163
);
163164

164165
if (!StringUtils.isBlank(imageInfo.getThumbUrl())) {
@@ -170,17 +171,17 @@ public static Media from(MwQueryPage page) {
170171
language = "default";
171172
}
172173

173-
media.setDescriptions(Collections.singletonMap(language, metadata.imageDescription().value()));
174-
media.setCategories(MediaDataExtractorUtil.extractCategoriesFromList(metadata.categories().value()));
175-
String latitude = metadata.gpsLatitude().value();
176-
String longitude = metadata.gpsLongitude().value();
174+
media.setDescriptions(Collections.singletonMap(language, metadata.imageDescription()));
175+
media.setCategories(MediaDataExtractorUtil.extractCategoriesFromList(metadata.getCategories()));
176+
String latitude = metadata.getGpsLatitude();
177+
String longitude = metadata.getGpsLongitude();
177178

178179
if (!StringUtils.isBlank(latitude) && !StringUtils.isBlank(longitude)) {
179180
LatLng latLng = new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude), 0);
180181
media.setCoordinates(latLng);
181182
}
182183

183-
media.setLicenseInformation(metadata.licenseShortName().value(), metadata.licenseUrl().value());
184+
media.setLicenseInformation(metadata.licenseShortName(), metadata.licenseUrl());
184185
return media;
185186
}
186187

app/src/main/java/fr/free/nrw/commons/MediaDataExtractor.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package fr.free.nrw.commons;
22

3+
import androidx.core.text.HtmlCompat;
4+
35
import javax.inject.Inject;
46
import javax.inject.Singleton;
57

6-
import androidx.core.text.HtmlCompat;
8+
import fr.free.nrw.commons.media.MediaClient;
79
import fr.free.nrw.commons.mwapi.MediaWikiApi;
810
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
911
import io.reactivex.Single;
@@ -19,12 +21,15 @@
1921
public class MediaDataExtractor {
2022
private final MediaWikiApi mediaWikiApi;
2123
private final OkHttpJsonApiClient okHttpJsonApiClient;
24+
private final MediaClient mediaClient;
2225

2326
@Inject
2427
public MediaDataExtractor(MediaWikiApi mwApi,
25-
OkHttpJsonApiClient okHttpJsonApiClient) {
28+
OkHttpJsonApiClient okHttpJsonApiClient,
29+
MediaClient mediaClient) {
2630
this.okHttpJsonApiClient = okHttpJsonApiClient;
2731
this.mediaWikiApi = mwApi;
32+
this.mediaClient = mediaClient;
2833
}
2934

3035
/**
@@ -35,7 +40,7 @@ public MediaDataExtractor(MediaWikiApi mwApi,
3540
*/
3641
public Single<Media> fetchMediaDetails(String filename) {
3742
Single<Media> mediaSingle = getMediaFromFileName(filename);
38-
Single<Boolean> pageExistsSingle = mediaWikiApi.pageExists("Commons:Deletion_requests/" + filename);
43+
Single<Boolean> pageExistsSingle = mediaClient.checkPageExistsUsingTitle("Commons:Deletion_requests/" + filename);
3944
Single<String> discussionSingle = getDiscussion(filename);
4045
return Single.zip(mediaSingle, pageExistsSingle, discussionSingle, (media, deletionStatus, discussion) -> {
4146
media.setDiscussion(discussion);

app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ private static OkHttpClient createClient() {
3131
return new OkHttpClient.Builder()
3232
.cookieJar(SharedPreferenceCookieManager.getInstance())
3333
.cache(NET_CACHE)
34-
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC))
34+
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
3535
.addInterceptor(new UnsuccessfulResponseInterceptor())
3636
.addInterceptor(new CommonHeaderRequestInterceptor())
3737
.build();

app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import dagger.Provides;
2020
import fr.free.nrw.commons.BuildConfig;
2121
import fr.free.nrw.commons.kvstore.JsonKvStore;
22+
import fr.free.nrw.commons.media.MediaInterface;
2223
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
2324
import fr.free.nrw.commons.mwapi.MediaWikiApi;
2425
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
@@ -39,6 +40,8 @@ public class NetworkingModule {
3940

4041
public static final long OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024;
4142

43+
private static final String NAMED_COMMONS_WIKI_SITE = "commons-wikisite";
44+
4245
@Provides
4346
@Singleton
4447
public OkHttpClient provideOkHttpClient(Context context,
@@ -120,7 +123,13 @@ public WikiSite provideCommonsWikiSite() {
120123

121124
@Provides
122125
@Singleton
123-
public ReviewInterface provideReviewInterface(@Named("commons-wikisite") WikiSite commonsWikiSite) {
126+
public ReviewInterface provideReviewInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) {
124127
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, ReviewInterface.class);
125128
}
129+
130+
@Provides
131+
@Singleton
132+
public MediaInterface provideMediaInterface(@Named(NAMED_COMMONS_WIKI_SITE) WikiSite commonsWikiSite) {
133+
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, MediaInterface.class);
134+
}
126135
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package fr.free.nrw.commons.media;
2+
3+
4+
import javax.inject.Inject;
5+
import javax.inject.Singleton;
6+
7+
import io.reactivex.Single;
8+
9+
/**
10+
* Media Client to handle custom calls to Commons MediaWiki APIs
11+
*/
12+
@Singleton
13+
public class MediaClient {
14+
15+
private final MediaInterface mediaInterface;
16+
17+
@Inject
18+
public MediaClient(MediaInterface mediaInterface) {
19+
this.mediaInterface = mediaInterface;
20+
}
21+
22+
/**
23+
* Checks if a page exists on Commons
24+
* The same method can be used to check for file or talk page
25+
*
26+
* @param title File:Test.jpg or Commons:Deletion_requests/File:Test1.jpeg
27+
*/
28+
public Single<Boolean> checkPageExistsUsingTitle(String title) {
29+
return mediaInterface.checkPageExistsUsingTitle(title)
30+
.map(mwQueryResponse -> mwQueryResponse
31+
.query().firstPage().pageId() > 0)
32+
.singleOrError();
33+
}
34+
35+
/**
36+
* Take the fileSha and returns whether a file with a matching SHA exists or not
37+
*
38+
* @param fileSha SHA of the file to be checked
39+
*/
40+
public Single<Boolean> checkFileExistsUsingSha(String fileSha) {
41+
return mediaInterface.checkFileExistsUsingSha(fileSha)
42+
.map(mwQueryResponse -> mwQueryResponse
43+
.query().allImages().size() > 0)
44+
.singleOrError();
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package fr.free.nrw.commons.media;
2+
3+
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
4+
5+
import io.reactivex.Observable;
6+
import retrofit2.http.GET;
7+
import retrofit2.http.Query;
8+
9+
/**
10+
* Interface for interacting with Commons media related APIs
11+
*/
12+
public interface MediaInterface {
13+
/**
14+
* Checks if a page exists or not.
15+
* @param title the title of the page to be checked
16+
* @return
17+
*/
18+
@GET("w/api.php?action=query&format=json&formatversion=2")
19+
Observable<MwQueryResponse> checkPageExistsUsingTitle(@Query("titles") String title);
20+
21+
/**
22+
* Check if file exists
23+
* @param aisha1 the SHA of the media file to be checked
24+
* @return
25+
*/
26+
@GET("w/api.php?action=query&format=json&formatversion=2&list=allimages")
27+
Observable<MwQueryResponse> checkFileExistsUsingSha(@Query("aisha1") String aisha1);
28+
}

app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java

+3-29
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import android.net.Uri;
55
import android.text.TextUtils;
66

7+
import androidx.annotation.NonNull;
8+
import androidx.annotation.Nullable;
9+
710
import com.google.gson.Gson;
811

912
import org.apache.commons.lang3.StringUtils;
@@ -32,8 +35,6 @@
3235
import java.util.Locale;
3336
import java.util.concurrent.Callable;
3437

35-
import androidx.annotation.NonNull;
36-
import androidx.annotation.Nullable;
3738
import fr.free.nrw.commons.BuildConfig;
3839
import fr.free.nrw.commons.CommonsApplication;
3940
import fr.free.nrw.commons.R;
@@ -224,23 +225,6 @@ public String getCentralAuthToken() throws IOException {
224225
return centralAuthToken;
225226
}
226227

227-
@Override
228-
public boolean fileExistsWithName(String fileName) throws IOException {
229-
return api.action("query")
230-
.param("prop", "imageinfo")
231-
.param("titles", "File:" + fileName)
232-
.get()
233-
.getNodes("/api/query/pages/page/imageinfo").size() > 0;
234-
}
235-
236-
@Override
237-
public Single<Boolean> pageExists(String pageName) {
238-
return Single.fromCallable(() -> Double.parseDouble(api.action("query")
239-
.param("titles", pageName)
240-
.get()
241-
.getString("/api/query/pages/page/@_idx")) != -1);
242-
}
243-
244228
@Override
245229
public boolean thank(String editToken, long revision) throws IOException {
246230
CustomApiResult res = api.action("thank")
@@ -749,16 +733,6 @@ private QueryContinue getQueryContinueValues(String keyword) {
749733
return gson.fromJson(queryContinueString, QueryContinue.class);
750734
}
751735

752-
@Override
753-
public boolean existingFile(String fileSha1) throws IOException {
754-
return api.action("query")
755-
.param("format", "xml")
756-
.param("list", "allimages")
757-
.param("aisha1", fileSha1)
758-
.get()
759-
.getNodes("/api/query/allimages/img").size() > 0;
760-
}
761-
762736
@Override
763737
@NonNull
764738
public Single<UploadStash> uploadFile(

app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java

-6
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ public interface MediaWikiApi {
3030

3131
String getCentralAuthToken() throws IOException;
3232

33-
boolean fileExistsWithName(String fileName) throws IOException;
34-
35-
Single<Boolean> pageExists(String pageName);
36-
3733
List<String> getSubCategoryList(String categoryName);
3834

3935
List<String> getParentCategoryList(String categoryName);
@@ -87,8 +83,6 @@ Single<UploadResult> uploadFileFinalize(String filename, String filekey,
8783
@Nullable
8884
String revisionsByFilename(String filename) throws IOException;
8985

90-
boolean existingFile(String fileSha1) throws IOException;
91-
9286
@NonNull
9387
LogEventResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException;
9488

app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import javax.inject.Singleton;
1515

1616
import fr.free.nrw.commons.Media;
17+
import fr.free.nrw.commons.media.MediaClient;
1718
import fr.free.nrw.commons.mwapi.MediaWikiApi;
1819
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
1920
import io.reactivex.Observable;
@@ -26,14 +27,16 @@ public class ReviewHelper {
2627

2728
private final OkHttpJsonApiClient okHttpJsonApiClient;
2829
private final MediaWikiApi mediaWikiApi;
30+
private final MediaClient mediaClient;
2931
private final ReviewInterface reviewInterface;
3032

3133
@Inject
3234
public ReviewHelper(OkHttpJsonApiClient okHttpJsonApiClient,
3335
MediaWikiApi mediaWikiApi,
34-
ReviewInterface reviewInterface) {
36+
MediaClient mediaClient, ReviewInterface reviewInterface) {
3537
this.okHttpJsonApiClient = okHttpJsonApiClient;
3638
this.mediaWikiApi = mediaWikiApi;
39+
this.mediaClient = mediaClient;
3740
this.reviewInterface = reviewInterface;
3841
}
3942

@@ -86,7 +89,7 @@ public Single<Media> getRandomMedia() {
8689
*/
8790
private Single<Media> getRandomMediaFromRecentChange(RecentChange recentChange) {
8891
return Single.just(recentChange)
89-
.flatMap(change -> mediaWikiApi.pageExists("Commons:Deletion_requests/" + change.getTitle()))
92+
.flatMap(change -> mediaClient.checkPageExistsUsingTitle("Commons:Deletion_requests/" + change.getTitle()))
9093
.flatMap(isDeleted -> {
9194
if (isDeleted) {
9295
return Single.just(new Media(""));

app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import javax.inject.Inject;
1111
import javax.inject.Singleton;
1212

13+
import fr.free.nrw.commons.media.MediaClient;
1314
import fr.free.nrw.commons.mwapi.MediaWikiApi;
1415
import fr.free.nrw.commons.nearby.Place;
1516
import fr.free.nrw.commons.utils.ImageUtils;
@@ -34,18 +35,20 @@ public class ImageProcessingService {
3435
private final MediaWikiApi mwApi;
3536
private final ReadFBMD readFBMD;
3637
private final EXIFReader EXIFReader;
38+
private final MediaClient mediaClient;
3739
private final Context context;
3840

3941
@Inject
4042
public ImageProcessingService(FileUtilsWrapper fileUtilsWrapper,
4143
ImageUtilsWrapper imageUtilsWrapper,
4244
MediaWikiApi mwApi, ReadFBMD readFBMD, EXIFReader EXIFReader,
43-
Context context) {
45+
MediaClient mediaClient, Context context) {
4446
this.fileUtilsWrapper = fileUtilsWrapper;
4547
this.imageUtilsWrapper = imageUtilsWrapper;
4648
this.mwApi = mwApi;
4749
this.readFBMD = readFBMD;
4850
this.EXIFReader = EXIFReader;
51+
this.mediaClient = mediaClient;
4952
this.context = context;
5053
}
5154

@@ -128,7 +131,7 @@ private Single<Integer> validateItemTitle(UploadModel.UploadItem uploadItem) {
128131
return Single.just(EMPTY_TITLE);
129132
}
130133

131-
return Single.fromCallable(() -> mwApi.fileExistsWithName(uploadItem.getFileName()))
134+
return mediaClient.checkPageExistsUsingTitle("File:" + uploadItem.getFileName())
132135
.map(doesFileExist -> {
133136
Timber.d("Result for valid title is %s", doesFileExist);
134137
return doesFileExist ? FILE_NAME_EXISTS : IMAGE_OK;
@@ -146,7 +149,7 @@ private Single<Integer> checkDuplicateImage(String filePath) {
146149
return Single.fromCallable(() ->
147150
fileUtilsWrapper.getFileInputStream(filePath))
148151
.map(fileUtilsWrapper::getSHA1)
149-
.map(mwApi::existingFile)
152+
.flatMap(mediaClient::checkFileExistsUsingSha)
150153
.map(b -> {
151154
Timber.d("Result for duplicate image %s", b);
152155
return b ? ImageUtils.IMAGE_DUPLICATE : ImageUtils.IMAGE_OK;

0 commit comments

Comments
 (0)