/* * This file is part of Transdroid * * 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 . * */ package org.transdroid.daemon.Deluge; import androidx.annotation.NonNull; import org.base64.android.Base64; import org.transdroid.core.gui.log.Log; import org.transdroid.core.gui.remoterss.data.RemoteRssChannel; import org.transdroid.core.gui.remoterss.data.RemoteRssItem; import org.transdroid.core.gui.remoterss.data.RemoteRssSupplier; import org.transdroid.core.rssparser.Channel; import org.transdroid.core.rssparser.Item; import org.transdroid.core.rssparser.RssParser; import org.transdroid.daemon.*; import org.transdroid.daemon.DaemonException.ExceptionType; import org.transdroid.daemon.task.*; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import java.io.*; import java.net.URI; import java.util.*; import java.util.Map.Entry; import static org.transdroid.daemon.Deluge.DelugeCommon.*; /** * The daemon adapter from the Deluge torrent client using deluged API directly. * * @author alon.albert */ public class DelugeRpcAdapter implements IDaemonAdapter, RemoteRssSupplier { public static final int DEFAULT_PORT = 58846; private final DaemonSettings settings; private final boolean isVersion2; private int version = -1; public DelugeRpcAdapter(DaemonSettings settings, boolean isVersion2) { this.settings = settings; this.isVersion2 = isVersion2; } @Override public DaemonTaskResult executeTask(Log log, DaemonTask task) { final DelugeRpcClient client = new DelugeRpcClient(isVersion2); try { client.connect(settings); switch (task.getMethod()) { case Retrieve: return doRetrieve(client, (RetrieveTask) task); case AddByUrl: return doAddByUrl(client, (AddByUrlTask) task); case AddByMagnetUrl: return doAddByMagnetUrl(client, (AddByMagnetUrlTask) task); case AddByFile: return doAddByFile(client, (AddByFileTask) task); case Remove: return doRemove(client, (RemoveTask) task); case Pause: return doControl(client, task, RPC_METHOD_PAUSE); case PauseAll: return doControlAll(client, task, RPC_METHOD_PAUSE_ALL); case Resume: return doControl(client, task, RPC_METHOD_RESUME); case ResumeAll: return doControlAll(client, task, RPC_METHOD_RESUME_ALL); case GetFileList: return doGetFileList(client, (GetFileListTask) task); case SetFilePriorities: return doSetFilePriorities(client, (SetFilePriorityTask) task); case SetTransferRates: return doSetTransferRates(client, (SetTransferRatesTask) task); case SetLabel: return doSetLabel(client, (SetLabelTask) task); case SetDownloadLocation: return doSetDownloadLocation(client, (SetDownloadLocationTask) task); case GetTorrentDetails: return doGetTorrentDetails(client, (GetTorrentDetailsTask) task); case SetTrackers: return doSetTrackers(client, (SetTrackersTask) task); case ForceRecheck: return doForceRecheck(client, (ForceRecheckTask) task); default: return new DaemonTaskFailureResult(task, new DaemonException(ExceptionType.MethodUnsupported, task.getMethod() + " is not " + "supported by " + getType())); } } catch (DaemonException e) { return new DaemonTaskFailureResult(task, e); } finally { client.close(); } } @Override public Daemon getType() { return isVersion2 ? Daemon.Deluge2Rpc : Daemon.DelugeRpc; } @Override public DaemonSettings getSettings() { return settings; } @Override public ArrayList getRemoteRssChannels(Log log) throws DaemonException { final long now = System.currentTimeMillis(); final DelugeRpcClient client = new DelugeRpcClient(isVersion2); try { client.connect(settings); if (!hasMethod(client, RPC_METHOD_GET_RSS_CONFIG)) { throw new DaemonException(ExceptionType.MethodUnsupported, "YaRRS2 plugin not installed"); } //noinspection unchecked final Map rssConfig = (Map) client.sendRequest(RPC_METHOD_GET_RSS_CONFIG); //noinspection unchecked final Map> rssFeeds = (Map>) rssConfig.get(RPC_RSSFEEDS); final Map feedUrlMap = new HashMap<>(); final Map> feedItemMap = new HashMap<>(); if (rssFeeds != null) { for (Map feed : rssFeeds.values()) { final String feedUrl = (String) feed.get(RPC_URL); final Object key = feed.get(RPC_KEY); feedUrlMap.put(key, feedUrl); final List items = getRssFeedItems(feedUrl, log); feedItemMap.put(key, items); } } //noinspection unchecked final Map> subscriptions = (Map>) rssConfig.get(RPC_SUBSCRIPTIONS); final ArrayList channels = new ArrayList<>(); if (subscriptions != null) { for (Map subscription : subscriptions.values()) { final Integer key = Integer.valueOf(subscription.get(RPC_KEY).toString()); final String name = (String) subscription.get(RPC_NAME); final String label = (String) subscription.get(RPC_LABEL); final String downloadLocation = (String) subscription.get(RPC_DOWNLOAD_LOCATION); final String moveCompleted = (String) subscription.get(RPC_MOVE_COMPLETED); final Object feedKey = subscription.get(RPC_RSSFEED_KEY); final String feedUrl = feedUrlMap.get(feedKey); final List items = new ArrayList<>(); final List feedItems = feedItemMap.get(feedKey); if (feedItems != null) { for (Item item : feedItems) { items.add(new DelugeRemoteRssItem(item.getTitle(), item.getLink(), name, item.getPubdate())); } } channels.add(new DelugeRemoteRssChannel(key, name, feedUrl, now, label, downloadLocation, moveCompleted, items)); } } return channels; } finally { client.close(); android.util.Log.i("Alon", String.format("getRemoteRssChannels: %dms", System.currentTimeMillis() - now)); } } @Override public void downloadRemoteRssItem(Log log, RemoteRssItem rssItem, RemoteRssChannel rssChannel) throws DaemonException { final DelugeRemoteRssItem item = (DelugeRemoteRssItem) rssItem; final DelugeRemoteRssChannel channel = (DelugeRemoteRssChannel) rssChannel; final Map options = new HashMap<>(); final String label; if (channel != null) { final String downloadLocation = channel.getDownloadLocation(); if (downloadLocation != null) { options.put(RPC_DOWNLOAD_LOCATION, downloadLocation); } final String moveCompleted = channel.getMoveCompleted(); if (moveCompleted != null) { options.put(RPC_MOVE_COMPLETED, true); options.put(RPC_MOVE_COMPLETED_PATH, moveCompleted); } label = channel.getLabel(); } else { label = null; } final DelugeRpcClient client = new DelugeRpcClient(isVersion2); try { client.connect(settings); final String torrentId = (String) client .sendRequest(item.isMagnetLink() ? RPC_METHOD_ADD_MAGNET : RPC_METHOD_ADD, item.getLink(), options); if (label != null && hasMethod(client, RPC_METHOD_SETLABEL)) { client.sendRequest(RPC_METHOD_SETLABEL, torrentId, label); } } finally { client.close(); } } @NonNull private RetrieveTaskSuccessResult doRetrieve(DelugeRpcClient client, RetrieveTask task) throws DaemonException { // Get torrents //noinspection unchecked final Map> torrentsStatus = (Map>) client.sendRequest (RPC_METHOD_GET_TORRENTS_STATUS, new HashMap<>(), RPC_FIELDS_ARRAY); final List torrents = getTorrents(torrentsStatus.values()); // Check if Label plugin is enabled final boolean hasLabelPlugin = hasMethod(client, RPC_METHOD_GET_LABELS); // Get label list from server //noinspection unchecked final List labelNames = hasLabelPlugin ? (List) client.sendRequest(RPC_METHOD_GET_LABELS) : new ArrayList(); // Extract labels & counts from torrents. final List