|
|
@ -25,6 +25,8 @@ import org.apache.http.HttpEntity; |
|
|
|
import org.apache.http.HttpResponse; |
|
|
|
import org.apache.http.HttpResponse; |
|
|
|
import org.apache.http.NameValuePair; |
|
|
|
import org.apache.http.NameValuePair; |
|
|
|
import org.apache.http.client.entity.UrlEncodedFormEntity; |
|
|
|
import org.apache.http.client.entity.UrlEncodedFormEntity; |
|
|
|
|
|
|
|
import org.apache.http.client.methods.HttpRequestBase; |
|
|
|
|
|
|
|
import org.apache.http.client.methods.HttpGet; |
|
|
|
import org.apache.http.client.methods.HttpPost; |
|
|
|
import org.apache.http.client.methods.HttpPost; |
|
|
|
import org.apache.http.cookie.Cookie; |
|
|
|
import org.apache.http.cookie.Cookie; |
|
|
|
import org.apache.http.impl.client.DefaultHttpClient; |
|
|
|
import org.apache.http.impl.client.DefaultHttpClient; |
|
|
@ -70,7 +72,8 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
private DaemonSettings settings; |
|
|
|
private DaemonSettings settings; |
|
|
|
private DefaultHttpClient httpclient; |
|
|
|
private DefaultHttpClient httpclient; |
|
|
|
private int version = -1; |
|
|
|
private int version = -1; |
|
|
|
private int apiVersion = -1; |
|
|
|
private float apiVersion = -1; // starting from 2.3 old API is dropped so we are going to use float
|
|
|
|
|
|
|
|
private int http_response_code = -1; |
|
|
|
|
|
|
|
|
|
|
|
public QbittorrentAdapter(DaemonSettings settings) { |
|
|
|
public QbittorrentAdapter(DaemonSettings settings) { |
|
|
|
this.settings = settings; |
|
|
|
this.settings = settings; |
|
|
@ -83,18 +86,40 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Since 4.2.0, old API is dropped. Fallback to old one if the new one failed for version <4.2.0
|
|
|
|
// The API version is only supported since qBittorrent 3.2, so otherwise we assume version 1
|
|
|
|
// The API version is only supported since qBittorrent 3.2, so otherwise we assume version 1
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
String apiVerText = makeRequest(log, "/version/api"); |
|
|
|
String apiVerText = makeRequest(log, "/api/v2/app/webapiVersion", new BasicNameValuePair("username", settings.getUsername()), |
|
|
|
apiVersion = Integer.parseInt(apiVerText.trim()); |
|
|
|
new BasicNameValuePair("password", settings.getPassword())); |
|
|
|
|
|
|
|
apiVersion = Float.parseFloat(apiVerText.trim()); |
|
|
|
} catch (DaemonException | NumberFormatException e) { |
|
|
|
} catch (DaemonException | NumberFormatException e) { |
|
|
|
apiVersion = 1; |
|
|
|
if (http_response_code == 403) { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
ensureAuthenticated(log); |
|
|
|
|
|
|
|
String apiVerText = makeRequest(log, "/api/v2/app/webapiVersion"); |
|
|
|
|
|
|
|
apiVersion = Float.parseFloat(apiVerText.trim()); |
|
|
|
|
|
|
|
} catch (DaemonException | NumberFormatException e2) { |
|
|
|
|
|
|
|
apiVersion = (float) 2.3; // assume this is new API since we are forbidden to access API
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
String apiVerText = makeRequest(log, "/version/api"); |
|
|
|
|
|
|
|
apiVersion = Float.parseFloat(apiVerText.trim()); |
|
|
|
|
|
|
|
} catch (DaemonException | NumberFormatException e3) { |
|
|
|
|
|
|
|
apiVersion = 1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
log.d(LOG_NAME, "qBittorrent API version is " + apiVersion); |
|
|
|
log.d(LOG_NAME, "qBittorrent API version is " + apiVersion); |
|
|
|
|
|
|
|
|
|
|
|
// The qBittorent version is only supported since 3.2; for earlier versions we parse the about dialog and parse it
|
|
|
|
// The qBittorent version is only supported since 3.2; for earlier versions we parse the about dialog and parse it
|
|
|
|
|
|
|
|
// Since 4.2.0, new API version is used instead
|
|
|
|
String versionText = ""; |
|
|
|
String versionText = ""; |
|
|
|
if (apiVersion > 1) { |
|
|
|
if (apiVersion >= (float) 2.3) { |
|
|
|
|
|
|
|
ensureAuthenticated(log); |
|
|
|
|
|
|
|
versionText = makeRequest(log, "/api/v2/app/version").substring(1); |
|
|
|
|
|
|
|
} else if (apiVersion > (float) 1) { |
|
|
|
// Format is something like 'v3.2.0'
|
|
|
|
// Format is something like 'v3.2.0'
|
|
|
|
versionText = makeRequest(log, "/version/qbittorrent").substring(1); |
|
|
|
versionText = makeRequest(log, "/version/qbittorrent").substring(1); |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -108,13 +133,14 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
versionText = about.substring(aboutStart + aboutStartText.length(), aboutEnd); |
|
|
|
versionText = about.substring(aboutStart + aboutStartText.length(), aboutEnd); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
log.d(LOG_NAME, "qBittorrent client version is " + versionText); |
|
|
|
|
|
|
|
|
|
|
|
// String found: now parse a version like 2.9.7 as a number like 20907 (allowing 10 places for each .)
|
|
|
|
// String found: now parse a version like 2.9.7 as a number like 20907 (allowing 10 places for each .)
|
|
|
|
String[] parts = versionText.split("\\."); |
|
|
|
String[] parts = versionText.split("\\."); |
|
|
|
if (parts.length > 0) { |
|
|
|
if (parts.length > 0) { |
|
|
|
version = Integer.parseInt(parts[0]) * 100 * 100; |
|
|
|
version = Integer.parseInt(parts[0]) * 100 * 100; |
|
|
|
if (parts.length > 1) { |
|
|
|
if (parts.length > 1) { |
|
|
|
version += Integer.parseInt(parts[1]) * 100; |
|
|
|
version += Float.parseFloat(parts[1]) * 100; |
|
|
|
if (parts.length > 2) { |
|
|
|
if (parts.length > 2) { |
|
|
|
// For the last part only read until a non-numeric character is read
|
|
|
|
// For the last part only read until a non-numeric character is read
|
|
|
|
// For example version 3.0.0-alpha5 is read as version code 30000
|
|
|
|
// For example version 3.0.0-alpha5 is read as version code 30000
|
|
|
@ -128,8 +154,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
version += Integer.parseInt(numbers); |
|
|
|
version += Float.parseFloat(numbers); |
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -146,7 +171,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
// API changed in 3.2.0, login is now handled by its own request, which provides you a cookie.
|
|
|
|
// 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.
|
|
|
|
// If we don't have that cookie, let's try and get it.
|
|
|
|
|
|
|
|
|
|
|
|
if (apiVersion < 2) { |
|
|
|
if (apiVersion < (float) 2) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -159,8 +184,13 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
makeRequest(log, "/login", new BasicNameValuePair("username", settings.getUsername()), |
|
|
|
if (apiVersion >= (float) 2.3) { |
|
|
|
new BasicNameValuePair("password", settings.getPassword())); |
|
|
|
makeRequest(log, "/api/v2/auth/login", new BasicNameValuePair("username", settings.getUsername()), |
|
|
|
|
|
|
|
new BasicNameValuePair("password", settings.getPassword())); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
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.
|
|
|
|
// The HttpClient will automatically remember the cookie for us, no need to parse it out.
|
|
|
|
|
|
|
|
|
|
|
|
// However, we would like to see if authentication was successful or not...
|
|
|
|
// However, we would like to see if authentication was successful or not...
|
|
|
@ -185,63 +215,113 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
|
|
|
|
|
|
|
|
switch (task.getMethod()) { |
|
|
|
switch (task.getMethod()) { |
|
|
|
case Retrieve: |
|
|
|
case Retrieve: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Request all torrents from server
|
|
|
|
String path; |
|
|
|
String path; |
|
|
|
if (version >= 30200) { |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/info"; |
|
|
|
|
|
|
|
} else if (version >= 30200) { |
|
|
|
path = "/query/torrents"; |
|
|
|
path = "/query/torrents"; |
|
|
|
} else if (version >= 30000) { |
|
|
|
} else if (version >= 30000) { |
|
|
|
path = "/json/torrents"; |
|
|
|
path = "/json/torrents";; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
path = "/json/events"; |
|
|
|
path = "/json/events"; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Request all torrents from server
|
|
|
|
|
|
|
|
JSONArray result = new JSONArray(makeRequest(log, path)); |
|
|
|
JSONArray result = new JSONArray(makeRequest(log, path)); |
|
|
|
|
|
|
|
|
|
|
|
return new RetrieveTaskSuccessResult((RetrieveTask) task, parseJsonTorrents(result), parseJsonLabels(result)); |
|
|
|
return new RetrieveTaskSuccessResult((RetrieveTask) task, parseJsonTorrents(result), parseJsonLabels(result)); |
|
|
|
|
|
|
|
|
|
|
|
case GetTorrentDetails: |
|
|
|
case GetTorrentDetails: |
|
|
|
|
|
|
|
|
|
|
|
// Request tracker and error details for a specific teacher
|
|
|
|
// Request tracker and error details for a specific teacher
|
|
|
|
String mhash = task.getTargetTorrent().getUniqueID(); |
|
|
|
String mhash = task.getTargetTorrent().getUniqueID(); |
|
|
|
JSONArray messages = |
|
|
|
JSONArray messages; |
|
|
|
new JSONArray(makeRequest(log, (version >= 30200 ? "/query/propertiesTrackers/" : "/json/propertiesTrackers/") + mhash)); |
|
|
|
JSONArray pieces; |
|
|
|
JSONArray pieces = new JSONArray(makeRequest(log, "/query/getPieceStates/" + mhash)); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
messages = new JSONArray(makeRequest(log, "/api/v2/torrents/trackers", new BasicNameValuePair("hash", mhash))); |
|
|
|
|
|
|
|
pieces = new JSONArray(makeRequest(log, "/api/v2/torrents/pieceStates", new BasicNameValuePair("hash", mhash))); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
messages = new JSONArray(makeRequest(log, "/query/propertiesTrackers/" + mhash)); |
|
|
|
|
|
|
|
pieces = new JSONArray(makeRequest(log, "/query/getPieceStates/" + mhash)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return new GetTorrentDetailsTaskSuccessResult((GetTorrentDetailsTask) task, parseJsonTorrentDetails(messages, pieces)); |
|
|
|
return new GetTorrentDetailsTaskSuccessResult((GetTorrentDetailsTask) task, parseJsonTorrentDetails(messages, pieces)); |
|
|
|
|
|
|
|
|
|
|
|
case GetFileList: |
|
|
|
case GetFileList: |
|
|
|
|
|
|
|
|
|
|
|
// Request files listing for a specific torrent
|
|
|
|
// Request files listing for a specific torrent
|
|
|
|
String fhash = task.getTargetTorrent().getUniqueID(); |
|
|
|
String fhash = task.getTargetTorrent().getUniqueID(); |
|
|
|
JSONArray files = |
|
|
|
JSONArray files; |
|
|
|
new JSONArray(makeRequest(log, (version >= 30200 ? "/query/propertiesFiles/" : "/json/propertiesFiles/") + fhash)); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
files = new JSONArray(makeRequest(log, "/api/v2/torrents/files", new BasicNameValuePair("hash", fhash))); |
|
|
|
|
|
|
|
} else if (version >= 30200) { |
|
|
|
|
|
|
|
files = new JSONArray(makeRequest(log, "/query/propertiesFiles/" + fhash)); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
files = new JSONArray(makeRequest(log, "/json/propertiesFiles/" + fhash)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return new GetFileListTaskSuccessResult((GetFileListTask) task, parseJsonFiles(files)); |
|
|
|
return new GetFileListTaskSuccessResult((GetFileListTask) task, parseJsonFiles(files)); |
|
|
|
|
|
|
|
|
|
|
|
case AddByFile: |
|
|
|
case AddByFile: |
|
|
|
|
|
|
|
|
|
|
|
// Upload a local .torrent file
|
|
|
|
// Upload a local .torrent file
|
|
|
|
|
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/add"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/upload"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String ufile = ((AddByFileTask) task).getFile(); |
|
|
|
String ufile = ((AddByFileTask) task).getFile(); |
|
|
|
makeUploadRequest("/command/upload", ufile, log); |
|
|
|
makeUploadRequest(path, ufile, log); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case AddByUrl: |
|
|
|
case AddByUrl: |
|
|
|
|
|
|
|
|
|
|
|
// Request to add a torrent by URL
|
|
|
|
// Request to add a torrent by URL
|
|
|
|
String url = ((AddByUrlTask) task).getUrl(); |
|
|
|
String url = ((AddByUrlTask) task).getUrl(); |
|
|
|
makeRequest(log, "/command/download", new BasicNameValuePair("urls", url)); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/add"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/upload"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("urls", url)); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case AddByMagnetUrl: |
|
|
|
case AddByMagnetUrl: |
|
|
|
|
|
|
|
|
|
|
|
// Request to add a magnet link by URL
|
|
|
|
// Request to add a magnet link by URL
|
|
|
|
String magnet = ((AddByMagnetUrlTask) task).getUrl(); |
|
|
|
String magnet = ((AddByMagnetUrlTask) task).getUrl(); |
|
|
|
makeRequest(log, "/command/download", new BasicNameValuePair("urls", magnet)); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/add"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/download"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("urls", magnet)); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case Remove: |
|
|
|
case Remove: |
|
|
|
|
|
|
|
|
|
|
|
// Remove a torrent
|
|
|
|
// Remove a torrent
|
|
|
|
RemoveTask removeTask = (RemoveTask) task; |
|
|
|
RemoveTask removeTask = (RemoveTask) task; |
|
|
|
makeRequest(log, (removeTask.includingData() ? "/command/deletePerm" : "/command/delete"), |
|
|
|
if (version >= 40200) { |
|
|
|
new BasicNameValuePair("hashes", removeTask.getTargetTorrent().getUniqueID())); |
|
|
|
if (removeTask.includingData()) { |
|
|
|
|
|
|
|
makeRequest(log, "/api/v2/torrents/delete", |
|
|
|
|
|
|
|
new BasicNameValuePair("hashes", removeTask.getTargetTorrent().getUniqueID()), |
|
|
|
|
|
|
|
new BasicNameValuePair("deleteFiles", "true")); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
makeRequest(log, "/api/v2/torrents/delete", |
|
|
|
|
|
|
|
new BasicNameValuePair("hashes", removeTask.getTargetTorrent().getUniqueID()), |
|
|
|
|
|
|
|
new BasicNameValuePair("deleteFiles", "false")); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = (removeTask.includingData() ? "/command/deletePerm" : "/command/delete"); |
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("hashes", removeTask.getTargetTorrent().getUniqueID())); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case Pause: |
|
|
|
case Pause: |
|
|
@ -253,19 +333,35 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
case PauseAll: |
|
|
|
case PauseAll: |
|
|
|
|
|
|
|
|
|
|
|
// Resume all torrents
|
|
|
|
// Resume all torrents
|
|
|
|
makeRequest(log, "/command/pauseall"); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/pause"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/pauseall"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case Resume: |
|
|
|
case Resume: |
|
|
|
|
|
|
|
|
|
|
|
// Resume a torrent
|
|
|
|
// Resume a torrent
|
|
|
|
makeRequest(log, "/command/resume", new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID())); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/resume"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/resume"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID())); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case ResumeAll: |
|
|
|
case ResumeAll: |
|
|
|
|
|
|
|
|
|
|
|
// Resume all torrents
|
|
|
|
// Resume all torrents
|
|
|
|
makeRequest(log, "/command/resumeall"); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/resume"; |
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("hash", "all")); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
makeRequest(log, "/command/resumeall"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case SetFilePriorities: |
|
|
|
case SetFilePriorities: |
|
|
@ -282,33 +378,59 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
} |
|
|
|
} |
|
|
|
// We have to make a separate request per file, it seems
|
|
|
|
// We have to make a separate request per file, it seems
|
|
|
|
for (TorrentFile file : setPrio.getForFiles()) { |
|
|
|
for (TorrentFile file : setPrio.getForFiles()) { |
|
|
|
makeRequest(log, "/command/setFilePrio", new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID()), |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/filePrio"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/setFilePrio"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID()), |
|
|
|
new BasicNameValuePair("id", file.getKey()), new BasicNameValuePair("priority", newPrio)); |
|
|
|
new BasicNameValuePair("id", file.getKey()), new BasicNameValuePair("priority", newPrio)); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case ForceRecheck: |
|
|
|
case ForceRecheck: |
|
|
|
|
|
|
|
|
|
|
|
// Force recheck a torrent
|
|
|
|
// Force recheck a torrent
|
|
|
|
makeRequest(log, "/command/recheck", new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID())); |
|
|
|
if (version >= 40200) { |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
path = "/api/v2/torrents/recheck"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/recheck"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID())); |
|
|
|
|
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case ToggleSequentialDownload: |
|
|
|
case ToggleSequentialDownload: |
|
|
|
|
|
|
|
|
|
|
|
// Toggle sequential download mode on a torrent
|
|
|
|
// Toggle sequential download mode on a torrent
|
|
|
|
makeRequest(log, "/command/toggleSequentialDownload", new BasicNameValuePair("hashes", task.getTargetTorrent().getUniqueID())); |
|
|
|
if (version >= 40200) { |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
path = "/api/v2/torrents/toggleSequentialDownload"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/toggleSequentialDownload"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("hashes", task.getTargetTorrent().getUniqueID())); |
|
|
|
|
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case ToggleFirstLastPieceDownload: |
|
|
|
case ToggleFirstLastPieceDownload: |
|
|
|
|
|
|
|
|
|
|
|
// Set policy for downloading first and last piece first on a torrent
|
|
|
|
// Set policy for downloading first and last piece first on a torrent
|
|
|
|
makeRequest(log, "/command/toggleFirstLastPiecePrio", new BasicNameValuePair("hashes", task.getTargetTorrent().getUniqueID())); |
|
|
|
if (version >= 40200) { |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
path = "/api/v2/torrents/toggleFirstLastPiecePrio"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/toggleFirstLastPiecePrio"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path, new BasicNameValuePair("hashes", task.getTargetTorrent().getUniqueID())); |
|
|
|
|
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case SetLabel: |
|
|
|
case SetLabel: |
|
|
|
|
|
|
|
|
|
|
|
SetLabelTask labelTask = (SetLabelTask) task; |
|
|
|
SetLabelTask labelTask = (SetLabelTask) task; |
|
|
|
makeRequest(log, "/command/setCategory", |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/setCategory"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/setCategory"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path, |
|
|
|
new BasicNameValuePair("hashes", task.getTargetTorrent().getUniqueID()), |
|
|
|
new BasicNameValuePair("hashes", task.getTargetTorrent().getUniqueID()), |
|
|
|
new BasicNameValuePair("category", labelTask.getNewLabel())); |
|
|
|
new BasicNameValuePair("category", labelTask.getNewLabel())); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
@ -316,7 +438,12 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
case SetDownloadLocation: |
|
|
|
case SetDownloadLocation: |
|
|
|
|
|
|
|
|
|
|
|
SetDownloadLocationTask setLocationTask = (SetDownloadLocationTask) task; |
|
|
|
SetDownloadLocationTask setLocationTask = (SetDownloadLocationTask) task; |
|
|
|
makeRequest(log, "/command/setLocation", |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/torrents/setLocation"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/setLocation"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path, |
|
|
|
new BasicNameValuePair("hashes", task.getTargetTorrent().getUniqueID()), |
|
|
|
new BasicNameValuePair("hashes", task.getTargetTorrent().getUniqueID()), |
|
|
|
new BasicNameValuePair("location", setLocationTask.getNewLocation())); |
|
|
|
new BasicNameValuePair("location", setLocationTask.getNewLocation())); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
@ -324,18 +451,33 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
case SetTransferRates: |
|
|
|
case SetTransferRates: |
|
|
|
|
|
|
|
|
|
|
|
// Request to set the maximum transfer rates
|
|
|
|
// Request to set the maximum transfer rates
|
|
|
|
|
|
|
|
String pathDL; |
|
|
|
|
|
|
|
String pathUL; |
|
|
|
SetTransferRatesTask ratesTask = (SetTransferRatesTask) task; |
|
|
|
SetTransferRatesTask ratesTask = (SetTransferRatesTask) task; |
|
|
|
String dl = (ratesTask.getDownloadRate() == null ? "NaN" : Long.toString(ratesTask.getDownloadRate() * 1024)); |
|
|
|
String dl = (ratesTask.getDownloadRate() == null ? "NaN" : Long.toString(ratesTask.getDownloadRate() * 1024)); |
|
|
|
String ul = (ratesTask.getUploadRate() == null ? "NaN" : Long.toString(ratesTask.getUploadRate() * 1024)); |
|
|
|
String ul = (ratesTask.getUploadRate() == null ? "NaN" : Long.toString(ratesTask.getUploadRate() * 1024)); |
|
|
|
|
|
|
|
|
|
|
|
makeRequest(log, "/command/setGlobalDlLimit", new BasicNameValuePair("limit", dl)); |
|
|
|
if (version >= 40200) { |
|
|
|
makeRequest(log, "/command/setGlobalUpLimit", new BasicNameValuePair("limit", ul)); |
|
|
|
pathDL = "/api/v2/torrents/setDownloadLimit"; |
|
|
|
|
|
|
|
pathUL = "/api/v2/torrents/setUploadLimit"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
pathDL = "/command/setGlobalDlLimit"; |
|
|
|
|
|
|
|
pathUL = "/command/setGlobalUpLimit"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
makeRequest(log, pathDL, new BasicNameValuePair("limit", dl)); |
|
|
|
|
|
|
|
makeRequest(log, pathUL, new BasicNameValuePair("limit", ul)); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
case GetStats: |
|
|
|
case GetStats: |
|
|
|
|
|
|
|
|
|
|
|
// Refresh alternative download speeds setting
|
|
|
|
// Refresh alternative download speeds setting
|
|
|
|
JSONObject stats = new JSONObject(makeRequest(log, "/sync/maindata?rid=0")); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/sync/maindata?rid=0"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/sync/maindata?rid=0"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
JSONObject stats = new JSONObject(makeRequest(log, path)); |
|
|
|
JSONObject serverStats = stats.optJSONObject("server_state"); |
|
|
|
JSONObject serverStats = stats.optJSONObject("server_state"); |
|
|
|
boolean alternativeSpeeds = false; |
|
|
|
boolean alternativeSpeeds = false; |
|
|
|
if (serverStats != null) { |
|
|
|
if (serverStats != null) { |
|
|
@ -346,7 +488,12 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
case SetAlternativeMode: |
|
|
|
case SetAlternativeMode: |
|
|
|
|
|
|
|
|
|
|
|
// Flip alternative speed mode
|
|
|
|
// Flip alternative speed mode
|
|
|
|
makeRequest(log, "/command/toggleAlternativeSpeedLimits"); |
|
|
|
if (version >= 40200) { |
|
|
|
|
|
|
|
path = "/api/v2/transfer/toggleSpeedLimitsMode"; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
path = "/command/toggleAlternativeSpeedLimits"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
makeRequest(log, path); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
return new DaemonTaskSuccessResult(task); |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
@ -365,7 +512,10 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
try { |
|
|
|
try { |
|
|
|
|
|
|
|
|
|
|
|
// Setup request using POST
|
|
|
|
// Setup request using POST
|
|
|
|
HttpPost httppost = new HttpPost(buildWebUIUrl(path)); |
|
|
|
String url_to_request = buildWebUIUrl(path); |
|
|
|
|
|
|
|
HttpPost httppost = new HttpPost(url_to_request); |
|
|
|
|
|
|
|
log.d(LOG_NAME, "URL to request: "+ url_to_request); |
|
|
|
|
|
|
|
|
|
|
|
List<NameValuePair> nvps = new ArrayList<>(); |
|
|
|
List<NameValuePair> nvps = new ArrayList<>(); |
|
|
|
Collections.addAll(nvps, params); |
|
|
|
Collections.addAll(nvps, params); |
|
|
|
httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); |
|
|
|
httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); |
|
|
@ -377,6 +527,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String makeUploadRequest(String path, String file, Log log) throws DaemonException { |
|
|
|
private String makeUploadRequest(String path, String file, Log log) throws DaemonException { |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
@ -394,7 +545,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private String makeWebRequest(HttpPost httppost, Log log) throws DaemonException { |
|
|
|
private String makeWebRequest(HttpRequestBase httpmethod, Log log) throws DaemonException { |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
|
|
|
|
|
|
|
@ -404,7 +555,9 @@ public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Execute
|
|
|
|
// Execute
|
|
|
|
HttpResponse response = httpclient.execute(httppost); |
|
|
|
HttpResponse response = httpclient.execute(httpmethod); |
|
|
|
|
|
|
|
http_response_code = response.getStatusLine().getStatusCode(); |
|
|
|
|
|
|
|
log.d(LOG_NAME, "Response code is: " + http_response_code); |
|
|
|
|
|
|
|
|
|
|
|
HttpEntity entity = response.getEntity(); |
|
|
|
HttpEntity entity = response.getEntity(); |
|
|
|
if (entity != null) { |
|
|
|
if (entity != null) { |
|
|
|