Browse Source

Merging qBittorrent adapter fixes with support for 3.2+, added proper version number retrieval.

material
Eric Kok 9 years ago
parent
commit
5d68d06122
  1. 108
      app/src/main/java/org/transdroid/daemon/Qbittorrent/QbittorrentAdapter.java

108
app/src/main/java/org/transdroid/daemon/Qbittorrent/QbittorrentAdapter.java

@ -17,24 +17,18 @@ @@ -17,24 +17,18 @@
*/
package org.transdroid.daemon.Qbittorrent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.android.internalcopy.http.multipart.FilePart;
import com.android.internalcopy.http.multipart.MultipartEntity;
import com.android.internalcopy.http.multipart.Part;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.cookie.Cookie;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONException;
@ -42,6 +36,7 @@ import org.json.JSONObject; @@ -42,6 +36,7 @@ import org.json.JSONObject;
import org.transdroid.core.gui.log.Log;
import org.transdroid.daemon.Daemon;
import org.transdroid.daemon.DaemonException;
import org.transdroid.daemon.DaemonException.ExceptionType;
import org.transdroid.daemon.DaemonSettings;
import org.transdroid.daemon.IDaemonAdapter;
import org.transdroid.daemon.Priority;
@ -49,7 +44,6 @@ import org.transdroid.daemon.Torrent; @@ -49,7 +44,6 @@ import org.transdroid.daemon.Torrent;
import org.transdroid.daemon.TorrentDetails;
import org.transdroid.daemon.TorrentFile;
import org.transdroid.daemon.TorrentStatus;
import org.transdroid.daemon.DaemonException.ExceptionType;
import org.transdroid.daemon.task.AddByFileTask;
import org.transdroid.daemon.task.AddByMagnetUrlTask;
import org.transdroid.daemon.task.AddByUrlTask;
@ -67,9 +61,15 @@ import org.transdroid.daemon.task.RetrieveTaskSuccessResult; @@ -67,9 +61,15 @@ import org.transdroid.daemon.task.RetrieveTaskSuccessResult;
import org.transdroid.daemon.task.SetFilePriorityTask;
import org.transdroid.daemon.task.SetTransferRatesTask;
import org.transdroid.daemon.util.HttpHelper;
import com.android.internalcopy.http.multipart.FilePart;
import com.android.internalcopy.http.multipart.MultipartEntity;
import com.android.internalcopy.http.multipart.Part;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* The daemon adapter for the qBittorrent torrent client.
@ -89,36 +89,40 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -89,36 +89,40 @@ public class QbittorrentAdapter implements IDaemonAdapter {
}
private synchronized void ensureVersion(Log log) throws DaemonException {
if (version > 0)
// Still need to retrieve the API and qBittorrent version numbers from the server?
if (version > 0 && apiVersion > 0)
return;
// We still need to retrieve the version number from the server
// Do this by getting the web interface about page and trying to parse the version number
// Format is something like 'qBittorrent v2.9.7 (Web UI)'
try {
// The API version is only supported since qBittorrent 3.2, so otherwise we assume version 1
try {
String apiVerText = makeRequest(log, "/version/api");
apiVersion = Integer.parseInt(apiVerText.trim());
}
catch (DaemonException e) {
} catch (DaemonException | NumberFormatException e) {
apiVersion = 1;
}
catch (NumberFormatException e) {
apiVersion = 1;
}
log.d(LOG_NAME, "qBittorrent API version is " + apiVersion);
// TODO: In API ver 2, query this information from /version/qbittorrent instead.
// For now at least this works fine, though
// The qBittorent version is only supported since 3.2; for earlier versions we parse the about dialog and parse it
String versionText = "";
if (apiVersion > 1) {
// Format is something like 'v3.2.0'
versionText = makeRequest(log, "/version/qbittorrent").substring(1);
} else {
// Format is something like 'qBittorrent v2.9.7 (Web UI)' or 'qBittorrent v3.0.0-alpha5 (Web UI)'
String about = makeRequest(log, "/about.html");
String aboutStartText = "qBittorrent v";
String aboutEndText = " (Web UI)";
int aboutStart = about.indexOf(aboutStartText);
int aboutEnd = about.indexOf(aboutEndText);
try {
if (aboutStart >= 0 && aboutEnd > aboutStart) {
versionText = about.substring(aboutStart + aboutStartText.length(), aboutEnd);
}
}
// String found: now parse a version like 2.9.7 as a number like 20907 (allowing 10 places for each .)
String[] parts = about.substring(aboutStart + aboutStartText.length(), aboutEnd).split("\\.");
String[] parts = versionText.split("\\.");
if (parts.length > 0) {
version = Integer.parseInt(parts[0]) * 100 * 100;
if (parts.length > 1) {
@ -141,14 +145,15 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -141,14 +145,15 @@ public class QbittorrentAdapter implements IDaemonAdapter {
}
}
}
}
} catch (NumberFormatException e) {
}
} catch (Exception e) {
// Unable to establish version number; assume an old version by setting it to version 1
version = 10000;
apiVersion = 1;
}
}
private synchronized void ensureAuthenticated(Log log) throws DaemonException {
// API changed in 3.2.0, login is now handled by its own request, which provides you a cookie.
// If we don't have that cookie, let's try and get it.
@ -166,8 +171,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -166,8 +171,7 @@ public class QbittorrentAdapter implements IDaemonAdapter {
}
}
makeRequest(log, "/login",
new BasicNameValuePair("username", settings.getUsername()),
makeRequest(log, "/login", new BasicNameValuePair("username", settings.getUsername()),
new BasicNameValuePair("password", settings.getPassword()));
// The HttpClient will automatically remember the cookie for us, no need to parse it out.
@ -210,17 +214,16 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -210,17 +214,16 @@ public class QbittorrentAdapter implements IDaemonAdapter {
// Request tracker and error details for a specific teacher
String mhash = task.getTargetTorrent().getUniqueID();
JSONArray messages = new JSONArray(makeRequest(log,
(version >= 30200 ? "/query/propertiesTrackers/" : "/json/propertiesTrackers/") + mhash));
return new GetTorrentDetailsTaskSuccessResult((GetTorrentDetailsTask) task,
parseJsonTorrentDetails(messages));
JSONArray messages =
new JSONArray(makeRequest(log, (version >= 30200 ? "/query/propertiesTrackers/" : "/json/propertiesTrackers/") + mhash));
return new GetTorrentDetailsTaskSuccessResult((GetTorrentDetailsTask) task, parseJsonTorrentDetails(messages));
case GetFileList:
// Request files listing for a specific torrent
String fhash = task.getTargetTorrent().getUniqueID();
JSONArray files = new JSONArray(makeRequest(log,
(version >= 30200 ? "/query/propertiesFiles/" : "/json/propertiesFiles/") + fhash));
JSONArray files =
new JSONArray(makeRequest(log, (version >= 30200 ? "/query/propertiesFiles/" : "/json/propertiesFiles/") + fhash));
return new GetFileListTaskSuccessResult((GetFileListTask) task, parseJsonFiles(files));
case AddByFile:
@ -290,9 +293,8 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -290,9 +293,8 @@ public class QbittorrentAdapter implements IDaemonAdapter {
}
// We have to make a separate request per file, it seems
for (TorrentFile file : setPrio.getForFiles()) {
makeRequest(log, "/command/setFilePrio", new BasicNameValuePair("hash", task.getTargetTorrent()
.getUniqueID()), new BasicNameValuePair("id", file.getKey()), new BasicNameValuePair(
"priority", newPrio));
makeRequest(log, "/command/setFilePrio", new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID()),
new BasicNameValuePair("id", file.getKey()), new BasicNameValuePair("priority", newPrio));
}
return new DaemonTaskSuccessResult(task);
@ -308,13 +310,12 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -308,13 +310,12 @@ public class QbittorrentAdapter implements IDaemonAdapter {
JSONObject prefs = new JSONObject(makeRequest(log, "/json/preferences"));
prefs.put("dl_limit", dl);
prefs.put("up_limit", ul);
makeRequest(log, "/command/setPreferences",
new BasicNameValuePair("json", URLEncoder.encode(prefs.toString(), HTTP.UTF_8)));
makeRequest(log, "/command/setPreferences", new BasicNameValuePair("json", URLEncoder.encode(prefs.toString(), HTTP.UTF_8)));
return new DaemonTaskSuccessResult(task);
default:
return new DaemonTaskFailureResult(task, new DaemonException(ExceptionType.MethodUnsupported,
task.getMethod() + " is not supported by " + getType()));
return new DaemonTaskFailureResult(task,
new DaemonException(ExceptionType.MethodUnsupported, task.getMethod() + " is not supported by " + getType()));
}
} catch (JSONException e) {
return new DaemonTaskFailureResult(task, new DaemonException(ExceptionType.ParsingFailed, e.toString()));
@ -331,7 +332,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -331,7 +332,7 @@ public class QbittorrentAdapter implements IDaemonAdapter {
// Setup request using POST
HttpPost httppost = new HttpPost(buildWebUIUrl(path));
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
List<NameValuePair> nvps = new ArrayList<>();
Collections.addAll(nvps, params);
httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
return makeWebRequest(httppost, log);
@ -414,8 +415,8 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -414,8 +415,8 @@ public class QbittorrentAdapter implements IDaemonAdapter {
private TorrentDetails parseJsonTorrentDetails(JSONArray messages) throws JSONException {
ArrayList<String> trackers = new ArrayList<String>();
ArrayList<String> errors = new ArrayList<String>();
ArrayList<String> trackers = new ArrayList<>();
ArrayList<String> errors = new ArrayList<>();
// Parse response
if (messages.length() > 0) {
@ -436,7 +437,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -436,7 +437,7 @@ public class QbittorrentAdapter implements IDaemonAdapter {
private ArrayList<Torrent> parseJsonTorrents(JSONArray response) throws JSONException {
// Parse response
ArrayList<Torrent> torrents = new ArrayList<Torrent>();
ArrayList<Torrent> torrents = new ArrayList<>();
for (int i = 0; i < response.length(); i++) {
JSONObject tor = response.getJSONObject(i);
int leechers[] = parsePeers(tor.getString("num_leechs"));
@ -533,8 +534,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -533,8 +534,7 @@ public class QbittorrentAdapter implements IDaemonAdapter {
// In some situations it it just a "6" string
String[] parts = seeds.split(" ");
if (parts.length > 1) {
return new int[] { Integer.parseInt(parts[0]),
Integer.parseInt(parts[1].substring(1, parts[1].length() - 1)) };
return new int[]{Integer.parseInt(parts[0]), Integer.parseInt(parts[1].substring(1, parts[1].length() - 1))};
}
return new int[]{Integer.parseInt(parts[0]), Integer.parseInt(parts[0])};
}
@ -612,8 +612,8 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -612,8 +612,8 @@ public class QbittorrentAdapter implements IDaemonAdapter {
size = parseSize(file.getString("size"));
}
torrentfiles.add(new TorrentFile("" + i, file.getString("name"), null, null, size, (long) (size * file
.getDouble("progress")), parsePriority(file.getInt("priority"))));
torrentfiles.add(new TorrentFile("" + i, file.getString("name"), null, null, size, (long) (size * file.getDouble("progress")),
parsePriority(file.getInt("priority"))));
}
// Return the list

Loading…
Cancel
Save