transdroid icon indicating copy to clipboard operation
transdroid copied to clipboard

Allow to change download location in rTorrent

Open linost-xx opened this issue 11 years ago • 29 comments

As far as i know it is only possible to change download location if you use Transmission or Deluge. But i think it is possible to add this feature to rTorrent as well.

From what i understand from:

http://libtorrent.rakshasa.no/wiki/RTorrentXMLRPCGuide

Change the directory for a specific download.

xmlrpc localhost d.set_directory 91A2DF0C9288BC4C5D03EC8D8C26B4CF95A4DBEF foo/bar/

And:

http://libtorrent.rakshasa.no/wiki/RTorrentCommandsRaw

Index 55 String: 'd.directory' Index 56 String: 'd.directory.set' Index 57 String: 'd.directory_base' Index 58 String: 'd.directory_base.set'

It should be doable.

linost-xx avatar Oct 26 '13 19:10 linost-xx

If someone is interested i have made some modifications to the code to support this feature. It's far from a perfect solution.

I modified the way "Set label" works so it instead sets a new download location.

It will by default download to your /default/download/locaton/ and if you "change label" it will download to /default/download/locaton/NewLabel

It also works to save to subdirs if you name the "label" Movies/Comedy/Disney for example.

Here is a screenshot: http://i40.tinypic.com/2mqrp1w.jpg

The location history list is based on labels from your other downloads.

Bugs

§1 If your download is in a folder - ex "/Suber Ubuntu Release/ubuntu.bin/" and you want to move the download to the folder "Linux" there will have to be an existing folder named "Linux" otherwise it wont work.

§2 When you change the download location the download will start from 0% so change it directly when you add it.

§3 When you change the location a copy of the original file will still be in /default/download/directory - I have made a cron job to emty that directory every hour.

So, if you want the code or apk send me a message.

linost-xx avatar Dec 01 '13 18:12 linost-xx

It would be great to see that code. Do you have it in your own clone? (If you do, you haven't pushed it to GitHub yet.)

My guess is that you 'hijacked' the labels support because you didn't want to mess with the UI code. But there is already an option to change the download directory for torrents (with Transmission, for example). Any reason you dod not use that UI?

erickok avatar Dec 02 '13 06:12 erickok

No i had some trouble with importing from github so i just downloaded the .zip and imported from that.

Honestly i just wanted to use the label support because it looks awesome, and i have a autolabel feature on my server. So I actually never used it in transdroid.

Here is the code: > transdroid / lib / src / org / transdroid / daemon / Rtorrent / RtorrentAdapter.java

case SetLabel: SetLabelTask labelTask = (SetLabelTask) task; makeRtorrentCall("d.stop", new String[] { task.getTargetTorrent().getUniqueID() }); makeRtorrentCall("d.set_directory", new String[] { task.getTargetTorrent().getUniqueID(), task.getTargetTorrent().getLocationDir()+labelTask.getNewLabel() }); makeRtorrentCall("d.check_hash", new String[] { task.getTargetTorrent().getUniqueID() }); makeRtorrentCall("d.start", new String[] { task.getTargetTorrent().getUniqueID() }); return new DaemonTaskSuccessResult(task);

The problem is that, as far as i know xmlrpc don't support any "move" command. I don't know how you made it work in transmission but i suspect there is some php involved.

I'm considering if there is a way to use some kind of "event." to make rtorrent move the files but i havent found any solution for that yet.

linost-xx avatar Dec 02 '13 08:12 linost-xx

Or maybe an easier and more general solution would be to d.set_directory before starting the download in the first place. Like an "save as.." type of action.

linost-xx avatar Dec 02 '13 09:12 linost-xx

Also wait for this feature. Sorry for offtop.

ncyclon avatar Dec 04 '13 09:12 ncyclon

Already so it looks like I can just call d.set_directory, but it is far from ideal that any existing data is not moved. Is there another rTorrent command that can do that (too)? From http://libtorrent.rakshasa.no/wiki/RTorrentCommonTasks#Movecompletedtorrents I infer that you need a custom command.

If it is not possible, would you still like me to support this command?

erickok avatar Mar 04 '14 10:03 erickok

I have not been able to find a "move" command. But a custom command should work, I was looking at them but didn't really know what event to use for the command. But here is a list of events that can be used, don't know if there are any more.

  Index 159 String: 'event.download.closed'
  Index 160 String: 'event.download.erased'
  Index 161 String: 'event.download.finished'
  Index 162 String: 'event.download.hash_done'
  Index 163 String: 'event.download.hash_failed'
  Index 164 String: 'event.download.hash_final_failed'
  Index 165 String: 'event.download.hash_queued'
  Index 166 String: 'event.download.hash_removed'
  Index 167 String: 'event.download.inserted'
  Index 168 String: 'event.download.inserted_new'
  Index 169 String: 'event.download.inserted_session'
  Index 170 String: 'event.download.opened'
  Index 171 String: 'event.download.paused'
  Index 172 String: 'event.download.resumed'

But if it's not possible to get a "move" command to work it is as as you say not ideal. But in that case as i wrote above it might be better with a "save as" action where you set the default directory before starting the download. Then a move command wont be needed.

  Index 55 String: 'd.directory'
  Index 56 String: 'd.directory.set'
  Index 57 String: 'd.directory_base'
  Index 58 String: 'd.directory_base.set'

I'm guessing that d.directory_base.set would be the command to use in that case.

pseudo:

string baseDir = /standart/parth/ 

click to add torrent
set directory dialog
d.directory_base.set = /new/dir
d.start
d.directory_base.set = baseDir

and possibly an option in settings to enable/disable "save as"

linost-xx avatar Mar 04 '14 12:03 linost-xx

I would like to ask that this is implemented as an optional dialog (server preference toggle) that shows itself whenever a torrent is sent to transdroid, preferably with a history of 3 or 5 dirs. This is how the Chrome Remote Torrent adder extension works.

As for moving data for already existing torrents, I believe rutorrent does the actual moving of data itself in php. It may be possible in rtorrent but I would view it as an additional feature.

The directory selection dialog alone would be a huge timesaver for me.

infernix avatar Jul 17 '14 02:07 infernix

I've done some digging, and choosing the target download directory for rtorrent can completely be done through the XML API:

  • First use load_raw to load the torrent data in base64 encoding
  • Then get the state through d.state to ensure it's loaded (should return 0 for stopped)
  • Then change path with d.set_directory
  • Finally start with d.start

Relevant code from rt-cli:

(print "Adding torrent file '" tor "'" (if dest (string-append " to " dest) ""))
    (rt:cmd connection 'load_raw (string->blob (bencode torrent)))
      ;; check that torrent was added
      (if (rt:cmd connection 'd.state th)
          (begin
            (if dest (rt:cmd connection 'd.set_directory th dest))
            (rt:cmd connection 'd.start th))
          (begin
            (print "Hm. Seems torrent file wasn't added correctly. Aborting.")
            (exit 1))))

I tried looking for an existing interface to enter download directories but did not find it; is there one for other clients? Or is there just getDownloadDir()?

infernix avatar Aug 10 '14 03:08 infernix

This is the one reason keeping me from using Transdroid with my rtorrent server other than looking at the status of my torrents sometimes.

Any chance this could be added to it?

alethenorio avatar Jun 09 '15 18:06 alethenorio

If ruTorrent is added then php/addtorrent.php accepts a dir_edit parameter and httprpc already have works fine for the rpc calls

alexcoe avatar Jun 12 '15 07:06 alexcoe

:+1: I do need this feature. Thanks to all of you

guiled avatar Dec 01 '15 14:12 guiled

Is there any progress update on this? Still being the only feature preventing me from using transdroid in a more meaningful way

alethenorio avatar Dec 03 '15 18:12 alethenorio

+1 please !

Eikichi60 avatar Dec 03 '15 21:12 Eikichi60

Yes would love this!

pokegoo avatar Aug 20 '16 02:08 pokegoo

Due to watch folders, subfolder auto labeling, and automove functions, being able to specify a download location is keeping me from using Transdroid.

rutorrent does indeed have an option to set a location and should be able to be hooked into.

Please implement this feature if possible! Thanks!!!

vhodh avatar Sep 20 '16 07:09 vhodh

I think there is enough interest from people for this, the question is, is it possible?

One thing to keep in mine is that ruTorrent does use SCGI while most transdroid setups, though it seems to have support for it, probably do not. Does transdroid support this if one use SCGI? Does rTorrent supports this when not using no SCGI?

I think I tried once setting up ruTorrent on a separate machine from rTorrent and found out it does not work so I am not sure how is transdroid supposed to be able to work with it.

On Tue, 20 Sep 2016, 00:02 vhodh, [email protected] wrote:

Due to watch folders, subfolder auto labeling, and automove functions, being able to specify a download location is keeping me from using Transdroid.

rutorrent does indeed have an option to set a location and should be able to be hooked into.

Please implement this feature if possible! Thanks!!!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/erickok/transdroid/issues/49#issuecomment-248219940, or mute the thread https://github.com/notifications/unsubscribe-auth/ACn1SynrzZfXCMpeE6U-tOcbn02nOvJ_ks5qr4T5gaJpZM4BI6sa .

alethenorio avatar Sep 20 '16 12:09 alethenorio

This is the thing. As far as I understand it, the way ruTorrent does it is by defining custom commands on rTorrent directly and using these custom commands afterwards via scgi. But Transdroid has no direct connection, so I have to rely on any existing commands. Now if we would know where (under what name) ruTorrent defines the command, Transdroid could call them as well. At least this way it will work for people who have set up ruTorrent too with their rTorrent setups.

erickok avatar Sep 20 '16 12:09 erickok

To be clear, I know there exists a 'd.directory_base.set' command but that would not work for existing downloads as no data is moved. Hence, it is not what we are after.

erickok avatar Sep 20 '16 12:09 erickok

@erickok but can't we at least add this functionality when adding a torrent? That would totally cover my use case at least?

As for moving, I dug into the source. ruTorrent does the moving itself within PHP. There isn't anything in rtorrent for moving data as far as I can see.

Some digging seems to point at ruTorrent calling this in plugins/datadir/action.php:

 $res = rtExec( "execute",
                        array( "sh",
                                "-c",
                                escapeshellarg($php)." ".escapeshellarg($script_dir."setdir.php").
                                        " ".$hash." ".escapeshellarg($datadir).
                                        " ".$move_addpath." ".$move_datafiles." ".$move_fastresume.
                                        " ".escapeshellarg(getUser())." & exit 0",
                        ),
                        $datadir_debug_enabled );

plugins/datadir/setdir.php then does:

# Script arguments are:
# 0: script name
# 1: hash
# 2: target datadir
# 3: flag, "1" means "add torrent's path"
# 4: flag, "1" means "move datafiles"
# 5: flag, "1" means "fast resume"
# 6: username

...

        if( !rtMkDir( $datadir, 0777 ) )
        {
                Debug( "can't create ".$datadir );
        }
        elseif( !rtSetDataDir( $hash, $datadir, 
                $move_addpath == '1', $move_datafiles == '1', $move_fastresume == '1',
                $datadir_debug_enabled ) )
        {
                Debug( "rtSetDataDir() fail!" );
        }

rtSetDataDir in plugins/datadir/util_setdir.php then calls back to rtorrent to get some variables:

     // Ask info from rTorrent
        if( $is_ok && $move_files )
        {
                $req = rtExec(
                        array(  "d.get_name", 
                                "d.get_base_path", 
                                "d.get_base_filename", 
                                "d.is_multi_file", 
                                "d.get_complete" ),
                        $hash, $dbg );

And a bit further down (after stopping and closing torrent):

if( !rtOpFiles( $torrent_files, $full_base_path, $full_dest_path, "Move", $dbg ) )
                                $is_ok = false;

rtOpFiles is in plugins/datadir/util_rt.php:

/------------------------------------------------------------------------------
// Make operation an array of files from $src directory to $dst directory
// ( files in array are relative to $src directory )
//------------------------------------------------------------------------------
function rtOpFiles( $files, $src, $dst, $op, $dbg = false )
{
...
                                if( !rtMoveFile( $source, $dest, $dbg ) )
                                        return false;
                                break;

And finally rtMoveFile in the same file:

//------------------------------------------------------------------------------
// Move $src file to $dst
//------------------------------------------------------------------------------
function rtMoveFile( $src, $dst, $dbg = false )
{
        $ss = LFS::stat($src);
        if( !rename( $src, $dst ) )
        {
                if( $dbg ) rtDbg( __FUNCTION__, "from ".$src );
                if( $dbg ) rtDbg( __FUNCTION__, "to   ".$dst );
                if( $dbg ) rtDbg( __FUNCTION__, "move fail, try to copy" );
                if( !copy( $src, $dst ) )
                {
                        if( $dbg ) rtDbg( __FUNCTION__, "copy fail" );
                        return false;
                }
                if( !unlink( $src ) )
                        if( $dbg ) rtDbg( __FUNCTION__, "delete fail (".$src.")" );
        }
        // there are problems here, if run-user is not file owner
        if($ss!==false)
                touch( $dst, $ss['mtime'], $ss['atime'] );
        return true;
}

The best way to mimic what ruTorrent itself does is to either post to plugins/datadir/action.php or to plugins/datadir/setdir.php

infernix avatar Sep 20 '16 13:09 infernix

Right so ruTorrent has local script access, something which Transdroid cannot do. You are right that (IF the user has installed ruTorrent and IF those php scrips accept remote commands, something I doubt but have not checked) calling into those action/setdir.php scripts could be a solution, maybe.

erickok avatar Sep 20 '16 13:09 erickok

@erickok and simply adding the option to specify a dir when adding a torrent is not acceptable?

infernix avatar Sep 20 '16 13:09 infernix

That's a possibility but only 'simple' in the function sense. It would require a lot of work in the app. See #112 for my earlier concerns.

erickok avatar Sep 20 '16 13:09 erickok

setdir.php looks for $argv so it can't be called.

But action.php can be called! Watch:

Using https://github.com/eliangcs/http-prompt:

https://my-server/rutorrent/plugins/datadir/action.php> post -f hash=FOOBARLONGTORRENTHASHSTRING datadir=/my/destination/path move_datafiles=1 move_addpath=1 move_fastresume=1

rutorrent output:

[20.09.16 15:57:43] 
[20.09.16 15:57:43] DataDir: --- begin ---
[20.09.16 15:57:43] DataDir: /my/destination/path
[20.09.16 15:57:43] DataDir: "add path", "move files", "fast resume"
[20.09.16 15:57:43] DataDir: script dir  : /var/www/rutorrent/plugins/datadir/
[20.09.16 15:57:43] DataDir: path to php : php
[20.09.16 15:57:43] DataDir: hash        : FOOBARLONGTORRENTHASHSTRING
[20.09.16 15:57:43] DataDir: data dir    : /my/destination/path
[20.09.16 15:57:43] DataDir: add path    : 1
[20.09.16 15:57:43] DataDir: move files  : 1
[20.09.16 15:57:43] DataDir: fast resume : 1
[20.09.16 15:57:43] rtExec: execute
[20.09.16 15:57:43] DataDir: --- end ---
[20.09.16 15:57:43] 
[20.09.16 15:57:43] SetDir: --- begin ---
[20.09.16 15:57:43] SetDir: hash        : FOOBARLONGTORRENTHASHSTRING
[20.09.16 15:57:43] SetDir: data dir    : /my/destination/path
[20.09.16 15:57:43] SetDir: add path    : 1
[20.09.16 15:57:43] SetDir: move files  : 1
[20.09.16 15:57:43] SetDir: fast resume : 1
[20.09.16 15:57:43] rtSetDataDir: hash        : FOOBARLONGTORRENTHASHSTRING
[20.09.16 15:57:43] rtSetDataDir: dest_path   : /my/destination/path
[20.09.16 15:57:43] rtSetDataDir: add path    : 1
[20.09.16 15:57:43] rtSetDataDir: move files  : 1
[20.09.16 15:57:43] rtSetDataDir: fast resume : 1
[20.09.16 15:57:43] rtExec: d.is_open, d.is_active
[20.09.16 15:57:43] rtSetDataDir: is_open=1, is_active=1
[20.09.16 15:57:43] rtExec: d.get_name, d.get_base_path, d.get_base_filename, d.is_multi_file, d.get_complete
[20.09.16 15:57:43] rtSetDataDir: d.get_name          : mytestfile.iso
[20.09.16 15:57:43] rtSetDataDir: d.get_base_path     : /the/current/path/mytestfolder/mytestfile.iso
[20.09.16 15:57:43] rtSetDataDir: d.get_base_filename : mytestfile.iso
[20.09.16 15:57:43] rtSetDataDir: d.is_multy_file     : 0
[20.09.16 15:57:43] rtSetDataDir: d.get_complete      : 1
[20.09.16 15:57:43] rtExec: f.multicall
[20.09.16 15:57:43] rtSetDataDir: files in torrent    : 1
[20.09.16 15:57:43] rtExec: d.stop, d.close
[20.09.16 15:57:43] rtSetDataDir: from /the/current/path/mytestfolder/
[20.09.16 15:57:43] rtSetDataDir: to  /my/destination/path/
[20.09.16 15:57:43] rtOpFiles: finished
[20.09.16 15:57:43] rtSetDataDir: clean /the/current/path/mytestfolder/
[20.09.16 15:57:43] rtSetDataDir: trying fast resume
[20.09.16 15:57:43] rtExec: get_session, d.get_tied_to_file, d.get_custom1, d.get_connection_seed, d.get_throttle_name
[20.09.16 15:57:43] rtExec: d.set_directory
[20.09.16 15:57:43] rtExec: d.erase
[20.09.16 15:57:43] rtSetDataDir: fast resume done
[20.09.16 15:57:43] rtSetDataDir: finished
[20.09.16 15:57:43] SetDir: --- end ---

So this is actually really simple. You just post the hash, the destination dir, and the optional flags.

move_addpath: "Don't add torrent's name to path" move_datafiles: "Move data files" move_fastresume: "Fast resume"

For all moves I've ever done, move_addpath=0 move_datafiles=1 move_fastresume=1 but YMMV between users.

@erickok, that's about as far as I can take it. Is calling action.php this way feasible?

infernix avatar Sep 20 '16 14:09 infernix

Yes it is (given that the user has ruTorrent installed). Thanks for the work, I need to find some time now to work on it and try it myself.... 😊

erickok avatar Sep 20 '16 14:09 erickok

Hi guy, I'm really waiting for this feature, now you have the technical solution do you know where you'll have time to implement it?

Thanks a lot.

loubinator avatar Feb 23 '17 22:02 loubinator

@erickok I know we're all busy all the time, but will you ever find time for this? Would sponsoring this work help with that? I've done the legwork and would submit a PR myself if it weren't for my lack of Java skills :)

infernix avatar May 06 '17 20:05 infernix

And one more year past :) any news?

baragoon avatar Dec 13 '18 08:12 baragoon

I think you know the answer to that question.

Transdroid is in maintenance mode so don't expect anything feature-related at the moment any time soon, sorry.

erickok avatar Dec 14 '18 09:12 erickok