Skip to content

Commit 2de52c3

Browse files
committed
Use data client for peer review calls
1 parent 98d28c6 commit 2de52c3

File tree

7 files changed

+147
-156
lines changed

7 files changed

+147
-156
lines changed

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
import android.app.Activity;
44
import android.content.ContentProviderClient;
55
import android.content.Context;
6-
import androidx.collection.LruCache;
76
import android.view.inputmethod.InputMethodManager;
87

98
import com.google.gson.Gson;
109

10+
import org.wikipedia.dataclient.WikiSite;
11+
1112
import java.util.ArrayList;
1213
import java.util.HashMap;
1314
import java.util.List;
@@ -16,6 +17,7 @@
1617
import javax.inject.Named;
1718
import javax.inject.Singleton;
1819

20+
import androidx.collection.LruCache;
1921
import dagger.Module;
2022
import dagger.Provides;
2123
import fr.free.nrw.commons.BuildConfig;
@@ -24,7 +26,6 @@
2426
import fr.free.nrw.commons.auth.SessionManager;
2527
import fr.free.nrw.commons.data.DBOpenHelper;
2628
import fr.free.nrw.commons.kvstore.JsonKvStore;
27-
import fr.free.nrw.commons.kvstore.JsonKvStore;
2829
import fr.free.nrw.commons.location.LocationServiceManager;
2930
import fr.free.nrw.commons.settings.Prefs;
3031
import fr.free.nrw.commons.upload.UploadController;

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

+15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
import com.google.gson.Gson;
66

7+
import org.wikipedia.dataclient.ServiceFactory;
8+
import org.wikipedia.dataclient.WikiSite;
79
import org.wikipedia.json.GsonUtil;
810

911
import java.io.File;
@@ -20,6 +22,7 @@
2022
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
2123
import fr.free.nrw.commons.mwapi.MediaWikiApi;
2224
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
25+
import fr.free.nrw.commons.review.ReviewInterface;
2326
import okhttp3.Cache;
2427
import okhttp3.HttpUrl;
2528
import okhttp3.OkHttpClient;
@@ -108,4 +111,16 @@ public Gson provideGson() {
108111
return GsonUtil.getDefaultGson();
109112
}
110113

114+
@Provides
115+
@Singleton
116+
@Named("commons-wikisite")
117+
public WikiSite provideCommonsWikiSite() {
118+
return new WikiSite(BuildConfig.COMMONS_URL);
119+
}
120+
121+
@Provides
122+
@Singleton
123+
public ReviewInterface provideReviewInterface(@Named("commons-wikisite") WikiSite commonsWikiSite) {
124+
return ServiceFactory.get(commonsWikiSite, BuildConfig.COMMONS_URL, ReviewInterface.class);
125+
}
111126
}

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

-79
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import org.apache.commons.lang3.StringUtils;
77
import org.wikipedia.dataclient.mwapi.MwQueryPage;
88
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
9-
import org.wikipedia.dataclient.mwapi.RecentChange;
10-
import org.wikipedia.util.DateUtil;
119

1210
import java.io.IOException;
1311
import java.lang.reflect.Type;
@@ -16,7 +14,6 @@
1614
import java.util.List;
1715
import java.util.Locale;
1816
import java.util.Map;
19-
import java.util.Random;
2017

2118
import javax.inject.Inject;
2219
import javax.inject.Singleton;
@@ -406,80 +403,4 @@ private void putContinueValues(String keyword, Map<String, String> values) {
406403
private Map<String, String> getContinueValues(String keyword) {
407404
return defaultKvStore.getJson("query_continue_" + keyword, mapType);
408405
}
409-
410-
/**
411-
* Returns recent changes on commons
412-
*
413-
* @return list of recent changes made
414-
*/
415-
@Nullable
416-
public Single<List<RecentChange>> getRecentFileChanges() {
417-
final int RANDOM_SECONDS = 60 * 60 * 24 * 30;
418-
final String FILE_NAMESPACE = "6";
419-
Random r = new Random();
420-
Date now = new Date();
421-
Date startDate = new Date(now.getTime() - r.nextInt(RANDOM_SECONDS) * 1000L);
422-
423-
String rcStart = DateUtil.iso8601DateFormat(startDate);
424-
HttpUrl.Builder urlBuilder = HttpUrl
425-
.parse(commonsBaseUrl)
426-
.newBuilder()
427-
.addQueryParameter("action", "query")
428-
.addQueryParameter("format", "json")
429-
.addQueryParameter("formatversion", "2")
430-
.addQueryParameter("list", "recentchanges")
431-
.addQueryParameter("rcstart", rcStart)
432-
.addQueryParameter("rcnamespace", FILE_NAMESPACE)
433-
.addQueryParameter("rcprop", "title|ids")
434-
.addQueryParameter("rctype", "new|log")
435-
.addQueryParameter("rctoponly", "1");
436-
437-
Request request = new Request.Builder()
438-
.url(urlBuilder.build())
439-
.build();
440-
441-
return Single.fromCallable(() -> {
442-
Response response = okHttpClient.newCall(request).execute();
443-
if (response.body() != null && response.isSuccessful()) {
444-
String json = response.body().string();
445-
MwQueryResponse mwQueryPage = gson.fromJson(json, MwQueryResponse.class);
446-
return mwQueryPage.query().getRecentChanges();
447-
}
448-
return new ArrayList<>();
449-
});
450-
}
451-
452-
/**
453-
* Returns the first revision of the file
454-
*
455-
* @return Revision object
456-
*/
457-
@Nullable
458-
public Single<MwQueryPage.Revision> getFirstRevisionOfFile(String filename) {
459-
HttpUrl.Builder urlBuilder = HttpUrl
460-
.parse(commonsBaseUrl)
461-
.newBuilder()
462-
.addQueryParameter("action", "query")
463-
.addQueryParameter("format", "json")
464-
.addQueryParameter("formatversion", "2")
465-
.addQueryParameter("prop", "revisions")
466-
.addQueryParameter("rvprop", "timestamp|ids|user")
467-
.addQueryParameter("titles", filename)
468-
.addQueryParameter("rvdir", "newer")
469-
.addQueryParameter("rvlimit", "1");
470-
471-
Request request = new Request.Builder()
472-
.url(urlBuilder.build())
473-
.build();
474-
475-
return Single.fromCallable(() -> {
476-
Response response = okHttpClient.newCall(request).execute();
477-
if (response.body() != null && response.isSuccessful()) {
478-
String json = response.body().string();
479-
MwQueryResponse mwQueryPage = gson.fromJson(json, MwQueryResponse.class);
480-
return mwQueryPage.query().firstPage().revisions().get(0);
481-
}
482-
return null;
483-
});
484-
}
485406
}

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

+9-5
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,19 @@
1212
import android.widget.Button;
1313
import android.widget.ProgressBar;
1414
import android.widget.TextView;
15+
16+
import com.facebook.drawee.view.SimpleDraweeView;
17+
import com.google.android.material.navigation.NavigationView;
18+
import com.viewpagerindicator.CirclePageIndicator;
19+
20+
import java.util.ArrayList;
21+
22+
import javax.inject.Inject;
23+
1524
import androidx.appcompat.widget.Toolbar;
1625
import androidx.drawerlayout.widget.DrawerLayout;
1726
import butterknife.BindView;
1827
import butterknife.ButterKnife;
19-
import com.facebook.drawee.view.SimpleDraweeView;
20-
import com.google.android.material.navigation.NavigationView;
21-
import com.viewpagerindicator.CirclePageIndicator;
2228
import fr.free.nrw.commons.Media;
2329
import fr.free.nrw.commons.R;
2430
import fr.free.nrw.commons.auth.AuthenticatedActivity;
@@ -29,8 +35,6 @@
2935
import io.reactivex.android.schedulers.AndroidSchedulers;
3036
import io.reactivex.disposables.CompositeDisposable;
3137
import io.reactivex.schedulers.Schedulers;
32-
import java.util.ArrayList;
33-
import javax.inject.Inject;
3438

3539
public class ReviewActivity extends AuthenticatedActivity {
3640

Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
package fr.free.nrw.commons.review;
22

3+
4+
import androidx.core.util.Pair;
5+
36
import org.wikipedia.dataclient.mwapi.MwQueryPage;
47
import org.wikipedia.dataclient.mwapi.RecentChange;
8+
import org.wikipedia.util.DateUtil;
59

10+
import java.util.Collections;
11+
import java.util.Date;
612
import java.util.List;
713
import java.util.Random;
814

9-
import javax.annotation.Nullable;
1015
import javax.inject.Inject;
1116
import javax.inject.Singleton;
1217

13-
import androidx.core.util.Pair;
1418
import fr.free.nrw.commons.Media;
1519
import fr.free.nrw.commons.mwapi.MediaWikiApi;
1620
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
17-
import io.reactivex.Single;
21+
import io.reactivex.Maybe;
22+
import io.reactivex.Observable;
1823

1924
@Singleton
2025
public class ReviewHelper {
@@ -24,16 +29,29 @@ public class ReviewHelper {
2429

2530
private final OkHttpJsonApiClient okHttpJsonApiClient;
2631
private final MediaWikiApi mediaWikiApi;
32+
private final ReviewInterface reviewInterface;
2733

2834
@Inject
29-
public ReviewHelper(OkHttpJsonApiClient okHttpJsonApiClient, MediaWikiApi mediaWikiApi) {
35+
public ReviewHelper(OkHttpJsonApiClient okHttpJsonApiClient,
36+
MediaWikiApi mediaWikiApi,
37+
ReviewInterface reviewInterface) {
3038
this.okHttpJsonApiClient = okHttpJsonApiClient;
3139
this.mediaWikiApi = mediaWikiApi;
40+
this.reviewInterface = reviewInterface;
3241
}
3342

34-
Single<Media> getRandomMedia() {
35-
return getRandomFileChange()
36-
.flatMap(fileName -> okHttpJsonApiClient.getMedia(fileName, false));
43+
private Observable<List<RecentChange>> getRecentChanges() {
44+
final int RANDOM_SECONDS = 60 * 60 * 24 * 30;
45+
Random r = new Random();
46+
Date now = new Date();
47+
Date startDate = new Date(now.getTime() - r.nextInt(RANDOM_SECONDS) * 1000L);
48+
49+
String rcStart = DateUtil.iso8601DateFormat(startDate);
50+
return reviewInterface.getRecentChanges(rcStart).map(mwQueryResponse -> mwQueryResponse.query().getRecentChanges())
51+
.map(recentChanges -> {
52+
Collections.shuffle(recentChanges);
53+
return recentChanges;
54+
});
3755
}
3856

3957
/**
@@ -43,57 +61,40 @@ Single<Media> getRandomMedia() {
4361
* - Checks if the file is nominated for deletion
4462
* - Retries upto 5 times for getting a file which is not nominated for deletion
4563
*
46-
* @return
64+
* @return Random file change
4765
*/
48-
private Single<String> getRandomFileChange() {
49-
return okHttpJsonApiClient.getRecentFileChanges()
50-
.map(this::findImageInRecentChanges)
51-
.flatMap(title -> mediaWikiApi.pageExists("Commons:Deletion_requests/" + title)
52-
.map(pageExists -> new Pair<>(title, pageExists)))
53-
.map((Pair<String, Boolean> pair) -> {
54-
if (!pair.second) {
55-
return pair.first;
66+
public Maybe<Media> getRandomMedia() {
67+
return getRecentChanges()
68+
.flatMapIterable(changes -> changes)
69+
.filter(this::isChangeReviewable)
70+
.flatMapSingle(change -> mediaWikiApi.pageExists("Commons:Deletion_requests/" + change.getTitle())
71+
.map(exists -> new Pair<>(change.getTitle(), exists)))
72+
.flatMapSingle(fileNamePair -> {
73+
if (fileNamePair.second != null && !fileNamePair.second) {
74+
return okHttpJsonApiClient.getMedia(fileNamePair.first, false);
5675
}
57-
throw new Exception("Already nominated for deletion");
58-
}).retry(MAX_RANDOM_TRIES);
76+
return null;
77+
})
78+
.filter(media -> media != null)
79+
.firstElement();
5980
}
6081

61-
Single<MwQueryPage.Revision> getFirstRevisionOfFile(String fileName) {
62-
return okHttpJsonApiClient.getFirstRevisionOfFile(fileName);
82+
Observable<MwQueryPage.Revision> getFirstRevisionOfFile(String filename) {
83+
return reviewInterface.getFirstRevisionOfFile(filename)
84+
.map(response -> response.query().firstPage().revisions().get(0));
6385
}
6486

65-
@Nullable
66-
private String findImageInRecentChanges(List<RecentChange> recentChanges) {
67-
String imageTitle;
68-
Random r = new Random();
69-
int count = recentChanges.size();
70-
// Build a range array
71-
int[] randomIndexes = new int[count];
72-
for (int i = 0; i < count; i++) {
73-
randomIndexes[i] = i;
74-
}
75-
// Then shuffle it
76-
for (int i = 0; i < count; i++) {
77-
int swapIndex = r.nextInt(count);
78-
int temp = randomIndexes[i];
79-
randomIndexes[i] = randomIndexes[swapIndex];
80-
randomIndexes[swapIndex] = temp;
87+
private boolean isChangeReviewable(RecentChange recentChange) {
88+
if (recentChange.getType().equals("log") && !(recentChange.getOldRevisionId() == 0)) {
89+
return false;
8190
}
82-
for (int i = 0; i < count; i++) {
83-
int randomIndex = randomIndexes[i];
84-
RecentChange recentChange = recentChanges.get(randomIndex);
85-
if (recentChange.getType().equals("log") && !(recentChange.getOldRevisionId() == 0)) {
86-
// For log entries, we only want ones where old_revid is zero, indicating a new file
87-
continue;
88-
}
89-
imageTitle = recentChange.getTitle();
9091

91-
for (String imageExtension : imageExtensions) {
92-
if (imageTitle.toLowerCase().endsWith(imageExtension)) {
93-
return imageTitle;
94-
}
92+
for (String extension : imageExtensions) {
93+
if (recentChange.getTitle().endsWith(extension)) {
94+
return true;
9595
}
9696
}
97-
return null;
97+
98+
return false;
9899
}
99100
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package fr.free.nrw.commons.review;
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+
public interface ReviewInterface {
10+
@GET("w/api.php?action=query&format=json&formatversion=2&list=recentchanges&rcprop=title|ids&rctype=new|log&rctoponly=1&rcnamespace=6")
11+
Observable<MwQueryResponse> getRecentChanges(@Query("rcstart") String rcStart);
12+
13+
@GET("w/api.php?action=query&format=json&formatversion=2&prop=revisions&rvprop=timestamp|ids|user&rvdir=newer&rvlimit=1")
14+
Observable<MwQueryResponse> getFirstRevisionOfFile(@Query("titles") String titles);
15+
}

0 commit comments

Comments
 (0)