With wikidata changes (#3199)

This commit is contained in:
Vivek Maskara 2019-11-23 15:26:18 +05:30 committed by Ashish Kumar
parent 02f5cdac59
commit 891d9ec41c
15 changed files with 360 additions and 84 deletions

View file

@ -1,40 +1,70 @@
package fr.free.nrw.commons.wikidata;
import org.wikipedia.csrf.CsrfTokenClient;
import org.wikipedia.dataclient.Service;
import org.jetbrains.annotations.NotNull;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import fr.free.nrw.commons.wikidata.model.AddEditTagResponse;
import io.reactivex.Observable;
import static fr.free.nrw.commons.di.NetworkingModule.NAMED_WIKI_DATA_CSRF;
import io.reactivex.ObservableSource;
import okhttp3.MediaType;
import okhttp3.RequestBody;
@Singleton
public class WikidataClient {
private final Service service;
private final CsrfTokenClient csrfTokenClient;
private final WikidataInterface wikidataInterface;
@Inject
public WikidataClient(@Named("wikidata-service") Service service,
@Named(NAMED_WIKI_DATA_CSRF) CsrfTokenClient csrfTokenClient) {
this.service = service;
this.csrfTokenClient = csrfTokenClient;
public WikidataClient(WikidataInterface wikidataInterface) {
this.wikidataInterface = wikidataInterface;
}
public Observable<Long> createClaim(String entityId, String property, String snaktype, String value) {
try {
return service.postCreateClaim(entityId, snaktype, property, value, "en", csrfTokenClient.getTokenBlocking())
.map(mwPostResponse -> {
if (mwPostResponse.getSuccessVal() == 1) {
return 1L;
}
return -1L;
});
} catch (Throwable throwable) {
return Observable.just(-1L);
}
/**
* Create wikidata claim to add P18 value
* @param entityId wikidata entity ID
* @param value value of the P18 edit
* @return revisionID of the edit
*/
Observable<Long> createClaim(String entityId, String value) {
return getCsrfToken()
.flatMap(csrfToken -> wikidataInterface.postCreateClaim(toRequestBody(entityId),
toRequestBody("value"),
toRequestBody("P18"),
toRequestBody(value),
toRequestBody("en"),
toRequestBody(csrfToken)))
.map(mwPostResponse -> mwPostResponse.getPageinfo().getLastrevid());
}
/**
* Converts string value to RequestBody for multipart request
*/
private RequestBody toRequestBody(String value) {
return RequestBody.create(MediaType.parse("text/plain"), value);
}
/**
* Get csrf token for wikidata edit
*/
@NotNull
private Observable<String> getCsrfToken() {
return wikidataInterface.getCsrfToken().map(mwQueryResponse -> mwQueryResponse.query().csrfToken());
}
/**
* Add edit tag for a given revision ID. The app currently uses this to tag P18 edits
* @param revisionId revision ID of the page edited
* @param tag to be added
* @param reason to be mentioned
*/
ObservableSource<AddEditTagResponse> addEditTag(Long revisionId, String tag, String reason) {
return getCsrfToken()
.flatMap(csrfToken -> wikidataInterface.addEditTag(String.valueOf(revisionId),
tag,
reason,
csrfToken));
}
}

View file

@ -10,7 +10,6 @@ import javax.inject.Named;
import javax.inject.Singleton;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.actions.PageEditClient;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.android.schedulers.AndroidSchedulers;
@ -32,19 +31,16 @@ public class WikidataEditService {
private final WikidataEditListener wikidataEditListener;
private final JsonKvStore directKvStore;
private final WikidataClient wikidataClient;
private final PageEditClient wikiDataPageEditClient;
@Inject
public WikidataEditService(Context context,
WikidataEditListener wikidataEditListener,
@Named("default_preferences") JsonKvStore directKvStore,
WikidataClient wikidataClient,
@Named("wikidata-page-edit") PageEditClient wikiDataPageEditClient) {
WikidataEditService(Context context,
WikidataEditListener wikidataEditListener,
@Named("default_preferences") JsonKvStore directKvStore,
WikidataClient wikidataClient) {
this.context = context;
this.wikidataEditListener = wikidataEditListener;
this.directKvStore = directKvStore;
this.wikidataClient = wikidataClient;
this.wikiDataPageEditClient = wikiDataPageEditClient;
}
/**
@ -85,11 +81,11 @@ public class WikidataEditService {
String propertyValue = getFileName(fileName);
Timber.d(propertyValue);
wikidataClient.createClaim(wikidataEntityId, "P18", "value", propertyValue)
Timber.d("Entity id is %s and property value is %s", wikidataEntityId, propertyValue);
wikidataClient.createClaim(wikidataEntityId, propertyValue)
.flatMap(revisionId -> {
if (revisionId != -1) {
return wikiDataPageEditClient.addEditTag(revisionId, COMMONS_APP_TAG, COMMONS_APP_EDIT_REASON);
return wikidataClient.addEditTag(revisionId, COMMONS_APP_TAG, COMMONS_APP_EDIT_REASON);
}
throw new RuntimeException("Unable to edit wikidata item");
})

View file

@ -0,0 +1,54 @@
package fr.free.nrw.commons.wikidata;
import androidx.annotation.NonNull;
import org.wikipedia.dataclient.mwapi.MwQueryResponse;
import fr.free.nrw.commons.wikidata.model.AddEditTagResponse;
import fr.free.nrw.commons.wikidata.model.WbCreateClaimResponse;
import io.reactivex.Observable;
import okhttp3.RequestBody;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.Multipart;
import retrofit2.http.POST;
import retrofit2.http.Part;
import static org.wikipedia.dataclient.Service.MW_API_PREFIX;
public interface WikidataInterface {
/**
* Wikidata create claim API. Posts a new claim for the given entity ID
*/
@Headers("Cache-Control: no-cache")
@POST("w/api.php?format=json&errorformat=plaintext&action=wbcreateclaim&errorlang=uselang")
@Multipart
Observable<WbCreateClaimResponse> postCreateClaim(@NonNull @Part("entity") RequestBody entity,
@NonNull @Part("snaktype") RequestBody snakType,
@NonNull @Part("property") RequestBody property,
@NonNull @Part("value") RequestBody value,
@NonNull @Part("uselang") RequestBody useLang,
@NonNull @Part("token") RequestBody token);
/**
* Add edit tag and reason for any revision
*/
@Headers("Cache-Control: no-cache")
@POST(MW_API_PREFIX + "action=tag")
@FormUrlEncoded
Observable<AddEditTagResponse> addEditTag(@NonNull @Field("revid") String revId,
@NonNull @Field("add") String tagName,
@NonNull @Field("reason") String reason,
@NonNull @Field("token") String token);
/**
* Get edit token for wikidata wiki site
*/
@Headers("Cache-Control: no-cache")
@GET(MW_API_PREFIX + "action=query&meta=tokens&type=csrf")
@NonNull
Observable<MwQueryResponse> getCsrfToken();
}

View file

@ -0,0 +1,25 @@
package fr.free.nrw.commons.wikidata.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
/**
* Response class for add edit tag
*/
public class AddEditTagResponse {
@SerializedName("tag")
@Expose
private List<EditTag> tag = null;
public List<EditTag> getTag() {
return tag;
}
public void setTag(List<EditTag> tag) {
this.tag = tag;
}
}

View file

@ -0,0 +1,56 @@
package fr.free.nrw.commons.wikidata.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
/**
* Tag class used when adding wikidata edit tag
*/
public class EditTag {
@SerializedName("revid")
@Expose
private Integer revid;
@SerializedName("status")
@Expose
private String status;
@SerializedName("actionlogid")
@Expose
private Integer actionlogid;
@SerializedName("added")
@Expose
private List<String> added;
@SerializedName("removed")
@Expose
private List<Object> removed;
public EditTag(Integer revid, String status, Integer actionlogid, List<String> added, List<Object> removed) {
this.revid = revid;
this.status = status;
this.actionlogid = actionlogid;
this.added = added;
this.removed = removed;
}
public Integer getRevid() {
return revid;
}
public String getStatus() {
return status;
}
public Integer getActionlogid() {
return actionlogid;
}
public List<String> getAdded() {
return added;
}
public List<Object> getRemoved() {
return removed;
}
}

View file

@ -0,0 +1,21 @@
package fr.free.nrw.commons.wikidata.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* PageInfo model class with last revision id of the edited Wikidata entity
*/
public class PageInfo {
@SerializedName("lastrevid")
@Expose
private Long lastrevid;
public PageInfo(Long lastrevid) {
this.lastrevid = lastrevid;
}
public Long getLastrevid() {
return lastrevid;
}
}

View file

@ -0,0 +1,30 @@
package fr.free.nrw.commons.wikidata.model;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Wikidata create claim response model class
*/
public class WbCreateClaimResponse {
@SerializedName("pageinfo")
@Expose
private PageInfo pageinfo;
@SerializedName("success")
@Expose
private Integer success;
public WbCreateClaimResponse(PageInfo pageinfo, Integer success) {
this.pageinfo = pageinfo;
this.success = success;
}
public PageInfo getPageinfo() {
return pageinfo;
}
public Integer getSuccess() {
return success;
}
}