mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-28 13:23:58 +01:00
Consume login client from data client library (#2894)
Fix actions for review client Use data client library for notifications With delete helper migrated to data client With wikidata edits With notifications and modifications migrated to data client With upload migrated to retrofit Delete unused code Reuse thank interface from the library
This commit is contained in:
parent
623c2f5467
commit
d427a77c2a
35 changed files with 883 additions and 1668 deletions
|
|
@ -1,15 +1,10 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
|
|
@ -20,28 +15,15 @@ import org.apache.http.impl.client.DefaultHttpClient;
|
|||
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.CoreProtocolPNames;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.wikipedia.util.DateUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.auth.AccountUtil;
|
||||
import fr.free.nrw.commons.category.QueryContinue;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.notification.Notification;
|
||||
import fr.free.nrw.commons.notification.NotificationUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import io.reactivex.Single;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
|
@ -51,17 +33,8 @@ import timber.log.Timber;
|
|||
public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
||||
private AbstractHttpClient httpClient;
|
||||
private CustomMwApi api;
|
||||
private CustomMwApi wikidataApi;
|
||||
private Context context;
|
||||
private JsonKvStore defaultKvStore;
|
||||
|
||||
private final String ERROR_CODE_BAD_TOKEN = "badtoken";
|
||||
|
||||
public ApacheHttpClientMediaWikiApi(Context context,
|
||||
String apiURL,
|
||||
String wikidatApiURL,
|
||||
JsonKvStore defaultKvStore) {
|
||||
this.context = context;
|
||||
public ApacheHttpClientMediaWikiApi(String apiURL) {
|
||||
BasicHttpParams params = new BasicHttpParams();
|
||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
|
||||
|
|
@ -74,198 +47,6 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
httpClient.addRequestInterceptor(NetworkInterceptors.getHttpRequestInterceptor());
|
||||
}
|
||||
api = new CustomMwApi(apiURL, httpClient);
|
||||
wikidataApi = new CustomMwApi(wikidatApiURL, httpClient);
|
||||
this.defaultKvStore = defaultKvStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param username String
|
||||
* @param password String
|
||||
* @return String as returned by this.getErrorCodeToReturn()
|
||||
* @throws IOException On api request IO issue
|
||||
*/
|
||||
public String login(String username, String password) throws IOException {
|
||||
String loginToken = getLoginToken();
|
||||
Timber.d("Login token is %s", loginToken);
|
||||
return getErrorCodeToReturn(api.action("clientlogin")
|
||||
.param("rememberMe", "1")
|
||||
.param("username", username)
|
||||
.param("password", password)
|
||||
.param("logintoken", loginToken)
|
||||
.param("loginreturnurl", "https://commons.wikimedia.org")
|
||||
.post());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param username String
|
||||
* @param password String
|
||||
* @param twoFactorCode String
|
||||
* @return String as returned by this.getErrorCodeToReturn()
|
||||
* @throws IOException On api request IO issue
|
||||
*/
|
||||
public String login(String username, String password, String twoFactorCode) throws IOException {
|
||||
String loginToken = getLoginToken();
|
||||
Timber.d("Login token is %s", loginToken);
|
||||
return getErrorCodeToReturn(api.action("clientlogin")
|
||||
.param("rememberMe", "true")
|
||||
.param("username", username)
|
||||
.param("password", password)
|
||||
.param("logintoken", loginToken)
|
||||
.param("logincontinue", "true")
|
||||
.param("OATHToken", twoFactorCode)
|
||||
.post());
|
||||
}
|
||||
|
||||
private String getLoginToken() throws IOException {
|
||||
return api.action("query")
|
||||
.param("action", "query")
|
||||
.param("meta", "tokens")
|
||||
.param("type", "login")
|
||||
.post()
|
||||
.getString("/api/query/tokens/@logintoken");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loginCustomApiResult CustomApiResult Any clientlogin api result
|
||||
* @return String On success: "PASS"
|
||||
* continue: "2FA" (More information required for 2FA)
|
||||
* failure: A failure message code (defined by mediawiki)
|
||||
* misc: genericerror-UI, genericerror-REDIRECT, genericerror-RESTART
|
||||
*/
|
||||
private String getErrorCodeToReturn(CustomApiResult loginCustomApiResult) {
|
||||
String status = loginCustomApiResult.getString("/api/clientlogin/@status");
|
||||
if (status.equals("PASS")) {
|
||||
api.isLoggedIn = true;
|
||||
setAuthCookieOnLogin(true);
|
||||
return status;
|
||||
} else if (status.equals("FAIL")) {
|
||||
setAuthCookieOnLogin(false);
|
||||
return loginCustomApiResult.getString("/api/clientlogin/@messagecode");
|
||||
} else if (
|
||||
status.equals("UI")
|
||||
&& loginCustomApiResult.getString("/api/clientlogin/requests/_v/@id").equals("TOTPAuthenticationRequest")
|
||||
&& loginCustomApiResult.getString("/api/clientlogin/requests/_v/@provider").equals("Two-factor authentication (OATH).")
|
||||
) {
|
||||
setAuthCookieOnLogin(false);
|
||||
return "2FA";
|
||||
}
|
||||
|
||||
// UI, REDIRECT, RESTART
|
||||
return "genericerror-" + status;
|
||||
}
|
||||
|
||||
private void setAuthCookieOnLogin(boolean isLoggedIn) {
|
||||
if (isLoggedIn) {
|
||||
defaultKvStore.putBoolean("isUserLoggedIn", true);
|
||||
defaultKvStore.putString("getAuthCookie", api.getAuthCookie());
|
||||
} else {
|
||||
defaultKvStore.putBoolean("isUserLoggedIn", false);
|
||||
defaultKvStore.remove("getAuthCookie");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthCookie() {
|
||||
return api.getAuthCookie();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAuthCookie(String authCookie) {
|
||||
api.setAuthCookie(authCookie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateLogin() throws IOException {
|
||||
boolean validateLoginResp = api.validateLogin();
|
||||
Timber.d("Validate login response is %s", validateLoginResp);
|
||||
return validateLoginResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEditToken() throws IOException {
|
||||
String editToken = api.action("query")
|
||||
.param("meta", "tokens")
|
||||
.post()
|
||||
.getString("/api/query/tokens/@csrftoken");
|
||||
Timber.d("MediaWiki edit token is %s", editToken);
|
||||
return editToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCentralAuthToken() throws IOException {
|
||||
CustomApiResult result = api.action("centralauthtoken").get();
|
||||
String centralAuthToken = result.getString("/api/centralauthtoken/@centralauthtoken");
|
||||
|
||||
Timber.d("MediaWiki Central auth token is %s", centralAuthToken);
|
||||
|
||||
if ((centralAuthToken == null || centralAuthToken.isEmpty())
|
||||
&& "notLoggedIn".equals(result.getString("api/error/@code"))) {
|
||||
Timber.d("Central auth token isn't valid. Trying to fetch a fresh token");
|
||||
api.removeAllCookies();
|
||||
String loginResultCode = login(AccountUtil.getUserName(context), AccountUtil.getPassword(context));
|
||||
if (loginResultCode.equals("PASS")) {
|
||||
return getCentralAuthToken();
|
||||
} else if (loginResultCode.equals("2FA")) {
|
||||
Timber.e("Cannot refresh session for 2FA enabled user. Login required");
|
||||
} else {
|
||||
Timber.e("Error occurred in refreshing session. Error code is %s", loginResultCode);
|
||||
}
|
||||
} else {
|
||||
Timber.e("Error occurred while fetching auth token. Error code is %s and message is %s",
|
||||
result.getString("api/error/@code"),
|
||||
result.getString("api/error/@info"));
|
||||
}
|
||||
return centralAuthToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean thank(String editToken, long revision) throws IOException {
|
||||
CustomApiResult res = api.action("thank")
|
||||
.param("rev", revision)
|
||||
.param("token", editToken)
|
||||
.param("source", CommonsApplication.getInstance().getUserAgent())
|
||||
.post();
|
||||
String r = res.getString("/api/result/@success");
|
||||
// Does this correctly check the success/failure?
|
||||
// The docs https://www.mediawiki.org/wiki/Extension:Thanks seems unclear about that.
|
||||
return r.equals("success");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String edit(String editToken, String processedPageContent, String filename, String summary) throws IOException {
|
||||
return api.action("edit")
|
||||
.param("title", filename)
|
||||
.param("token", getEditToken())
|
||||
.param("text", processedPageContent)
|
||||
.param("summary", summary)
|
||||
.post()
|
||||
.getString("/api/edit/@result");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String appendEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException {
|
||||
return api.action("edit")
|
||||
.param("title", filename)
|
||||
.param("token", getEditToken())
|
||||
.param("appendtext", processedPageContent)
|
||||
.param("summary", summary)
|
||||
.post()
|
||||
.getString("/api/edit/@result");
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String prependEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException {
|
||||
return api.action("edit")
|
||||
.param("title", filename)
|
||||
.param("token", getEditToken())
|
||||
.param("prependtext", processedPageContent)
|
||||
.param("summary", summary)
|
||||
.post()
|
||||
.getString("/api/edit/@result");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -297,89 +78,6 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWikidataCsrfToken() throws IOException {
|
||||
String wikidataCsrfToken = wikidataApi.action("query")
|
||||
.param("action", "query")
|
||||
.param("centralauthtoken", getCentralAuthToken())
|
||||
.param("meta", "tokens")
|
||||
.post()
|
||||
.getString("/api/query/tokens/@csrftoken");
|
||||
Timber.d("Wikidata csrf token is %s", wikidataCsrfToken);
|
||||
return wikidataCsrfToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new claim using the wikidata API
|
||||
* https://www.mediawiki.org/wiki/Wikibase/API
|
||||
*
|
||||
* @param entityId the wikidata entity to be edited
|
||||
* @param property the property to be edited, for eg P18 for images
|
||||
* @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
|
||||
* @return returns revisionId if the claim is successfully created else returns null
|
||||
* @throws IOException
|
||||
*/
|
||||
@Nullable
|
||||
@Override
|
||||
public String wikidataCreateClaim(String entityId, String property, String snaktype, String value) throws IOException {
|
||||
Timber.d("Filename is %s", value);
|
||||
CustomApiResult result = wikidataApi.action("wbcreateclaim")
|
||||
.param("entity", entityId)
|
||||
.param("centralauthtoken", getCentralAuthToken())
|
||||
.param("token", getWikidataCsrfToken())
|
||||
.param("snaktype", snaktype)
|
||||
.param("property", property)
|
||||
.param("value", value)
|
||||
.post();
|
||||
|
||||
if (result == null || result.getNode("api") == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Node node = result.getNode("api").getDocument();
|
||||
Element element = (Element) node;
|
||||
|
||||
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 {
|
||||
CustomApiResult 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;
|
||||
}
|
||||
|
||||
if ("success".equals(result.getString("api/tag/result/@status"))) {
|
||||
return true;
|
||||
} else {
|
||||
Timber.e("Error occurred in creating claim. Error code is: %s and message is %s",
|
||||
result.getString("api/error/@code"),
|
||||
result.getString("api/error/@info"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public LogEventResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException {
|
||||
|
|
@ -428,128 +126,6 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
|
|||
.getString("/api/query/pages/page/revisions/rev");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public List<Notification> getNotifications(boolean archived) {
|
||||
CustomApiResult notificationNode = null;
|
||||
String notfilter;
|
||||
try {
|
||||
if (archived) {
|
||||
notfilter = "read";
|
||||
} else {
|
||||
notfilter = "!read";
|
||||
}
|
||||
String language = Locale.getDefault().getLanguage();
|
||||
if (StringUtils.isBlank(language)) {
|
||||
//if no language is set we use the default user language defined on wikipedia
|
||||
language = "user";
|
||||
}
|
||||
notificationNode = api.action("query")
|
||||
.param("notprop", "list")
|
||||
.param("format", "xml")
|
||||
.param("meta", "notifications")
|
||||
.param("notformat", "model")
|
||||
.param("notwikis", "wikidatawiki|commonswiki|enwiki")
|
||||
.param("notfilter", notfilter)
|
||||
.param("uselang", language)
|
||||
.get()
|
||||
.getNode("/api/query/notifications/list");
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "Failed to obtain searchCategories");
|
||||
}
|
||||
|
||||
if (notificationNode == null
|
||||
|| notificationNode.getDocument() == null
|
||||
|| notificationNode.getDocument().getChildNodes() == null
|
||||
|| notificationNode.getDocument().getChildNodes().getLength() == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
NodeList childNodes = notificationNode.getDocument().getChildNodes();
|
||||
return NotificationUtils.getNotificationsFromList(context, childNodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markNotificationAsRead(Notification notification) throws IOException {
|
||||
Timber.d("Trying to mark notification as read: %s", notification.toString());
|
||||
String result = api.action("echomarkread")
|
||||
.param("token", getEditToken())
|
||||
.param("list", notification.notificationId)
|
||||
.post()
|
||||
.getString("/api/query/echomarkread/@result");
|
||||
|
||||
if (StringUtils.isBlank(result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return result.equals("success");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Single<UploadStash> uploadFile(
|
||||
String filename,
|
||||
@NonNull InputStream file,
|
||||
long dataLength,
|
||||
Uri fileUri,
|
||||
Uri contentProviderUri,
|
||||
ProgressListener progressListener) {
|
||||
return Single.fromCallable(() -> {
|
||||
CustomApiResult result = api.uploadToStash(filename, file, dataLength, getEditToken(), progressListener::onProgress);
|
||||
|
||||
Timber.wtf("Result: " + result.toString());
|
||||
|
||||
String resultStatus = result.getString("/api/upload/@result");
|
||||
if (!resultStatus.equals("Success")) {
|
||||
String errorCode = result.getString("/api/error/@code");
|
||||
Timber.e(errorCode);
|
||||
|
||||
if (errorCode.equals(ERROR_CODE_BAD_TOKEN)) {
|
||||
ViewUtil.showLongToast(context, R.string.bad_token_error_proposed_solution);
|
||||
}
|
||||
return new UploadStash(errorCode, resultStatus, filename, "");
|
||||
} else {
|
||||
String filekey = result.getString("/api/upload/@filekey");
|
||||
return new UploadStash("", resultStatus, filename, filekey);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public Single<UploadResult> uploadFileFinalize(
|
||||
String filename,
|
||||
String filekey,
|
||||
String pageContents,
|
||||
String editSummary) throws IOException {
|
||||
return Single.fromCallable(() -> {
|
||||
CustomApiResult result = api.uploadFromStash(
|
||||
filename, filekey, pageContents, editSummary,
|
||||
getEditToken());
|
||||
|
||||
Timber.d("Result: %s", result.toString());
|
||||
|
||||
String resultStatus = result.getString("/api/upload/@result");
|
||||
if (!resultStatus.equals("Success")) {
|
||||
String errorCode = result.getString("/api/error/@code");
|
||||
Timber.e(errorCode);
|
||||
|
||||
if (errorCode.equals(ERROR_CODE_BAD_TOKEN)) {
|
||||
ViewUtil.showLongToast(context, R.string.bad_token_error_proposed_solution);
|
||||
}
|
||||
return new UploadResult(resultStatus, errorCode);
|
||||
} else {
|
||||
Date dateUploaded = parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));
|
||||
String canonicalFilename = "File:" + result.getString("/api/upload/@filename")
|
||||
.replace("_", " ")
|
||||
.trim(); // Title vs Filename
|
||||
String imageUrl = result.getString("/api/upload/imageinfo/@url");
|
||||
return new UploadResult(resultStatus, dateUploaded, canonicalFilename, imageUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a user is currently blocked from Commons
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,69 +1,19 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import fr.free.nrw.commons.notification.Notification;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.reactivex.Single;
|
||||
|
||||
public interface MediaWikiApi {
|
||||
|
||||
String getAuthCookie();
|
||||
|
||||
void setAuthCookie(String authCookie);
|
||||
|
||||
String login(String username, String password) throws IOException;
|
||||
|
||||
String login(String username, String password, String twoFactorCode) throws IOException;
|
||||
|
||||
boolean validateLogin() throws IOException;
|
||||
|
||||
String getEditToken() throws IOException;
|
||||
|
||||
String getWikidataCsrfToken() throws IOException;
|
||||
|
||||
String getCentralAuthToken() throws IOException;
|
||||
|
||||
@NonNull
|
||||
Single<UploadStash> uploadFile(String filename, InputStream file,
|
||||
long dataLength, Uri fileUri, Uri contentProviderUri,
|
||||
final ProgressListener progressListener);
|
||||
|
||||
@NonNull
|
||||
Single<UploadResult> uploadFileFinalize(String filename, String filekey,
|
||||
String pageContents, String editSummary) throws IOException;
|
||||
@Nullable
|
||||
String edit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
|
||||
|
||||
@Nullable
|
||||
String prependEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
|
||||
|
||||
@Nullable
|
||||
String appendEdit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
|
||||
|
||||
@Nullable
|
||||
String wikidataCreateClaim(String entityId, String property, String snaktype, String value) throws IOException;
|
||||
|
||||
@Nullable
|
||||
boolean addWikidataEditTag(String revisionId) throws IOException;
|
||||
|
||||
Single<String> parseWikicode(String source);
|
||||
|
||||
@NonNull
|
||||
Single<MediaResult> fetchMediaByFilename(String filename);
|
||||
|
||||
@NonNull
|
||||
List<Notification> getNotifications(boolean archived) throws IOException;
|
||||
|
||||
@NonNull
|
||||
boolean markNotificationAsRead(Notification notification) throws IOException;
|
||||
|
||||
@Nullable
|
||||
String revisionsByFilename(String filename) throws IOException;
|
||||
|
||||
|
|
@ -76,8 +26,6 @@ public interface MediaWikiApi {
|
|||
|
||||
// Single<CampaignResponseDTO> getCampaigns();
|
||||
|
||||
boolean thank(String editToken, long revision) throws IOException;
|
||||
|
||||
interface ProgressListener {
|
||||
void onProgress(long transferred, long total);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,90 +0,0 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class UploadResult {
|
||||
private String errorCode;
|
||||
private String resultStatus;
|
||||
private Date dateUploaded;
|
||||
private String imageUrl;
|
||||
private String canonicalFilename;
|
||||
|
||||
/**
|
||||
* Minimal constructor
|
||||
*
|
||||
* @param resultStatus Upload result status
|
||||
* @param errorCode Upload error code
|
||||
*/
|
||||
UploadResult(String resultStatus, String errorCode) {
|
||||
this.resultStatus = resultStatus;
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full-fledged constructor
|
||||
* @param resultStatus Upload result status
|
||||
* @param dateUploaded Uploaded date
|
||||
* @param canonicalFilename Uploaded file name
|
||||
* @param imageUrl Uploaded image file name
|
||||
*/
|
||||
UploadResult(String resultStatus, Date dateUploaded, String canonicalFilename, String imageUrl) {
|
||||
this.resultStatus = resultStatus;
|
||||
this.dateUploaded = dateUploaded;
|
||||
this.canonicalFilename = canonicalFilename;
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UploadResult{" +
|
||||
"errorCode='" + errorCode + '\'' +
|
||||
", resultStatus='" + resultStatus + '\'' +
|
||||
", dateUploaded='" + (dateUploaded == null ? "" : dateUploaded.toString()) + '\'' +
|
||||
", imageUrl='" + imageUrl + '\'' +
|
||||
", canonicalFilename='" + canonicalFilename + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets uploaded date
|
||||
* @return Upload date
|
||||
*/
|
||||
public Date getDateUploaded() {
|
||||
return dateUploaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets image url
|
||||
* @return Uploaded image url
|
||||
*/
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets canonical file name
|
||||
* @return Uploaded file name
|
||||
*/
|
||||
public String getCanonicalFilename() {
|
||||
return canonicalFilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets upload error code
|
||||
* @return Error code
|
||||
*/
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets upload result status
|
||||
* @return Upload result status
|
||||
*/
|
||||
public String getResultStatus() {
|
||||
return resultStatus;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class UploadStash {
|
||||
@NonNull
|
||||
private String errorCode;
|
||||
@NonNull
|
||||
private String resultStatus;
|
||||
@NonNull
|
||||
private String filename;
|
||||
@NonNull
|
||||
private String filekey;
|
||||
|
||||
@NonNull
|
||||
public final String getErrorCode() {
|
||||
return this.errorCode;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public final String getResultStatus() {
|
||||
return this.resultStatus;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public final String getFilename() {
|
||||
return this.filename;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public final String getFilekey() {
|
||||
return this.filekey;
|
||||
}
|
||||
|
||||
public UploadStash(@NonNull String errorCode, @NonNull String resultStatus, @NonNull String filename, @NonNull String filekey) {
|
||||
this.errorCode = errorCode;
|
||||
this.resultStatus = resultStatus;
|
||||
this.filename = filename;
|
||||
this.filekey = filekey;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "UploadStash(errorCode=" + this.errorCode + ", resultStatus=" + this.resultStatus + ", filename=" + this.filename + ", filekey=" + this.filekey + ")";
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return ((this.errorCode.hashCode() * 31 + this.resultStatus.hashCode()
|
||||
) * 31 + this.filename.hashCode()
|
||||
) * 31 + this.filekey.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (this != obj) {
|
||||
if (obj instanceof UploadStash) {
|
||||
UploadStash that = (UploadStash)obj;
|
||||
if (this.errorCode.equals(that.errorCode)
|
||||
&& this.resultStatus.equals(that.resultStatus)
|
||||
&& this.filename.equals(that.filename)
|
||||
&& this.filekey.equals(that.filekey)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue