From 496933654b8c8914ad195193532bd7ca5f4e373e Mon Sep 17 00:00:00 2001 From: Arin Modi Date: Tue, 7 Mar 2023 11:16:36 +0530 Subject: [PATCH] Skip used images (#5160) * Only Review Images That Has No Usage * Coding Standard Related Changes * Coding Standard Changes - 1 * small change --- .../nrw/commons/review/ReviewActivity.java | 24 ++++++- .../free/nrw/commons/review/ReviewHelper.java | 13 ++++ .../nrw/commons/review/ReviewInterface.java | 3 + .../dataclient/mwapi/MwQueryPage.java | 70 +++++++++++++++++++ .../dataclient/mwapi/MwQueryResponse.java | 2 +- .../dataclient/mwapi/MwQueryResult.java | 2 +- 6 files changed, 109 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/review/ReviewActivity.java b/app/src/main/java/fr/free/nrw/commons/review/ReviewActivity.java index d291815ea..da8cb5897 100644 --- a/app/src/main/java/fr/free/nrw/commons/review/ReviewActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/review/ReviewActivity.java @@ -6,6 +6,7 @@ import android.content.Intent; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -161,14 +162,31 @@ public class ReviewActivity extends BaseActivity { hasNonHiddenCategories = false; progressBar.setVisibility(View.VISIBLE); reviewPager.setCurrentItem(0); + // Finds non-hidden categories from Media instance compositeDisposable.add(reviewHelper.getRandomMedia() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(media -> { + .subscribe(this::checkWhetherFileIsUsedInWikis)); + return true; + } + + /** + * Check whether media is used or not in any Wiki Page + */ + @SuppressLint("CheckResult") + private void checkWhetherFileIsUsedInWikis(final Media media) { + compositeDisposable.add(reviewHelper.checkFileUsage(media.getFilename()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + // result false indicates media is not used in any wiki + if (!result) { // Finds non-hidden categories from Media instance findNonHiddenCategories(media); - })); - return true; + } else { + runRandomizer(); + } + })); } /** diff --git a/app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java b/app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java index 040231792..a69024209 100644 --- a/app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java +++ b/app/src/main/java/fr/free/nrw/commons/review/ReviewHelper.java @@ -100,6 +100,19 @@ public class ReviewHelper { .map(response -> response.query().firstPage().revisions().get(0)); } + /** + * Checks Whether Given File is used in any Wiki page or not + * by calling api for given file + * + * @param filename + * @return + */ + Observable checkFileUsage(final String filename) { + return reviewInterface.getGlobalUsageInfo(filename) + .map(mwQueryResponse -> mwQueryResponse.query().firstPage() + .checkWhetherFileIsUsedInWikis()); + } + /** * Checks if the change is reviewable or not. * - checks the type and revisionId of the change diff --git a/app/src/main/java/fr/free/nrw/commons/review/ReviewInterface.java b/app/src/main/java/fr/free/nrw/commons/review/ReviewInterface.java index 920c78a49..f5fe64bd5 100644 --- a/app/src/main/java/fr/free/nrw/commons/review/ReviewInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/review/ReviewInterface.java @@ -15,4 +15,7 @@ public interface ReviewInterface { @GET("w/api.php?action=query&format=json&formatversion=2&prop=revisions&rvprop=timestamp|ids|user&rvdir=newer&rvlimit=1") Observable getFirstRevisionOfFile(@Query("titles") String titles); + + @GET("w/api.php?action=query&format=json&formatversion=2&prop=fileusage|globalusage") + Observable getGlobalUsageInfo(@Query("titles") String title); } diff --git a/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryPage.java b/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryPage.java index fceeed938..3629fc7bf 100644 --- a/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryPage.java +++ b/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryPage.java @@ -25,6 +25,8 @@ public class MwQueryPage extends BaseModel { @SuppressWarnings("unused,NullableProblems") @NonNull private CategoryInfo categoryinfo; @SuppressWarnings("unused") @Nullable private List langlinks; @SuppressWarnings("unused") @Nullable private List revisions; + @SuppressWarnings("unused") @SerializedName("fileusage") @Nullable private List fileUsages; + @SuppressWarnings("unused") @SerializedName("globalusage") @Nullable private List globalUsages; @SuppressWarnings("unused") @Nullable private List coordinates; @SuppressWarnings("unused") @Nullable private List categories; @SuppressWarnings("unused") @Nullable private PageProps pageprops; @@ -67,6 +69,14 @@ public class MwQueryPage extends BaseModel { return categories; } + @Nullable public List globalUsages() { + return globalUsages; + } + + @Nullable public List fileUsages() { + return fileUsages; + } + @Nullable public List coordinates() { // TODO: Handle null values in lists during deserialization, perhaps with a new // @RequiredElements annotation and corresponding TypeAdapter @@ -141,6 +151,28 @@ public class MwQueryPage extends BaseModel { title += "#" + fragment; } + public boolean checkWhetherFileIsUsedInWikis() { + if (globalUsages != null && globalUsages.size() > 0) { + return true; + } + + if (fileUsages == null || fileUsages.size() == 0) { + return false; + } + + final int totalCount = fileUsages.size(); + + /* Ignore usage under https://commons.wikimedia.org/wiki/User:Didym/Mobile_upload/ + which has been a gallery of all of our uploads since 2014 */ + for (final FileUsage fileUsage : fileUsages) { + if ( ! fileUsage.title().contains("User:Didym/Mobile upload")) { + return true; + } + } + + return false; + } + public static class Revision { @SerializedName("revid") private long revisionId; private String user; @@ -228,6 +260,44 @@ public class MwQueryPage extends BaseModel { } } + public static class GlobalUsage { + @SerializedName("title") private String title; + @SerializedName("wiki")private String wiki; + @SerializedName("url") private String url; + + public String getTitle() { + return title; + } + + public String getWiki() { + return wiki; + } + + public String getUrl() { + return url; + } + + + } + + public static class FileUsage { + @SerializedName("pageid") private int pageid; + @SerializedName("ns") private int ns; + @SerializedName("title") private String title; + + public int pageId() { + return pageid; + } + + public int ns() { + return ns; + } + + public String title() { + return title; + } + } + public static class Category { @SuppressWarnings("unused") private int ns; @SuppressWarnings("unused,NullableProblems") @Nullable private String title; diff --git a/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.java b/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.java index 92aed30c8..8ed544c48 100644 --- a/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.java +++ b/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.java @@ -13,7 +13,7 @@ public class MwQueryResponse extends MwResponse { @SuppressWarnings("unused") @SerializedName("continue") @Nullable private Map continuation; - @Nullable private MwQueryResult query; + @SerializedName("query") @Nullable private MwQueryResult query; public boolean batchComplete() { return batchComplete; diff --git a/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResult.java b/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResult.java index 16df47d7e..6c7434ada 100644 --- a/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResult.java +++ b/data-client/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResult.java @@ -23,7 +23,7 @@ import java.util.Map; @SuppressWarnings("unused") public class MwQueryResult extends BaseModel implements PostProcessingTypeAdapter.PostProcessable { - @Nullable private List pages; + @SerializedName("pages") @Nullable private List pages; @Nullable private List redirects; @Nullable private List converted; @SerializedName("userinfo") private UserInfo userInfo;