mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 12:53:55 +01:00
Log P18 edits with custom tag (#1583)
* Log P18 edits by adding custom tag to the edits * Add javadocs
This commit is contained in:
parent
e46228205e
commit
f7c57c03ba
4 changed files with 173 additions and 50 deletions
|
|
@ -394,12 +394,13 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
* @param property the property to be edited, for eg P18 for images
|
* @param property the property to be edited, for eg P18 for images
|
||||||
* @param snaktype the type of value stored for that property
|
* @param snaktype the type of value stored for that property
|
||||||
* @param value the actual value to be stored for the property, for eg filename in case of P18
|
* @param value the actual value to be stored for the property, for eg filename in case of P18
|
||||||
* @return returns true if the claim is successfully created
|
* @return returns revisionId if the claim is successfully created else returns null
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public boolean wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException {
|
public String wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException {
|
||||||
|
Timber.d("Filename is %s", value);
|
||||||
ApiResult result = wikidataApi.action("wbcreateclaim")
|
ApiResult result = wikidataApi.action("wbcreateclaim")
|
||||||
.param("entity", entityId)
|
.param("entity", entityId)
|
||||||
.param("centralauthtoken", getCentralAuthToken())
|
.param("centralauthtoken", getCentralAuthToken())
|
||||||
|
|
@ -410,13 +411,45 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||||
.post();
|
.post();
|
||||||
|
|
||||||
if (result == null || result.getNode("api") == null) {
|
if (result == null || result.getNode("api") == null) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node node = result.getNode("api").getDocument();
|
Node node = result.getNode("api").getDocument();
|
||||||
Element element = (Element) node;
|
Element element = (Element) node;
|
||||||
|
|
||||||
if (element != null && element.getAttribute("success").equals("1")) {
|
if (element != null && element.getAttribute("success").equals("1")) {
|
||||||
|
return result.getString("api/pageinfo/@lastrevid");
|
||||||
|
} else {
|
||||||
|
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the wikimedia-commons-app tag to the edits made on wikidata
|
||||||
|
* @param revisionId
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public boolean addWikidataEditTag(String revisionId) throws IOException {
|
||||||
|
ApiResult result = wikidataApi.action("tag")
|
||||||
|
.param("revid", revisionId)
|
||||||
|
.param("centralauthtoken", getCentralAuthToken())
|
||||||
|
.param("token", getWikidataCsrfToken())
|
||||||
|
.param("add", "wikimedia-commons-app")
|
||||||
|
.param("reason", "Add tag for edits made using Android Commons app")
|
||||||
|
.post();
|
||||||
|
|
||||||
|
if (result == null || result.getNode("api") == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node node = result.getNode("api").getDocument();
|
||||||
|
Element element = (Element) node;
|
||||||
|
|
||||||
|
if (element != null && element.getAttribute("status").equals("success")) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
|
Timber.e(result.getString("api/error/@code") + " " + result.getString("api/error/@info"));
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,10 @@ public interface MediaWikiApi {
|
||||||
String appendEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
|
String appendEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
boolean wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException;
|
String wikidatCreateClaim(String entityId, String property, String snaktype, String value) throws IOException;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
boolean addWikidataEditTag(String revisionId) throws IOException;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
MediaResult fetchMediaByFilename(String filename) throws IOException;
|
MediaResult fetchMediaByFilename(String filename) throws IOException;
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
import fr.free.nrw.commons.mwapi.UploadResult;
|
import fr.free.nrw.commons.mwapi.UploadResult;
|
||||||
import fr.free.nrw.commons.utils.ViewUtil;
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||||
|
import fr.free.nrw.commons.wikidata.WikidataEditService;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
@ -55,11 +56,9 @@ public class UploadService extends HandlerService<Contribution> {
|
||||||
public static final String EXTRA_CAMPAIGN = EXTRA_PREFIX + ".campaign";
|
public static final String EXTRA_CAMPAIGN = EXTRA_PREFIX + ".campaign";
|
||||||
|
|
||||||
@Inject MediaWikiApi mwApi;
|
@Inject MediaWikiApi mwApi;
|
||||||
@Inject WikidataEditListener wikidataEditListener;
|
@Inject WikidataEditService wikidataEditService;
|
||||||
@Inject SessionManager sessionManager;
|
@Inject SessionManager sessionManager;
|
||||||
@Inject @Named("default_preferences") SharedPreferences prefs;
|
|
||||||
@Inject ContributionDao contributionDao;
|
@Inject ContributionDao contributionDao;
|
||||||
@Inject @Named("direct_nearby_upload_prefs") SharedPreferences directPrefs;
|
|
||||||
|
|
||||||
private NotificationManager notificationManager;
|
private NotificationManager notificationManager;
|
||||||
private NotificationCompat.Builder curProgressNotification;
|
private NotificationCompat.Builder curProgressNotification;
|
||||||
|
|
@ -262,7 +261,7 @@ public class UploadService extends HandlerService<Contribution> {
|
||||||
if (!resultStatus.equals("Success")) {
|
if (!resultStatus.equals("Success")) {
|
||||||
showFailedNotification(contribution);
|
showFailedNotification(contribution);
|
||||||
} else {
|
} else {
|
||||||
editWikidataProperty(contribution);
|
wikidataEditService.createClaimWithLogging(contribution.getWikiDataEntityId(), filename);
|
||||||
contribution.setFilename(uploadResult.getCanonicalFilename());
|
contribution.setFilename(uploadResult.getCanonicalFilename());
|
||||||
contribution.setImageUrl(uploadResult.getImageUrl());
|
contribution.setImageUrl(uploadResult.getImageUrl());
|
||||||
contribution.setState(Contribution.STATE_COMPLETED);
|
contribution.setState(Contribution.STATE_COMPLETED);
|
||||||
|
|
@ -285,48 +284,6 @@ public class UploadService extends HandlerService<Contribution> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Edits the wikidata entity by adding the P18 property to it.
|
|
||||||
* Adding the P18 edit requires calling the wikidata API to create a claim against the entity
|
|
||||||
* @param contribution
|
|
||||||
*/
|
|
||||||
@SuppressLint("CheckResult")
|
|
||||||
private void editWikidataProperty(Contribution contribution) {
|
|
||||||
Timber.d("Upload successful with wiki data entity id as %s", contribution.getWikiDataEntityId());
|
|
||||||
Timber.d("Attempting to edit Wikidata property %s", contribution.getWikiDataEntityId());
|
|
||||||
Observable.fromCallable(() -> mwApi.wikidatCreateClaim(contribution.getWikiDataEntityId(), "P18", "value", getFileName(contribution)))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(result -> handleClaimResult(contribution, result), throwable -> {
|
|
||||||
Timber.e(throwable, "Error occurred while making claim");
|
|
||||||
ViewUtil.showLongToast(getBaseContext(), getResources().getString(R.string.wikidata_edit_failure));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleClaimResult(Contribution contribution, Boolean result) {
|
|
||||||
if(result) {
|
|
||||||
wikidataEditListener.onSuccessfulWikidataEdit();
|
|
||||||
String title = directPrefs.getString("Title", "");
|
|
||||||
String successStringTemplate = getResources().getString(R.string.successful_wikidata_edit);
|
|
||||||
String successMessage = String.format(Locale.getDefault(), successStringTemplate, title);
|
|
||||||
ViewUtil.showLongToast(getBaseContext(), successMessage);
|
|
||||||
} else {
|
|
||||||
Timber.d("Unable to make wiki data edit for entity %s", contribution.getWikiDataEntityId());
|
|
||||||
ViewUtil.showLongToast(getBaseContext(), getResources().getString(R.string.wikidata_edit_failure));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats and returns the filename as accepted by the wiki base API
|
|
||||||
* https://www.mediawiki.org/wiki/Wikibase/API#wbcreateclaim
|
|
||||||
* @param contribution
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private String getFileName(Contribution contribution) {
|
|
||||||
String filename = String.format("\"%s\"", contribution.getFilename().replace("File:", ""));
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("StringFormatInvalid")
|
@SuppressLint("StringFormatInvalid")
|
||||||
private void showFailedNotification(Contribution contribution) {
|
private void showFailedNotification(Contribution contribution) {
|
||||||
Notification failureNotification = new NotificationCompat.Builder(this).setAutoCancel(true)
|
Notification failureNotification = new NotificationCompat.Builder(this).setAutoCancel(true)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
package fr.free.nrw.commons.wikidata;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import fr.free.nrw.commons.R;
|
||||||
|
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||||
|
import fr.free.nrw.commons.utils.ViewUtil;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is meant to handle the Wikidata edits made through the app
|
||||||
|
* It will talk with MediaWikiApi to make necessary API calls, log the edits and fire listeners
|
||||||
|
* on successful edits
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class WikidataEditService {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final MediaWikiApi mediaWikiApi;
|
||||||
|
private final WikidataEditListener wikidataEditListener;
|
||||||
|
private final SharedPreferences directPrefs;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public WikidataEditService(Context context,
|
||||||
|
MediaWikiApi mediaWikiApi,
|
||||||
|
WikidataEditListener wikidataEditListener,
|
||||||
|
@Named("direct_nearby_upload_prefs") SharedPreferences directPrefs) {
|
||||||
|
this.context = context;
|
||||||
|
this.mediaWikiApi = mediaWikiApi;
|
||||||
|
this.wikidataEditListener = wikidataEditListener;
|
||||||
|
this.directPrefs = directPrefs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a P18 claim and log the edit with custom tag
|
||||||
|
* @param wikidataEntityId
|
||||||
|
* @param fileName
|
||||||
|
*/
|
||||||
|
public void createClaimWithLogging(String wikidataEntityId, String fileName) {
|
||||||
|
editWikidataProperty(wikidataEntityId, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits the wikidata entity by adding the P18 property to it.
|
||||||
|
* Adding the P18 edit requires calling the wikidata API to create a claim against the entity
|
||||||
|
*
|
||||||
|
* @param wikidataEntityId
|
||||||
|
* @param fileName
|
||||||
|
*/
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void editWikidataProperty(String wikidataEntityId, String fileName) {
|
||||||
|
Timber.d("Upload successful with wiki data entity id as %s", wikidataEntityId);
|
||||||
|
Timber.d("Attempting to edit Wikidata property %s", wikidataEntityId);
|
||||||
|
Observable.fromCallable(() -> {
|
||||||
|
String propertyValue = getFileName(fileName);
|
||||||
|
return mediaWikiApi.wikidatCreateClaim(wikidataEntityId, "P18", "value", propertyValue);
|
||||||
|
})
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(revisionId -> handleClaimResult(wikidataEntityId, revisionId), throwable -> {
|
||||||
|
Timber.e(throwable, "Error occurred while making claim");
|
||||||
|
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleClaimResult(String wikidataEntityId, String revisionId) {
|
||||||
|
if (revisionId != null) {
|
||||||
|
wikidataEditListener.onSuccessfulWikidataEdit();
|
||||||
|
showSuccessToast();
|
||||||
|
logEdit(revisionId);
|
||||||
|
} else {
|
||||||
|
Timber.d("Unable to make wiki data edit for entity %s", wikidataEntityId);
|
||||||
|
ViewUtil.showLongToast(context, context.getString(R.string.wikidata_edit_failure));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log the Wikidata edit by adding Wikimedia Commons App tag to the edit
|
||||||
|
* @param revisionId
|
||||||
|
*/
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
private void logEdit(String revisionId) {
|
||||||
|
Observable.fromCallable(() -> mediaWikiApi.addWikidataEditTag(revisionId))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(result -> {
|
||||||
|
if (result) {
|
||||||
|
Timber.d("Wikidata edit was tagged successfully");
|
||||||
|
} else {
|
||||||
|
Timber.d("Wikidata edit couldn't be tagged");
|
||||||
|
}
|
||||||
|
}, throwable -> {
|
||||||
|
Timber.e(throwable, "Error occurred while adding tag to the edit");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a success toast when the edit is made successfully
|
||||||
|
*/
|
||||||
|
private void showSuccessToast() {
|
||||||
|
String title = directPrefs.getString("Title", "");
|
||||||
|
String successStringTemplate = context.getString(R.string.successful_wikidata_edit);
|
||||||
|
String successMessage = String.format(Locale.getDefault(), successStringTemplate, title);
|
||||||
|
ViewUtil.showLongToast(context, successMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats and returns the filename as accepted by the wiki base API
|
||||||
|
* https://www.mediawiki.org/wiki/Wikibase/API#wbcreateclaim
|
||||||
|
*
|
||||||
|
* @param fileName
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getFileName(String fileName) {
|
||||||
|
fileName = String.format("\"%s\"", fileName.replace("File:", ""));
|
||||||
|
Timber.d("Wikidata property name is %s", fileName);
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue