Transmission и пустые папки / .part файлы при скачке торрентов.

Привет, ЛОР. Эта проблема существет все время сколько я пользуюсь этим торрент клиентом, но последнее время она начала меня сильно, пардон, задалбывать. Что происходит?
Добавляем торрент, но не скачиваем его полностью, а допустим отмечаем половину файлов и пару дирректорий из 10. Но по окончании загрузки все равно есть дирректории, которые я НЕ отмечал и файлы, с окончанием .part. Как это можно побороть? Я понимаю, что возможно это особенности работы торрента, но даже на чертовом андроиде есть опция «keep part files in separate folder», как можно запилить подобное в трансмиссии?
UPD: Кастую эксперта по написанию костылей #cast intelfx
Можешь написать скрипт, который пройдется по всем дирректориям внутри и сделает следующее:
1) Удалит пустые папки.
2) Удалит из папок файлы, которые на конце содержат .part

Jefail ★★★★
21.09.15 20:10:32 MSK
Transmission. Странности с сохранением торрентов.
У меня Transmission почему то сохраняет торренты в левую папку (которую кажется сам и создал) несмотря на собственные настройки указывающие на другую папку. Куда он сохраняет file.torrent я вообще не понял (после рестарта незаконченые закачки не идут) . Что с этим сделать?
https://yadi.sk/i/L8yzAbGzUhd4Cg
algri14 пишет:
dmitriy2323, не ставь на ссылку с картинкой тег «img», у него другая функция, сейчас она не работает, это загрузка на форумный сервер, некому сделать превью загружаемого файла (чтобы при загрузке больших изображений они не маячили на всю страницу)
2 Ответ от algri14 2019-01-26 04:01:41 (2019-01-27 11:31:33 отредактировано algri14)
dmitriy2323, особо не разбирался с ним, но после закрытия/открытия Transmission закачка продолжилась, file.torrent он похоже никуда не кладёт, во всяком случае у меня, я открыл торрент-сайт, Firefox спросил чем открыть, ответил что в Transmission, указал путь куда положить фильм, а file.torrent остался во временной папке системы /tmp/mozilla_имя-юзера0/
В Параметрах_Transmission =>Загрузка есть строка:
Automatically add .torrent files from: — Автоматически добавлять .torrent файлы из:
возможно их надо самому вручную сначала загрузить браузером туда, например в: /home/имя_юзера/Transmission/
а потом указать путь в строке Automatically add .torrent files from:
естественно галочку не забудь поставить
Про незаконченные закачки: возможно в сети нет сидов и пиров, т.е. раздающих нет
В КДЕ по дефолту стоит KTorrent, вот он сохраняет file.torrent автоматом в /home/имя_юзера/.local/share/ktorrent/
Ещё мне нравится qBittorrent (в винде его тоже ставлю), он тоже сохраняет автоматом file.torrent в /home/имя_юзера/.local/share/data/qBittorrent/
Спасибо сказали: dmitriy2323 1
Сообщений 2
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Работает на PunBB , при поддержке Informer Technologies, Inc , при поддержке sevo44.ru
Удобная загрузка торрентов
Сколько кликов вы делаете для того, чтобы фильм, который вы решили посмотреть сегодня вечером, оказался в вашем медиацентре? Я — один.
Я сохраняю на своём компьютере .torrent , и он начинает скачиваться на медиацентре (у меня это второй ноут). Я могу начать закачку с телефона, другого компьютера, из другого конца вселенной. Если медиацентр сейчас выключен или на нём нет интернета, то закачка начнётся как только он включится и появится в сети.
Для такой передачи файлов отлично подходит какой-нибудь облачный синхронизатор типа Дропбокса. Скачиваешь файл, кладёшь в определённую папку, он улетает в облако, из облака прилетает на медиацентр, как только тот появляется в сети. А там просто торрент-качалка подхватывает торренты из папки. Можно скинуть с любого устройства, для которого есть клиент. Можно даже через браузер закинуть.
Я выбрал именно Дропбокс, потому что
- для него есть клиенты под все платформы, которые я использую;
- в его консольном клиенте под линукс можно выбрать, какие папки синхронизировать, а какие нет;
- можно добавить автоматизации с IFTTT (типа отправить файл на почту, и он добавится в Дропбокс).
Настройка Дропбокса на медиацентре
Он должен запускаться при включении компьютера и синхронизировать только выбранную папку. Ребята в Дропбоксе сделали клиент, который можно запускать без иксов.
Устанавливаем по инструкции и запускаем:
cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf - ~/.dropbox-dist/dropboxd
Дропбокс скажет ссылку, по которой надо залогиниться в браузере, чтобы привязать этот компьютер к аккаунту. Теперь скачаем скрипт, который позволяет из консоли рулить дропбоксом, например, исключить папки из синхронизации:
wget -O dropbox.py - "https://www.dropbox.com/download?dl=packages/dropbox.py" sudo mv dropbox.py /usr/local/bin sudo chown root:staff /usr/local/bin/dropbox.py sudo chmod +x /usr/local/bin/dropbox.py
Запустим его и исключим все папки, кроме Dropbox/Automatic/Torrents (куда я торренты буду складывать):
dropbox.py start cd Dropbox dropbox.py exclude Documents Photos Public Projects # тут всё, что вам не надо синхронизировать
И создадим сервис /lib/systemd/system/dropbox@.service для systemd (а у вас что?), который будет запускать дропбокс:
[Unit] Description=Dropbox After=local-fs.target network.target [Service] Type=simple ExecStart=/usr/local/bin/dropbox.py start ExecReload=/usr/local/bin/dropbox.py stop && /usr/local/bin/dropbox.py start KillMode=process Restart=on-failure User=%I [Install] WantedBy=multi-user.target
И включим его для того пользователя, под которым вы настроили Дропбокс (имя пользователя после @):
sudo systemctl enable dropbox@isqua
Перезагружаемся и проверяем, что всё работает.
sudo systemctl status dropbox@isqua
Осталось в вашем торрент-клиенте указать, чтобы он брал торренты из папки, которую вы синхронизируете.
Настройка Transmission на медиацентре
Я использую сервер transmission с веб-интерфейсом. В дебиане он ставится из пакета transmission-daemon . Его настройки живут в /etc/transmission-daemon/settings.json . Прежде, чем их редактировать, нужно остановить сервис:
sudo systemctl stop transmission-daemon
Чтобы Transmission заглядывал в папку за торрентами, в конфиг надо добавить такие опции:
"watch-dir": "/path/to/your/synced/Torrents", "watch-dir-enabled": true,
После чего запустить сервис:
sudo systemctl start transmission-daemon
Не забудьте проверить, что пользователь, от которого запущен Transmission, имеет права на чтение из папки, в которой лежат торренты. Проверьте, как у него дела:
sudo systemctl status transmission-daemon
Настройка Automator на маке
Помните первый пункт? Я сохраняю .torrent , и вот кино уже качается. Но мне же надо ещё и в папку в Дропбоксе его положить! На самом деле нет. За меня это делает Automator. Браузер по умолчанию кладёт загрузки в Downloads, а Automator перекладывает все торрент-файлы в нужную папку. Как это настроить? Открывайте Automator.
При открытии он спросит, какого типа действие вы хотите создать. Выбирайте «Folder Action». В левой панели выбирайте «Files & Folders → Filter Finder Items» и добавляйте условие «File extension is torrent». Потом простейшее действие «Move Finder Items» и выбирайте вашу папку в Дропбоксе, которая синхронизируется с сервером. Короче:

Ну и тестируем. Скачиваем какой-нибудь .torrent и смотрим, добавился ли он в наш Дропбокс, а потом и в торренты. У меня работает. А у вас?
Подписывайтесь на телеграм-канал про фронтенд, дизайн, работу и жизнь.
Transmission — внедряем в него плюшки
Добрый день.
На своём домашнем серваке сменил систему, и собственно софт тоже нужно было переставлять.
Поэтому ради теста просмотрел несколько самых популярных торрент-клиентов, работающих на *nix (rTorrent, Deluge, MLDonkey, Transmission).
Последний понравился мне больше всего, однако для меня нашёлся существенный минус — невозможно переименовывать зашитые в .torrent-файл имена торрентов.
То есть у нас на диске будут всякие разные папки, например — «Krovavaja gora», «Место Преступления Нью-Йорк», а то и просто «7 Сезон».
Мне это не по нраву, я люблю порядок, соотвестсвенно свою фильмотеку (точнее её сериальную часть) организую в виде «%SERIAL_NAME%/Season N».
Transmission увы не позволяет такого. Но так как в основном всё было хорошо, я взялся подгонять клиент под себя.
Transmission. Rename
Первая подзадача — возможность переименования папки с содержимым торрента в файловой системе, и продолжение корректной работы.
Меня не первого посетила такая простая мысль, что это нужно для клиента. В багтрекинговой системе существует тикет трехгодичной давности #1220. К сожалению, разработчики как-то вяло реагируют на него, однако камрад juxda любезно написал патч, который добавляет данный функционал к сорцам.
Однако радиус кривизны моих рук не позволил корректно наложить патч даже на ту ревизию (11895) для которой он изготовлен. Кроме того хотелось всё же иметь наиболее свежую версию торрент-клиента с данной фишкой, ибо с той ревизии прошло ~500 коммитов.
Поэтому я избрал путь вдумчивого патчинга, с разбором того, что конкретно мы делаем, дабы можно было и самому подправить в случае чего, да и допилить клиенты к демону.
Начинается всё просто:
svn co svn://svn.transmissionbt.com/Transmission/trunk Transmission
Забираем HEAD-ревизию с SVN-сервера. Список нужных пакетов есть в траке, замечу что если не нужен gtk-клиент, то и часть либ можно не ставить (libgtk2.0-dev, libnotify-dev, libglib2.0-dev можно проигнорить). libevent-dev нужен свежий (2.0.10 на данный момент), мне пришлось компилировать из исходников, так как -dev пакеты в репозитории я не нашёл. Подготовительная часть закончена, можно идти копаться в исходники.
Начинаем с основы — ядра (папка libtransmission). Правим заголовок — transmission.h.
Добавляем поле в структуру описания метаданных торрента tr_info поле «char * rename«. Эта структура содержит данные, полученные из .torrent. Собственно если таких данных нет, то и переименование не возможно, поэтому логично затесаться в эту структуру.Добавленное поле будет содержать имя торрента в файловой системе после переименования.
Кроме того добавляем описание нашей новой функции:
int tr_torrentRename( tr_torrent * torrent, const char * newname );
Самое время упомянуть об одной сложности — имена файлов строятся на основе оригинального имени.
Конечно можно всё пропатчить, но таких мест довольно много, и лучше просто после загрузки «перегрузить» эти имена.
Поэтому мы используем встроенный механизм восстановления информации — добавляем поле, которое содержит этот самый список путей, для сохранение, и при загрузке «вспоминаем» всё то, что нам нужно.
Пока отложим этот момент ненадолго, но не забудем о нём.
Перейдём к главному — самой функции перемещения. Редактировать будем torrent.h/torrent.c.
Сначала добавим в заголовочный файл функцию, которая и будет записывать перезаписывать пути для файлов во внутренней структуре торрента, эта функции будет нужна в том самом механизме:
void tr_torrentInitFileName( tr_torrent * tor, tr_file_index_t fileIndex, const char * name );
Ну и в сам torrents.c её тело:
void tr_torrentInitFileName( tr_torrent * tor, tr_file_index_t fileIndex, const char * name ) < tr_file * file; assert( tr_isTorrent( tor ) ); assert( fileIndex < tor->info.fileCount ); assert( name != NULL ); assert( name[0] != '\0' ); file = &tor->info.files[fileIndex]; tr_free( file->name ); file->name = tr_strdup( name ); >
Всё примитивно — освобождаем старый путь, записываем новый. Такой небольшой хелпер.
Далее находим функцию fileExists() и после неё пишем основной код:
static bool dirExists( const char * path ) < struct stat sb; return stat( path, &sb ) == 0 && S_ISDIR( sb.st_mode ); >int tr_torrentRename( tr_torrent * tor, const char * newname ) < tr_info * info; const char * root, * p, * oldname, * base; char * oldpath = NULL, * newpath = NULL, * subpath = NULL; int err = 0; assert( tr_isTorrent( tor ) ); tr_torrentLock( tor ); if( !tr_torrentHasMetadata( tor ) ) < err = ENOENT; goto OUT; >if( !newname || !newname[0] || strchr( newname, TR_PATH_DELIMITER ) || !strcmp( newname, "." ) || !strcmp( newname, ".." ) ) < err = EINVAL; goto OUT; >info = &tor->info; if (info->rename) oldname = info->rename; else oldname = info->name; if( ( p = strchr( oldname, TR_PATH_DELIMITER ) ) ) < /* Should not happen, but just in case. */ err = EISDIR; goto OUT; >if( !strcmp( newname, oldname ) ) goto OUT; root = tr_torrentGetCurrentDir( tor ); if( info->fileCount > 1 ) < tr_file_index_t fi; oldpath = tr_buildPath( root, oldname, NULL ); if( dirExists( oldpath ) ) < newpath = tr_buildPath( root, newname, NULL ); if( fileExists( newpath, NULL) ) < err = EEXIST; goto OUT; >if( rename( oldpath, newpath ) == -1 ) < err = errno; goto OUT; >> for( fi = 0; fi < info->fileCount; ++fi ) < tr_file * file = &info->files[fi]; char * newfnam; if( !( p = strchr( file->name, TR_PATH_DELIMITER ) ) ) continue; newfnam = tr_buildPath( newname, p + 1, NULL ); tr_free( file->name ); file->name = newfnam; > > else < if( tr_torrentFindFile2( tor, 0, &base, &subpath, NULL) ) < oldpath = tr_buildPath( base, subpath, NULL ); newpath = tr_buildPath( base, newname, NULL ); if( fileExists( newpath, NULL) ) < err = EEXIST; goto OUT; >if( rename( oldpath, newpath ) == -1 ) < err = errno; goto OUT; >> tr_free( info->files[0].name ); info->files[0].name = tr_strdup( newname ); > tr_free( info->rename ); if( !strcmp( newname, info->name ) ) info->rename = NULL; else info->rename = tr_strdup( newname ); tr_torrentSetDirty( tor ); OUT: if( err ) < const char * es = tr_strerror( err ), * fmt; if( oldpath && newpath ) < /* %1$s is the original file path. * %2$s is the new file path. * %3$s is the error message. */ fmt = _( "Cannot rename \"%1$s\" to \"%2$s\": %3$s" ); tr_torerr( tor, fmt, oldpath, newpath, es ); >else if( oldpath ) < /* %1$s is the existing file name. * %2$s is the error message. */ fmt = _( "Cannot rename \"%1$s\": %2$s" ); tr_torerr( tor, fmt, oldpath, es ); >else < fmt = _( "Cannot rename torrent: %s" ); tr_torerr( tor, fmt, es ); >> tr_torrentUnlock( tor ); tr_free( oldpath ); tr_free( newpath ); tr_free( subpath ); return err; >
Большая часть кода это простые проверки, существенная часть это собственно сам вызов rename(), и правка info->files. Ну и не забываем заполнить info->rename.
Теперь нужно дать знать всем о том, что имя сменилось. Фактически это можно сделать прямыми правками. Несмотря на то что автор большей части кода пошёл по пути модификации tr_torrentName() я выбрал другой путь. Модификация той функции полезна только если собираетесь использовать gtk-клиент, тогда да, лучше заменить единственную строчку кода на:
return tor->info.rename ? tor->info.rename : tor->info.name;
Дабы всё было в ажуре для gtk, но так как я не использую это gui, то посчитал излишним портить кучу других вещей типа построения magnet-ссылки (оригинальный патч, само собой, портит). Фактически мне поле rename нужно только для построения пути к файлам, и для того чтобы отдавать по RPC, дабы RPC-клиент мог, например, открыть папку с торрентом. Первое у нас есть (пока что половинка), второе решается тоже несложно (переходим к правке имплементации RPC — rpcimpl.c).
Ищем функцию addField(), которая отвечает за формирование информационных полей торрента для ответа. То есть мы можем запросить некий набор полей о торренте, и с помощью этой функции Transmission сформирует данную информацию. Нас интересует поле «name«, заменяем параметр «tr_torrentName( tor )» на
tor->info.rename ? tor->info.rename : tor->info.name
Готово. Теперь и RPC знает о нашем новом статусе.
Раз уж взялись править RPC, то нужно добавить собственно команду переименования.
Функция-прослойка, которую нужно вставить до torrentSet():
static const char * renameTorrent( tr_torrent * tor, const char * str )
Теперь добавим саму команду, для этого и отредактируем функцию torrentSet():
Добавим в блок описания переменных — const char * str;
И проверку на команду rename:
if( !errmsg && tr_bencDictFindStr( args_in, "rename", &str ) ) errmsg = renameTorrent( tor, str );
Что же мы не сделали? А мы забыли о механизме сохранения состояния торрента!
Нужно восполнить этот пробел, этот модуль содержится в файлах (resume.c / resume.h).
Сначала добавим флажки сохраняемых полей. В заголовочном файле только одно перечисление, запутаться трудно.
Нам нужно будет сохранять информацию о настоящем местоположении торрента (inf->rename) и список файлов, о котором я говорил ранее.
Значит 2 флажка:
TR_FR_FILE_NAMES = ( 1
Несмотря на присутствие заголовочного файла, в resume.c есть список ключей-дефайнов (ключ описывает каждую сущность состояния сохраняющуюся на диск).
Туда нам тоже необходимо «вписаться»:
#define KEY_FILE_NAMES "name" #define KEY_RENAME "rename"
Оригинальное поле "name" не сохраняется, так как берется непосредственно из .torrent. Поэтому вполне можем в качестве ключа использовать этот идентификатор, и это не внесёт никакой путаницы в дальнейшем.
Добавим функции сохранения путей:
static void saveFileNames( tr_benc * dict, const tr_torrent * tor ) < const tr_info * inf = tr_torrentInfo( tor ); const tr_file_index_t n = inf->fileCount; tr_file_index_t i; tr_benc * list; list = tr_bencDictAddList( dict, KEY_FILE_NAMES, n ); for( i = 0; i < n; ++i ) tr_bencListAddStr( list, inf->files[i].name ); > static uint64_t loadFileNames( tr_benc * dict, tr_torrent * tor ) < uint64_t ret = 0; tr_info * inf = &tor->info; const tr_file_index_t n = inf->fileCount; tr_benc * list; if( tr_bencDictFindList( dict, KEY_FILE_NAMES, &list ) && tr_bencListSize( list ) == n ) < const char * name; tr_file_index_t i; for( i = 0; i < n; ++i ) if( tr_bencGetStr( tr_bencListChild( list, i ), &name ) ) tr_torrentInitFileName( tor, i, name ); ret = TR_FR_FILE_NAMES; >return ret; >
И добавим в интерфейсные функции наше пожелание о сохранении.
tr_torrentSaveResume(), сразу после проверки if( tr_torrentHasMetadata( tor )):
if( tor->info.rename ) tr_bencDictAddStr( &top, KEY_RENAME, tor->info.rename ); saveFileNames( &top, tor );
А код загрузки в loadFromFile():
if( fieldsToLoad & TR_FR_FILE_NAMES ) fieldsLoaded |= loadFileNames( &top, tor ); if( ( fieldsToLoad & TR_FR_RENAME ) && tr_bencDictFindStr( &top, KEY_RENAME, &str ) && str && str[0] ) < tr_free( tor->info.rename ); tor->info.rename = tr_strdup( str ); >
Можно заметить что мы нигде не выставляем эти флажки (TR_FR_*), а только проверяем их, как же менеджер узнает о том что грузить нужно?
Ответ заключается в том, что модуль использует правило «всё разрешено, что не запрещено», то есть примерно так: flags &= ~deniedFieilds;
Булева логика любезно нам подсказывает то что наши 20 и 21 биты будут установлены в любом случае.
Фактически это всё. В указанном в начале топика патче есть код правки gtk и transmission-remote, с добавлением этой функции, но там всё тривиально ибо это фактически простые клиенты перенаправляющие запросы к серверу (непосредственно к libtransmission для gtk, и через rpc для -remote) с каплей бизнес-логики.
Transmission. Display Name.
Так, с главной проблемой разобрались, теперь осталась вторая подзадача.
Я хочу видеть в клиенте не кучу «Season N» в качестве названий (а именно их передаст нам rpc-сервер, ибо как я объяснял в начале топика торренты у меня хранятся именно по такой схеме), а вполне осмысленные строки. Поэтому внесём совсем маленькую правку — просто добавим новое свойство "displayName" и набор геттеров/сеттеров в интерфейсе RPC.
Это очень маленькая и простая правка — нам нужно сделать всё тоже самое что и с полем rename, только без бизнес-логики и с модификацией rpc-отдачи.
- Добавляем поле в структуру tr_torrent в transmission.h
- В функцию torrentSet() добавляем простенькую модификацию tor->displayName используя tr_strdup() и команду "displayName", например.
- Добавляем новое поле в addField().
- В менеджер состояний так же вносим новый ключ "displayName" со всеми вытекающими.
Когда меняем это поле, необходимо пометить то, что торрент — «грязный», то есть его состояние было изменено со времени последнего сохранения.
В общем-то всё. Можно компилировать.
./autogen.sh --disable-gtk
make
make install prefix=/usr
Теперь transmission научилось выполнять данную задачу, однако вот клиенты не знают об этом.
Но это не беда. Модификаций нужно не так много, и я вполне успешно внёс исправления в Transmission GUI dotNet.
Не думаю что с остальными клиентами будет сложнее.
Ссылки
- Модифицированные исходники Transmission, rev 12431
- Модифицированные исходники Transmission Remote .NET
- Бинарник Transmission Remote .NET