You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
647 lines
21 KiB
647 lines
21 KiB
/* |
|
* This file is part of Transdroid <http://www.transdroid.org> |
|
* |
|
* Transdroid is free software: you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation, either version 3 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* Transdroid is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with Transdroid. If not, see <http://www.gnu.org/licenses/>. |
|
* |
|
*/ |
|
package org.transdroid.daemon.Qbittorrent; |
|
|
|
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.protocol.HTTP; |
|
import org.json.JSONArray; |
|
import org.json.JSONException; |
|
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; |
|
import org.transdroid.daemon.Torrent; |
|
import org.transdroid.daemon.TorrentDetails; |
|
import org.transdroid.daemon.TorrentFile; |
|
import org.transdroid.daemon.TorrentStatus; |
|
import org.transdroid.daemon.task.AddByFileTask; |
|
import org.transdroid.daemon.task.AddByMagnetUrlTask; |
|
import org.transdroid.daemon.task.AddByUrlTask; |
|
import org.transdroid.daemon.task.DaemonTask; |
|
import org.transdroid.daemon.task.DaemonTaskFailureResult; |
|
import org.transdroid.daemon.task.DaemonTaskResult; |
|
import org.transdroid.daemon.task.DaemonTaskSuccessResult; |
|
import org.transdroid.daemon.task.GetFileListTask; |
|
import org.transdroid.daemon.task.GetFileListTaskSuccessResult; |
|
import org.transdroid.daemon.task.GetTorrentDetailsTask; |
|
import org.transdroid.daemon.task.GetTorrentDetailsTaskSuccessResult; |
|
import org.transdroid.daemon.task.RemoveTask; |
|
import org.transdroid.daemon.task.RetrieveTask; |
|
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 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. |
|
* @author erickok |
|
*/ |
|
public class QbittorrentAdapter implements IDaemonAdapter { |
|
|
|
private static final String LOG_NAME = "qBittorrent daemon"; |
|
|
|
private DaemonSettings settings; |
|
private DefaultHttpClient httpclient; |
|
private int version = -1; |
|
private int apiVersion = -1; |
|
|
|
public QbittorrentAdapter(DaemonSettings settings) { |
|
this.settings = settings; |
|
} |
|
|
|
private synchronized void ensureVersion(Log log) throws DaemonException { |
|
// Still need to retrieve the API and qBittorrent version numbers from the server? |
|
if (version > 0 && apiVersion > 0) |
|
return; |
|
|
|
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 | NumberFormatException e) { |
|
apiVersion = 1; |
|
} |
|
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 |
|
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); |
|
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 = versionText.split("\\."); |
|
if (parts.length > 0) { |
|
version = Integer.parseInt(parts[0]) * 100 * 100; |
|
if (parts.length > 1) { |
|
version += Integer.parseInt(parts[1]) * 100; |
|
if (parts.length > 2) { |
|
// 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 |
|
String numbers = ""; |
|
for (char c : parts[2].toCharArray()) { |
|
if (Character.isDigit(c)) |
|
// Still a number; add it to the numbers string |
|
numbers += Character.toString(c); |
|
else { |
|
// No longer reading numbers; stop reading |
|
break; |
|
} |
|
} |
|
version += Integer.parseInt(numbers); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
} 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. |
|
|
|
if (apiVersion < 2) { |
|
return; |
|
} |
|
|
|
// Have we already authenticated? Check if we have the cookie that we need |
|
List<Cookie> cookies = httpclient.getCookieStore().getCookies(); |
|
for (Cookie c : cookies) { |
|
if (c.getName().equals("SID")) { |
|
// And here it is! Okay, no need authenticate again. |
|
return; |
|
} |
|
} |
|
|
|
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. |
|
|
|
// However, we would like to see if authentication was successful or not... |
|
cookies = httpclient.getCookieStore().getCookies(); |
|
for (Cookie c : cookies) { |
|
if (c.getName().equals("SID")) { |
|
// Good. Let's get out of here. |
|
return; |
|
} |
|
} |
|
|
|
// No cookie found, we didn't authenticate. |
|
throw new DaemonException(ExceptionType.AuthenticationFailure, "Server rejected our login"); |
|
} |
|
|
|
@Override |
|
public DaemonTaskResult executeTask(Log log, DaemonTask task) { |
|
|
|
try { |
|
ensureVersion(log); |
|
ensureAuthenticated(log); |
|
|
|
switch (task.getMethod()) { |
|
case Retrieve: |
|
String path; |
|
if (version >= 30200) { |
|
path = "/query/torrents"; |
|
} else if (version >= 30000) { |
|
path = "/json/torrents"; |
|
} else { |
|
path = "/json/events"; |
|
} |
|
|
|
// Request all torrents from server |
|
JSONArray result = new JSONArray(makeRequest(log, path)); |
|
return new RetrieveTaskSuccessResult((RetrieveTask) task, parseJsonTorrents(result), null); |
|
|
|
case GetTorrentDetails: |
|
|
|
// 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)); |
|
|
|
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)); |
|
return new GetFileListTaskSuccessResult((GetFileListTask) task, parseJsonFiles(files)); |
|
|
|
case AddByFile: |
|
|
|
// Upload a local .torrent file |
|
String ufile = ((AddByFileTask) task).getFile(); |
|
makeUploadRequest("/command/upload", ufile, log); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case AddByUrl: |
|
|
|
// Request to add a torrent by URL |
|
String url = ((AddByUrlTask) task).getUrl(); |
|
makeRequest(log, "/command/download", new BasicNameValuePair("urls", url)); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case AddByMagnetUrl: |
|
|
|
// Request to add a magnet link by URL |
|
String magnet = ((AddByMagnetUrlTask) task).getUrl(); |
|
makeRequest(log, "/command/download", new BasicNameValuePair("urls", magnet)); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case Remove: |
|
|
|
// Remove a torrent |
|
RemoveTask removeTask = (RemoveTask) task; |
|
makeRequest(log, (removeTask.includingData() ? "/command/deletePerm" : "/command/delete"), |
|
new BasicNameValuePair("hashes", removeTask.getTargetTorrent().getUniqueID())); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case Pause: |
|
|
|
// Pause a torrent |
|
makeRequest(log, "/command/pause", new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID())); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case PauseAll: |
|
|
|
// Resume all torrents |
|
makeRequest(log, "/command/pauseall"); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case Resume: |
|
|
|
// Resume a torrent |
|
makeRequest(log, "/command/resume", new BasicNameValuePair("hash", task.getTargetTorrent().getUniqueID())); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case ResumeAll: |
|
|
|
// Resume all torrents |
|
makeRequest(log, "/command/resumeall"); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case SetFilePriorities: |
|
|
|
// Update the priorities to a set of files |
|
SetFilePriorityTask setPrio = (SetFilePriorityTask) task; |
|
String newPrio = "0"; |
|
if (setPrio.getNewPriority() == Priority.Low) { |
|
newPrio = "1"; |
|
} else if (setPrio.getNewPriority() == Priority.Normal) { |
|
newPrio = "2"; |
|
} else if (setPrio.getNewPriority() == Priority.High) { |
|
newPrio = "7"; |
|
} |
|
// 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)); |
|
} |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
case SetTransferRates: |
|
|
|
// TODO: This doesn't seem to work yet |
|
// Request to set the maximum transfer rates |
|
SetTransferRatesTask ratesTask = (SetTransferRatesTask) task; |
|
int dl = (ratesTask.getDownloadRate() == null ? -1 : ratesTask.getDownloadRate()); |
|
int ul = (ratesTask.getUploadRate() == null ? -1 : ratesTask.getUploadRate()); |
|
|
|
// First get the preferences |
|
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))); |
|
return new DaemonTaskSuccessResult(task); |
|
|
|
default: |
|
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())); |
|
} catch (DaemonException e) { |
|
return new DaemonTaskFailureResult(task, e); |
|
} catch (UnsupportedEncodingException e) { |
|
return new DaemonTaskFailureResult(task, new DaemonException(ExceptionType.ParsingFailed, e.toString())); |
|
} |
|
} |
|
|
|
private String makeRequest(Log log, String path, NameValuePair... params) throws DaemonException { |
|
|
|
try { |
|
|
|
// Setup request using POST |
|
HttpPost httppost = new HttpPost(buildWebUIUrl(path)); |
|
List<NameValuePair> nvps = new ArrayList<>(); |
|
Collections.addAll(nvps, params); |
|
httppost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); |
|
return makeWebRequest(httppost, log); |
|
|
|
} catch (UnsupportedEncodingException e) { |
|
throw new DaemonException(ExceptionType.ConnectionError, e.toString()); |
|
} |
|
|
|
} |
|
|
|
private String makeUploadRequest(String path, String file, Log log) throws DaemonException { |
|
|
|
try { |
|
|
|
// Setup request using POST |
|
HttpPost httppost = new HttpPost(buildWebUIUrl(path)); |
|
File upload = new File(URI.create(file)); |
|
Part[] parts = {new FilePart("torrentfile", upload)}; |
|
httppost.setEntity(new MultipartEntity(parts, httppost.getParams())); |
|
return makeWebRequest(httppost, log); |
|
|
|
} catch (FileNotFoundException e) { |
|
throw new DaemonException(ExceptionType.FileAccessError, e.toString()); |
|
} |
|
|
|
} |
|
|
|
private String makeWebRequest(HttpPost httppost, Log log) throws DaemonException { |
|
|
|
try { |
|
|
|
// Initialise the HTTP client |
|
if (httpclient == null) { |
|
initialise(); |
|
} |
|
|
|
// Execute |
|
HttpResponse response = httpclient.execute(httppost); |
|
|
|
HttpEntity entity = response.getEntity(); |
|
if (entity != null) { |
|
|
|
// Read JSON response |
|
java.io.InputStream instream = entity.getContent(); |
|
String result = HttpHelper.convertStreamToString(instream); |
|
instream.close(); |
|
|
|
// TLog.d(LOG_NAME, "Success: " + (result.length() > 300? result.substring(0, 300) + "... (" + |
|
// result.length() + " chars)": result)); |
|
|
|
// Return raw result |
|
return result; |
|
} |
|
|
|
log.d(LOG_NAME, "Error: No entity in HTTP response"); |
|
throw new DaemonException(ExceptionType.UnexpectedResponse, "No HTTP entity object in response."); |
|
|
|
} catch (Exception e) { |
|
log.d(LOG_NAME, "Error: " + e.toString()); |
|
throw new DaemonException(ExceptionType.ConnectionError, e.toString()); |
|
} |
|
|
|
} |
|
|
|
/** |
|
* Instantiates an HTTP client with proper credentials that can be used for all qBittorrent requests. |
|
* @throws DaemonException On conflicting or missing settings |
|
*/ |
|
private void initialise() throws DaemonException { |
|
httpclient = HttpHelper.createStandardHttpClient(settings, true); |
|
} |
|
|
|
/** |
|
* Build the URL of the web UI request from the user settings |
|
* @return The URL to request |
|
*/ |
|
private String buildWebUIUrl(String path) { |
|
return (settings.getSsl() ? "https://" : "http://") + settings.getAddress() + ":" + settings.getPort() + path; |
|
} |
|
|
|
private TorrentDetails parseJsonTorrentDetails(JSONArray messages) throws JSONException { |
|
|
|
ArrayList<String> trackers = new ArrayList<>(); |
|
ArrayList<String> errors = new ArrayList<>(); |
|
|
|
// Parse response |
|
if (messages.length() > 0) { |
|
for (int i = 0; i < messages.length(); i++) { |
|
JSONObject tor = messages.getJSONObject(i); |
|
trackers.add(tor.getString("url")); |
|
String msg = tor.getString("msg"); |
|
if (msg != null && !msg.equals("")) |
|
errors.add(msg); |
|
} |
|
} |
|
|
|
// Return the list |
|
return new TorrentDetails(trackers, errors); |
|
|
|
} |
|
|
|
private ArrayList<Torrent> parseJsonTorrents(JSONArray response) throws JSONException { |
|
|
|
// Parse response |
|
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")); |
|
int seeders[] = parsePeers(tor.getString("num_seeds")); |
|
double ratio = parseRatio(tor.getString("ratio")); |
|
double progress = tor.getDouble("progress"); |
|
long size; |
|
int dlspeed; |
|
int upspeed; |
|
|
|
if (apiVersion >= 2) { |
|
size = tor.getLong("size"); |
|
dlspeed = tor.getInt("dlspeed"); |
|
upspeed = tor.getInt("upspeed"); |
|
} else { |
|
size = parseSize(tor.getString("size")); |
|
dlspeed = parseSpeed(tor.getString("dlspeed")); |
|
upspeed = parseSpeed(tor.getString("upspeed")); |
|
} |
|
|
|
long eta = -1L; |
|
if (dlspeed > 0) |
|
eta = (long) (size - (size * progress)) / dlspeed; |
|
// Date added is only available in /json/propertiesGeneral on a per-torrent basis, unfortunately |
|
// Add the parsed torrent to the list |
|
// @formatter:off |
|
torrents.add(new Torrent( |
|
(long) i, |
|
tor.getString("hash"), |
|
tor.getString("name"), |
|
parseStatus(tor.getString("state")), |
|
null, |
|
dlspeed, |
|
upspeed, |
|
seeders[0], |
|
seeders[1], |
|
leechers[0], |
|
leechers[1], |
|
(int) eta, |
|
(long) (size * progress), |
|
(long) (size * ratio), |
|
size, |
|
(float) progress, |
|
0f, |
|
null, |
|
null, |
|
null, |
|
null, |
|
settings.getType())); |
|
// @formatter:on |
|
} |
|
|
|
// Return the list |
|
return torrents; |
|
|
|
} |
|
|
|
private double parseRatio(String string) { |
|
// Ratio is given in "1.5" string format |
|
try { |
|
return Double.parseDouble(normalizeNumber(string)); |
|
} catch (Exception e) { |
|
return 0D; |
|
} |
|
} |
|
|
|
private long parseSize(String string) { |
|
// See https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-Documentation |
|
if (string.equals("Unknown")) |
|
return -1; |
|
// Sizes are given in "1,023.3 MiB"-like string format |
|
String[] parts = string.split(" "); |
|
double number; |
|
try { |
|
number = Double.parseDouble(normalizeNumber(parts[0])); |
|
} catch (Exception e) { |
|
return -1L; |
|
} |
|
// Returns size in B-based long |
|
if (parts[1].equals("TiB")) { |
|
return (long) (number * 1024L * 1024L * 1024L * 1024L); |
|
} else if (parts[1].equals("GiB")) { |
|
return (long) (number * 1024L * 1024L * 1024L); |
|
} else if (parts[1].equals("MiB")) { |
|
return (long) (number * 1024L * 1024L); |
|
} else if (parts[1].equals("KiB")) { |
|
return (long) (number * 1024L); |
|
} |
|
return (long) number; |
|
} |
|
|
|
private int[] parsePeers(String seeds) { |
|
// Peers (seeders or leechers) are defined in a string like "num_seeds":"6 (27)" |
|
// 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[0])}; |
|
} |
|
|
|
private int parseSpeed(String speed) { |
|
// See https://github.com/qbittorrent/qBittorrent/wiki/WebUI-API-Documentation |
|
if (speed.equals("Unknown")) |
|
return -1; |
|
// Sizes are given in "1,023.3 KiB/s"-like string format |
|
String[] parts = speed.split(" "); |
|
double number; |
|
try { |
|
number = Double.parseDouble(normalizeNumber(parts[0])); |
|
} catch (Exception e) { |
|
return -1; |
|
} |
|
// Returns size in B-based int |
|
if (parts[1].equals("GiB/s")) { |
|
return (int) (number * 1024 * 1024 * 1024); |
|
} else if (parts[1].equals("MiB/s")) { |
|
return (int) (number * 1024 * 1024); |
|
} else if (parts[1].equals("KiB/s")) { |
|
return (int) (number * 1024); |
|
} |
|
return (int) (Double.parseDouble(normalizeNumber(parts[0]))); |
|
} |
|
|
|
private String normalizeNumber(String in) { |
|
// FIXME Hack for issue #115: Strip the possible . and , separators in a hopefully reliable fashion, for now |
|
if (in.length() >= 3) { |
|
String part1 = in.substring(0, in.length() - 3); |
|
String part2 = in.substring(in.length() - 3); |
|
return part1.replace("Ê", "").replace(" ", "").replace(",", "").replace(".", "") + part2.replace(",", "."); |
|
} |
|
return in.replace(",", "."); |
|
} |
|
|
|
private TorrentStatus parseStatus(String state) { |
|
// Status is given as a descriptive string |
|
if (state.equals("downloading")) { |
|
return TorrentStatus.Downloading; |
|
} else if (state.equals("uploading")) { |
|
return TorrentStatus.Seeding; |
|
} else if (state.equals("pausedDL")) { |
|
return TorrentStatus.Paused; |
|
} else if (state.equals("pausedUL")) { |
|
return TorrentStatus.Paused; |
|
} else if (state.equals("stalledUP")) { |
|
return TorrentStatus.Seeding; |
|
} else if (state.equals("stalledDL")) { |
|
return TorrentStatus.Downloading; |
|
} else if (state.equals("checkingUP")) { |
|
return TorrentStatus.Checking; |
|
} else if (state.equals("checkingDL")) { |
|
return TorrentStatus.Checking; |
|
} else if (state.equals("queuedDL")) { |
|
return TorrentStatus.Queued; |
|
} else if (state.equals("queuedUL")) { |
|
return TorrentStatus.Queued; |
|
} |
|
return TorrentStatus.Unknown; |
|
} |
|
|
|
private ArrayList<TorrentFile> parseJsonFiles(JSONArray response) throws JSONException { |
|
|
|
// Parse response |
|
ArrayList<TorrentFile> torrentfiles = new ArrayList<TorrentFile>(); |
|
for (int i = 0; i < response.length(); i++) { |
|
JSONObject file = response.getJSONObject(i); |
|
|
|
long size; |
|
if (apiVersion >= 2) { |
|
size = file.getLong("size"); |
|
} else { |
|
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")))); |
|
} |
|
|
|
// Return the list |
|
return torrentfiles; |
|
|
|
} |
|
|
|
private Priority parsePriority(int priority) { |
|
// Priority is an integer |
|
// Actually 1 = Normal, 2 = High, 7 = Maximum, but adjust this to Transdroid values |
|
if (priority == 0) { |
|
return Priority.Off; |
|
} else if (priority == 1) { |
|
return Priority.Low; |
|
} else if (priority == 2) { |
|
return Priority.Normal; |
|
} |
|
return Priority.High; |
|
} |
|
|
|
@Override |
|
public Daemon getType() { |
|
return settings.getType(); |
|
} |
|
|
|
@Override |
|
public DaemonSettings getSettings() { |
|
return this.settings; |
|
} |
|
|
|
}
|
|
|