mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Consolidated media wiki api calls in a single place
This commit is contained in:
parent
5396fc6ed0
commit
599e7bb453
18 changed files with 467 additions and 376 deletions
|
|
@ -8,41 +8,30 @@ import android.app.Application;
|
|||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.util.LruCache;
|
||||
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.stetho.Stetho;
|
||||
|
||||
import fr.free.nrw.commons.caching.CacheController;
|
||||
import fr.free.nrw.commons.category.Category;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.data.DBOpenHelper;
|
||||
import fr.free.nrw.commons.modifications.ModifierSequence;
|
||||
import fr.free.nrw.commons.auth.AccountUtil;
|
||||
import fr.free.nrw.commons.nearby.NearbyPlaces;
|
||||
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
|
||||
import org.acra.ACRA;
|
||||
import org.acra.ReportingInteractionMode;
|
||||
import org.acra.annotation.ReportsCrashes;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
import org.apache.http.impl.client.AbstractHttpClient;
|
||||
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 java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import fr.free.nrw.commons.auth.AccountUtil;
|
||||
import fr.free.nrw.commons.caching.CacheController;
|
||||
import fr.free.nrw.commons.category.Category;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.data.DBOpenHelper;
|
||||
import fr.free.nrw.commons.modifications.ModifierSequence;
|
||||
import fr.free.nrw.commons.mwapi.ApacheHttpClientMediaWikiApi;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import fr.free.nrw.commons.nearby.NearbyPlaces;
|
||||
import fr.free.nrw.commons.utils.FileUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
|
@ -76,9 +65,8 @@ public class CommonsApplication extends Application {
|
|||
public static final String FEEDBACK_EMAIL_SUBJECT = "Commons Android App (%s) Feedback";
|
||||
|
||||
private static CommonsApplication instance = null;
|
||||
private AbstractHttpClient httpClient = null;
|
||||
private MWApi api = null;
|
||||
LruCache<String, String> thumbnailUrlCache = new LruCache<>(1024);
|
||||
private MediaWikiApi api = null;
|
||||
private LruCache<String, String> thumbnailUrlCache = new LruCache<>(1024);
|
||||
private CacheController cacheData = null;
|
||||
private DBOpenHelper dbOpenHelper = null;
|
||||
private NearbyPlaces nearbyPlaces = null;
|
||||
|
|
@ -98,35 +86,13 @@ public class CommonsApplication extends Application {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public AbstractHttpClient getHttpClient() {
|
||||
if (httpClient == null) {
|
||||
httpClient = newHttpClient();
|
||||
}
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
private AbstractHttpClient newHttpClient() {
|
||||
BasicHttpParams params = new BasicHttpParams();
|
||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
|
||||
final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
|
||||
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
|
||||
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
|
||||
params.setParameter(CoreProtocolPNames.USER_AGENT, "Commons/" + BuildConfig.VERSION_NAME + " (https://mediawiki.org/wiki/Apps/Commons) Android/" + Build.VERSION.RELEASE);
|
||||
return new DefaultHttpClient(cm, params);
|
||||
}
|
||||
|
||||
public MWApi getMWApi() {
|
||||
public MediaWikiApi getMWApi() {
|
||||
if (api == null) {
|
||||
api = newMWApi();
|
||||
api = new ApacheHttpClientMediaWikiApi(API_URL);
|
||||
}
|
||||
return api;
|
||||
}
|
||||
|
||||
private MWApi newMWApi() {
|
||||
return new MWApi(API_URL, getHttpClient());
|
||||
}
|
||||
|
||||
public CacheController getCacheData() {
|
||||
if (cacheData == null) {
|
||||
cacheData = new CacheController();
|
||||
|
|
@ -174,9 +140,6 @@ public class CommonsApplication extends Application {
|
|||
|
||||
Fresco.initialize(this);
|
||||
|
||||
// Initialize EventLogging
|
||||
EventLog.setApp(this);
|
||||
|
||||
//For caching area -> categories
|
||||
cacheData = new CacheController();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
package fr.free.nrw.commons;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.impl.client.AbstractHttpClient;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
import in.yuvi.http.fluent.Http;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class EventLog {
|
||||
|
||||
private static CommonsApplication app;
|
||||
|
||||
private static class LogTask extends AsyncTask<LogBuilder, Void, Boolean> {
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(LogBuilder... logBuilders) {
|
||||
|
||||
boolean allSuccess = true;
|
||||
// Not using the default URL connection, since that seems to have different behavior than the rest of the code
|
||||
for(LogBuilder logBuilder: logBuilders) {
|
||||
try {
|
||||
URL url = logBuilder.toUrl();
|
||||
AbstractHttpClient httpClient = CommonsApplication.getInstance().getHttpClient();
|
||||
HttpResponse response = Http.get(url.toString()).use(httpClient).asResponse();
|
||||
|
||||
if(response.getStatusLine().getStatusCode() != 204) {
|
||||
allSuccess = false;
|
||||
}
|
||||
Timber.d("EventLog hit %s", url);
|
||||
|
||||
} catch (IOException e) {
|
||||
// Probably just ignore for now. Can be much more robust with a service, etc later on.
|
||||
Timber.d("IO Error, EventLog hit skipped");
|
||||
}
|
||||
}
|
||||
|
||||
return allSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
private static final String DEVICE;
|
||||
static {
|
||||
if (Build.MODEL.startsWith(Build.MANUFACTURER)) {
|
||||
DEVICE = Utils.capitalize(Build.MODEL);
|
||||
} else {
|
||||
DEVICE = Utils.capitalize(Build.MANUFACTURER) + " " + Build.MODEL;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setApp(CommonsApplication app) {
|
||||
EventLog.app = app;
|
||||
}
|
||||
|
||||
public static class LogBuilder {
|
||||
private JSONObject data;
|
||||
private long rev;
|
||||
private String schema;
|
||||
|
||||
private LogBuilder(String schema, long revision) {
|
||||
data = new JSONObject();
|
||||
this.schema = schema;
|
||||
this.rev = revision;
|
||||
}
|
||||
|
||||
public LogBuilder param(String key, Object value) {
|
||||
try {
|
||||
data.put(key, value);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private URL toUrl() {
|
||||
JSONObject fullData = new JSONObject();
|
||||
try {
|
||||
fullData.put("schema", schema);
|
||||
fullData.put("revision", rev);
|
||||
fullData.put("wiki", CommonsApplication.EVENTLOG_WIKI);
|
||||
data.put("device", DEVICE);
|
||||
data.put("platform", "Android/" + Build.VERSION.RELEASE);
|
||||
data.put("appversion", "Android/" + BuildConfig.VERSION_NAME);
|
||||
fullData.put("event", data);
|
||||
return new URL(CommonsApplication.EVENTLOG_URL + "?" + Utils.urlEncode(fullData.toString()) + ";");
|
||||
} catch (MalformedURLException | JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// force param disregards user preference
|
||||
// Use *only* for tracking the user preference change for EventLogging
|
||||
// Attempting to use anywhere else will cause kitten explosions
|
||||
public void log(boolean force) {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(app);
|
||||
if(!settings.getBoolean(Prefs.TRACKING_ENABLED, true) && !force) {
|
||||
return; // User has disabled tracking
|
||||
}
|
||||
LogTask logTask = new LogTask();
|
||||
logTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, this);
|
||||
}
|
||||
|
||||
public void log() {
|
||||
log(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static LogBuilder schema(String schema, long revision) {
|
||||
return new LogBuilder(schema, revision);
|
||||
}
|
||||
|
||||
public static LogBuilder schema(Object[] scid) {
|
||||
if(scid.length != 2) {
|
||||
throw new IllegalArgumentException("Needs an object array with schema as first param and revision as second");
|
||||
}
|
||||
return schema((String)scid[0], (Long)scid[1]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
package fr.free.nrw.commons;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.impl.client.AbstractHttpClient;
|
||||
import org.mediawiki.api.ApiResult;
|
||||
|
||||
/**
|
||||
* @author Addshore
|
||||
*/
|
||||
public class MWApi extends org.mediawiki.api.MWApi {
|
||||
|
||||
/** We don't actually use this but need to pass it in requests */
|
||||
private static String LOGIN_RETURN_TO_URL = "https://commons.wikimedia.org";
|
||||
|
||||
public MWApi(String apiURL, AbstractHttpClient client) {
|
||||
super(apiURL, client);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 token = this.getLoginToken();
|
||||
ApiResult loginApiResult = this.action("clientlogin")
|
||||
.param("rememberMe", "1")
|
||||
.param("username", username)
|
||||
.param("password", password)
|
||||
.param("logintoken", token)
|
||||
.param("loginreturnurl", LOGIN_RETURN_TO_URL)
|
||||
.post();
|
||||
return this.getErrorCodeToReturn( loginApiResult );
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 token = this.getLoginToken();//TODO cache this instead of calling again when 2FAing
|
||||
ApiResult loginApiResult = this.action("clientlogin")
|
||||
.param("rememberMe", "1")
|
||||
.param("username", username)
|
||||
.param("password", password)
|
||||
.param("logintoken", token)
|
||||
.param("logincontinue", "1")
|
||||
.param("OATHToken", twoFactorCode)
|
||||
.post();
|
||||
|
||||
return this.getErrorCodeToReturn( loginApiResult );
|
||||
}
|
||||
|
||||
private String getLoginToken() throws IOException {
|
||||
ApiResult tokenResult = this.action("query")
|
||||
.param("action", "query")
|
||||
.param("meta", "tokens")
|
||||
.param("type", "login")
|
||||
.post();
|
||||
return tokenResult.getString("/api/query/tokens/@logintoken");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loginApiResult ApiResult 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( ApiResult loginApiResult ) {
|
||||
String status = loginApiResult.getString("/api/clientlogin/@status");
|
||||
if (status.equals("PASS")) {
|
||||
this.isLoggedIn = true;
|
||||
return status;
|
||||
} else if (status.equals("FAIL")) {
|
||||
return loginApiResult.getString("/api/clientlogin/@messagecode");
|
||||
} else if (
|
||||
status.equals("UI")
|
||||
&& loginApiResult.getString("/api/clientlogin/requests/_v/@id").equals("TOTPAuthenticationRequest")
|
||||
&& loginApiResult.getString("/api/clientlogin/requests/_v/@provider").equals("Two-factor authentication (OATH).")
|
||||
) {
|
||||
return "2FA";
|
||||
}
|
||||
|
||||
// UI, REDIRECT, RESTART
|
||||
return "genericerror-" + status;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
|
|
@ -62,16 +63,8 @@ public class MediaDataExtractor {
|
|||
throw new IllegalStateException("Tried to call MediaDataExtractor.fetch() again.");
|
||||
}
|
||||
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
ApiResult result = api.action("query")
|
||||
.param("prop", "revisions")
|
||||
.param("titles", filename)
|
||||
.param("rvprop", "content")
|
||||
.param("rvlimit", 1)
|
||||
.param("rvgeneratexml", 1)
|
||||
.get();
|
||||
|
||||
processResult(result);
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
processResult(api.fetchMediaByFilename(filename));
|
||||
fetched = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@ package fr.free.nrw.commons;
|
|||
import android.os.AsyncTask;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mediawiki.api.ApiResult;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
|
||||
class MediaThumbnailFetchTask extends AsyncTask<String, String, String> {
|
||||
private static final String THUMB_SIZE = "640";
|
||||
protected final Media media;
|
||||
|
||||
public MediaThumbnailFetchTask(@NonNull Media media) {
|
||||
|
|
@ -16,15 +15,8 @@ class MediaThumbnailFetchTask extends AsyncTask<String, String, String> {
|
|||
@Override
|
||||
protected String doInBackground(String... params) {
|
||||
try {
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
ApiResult result =api.action("query")
|
||||
.param("format", "xml")
|
||||
.param("prop", "imageinfo")
|
||||
.param("iiprop", "url")
|
||||
.param("iiurlwidth", THUMB_SIZE)
|
||||
.param("titles", params[0])
|
||||
.get();
|
||||
return result.getString("/api/query/pages/page/imageinfo/ii/@thumburl");
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
return api.findThumbnailByFilename(params[0]);
|
||||
} catch (Exception e) {
|
||||
// Do something better!
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import android.accounts.NetworkErrorException;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.MWApi;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
|
||||
public class WikiAccountAuthenticator extends AbstractAccountAuthenticator {
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ public class WikiAccountAuthenticator extends AbstractAccountAuthenticator {
|
|||
}
|
||||
|
||||
private String getAuthCookie(String username, String password) throws IOException {
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
//TODO add 2fa support here
|
||||
String result = api.login(username, password);
|
||||
if(result.equals("PASS")) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package fr.free.nrw.commons.category;
|
|||
import android.os.AsyncTask;
|
||||
import android.view.View;
|
||||
|
||||
import fr.free.nrw.commons.MWApi;
|
||||
import org.mediawiki.api.ApiResult;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -12,6 +11,7 @@ import java.util.Calendar;
|
|||
import java.util.Iterator;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
|
|
@ -79,20 +79,13 @@ public class MethodAUpdater extends AsyncTask<Void, Void, ArrayList<String>> {
|
|||
protected ArrayList<String> doInBackground(Void... voids) {
|
||||
|
||||
//otherwise if user has typed something in that isn't in cache, search API for matching categories
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
ApiResult result;
|
||||
ArrayList<String> categories = new ArrayList<>();
|
||||
|
||||
//URL https://commons.wikimedia.org/w/api.php?action=query&format=xml&list=search&srwhat=text&srenablerewrites=1&srnamespace=14&srlimit=10&srsearch=
|
||||
try {
|
||||
result = api.action("query")
|
||||
.param("format", "xml")
|
||||
.param("list", "search")
|
||||
.param("srwhat", "text")
|
||||
.param("srnamespace", "14")
|
||||
.param("srlimit", catFragment.SEARCH_CATS_LIMIT)
|
||||
.param("srsearch", filter)
|
||||
.get();
|
||||
result = api.searchCategories(CategorizationFragment.SEARCH_CATS_LIMIT, filter);
|
||||
Timber.d("Method A URL filter %s", result);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "IO Exception: ");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import android.os.AsyncTask;
|
|||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import fr.free.nrw.commons.MWApi;
|
||||
import org.mediawiki.api.ApiResult;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -13,6 +12,7 @@ import java.util.Calendar;
|
|||
import java.util.Iterator;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
|
|
@ -95,15 +95,11 @@ public class PrefixUpdater extends AsyncTask<Void, Void, ArrayList<String>> {
|
|||
|
||||
//otherwise if user has typed something in that isn't in cache, search API for matching categories
|
||||
//URL: https://commons.wikimedia.org/w/api.php?action=query&list=allcategories&acprefix=filter&aclimit=25
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
ApiResult result;
|
||||
ArrayList<String> categories = new ArrayList<>();
|
||||
try {
|
||||
result = api.action("query")
|
||||
.param("list", "allcategories")
|
||||
.param("acprefix", filter)
|
||||
.param("aclimit", catFragment.SEARCH_CATS_LIMIT)
|
||||
.get();
|
||||
result = api.allCategories(CategorizationFragment.SEARCH_CATS_LIMIT, this.filter);
|
||||
Timber.d("Prefix URL filter %s", result);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "IO Exception: ");
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ package fr.free.nrw.commons.category;
|
|||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import fr.free.nrw.commons.MWApi;
|
||||
import org.mediawiki.api.ApiResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
|
|
@ -34,20 +34,13 @@ public class TitleCategories extends AsyncTask<Void, Void, ArrayList<String>> {
|
|||
@Override
|
||||
protected ArrayList<String> doInBackground(Void... voids) {
|
||||
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
ApiResult result;
|
||||
ArrayList<String> items = new ArrayList<>();
|
||||
|
||||
//URL https://commons.wikimedia.org/w/api.php?action=query&format=xml&list=search&srwhat=text&srenablerewrites=1&srnamespace=14&srlimit=10&srsearch=
|
||||
try {
|
||||
result = api.action("query")
|
||||
.param("format", "xml")
|
||||
.param("list", "search")
|
||||
.param("srwhat", "text")
|
||||
.param("srnamespace", "14")
|
||||
.param("srlimit", SEARCH_CATS_LIMIT)
|
||||
.param("srsearch", title)
|
||||
.get();
|
||||
result = api.searchTitles(SEARCH_CATS_LIMIT, this.title);
|
||||
Timber.d("Searching for cats for title: %s", result);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "IO Exception: ");
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ import java.util.ArrayList;
|
|||
import java.util.Date;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.MWApi;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
|
|
@ -61,7 +61,7 @@ public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
public void onPerformSync(Account account, Bundle bundle, String s, ContentProviderClient contentProviderClient, SyncResult syncResult) {
|
||||
// This code is fraught with possibilities of race conditions, but lalalalala I can't hear you!
|
||||
String user = account.name;
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
SharedPreferences prefs = this.getContext().getSharedPreferences("prefs", Context.MODE_PRIVATE);
|
||||
String lastModified = prefs.getString("lastSyncTimestamp", "");
|
||||
Date curTime = new Date();
|
||||
|
|
@ -71,19 +71,7 @@ public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
while(!done) {
|
||||
|
||||
try {
|
||||
MWApi.RequestBuilder builder = api.action("query")
|
||||
.param("list", "logevents")
|
||||
.param("letype", "upload")
|
||||
.param("leprop", "title|timestamp|ids")
|
||||
.param("leuser", user)
|
||||
.param("lelimit", getLimit());
|
||||
if(!TextUtils.isEmpty(lastModified)) {
|
||||
builder.param("leend", lastModified);
|
||||
}
|
||||
if(!TextUtils.isEmpty(queryContinue)) {
|
||||
builder.param("lestart", queryContinue);
|
||||
}
|
||||
result = builder.get();
|
||||
result = api.logEvents(user, lastModified, queryContinue, getLimit());
|
||||
} catch (IOException e) {
|
||||
// There isn't really much we can do, eh?
|
||||
// FIXME: Perhaps add EventLogging?
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import android.database.Cursor;
|
|||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import fr.free.nrw.commons.MWApi;
|
||||
import org.mediawiki.api.ApiResult;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
@ -21,6 +20,7 @@ import fr.free.nrw.commons.CommonsApplication;
|
|||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.contributions.ContributionsContentProvider;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
|
|
@ -61,7 +61,7 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
return;
|
||||
}
|
||||
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
api.setAuthCookie(authCookie);
|
||||
String editToken;
|
||||
|
||||
|
|
@ -98,11 +98,7 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
if(contrib.getState() == Contribution.STATE_COMPLETED) {
|
||||
|
||||
try {
|
||||
requestResult = api.action("query")
|
||||
.param("prop", "revisions")
|
||||
.param("rvprop", "timestamp|content")
|
||||
.param("titles", contrib.getFilename())
|
||||
.get();
|
||||
requestResult = api.revisionsByFilename(contrib.getFilename());
|
||||
} catch (IOException e) {
|
||||
Timber.d("Network fuckup on modifications sync!");
|
||||
continue;
|
||||
|
|
@ -113,12 +109,7 @@ public class ModificationsSyncAdapter extends AbstractThreadedSyncAdapter {
|
|||
String processedPageContent = sequence.executeModifications(contrib.getFilename(), pageContent);
|
||||
|
||||
try {
|
||||
responseResult = api.action("edit")
|
||||
.param("title", contrib.getFilename())
|
||||
.param("token", editToken)
|
||||
.param("text", processedPageContent)
|
||||
.param("summary", sequence.getEditSummary())
|
||||
.post();
|
||||
responseResult = api.edit(editToken, processedPageContent, contrib.getFilename(), sequence.getEditSummary());
|
||||
} catch (IOException e) {
|
||||
Timber.d("Network fuckup on modifications sync!");
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,258 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
import org.apache.http.impl.client.AbstractHttpClient;
|
||||
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.mediawiki.api.ApiResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import in.yuvi.http.fluent.Http;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* @author Addshore
|
||||
*/
|
||||
public class ApacheHttpClientMediaWikiApi extends org.mediawiki.api.MWApi implements MediaWikiApi {
|
||||
private static final String THUMB_SIZE = "640";
|
||||
private static AbstractHttpClient httpClient;
|
||||
|
||||
public ApacheHttpClientMediaWikiApi(String apiURL) {
|
||||
super(apiURL, getHttpClient());
|
||||
}
|
||||
|
||||
private static AbstractHttpClient getHttpClient() {
|
||||
if (httpClient == null) {
|
||||
httpClient = newHttpClient();
|
||||
}
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
private static AbstractHttpClient newHttpClient() {
|
||||
BasicHttpParams params = new BasicHttpParams();
|
||||
SchemeRegistry schemeRegistry = new SchemeRegistry();
|
||||
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
|
||||
final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
|
||||
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
|
||||
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
|
||||
params.setParameter(CoreProtocolPNames.USER_AGENT, "Commons/" + BuildConfig.VERSION_NAME + " (https://mediawiki.org/wiki/Apps/Commons) Android/" + Build.VERSION.RELEASE);
|
||||
return new DefaultHttpClient(cm, params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
return getErrorCodeToReturn(action("clientlogin")
|
||||
.param("rememberMe", "1")
|
||||
.param("username", username)
|
||||
.param("password", password)
|
||||
.param("logintoken", this.getLoginToken())
|
||||
.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 {
|
||||
return getErrorCodeToReturn(action("clientlogin")
|
||||
.param("rememberMe", "1")
|
||||
.param("username", username)
|
||||
.param("password", password)
|
||||
.param("logintoken", getLoginToken())
|
||||
.param("logincontinue", "1")
|
||||
.param("OATHToken", twoFactorCode)
|
||||
.post());
|
||||
}
|
||||
|
||||
private String getLoginToken() throws IOException {
|
||||
return this.action("query")
|
||||
.param("action", "query")
|
||||
.param("meta", "tokens")
|
||||
.param("type", "login")
|
||||
.post()
|
||||
.getString("/api/query/tokens/@logintoken");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param loginApiResult ApiResult 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(ApiResult loginApiResult) {
|
||||
String status = loginApiResult.getString("/api/clientlogin/@status");
|
||||
if (status.equals("PASS")) {
|
||||
this.isLoggedIn = true;
|
||||
return status;
|
||||
} else if (status.equals("FAIL")) {
|
||||
return loginApiResult.getString("/api/clientlogin/@messagecode");
|
||||
} else if (
|
||||
status.equals("UI")
|
||||
&& loginApiResult.getString("/api/clientlogin/requests/_v/@id").equals("TOTPAuthenticationRequest")
|
||||
&& loginApiResult.getString("/api/clientlogin/requests/_v/@provider").equals("Two-factor authentication (OATH).")
|
||||
) {
|
||||
return "2FA";
|
||||
}
|
||||
|
||||
// UI, REDIRECT, RESTART
|
||||
return "genericerror-" + status;
|
||||
}
|
||||
|
||||
// Moved / consolidated methods
|
||||
@Override
|
||||
public boolean fileExistsWithName(String fileName) throws IOException {
|
||||
return action("query")
|
||||
.param("prop", "imageinfo")
|
||||
.param("titles", "File:" + fileName)
|
||||
.get()
|
||||
.getNodes("/api/query/pages/page/imageinfo").size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult edit(String editToken, String processedPageContent, String filename, String summary) throws IOException {
|
||||
return action("edit")
|
||||
.param("title", filename)
|
||||
.param("token", editToken)
|
||||
.param("text", processedPageContent)
|
||||
.param("summary", summary)
|
||||
.post();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String findThumbnailByFilename(String filename) throws IOException {
|
||||
return action("query")
|
||||
.param("format", "xml")
|
||||
.param("prop", "imageinfo")
|
||||
.param("iiprop", "url")
|
||||
.param("iiurlwidth", THUMB_SIZE)
|
||||
.param("titles", filename)
|
||||
.get()
|
||||
.getString("/api/query/pages/page/imageinfo/ii/@thumburl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult fetchMediaByFilename(String filename) throws IOException {
|
||||
return action("query")
|
||||
.param("prop", "revisions")
|
||||
.param("titles", filename)
|
||||
.param("rvprop", "content")
|
||||
.param("rvlimit", 1)
|
||||
.param("rvgeneratexml", 1)
|
||||
.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult searchCategories(int searchCatsLimit, String filterValue) throws IOException {
|
||||
return action("query")
|
||||
.param("format", "xml")
|
||||
.param("list", "search")
|
||||
.param("srwhat", "text")
|
||||
.param("srnamespace", "14")
|
||||
.param("srlimit", searchCatsLimit)
|
||||
.param("srsearch", filterValue)
|
||||
.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult allCategories(int searchCatsLimit, String filterValue) throws IOException {
|
||||
return action("query")
|
||||
.param("list", "allcategories")
|
||||
.param("acprefix", filterValue)
|
||||
.param("aclimit", searchCatsLimit)
|
||||
.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult searchTitles(int searchCatsLimit, String title) throws IOException {
|
||||
return action("query")
|
||||
.param("format", "xml")
|
||||
.param("list", "search")
|
||||
.param("srwhat", "text")
|
||||
.param("srnamespace", "14")
|
||||
.param("srlimit", searchCatsLimit)
|
||||
.param("srsearch", title)
|
||||
.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException {
|
||||
org.mediawiki.api.MWApi.RequestBuilder builder = action("query")
|
||||
.param("list", "logevents")
|
||||
.param("letype", "upload")
|
||||
.param("leprop", "title|timestamp|ids")
|
||||
.param("leuser", user)
|
||||
.param("lelimit", limit);
|
||||
if (!TextUtils.isEmpty(lastModified)) {
|
||||
builder.param("leend", lastModified);
|
||||
}
|
||||
if (!TextUtils.isEmpty(queryContinue)) {
|
||||
builder.param("lestart", queryContinue);
|
||||
}
|
||||
return builder.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult revisionsByFilename(String filename) throws IOException {
|
||||
return action("query")
|
||||
.param("prop", "revisions")
|
||||
.param("rvprop", "timestamp|content")
|
||||
.param("titles", filename)
|
||||
.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult existingFile(String fileSha1) throws IOException {
|
||||
return action("query")
|
||||
.param("format", "xml")
|
||||
.param("list", "allimages")
|
||||
.param("aisha1", fileSha1)
|
||||
.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logEvents(LogBuilder[] logBuilders) {
|
||||
boolean allSuccess = true;
|
||||
// Not using the default URL connection, since that seems to have different behavior than the rest of the code
|
||||
for (LogBuilder logBuilder : logBuilders) {
|
||||
try {
|
||||
URL url = logBuilder.toUrl();
|
||||
HttpResponse response = Http.get(url.toString()).use(httpClient).asResponse();
|
||||
|
||||
if (response.getStatusLine().getStatusCode() != 204) {
|
||||
allSuccess = false;
|
||||
}
|
||||
Timber.d("EventLog hit %s", url);
|
||||
|
||||
} catch (IOException e) {
|
||||
// Probably just ignore for now. Can be much more robust with a service, etc later on.
|
||||
Timber.d("IO Error, EventLog hit skipped");
|
||||
}
|
||||
}
|
||||
|
||||
return allSuccess;
|
||||
}
|
||||
}
|
||||
28
app/src/main/java/fr/free/nrw/commons/mwapi/EventLog.java
Normal file
28
app/src/main/java/fr/free/nrw/commons/mwapi/EventLog.java
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
import fr.free.nrw.commons.Utils;
|
||||
|
||||
public class EventLog {
|
||||
static final String DEVICE;
|
||||
|
||||
static {
|
||||
if (Build.MODEL.startsWith(Build.MANUFACTURER)) {
|
||||
DEVICE = Utils.capitalize(Build.MODEL);
|
||||
} else {
|
||||
DEVICE = Utils.capitalize(Build.MANUFACTURER) + " " + Build.MODEL;
|
||||
}
|
||||
}
|
||||
|
||||
private static LogBuilder schema(String schema, long revision) {
|
||||
return new LogBuilder(schema, revision);
|
||||
}
|
||||
|
||||
public static LogBuilder schema(Object[] scid) {
|
||||
if (scid.length != 2) {
|
||||
throw new IllegalArgumentException("Needs an object array with schema as first param and revision as second");
|
||||
}
|
||||
return schema((String) scid[0], (Long) scid[1]);
|
||||
}
|
||||
}
|
||||
71
app/src/main/java/fr/free/nrw/commons/mwapi/LogBuilder.java
Normal file
71
app/src/main/java/fr/free/nrw/commons/mwapi/LogBuilder.java
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
|
||||
public class LogBuilder {
|
||||
private JSONObject data;
|
||||
private long rev;
|
||||
private String schema;
|
||||
|
||||
LogBuilder(String schema, long revision) {
|
||||
data = new JSONObject();
|
||||
this.schema = schema;
|
||||
this.rev = revision;
|
||||
}
|
||||
|
||||
public LogBuilder param(String key, Object value) {
|
||||
try {
|
||||
data.put(key, value);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
URL toUrl() {
|
||||
JSONObject fullData = new JSONObject();
|
||||
try {
|
||||
fullData.put("schema", schema);
|
||||
fullData.put("revision", rev);
|
||||
fullData.put("wiki", CommonsApplication.EVENTLOG_WIKI);
|
||||
data.put("device", EventLog.DEVICE);
|
||||
data.put("platform", "Android/" + Build.VERSION.RELEASE);
|
||||
data.put("appversion", "Android/" + BuildConfig.VERSION_NAME);
|
||||
fullData.put("event", data);
|
||||
return new URL(CommonsApplication.EVENTLOG_URL + "?" + Utils.urlEncode(fullData.toString()) + ";");
|
||||
} catch (MalformedURLException | JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
// force param disregards user preference
|
||||
// Use *only* for tracking the user preference change for EventLogging
|
||||
// Attempting to use anywhere else will cause kitten explosions
|
||||
public void log(boolean force) {
|
||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(CommonsApplication.getInstance());
|
||||
if (!settings.getBoolean(Prefs.TRACKING_ENABLED, true) && !force) {
|
||||
return; // User has disabled tracking
|
||||
}
|
||||
LogTask logTask = new LogTask();
|
||||
logTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, this);
|
||||
}
|
||||
|
||||
public void log() {
|
||||
log(false);
|
||||
}
|
||||
|
||||
}
|
||||
12
app/src/main/java/fr/free/nrw/commons/mwapi/LogTask.java
Normal file
12
app/src/main/java/fr/free/nrw/commons/mwapi/LogTask.java
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
|
||||
class LogTask extends AsyncTask<LogBuilder, Void, Boolean> {
|
||||
@Override
|
||||
protected Boolean doInBackground(LogBuilder... logBuilders) {
|
||||
return CommonsApplication.getInstance().getMWApi().logEvents(logBuilders);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package fr.free.nrw.commons.mwapi;
|
||||
|
||||
import org.mediawiki.api.ApiResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import in.yuvi.http.fluent.ProgressListener;
|
||||
|
||||
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;
|
||||
|
||||
ApiResult upload(String filename, InputStream file, long dataLength, String pageContents, String editSummary, ProgressListener progressListener) throws IOException;
|
||||
|
||||
boolean fileExistsWithName(String fileName) throws IOException;
|
||||
|
||||
ApiResult edit(String editToken, String processedPageContent, String filename, String summary) throws IOException;
|
||||
|
||||
String findThumbnailByFilename(String filename) throws IOException;
|
||||
|
||||
ApiResult fetchMediaByFilename(String filename) throws IOException;
|
||||
|
||||
ApiResult searchCategories(int searchCatsLimit, String filterValue) throws IOException;
|
||||
|
||||
ApiResult allCategories(int searchCatsLimit, String filter) throws IOException;
|
||||
|
||||
ApiResult searchTitles(int searchCatsLimit, String title) throws IOException;
|
||||
|
||||
ApiResult logEvents(String user, String lastModified, String queryContinue, int limit) throws IOException;
|
||||
|
||||
ApiResult revisionsByFilename(String filename) throws IOException;
|
||||
|
||||
ApiResult existingFile(String fileSha1) throws IOException;
|
||||
|
||||
boolean logEvents(LogBuilder[] logBuilders);
|
||||
}
|
||||
|
|
@ -12,9 +12,9 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.MWApi;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
|
|
@ -49,16 +49,13 @@ public class ExistingFileAsync extends AsyncTask<Void, Void, Boolean> {
|
|||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
MWApi api = CommonsApplication.getInstance().getMWApi();
|
||||
MediaWikiApi api = CommonsApplication.getInstance().getMWApi();
|
||||
ApiResult result;
|
||||
|
||||
// https://commons.wikimedia.org/w/api.php?action=query&list=allimages&format=xml&aisha1=801957214aba50cb63bb6eb1b0effa50188900ba
|
||||
try {
|
||||
result = api.action("query")
|
||||
.param("format", "xml")
|
||||
.param("list", "allimages")
|
||||
.param("aisha1", fileSha1)
|
||||
.get();
|
||||
String fileSha1 = this.fileSha1;
|
||||
result = api.existingFile(fileSha1);
|
||||
Timber.d("Searching Commons API for existing file: %s", result);
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "IO Exception: ");
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import android.support.v4.app.NotificationCompat;
|
|||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.Toast;
|
||||
|
||||
import fr.free.nrw.commons.*;
|
||||
import org.mediawiki.api.ApiResult;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
|
|
@ -25,10 +24,16 @@ import java.util.Set;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.HandlerService;
|
||||
import fr.free.nrw.commons.R;
|
||||
import fr.free.nrw.commons.Utils;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.contributions.ContributionsActivity;
|
||||
import fr.free.nrw.commons.contributions.ContributionsContentProvider;
|
||||
import fr.free.nrw.commons.modifications.ModificationsContentProvider;
|
||||
import fr.free.nrw.commons.mwapi.EventLog;
|
||||
import fr.free.nrw.commons.mwapi.MediaWikiApi;
|
||||
import in.yuvi.http.fluent.ProgressListener;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
|
@ -176,7 +181,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
}
|
||||
|
||||
private void uploadContribution(Contribution contribution) {
|
||||
MWApi api = app.getMWApi();
|
||||
MediaWikiApi api = app.getMWApi();
|
||||
|
||||
ApiResult result;
|
||||
InputStream file = null;
|
||||
|
|
@ -304,7 +309,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
}
|
||||
|
||||
private String findUniqueFilename(String fileName) throws IOException {
|
||||
MWApi api = app.getMWApi();
|
||||
MediaWikiApi api = app.getMWApi();
|
||||
String sequenceFileName;
|
||||
for ( int sequenceNumber = 1; true; sequenceNumber++ ) {
|
||||
if (sequenceNumber == 1) {
|
||||
|
|
@ -320,7 +325,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
sequenceFileName = regexMatcher.replaceAll("$1 " + sequenceNumber + "$2");
|
||||
}
|
||||
}
|
||||
if ( fileExistsWithName(api, sequenceFileName) || unfinishedUploads.contains(sequenceFileName) ) {
|
||||
if ( api.fileExistsWithName(sequenceFileName) || unfinishedUploads.contains(sequenceFileName) ) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
|
|
@ -328,15 +333,4 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
}
|
||||
return sequenceFileName;
|
||||
}
|
||||
|
||||
private static boolean fileExistsWithName(MWApi api, String fileName) throws IOException {
|
||||
ApiResult result;
|
||||
|
||||
result = api.action("query")
|
||||
.param("prop", "imageinfo")
|
||||
.param("titles", "File:" + fileName)
|
||||
.get();
|
||||
|
||||
return result.getNodes("/api/query/pages/page/imageinfo").size() > 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue