Разбираемся с rtorrent всерьёз

  • Tutorial
Об установке и базовой настройке rtorrent на хабре хватает статей, как и споров о том, стоит ли вообще связываться с хардкорным rtorrent или лучше обойтись чем-нибудь более дружественным к пользователю. Лично я много лет назад пересмотрел все качалки и в результате rtorrent оказался самым стабильным и эффективным. Интерфейс у него не самый удобный, но достаточно понятный и юзабельный чтобы это не стало серьёзной проблемой. Альтернативные интерфейсы вроде rutorrent у меня как-то не прижились - ставить php только ради rutorrent неохота, а остальные варианты выглядят совсем слабо (и ни одного кроме rutorrent даже нет в портаж Gentoo).

  

Одно из основных преимуществ rtorrent — очень гибкие возможности по его настройке и автоматизации. К сожалению, синтаксис ~/.rtorrent.rc достаточно нестандартный, нормальная документация отсутствует, поэтому обычно настройка сводится к поиску и копированию (попытка что-то в них изменить кроме констант/путей к каталогам обычно проваливается) готовых рецептов или вообще ограничивается редактированием констант в базовой конфигурации.

На днях я решил, что так дальше продолжаться не может — мы очень много лет знакомы, он для меня столько хорошего выкачал, а я всё никак не познакомлюсь с ним поближе! Не скажу, что досконально с ним разобрался, но по крайней мере я смог реализовать все свои идеи по автоматизации rtorrent, и сделал это понимая, что и почему я делаю, без шаманства с чужими рецептами.



Обновление


Настраивался rtorrent-0.9.2 (с дополнительным color-патчем, как на скриншоте выше), и если у вас более старая версия настоятельно рекомендую обновиться. После обновления стоит запустить migrate_rtorrent_rc.sh для конвертации устаревшего синтаксиса внутри ~/.rtorrent.rc в более современный и просмотреть инструкции по миграции.

Другая документация


Изучение существующей документации вызывает только одно чувство: глубокую печаль. Вру. Оно вызывает желание грубо матерится. А глубокая печаль — это то, что приходит много позже, когда понимаешь что тебе не померещилось, и всё действительно настолько плохо. Тем не менее, хоть что-то это всё-таки лучше, чем совсем ничего (вот! я сумел таки найти что-то положительное), поэтому давайте посмотрим, что у нас есть:


Отладка


Для отладки и экспериментов можно вместо изменения конфиг-файла и перезапуска rtorrent воспользоваться встроенной в него командной строкой. Вызывается она нажатием Ctrl-X, после чего можно ввести любую команду, например:

command> print="Hello ",World!

нажать Enter и получить на экране и в логе:

(22:13:39) Hello World!

Недоступные на экране старые записи из лога можно увидеть нажав l, выйти из экрана просмотра лога нажав пробел.

При использовании в командной строке команд, которые должны применяться к конкретному объекту (торренту, файлу, трекеру, пирам) — будет использован текущий выбранный в интерфейсе rtorrent объект (т.е. нужно курсором стать на нужную строку перед выполнением команды).

Основное неудобство этой командной строки — отсутствие истории, нельзя нажав «вверх» увидеть предыдущую команду, модифицировать её и снова выполнить.

Синтаксис конфиг-файла


Первое, что необходимо понять про синтаксис ~/.rtorrent.rcэто не конфиг файл. Да, выглядит похоже, но это всего лишь опасная иллюзия. На самом деле это программа: последовательность команд (это официальный термин, но я их буду дальше называть функциями, так привычнее и по сути вернее), причём активно использующая передачу одних команд (вместе с их собственными параметрами) параметрами в другие (привет, callback-и в конфигах — только вас и не хватало для полного счастья!), с несколькими уровнями вложенности и разными вариантами экранирования. Можно (и придётся) создавать свои собственные функции — это сильно помогает уменьшить количество уровней вложенности и вызванные этим сложности с экранированием.

Таким образом, когда вы видите в конфиге строку вроде:

throttle.global_down.max_rate.set_kb = 10000

то это на самом деле вызов функции с одним параметром, более традиционно записываемый как:

throttle.global_down.max_rate.set_kb(10000)

Насколько я понял, точки в именах функций не несут особого смысла, просто обычный разделитель для читабельности, как подчёркивание.

Пробелы, как ни странно, допустимы далеко не везде где используются какие-либо разделители. Как минимум, их можно использовать:

  • вокруг = после имени первой команды в строке (не важно, это строка  конфиг-файла или строка в кавычках "" посередине строки конфиг-файла)
  • после , разделяющей параметры (перед запятой по-моему работает не  везде)
  • вокруг ; разделяющей команды в строке, описывающей тело новой функции

Вызов функции

# без параметров, аналог func()
func=
# с двумя параметрами, аналог func("param1","param2")
func=param1,param2

Значение параметра трактуется как строка. Брать значение параметра в кавычки необходимо если он содержит пробел или символ-разделитель вроде , или ; (использовать кавычки всегда — для наглядности - затруднительно, т.к. очень часто этот параметр и так уже находится внутри строки содержащей несколько команд, так что придётся использовать экранирование кавычек и наглядность в результате только ухудшится).

func="first param, with special chars","second;param"

Чтобы получить результат вызова функции (для передачи его параметром в другую функцию) нужно перед именем функции поставить $:

# выведет: system.hostname=
print=system.hostname=
# выведет: system.hostname=
print="system.hostname="
# выведет: powerman.name
print=$system.hostname=
# выведет: powerman.name
print="$system.hostname="

В первом и втором примерах функция print получает один параметр: строку "system.hostname=". В третьем и четвёртом print получает параметром результат выполнения функции system.hostname без параметров: строку "powerman.name".

Функция print выводит все свои параметры, и если одним из них будет вызов функции, у которой тоже есть параметры — необходимо разделить, какие параметры относятся к print, а какие к другой функции (на самом деле это не очень актуальная проблема, т.к. большинство функций rtorrent параметры или вообще не принимают или принимают один):

# выведет: oneСб сен 27 23:50:51 EEST 2014-utwo
print=one,$execute.capture=date,-u,two
# выведет: oneСб сен 27 20:51:05 UTC 2014two
print=one,"$execute.capture=date,-u",two

Функция execute.capture выполняет любую системную команду (через sh) и возвращает то, что эта команда выведет на STDOUT. Поэтому она может принимать любое количество параметров (имя команды и параметры для неё). Как видите в первом варианте она взяла только один параметр (и вызвала date) а остальные (-u,two) достались print-у. А во втором мы явно указали какие параметры относятся к execute.capture, поэтому она вызвала date -u а print-у достался только последний параметр (two).

Если вы попытаетесь запустить этот пример — он у вас не сработает как описано. Дело в том, что системная команда date завершает вывод переводом строки, так что остальные параметры print-а выводятся уже на другой строке и rtorrent это показывает не очень внятно, даже в логе. Поэтому, чтобы пример сработал, нужно подменить команду date вариантом, который перевод строки не выводит, например положить в ~/bin/date:

#!/bin/bash
echo -n `/bin/date "$@"`

callback-и

Некоторые функции rtorrent ожидают в своих параметрах переданные пользователем функции (которые они будут вызывать сами позднее). Есть два альтернативных синтаксиса, как можно передать одну функцию параметром в другую: либо передаётся обычная строка содержащая вызов функции и её параметры в обычном синтаксисе rtorrent, либо передаётся список строк внутри (( )), где имя функции это первая строка а остальные строки её параметры.

# func() вызывается с двумя параметрами:
# - пользовательским callback-ом func1()
# - строкой "param2"
func=func1=,param2
# func() вызывается с двумя параметрами:
# - пользовательским callback-ом func1("param11","param12")
# - строкой "param2"
func="func1=param11,param12",param2
# то же самое, что и в предыдущем примере
func=((func1,param11,param12)),param2

Соответственно, если передаваемому callback-у func1 в параметрах нужно тоже передать callback, то нужно либо использовать разные стили экранирования (кавычки/скобки), либо экранировать слешем кавычки внутри кавычек, либо использовать вложенные скобки.

# передадим в func1() первым параметром вместо строки param11
# callback func2("param21","param22") разными способами:
func="func1=\"func2=param21,param22\",param12",param2
func="func1=((func2,param21,param22)),param12",param2
func=((func1,((func2,param21,param22)),param12)),param2
func=((func1,"func2=param21,param22",param12)),param2

Кстати, в rtorrent есть ещё один способ синтаксически передать список - внутри { }. Где и для чего его стоит применять я пока не разбирался.

Пользовательские функции

Новые функции можно создавать используя функцию method.insert. Первым параметром передаётся имя для новой функции, вторым её тип (обычно simple, но если нужно создать не функцию а переменную то нужно использовать типы value, bool, string; так же можно сделать функцию/переменную private и const и не только — к сожалению, разбираться с этими возможностями нужно по исходникам), третьим строка с телом функции. В отличие от строк с callback-ами, описанными выше, в этой строке можно передать несколько команд через ; но нельзя использовать разделитель (( )).

# создаём новую функцию:
method.insert = newfunc, simple, "func=param1,param2;func1=;func2="
# и вызываем её:
newfunc=

Если нужно вызывать созданную функцию с разными параметрами (до 4-х) — к ним можно обратиться внутри функции через argument.0=argument.3.

method.insert = hello, simple, "print = \"Hello \", $argument.0=, !"
# выведет: Hello Powerman!
hello=Powerman

Переменные


С переменными работа идёт по сути тоже через функции (get/set), причём обычно есть несколько альтернативных вариантов записи.

# установить some.var в значение "value"
some.var.set = value
some.set_var = value
some.var = value
# получить значение some.var
$some.var=
$some.var.get=
$some.get_var=

Насколько я понял, первый из показанных выше вариантов считается современным и должен работать для любых переменных, а все остальные использовались в старых версиях rtorrent и сейчас поддерживаются для некоторых переменных ради обратной совместимости.

Чтобы не заморачиваться с method.insert ради создания пары переменных есть готовые функции позволяющие работать с переменными привязанными к конкретному торренту (что позволяет сохранять информацию по каждому торренту отдельно):

# установить переменную var в значение value для текущего торрента
d.custom.set = var, value
# получить значение переменной var для текущего торрента
$d.custom=var

# установить 5 предопределённых переменных для текущего торрента
d.custom1.set = value1
d.custom2.set = value2
d.custom3.set = value3
d.custom4.set = value4
d.custom5.set = value5
# получить 5 предопределённых переменных для текущего торрента
$d.custom1=
$d.custom2=
$d.custom3=
$d.custom4=
$d.custom5=

Выше я писал, что точки в именах функций не несут особого смысла и по сути не отличаются от подчёркиваний. Как видите, это не совсем так: переменные начинающиеся на d. связаны с конкретным торрентом, и у каждого торрента свои значения этих переменных. Аналогично с функциями начинающимися на d. — они тоже оперируют текущим торрентом. Тем не менее, я думаю что это особенность реализации встроенных функций, а для пользовательских функций и переменных наличие или отсутствие d. в имени не сделает их магически связанными с текущим торрентом (впрочем, я это не проверял).

Странности и баги


Если callback для schedule передаётся внутри (( )) а не " ", то параметры для этого callback так же заданные внутри вложенных (( )) почему-то обрабатываются как получение результата функции, а не передача её как callback:

schedule id,1,1, ((print, ((directory.default))))
# работает как
schedule id,1,1, "print = $directory.default="

Некоторые функции глючат, если вызываются при запуске rtorrent (например load.start или ui.current_view.set) — их выполнение нужно отложить через schedule, причём start time должен быть больше 0. Вероятно это вызвано тем, что при запуске rtorrent, к моменту когда выполняются команды из конфиг-файла, ещё не все структуры данных корректно инициализированы.

Краткий обзор полезных функций


print = список строк

Отладка в командной строке; вывод в лог.

$cat = список строк

Возвращает сконкатенированные строки (аналог print, только возвращает строку вместо вывода в лог).

$argument.0=
$argument.1=
$argument.2=
$argument.3=

Получить 1/2/3/4-й параметр текущей функции.

method.insert = имя_функции, simple, "тело; функции"

Создать пользовательскую функцию.

По-моему только в method.insert и method.set_key можно передать последовательность из нескольких команд через ; — все остальные функции куда можно передавать команды принимают их либо по одной, либо как список (напр. load.normal и load.start).

method.set_key = event.download.тип, имя_события, "список; команд"

Создать обработчик события. Допустимые значения для тип: insertedinserted_new, inserted_session, erased, opened, closedresumed, paused, finished, hash_done, hash_failedhash_final_failed, hash_removed, hash_queued. Зачем нужно имя_события не понятно (вероятно, его можно проверить через method.has_key и method.list_keys но неясно где это может пригодиться), но легко догадаться что оно должно быть уникальным.

schedule = имя_расписания, начало, интервал, список команд
schedule_remove = имя_расписания

Периодически выполняемый список команд, основной инструмент для автоматизации rtorrent. Значения для начало и интервал можно задавать либо в секундах либо в формате чч:мм:сс (если интервал установлен в 0 выполнится однократно). Для команд которые должны выполниться при запуске rtorrent значение для начало обычно устанавливают в 5 — вероятно, чтобы rtorrent успел полноценно запуститься и не возникали упомянутый мной выше баги.

load.normal = путь_к_torrent_файлу(ам), список команд
load.start  = путь_к_torrent_файлу(ам), список команд

Обычно вызывается из schedule для автоматической загрузки файлов добавленных в заданный каталог. load.start автоматически запускает выкачку файла после добавления.

execute             = системная_команда, список её параметров
execute.capture     = системная_команда, список её параметров
execute.nothrow     = системная_команда, список её параметров
execute.nothrow.bg  = системная_команда, список её параметров

Выполняет внешнюю программу. execute.capture возвращает вывод этой команды, execute.nothrow игнорирует ошибку запущенной команды, execute.nothrow.bg запускает программу в фоне.

if      = выражение,    команда_если_истина, команда_если_ложь
branch  = команда_тест, команда_если_истина, команда_если_ложь

Позволяет выбрать выполняемую команду в зависимости от условия. Разница между if и branch в том, как задаётся условие: как значение ($func=) или как команда (func=). Кроме того вместо команда_если_ложь можно задать следующее условие и добавить ещё два параметра-команды, и т.д.

false=
not     = команда
and     = список команд
or      = список команд
equal   = список команд
less    = список значений
greater = список значений

Думаю, общий смысл понятен. Помимо использования в if и branch функции less и greater используются для настройки разных сортировок.

У этих и последующих команд формат параметров я не проверял, так что могут быть ошибки (пишите в личку, исправлю).

import  = конфиг-файл

Подключение дополнительного конфиг-файла.

start_tied=
stop_untied=
close_untied=
remove_untied=

Tied-файлом rtorrent называет тот .torrent-файл, который вы скачали и загрузили в rtorrent (обычно — автоматически загружая все .torrent-файлы из заданный каталогов через schedule и load.start). Что любопытно, для выкачки rtorrent использует не этот файл, а его копию, которую он сохраняет в свой каталог session.path. Соответственно, stop_untiedclose_untied и remove_untied при выполнении определяют, что сделать с торрент-файлом в каталоге session.path если оригинальный торрент-файл связанный (tied) с ним был удалён. Что делает команда start_tied я пока не понял.

$d.base_filename=
$d.base_path=
$d.creation_date=
$d.directory=
$d.load_date=
$d.name=
$d.tied_to_file=

Разные свойства текущего торрента. На самом деле их в несколько раз больше, я просто упомянул самые полезные на первый взгляд. Например, d.directory это каталог куда будет выкачиваться торрент, d.tied_to_file имя оригинального (не из session.path) .torrent-файла, d.name имя файла или каталога выкачиваемого этим торрентом, etc.

$d.complete=

Текущее состояние — этот торрент скачался или ещё нет.

d.close=
d.create_link   = тип, префикс, постфикс
d.delete_link   = тип, префикс, постфикс
d.delete_tied=
d.erase=
d.open=
d.pause=
d.resume=
d.save_full_session=
d.start=
d.stop=

Разные операции над текущим торрентом. Значение тип может быть base_path, base_filename и tied и определяет каталог для симлинка (из d.base_path, d.base_filename или d.tied_to_file), префикс и постфикс добавляются к имени и могут быть пустыми.

d.multicall

Я с этим не разбирался, но насколько я понял через эту функцию выполняются массовые операции над группами торрентов.

Пример из моего конфига


При появлении .torrent-файла в одном из каталогов /mnt/torrent//mnt/torrent/serials/ и /mnt/torrent/music/ он должен быть:

  • автоматически загружен в rtorrent
  • настроен на выкачку в тот же каталог где лежит .torrent-файл
  • торренты из каталога /mnt/torrent/music/ должны сразу запуститься

schedule = watch_directory_1, 5, 5, ((load.normal, /mnt/torrent/*.torrent,         "d.custom.set = watchdir, /mnt/torrent",         "d.directory.set = $d.custom=watchdir"))
schedule = watch_directory_2, 5, 5, ((load.normal, /mnt/torrent/serials/*.torrent, "d.custom.set = watchdir, /mnt/torrent/serials", "d.directory.set = $d.custom=watchdir"))
schedule = watch_directory_3, 5, 5, ((load.start,  /mnt/torrent/music/*.torrent,   "d.custom.set = watchdir, /mnt/torrent/music",   "d.directory.set = $d.custom=watchdir"))

  • автоматически переименован чтобы соответствовать имени файла или  каталога который он будет выкачивать (т.е. файл  [rutracker.org].t4788972.torrent автоматически переименуется в  Читающий Мысли (The Listener) (Season V, 2014, WEB-DL 720p) [FOX].torrent)
  • перед расширением .torrent к имени файла должен быть добавлен суффикс  показывающий его текущий статус: --- если он ещё не скачался или +++  если он уже скачался

method.insert = d.renamed_suffix,   simple, "if = $d.complete=, +++, ---"
# - WORKAROUND: extra / at beginning needed because $d.tied_to_file= begins with //
method.insert = d.renamed_file,     simple, "cat = /, $d.custom=watchdir, /, $d.name=, ., $d.renamed_suffix=, .torrent"
method.insert = d.rename_file,      simple, "execute = mv, --, $d.tied_to_file=, $d.renamed_file=; d.tied_to_file.set = $d.renamed_file="
method.insert = d.safe_rename_file, simple, "branch = ((equal, d.tied_to_file=, d.renamed_file=)), , d.rename_file="
method.set_key = event.download.inserted_new,   rename_loaded,  d.safe_rename_file=
method.set_key = event.download.resumed,        rename_resumed, d.safe_rename_file=
method.set_key = event.download.finished,       rename_finished,d.safe_rename_file=

Если .torrent-файл удаляется то его копию из session.path тоже нужно удалить и убрать этот торрент из rtorrent.

# Watch a directory for torrents, and remove those that have been deleted.
schedule = watch_untied,      5, 5, ((remove_untied))

Показывать всплывающее уведомление на мониторе когда скачивается торрент с его именем (нужен мелкий вспомогательный скрипт).

# Notify when download finished
method.set_key = event.download.finished, notify_me, "execute = ~/bin/rtorrent_finished, $d.name="

После запуска rtorrent открыть список ещё недокачанных торрентов (аналог нажатия 6 вручную).

# Set default view
schedule = default_view, 1, 0, ui.current_view.set=incomplete

Отсортировать список недокачанных по дате добавления (этот код взят из рецепта в wiki и здесь приведён в качестве примера использования less=).

method.set_key = event.download.inserted_new,   loaded_time,  "d.custom.set = tm_loaded, $system.time=; d.save_full_session="
view.sort_new       = incomplete, less=d.custom=tm_loaded
view.sort_current   = incomplete, less=d.custom=tm_loaded

Заключение


Надеюсь, это описание поможет автоматизировать работу вашего rtorrent и решит проблему отсутствия подходящих лично вам рецептов. К сожалению, качество этой статьи заметно ниже моих обычных статей, многие вопросы до конца я так и не прояснил, в описаниях некоторых функций наверняка есть ошибки, но количество времени которое было не жалко убить на эту задачу было сильно ограничено. Вероятно, стоит использовать информацию из этой статьи для дополнения официальной wiki, но у меня на это уже сил и времени нет, будем надеяться это сделает кто-нибудь другой.

______________________
Текст конвертирован используя habrahabr backend для AsciiDoc.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 60

    +3
    Как-то искал демон для торрентов и остановился на deluge — удобный, есть нативные клиенты, а также web-based. Есть встроенный простенький планировщик, которого мне хватало.
    Ну и классика — transmission, но ИМХО, он сливает deluge по функционалу.
      +6
      я в свое время отказался от deluge из-за его прожорливости и нестабильности. Но это было, года 4 назад.
        0
        Какого рода функционал есть в deluge и нет в transmission. У меня transmission начал свою жизнь на роутере D-Link DIR-320 лет много назад, а сейчас перебрался на Atom-«сервер», но я никогда особо не страдал по какому-то функционалу, по-моему всё есть. И по ресурсам он меня тоже устраивает, хотя у меня только 100 торентов раздаётся:
        Uploaded: 55.2 TB
        Downloaded: 1.61 TB
        Ratio: 34.0
        Running Time: 1196 days
          +4
          Возможно это отличный демон, я лично пытался на него перейти 3 раза, когда надоедало патчить исходники rtorrent. Из того что я в нем не нашел:
          1) Автоматический парсер дирректорий с поддиректориями с нахождением .torrent файлов и закачкой в другое место с сохранением структуры каталогов.То-есть у меня есть .../autoload/films .../autoload/music .../autoload/iso и тому подобное все что помещается ниже .../autoload/ будет скачано в .../download/ с сохранением структуры каталогов и не нужно это все описывать для каждого подкаталога. Для удобной коллекции это удобней, чем руками разгребать помойку.
          2) Автоматическая сортировка контента, если заранее не определен его тег, то-есть скачанное с треккера lostfilm.tv, novafilm и тому подобное, автоматически попадает в фильмы, даже если я не выбирал директорию.
          3) Автоматическое слежение за треккерами с автоперезакачкой торрента, если обновился (я смотрю сериалы и многие треккеры ведут раздачи путем добавления новых серий в тот же треккер).
          4) Способность уверенно держать на раздаче более 10000 торрентов на сервер, не вешаясь наглухо и не теряя раздачи как трансмиссия и делюга.
          5) Возможность полного консольного управления. Удобно для своих скриптов.
          6) Хорошая интеграция с кучей морд, включая мобильные, сидя в маршрутке на телефоне я могу нажать скачать торрент с треккера и он начнет качаться на домашнем сервере.
          7) Интеграция с RSS, я всегда знаю когда скачалась новая серия сериала.
          Можно еще вспоминать, но влом, я пытался соскочить на другие качалки, но то одного нет, то другого. Ставится местами геморройно, часть опций можно понять только вкурив исходники, но те плюшки по кастомизации и логике, что он умеет из коробки это компенсируют.
            +2
            Да, с автоматизацией и производительностью rtorrent явно в другой весовой категории, это как Linux way против несчастных Windows потуг))
            Именно поэтому я спрашивал о разнице между deluge и transmission и не трогал rtorrent. Я не заморачивался с rtorrent по нескольким причинам:
            1) мне не нужно держать 10000 торрентов
            2) мне не хотелось стрелять из пушки по воробьям да ещё и ставить PHP для rutorrent
            3) я не такой заядлый видеоман, что мне нужно следить за раздачами, обычно я смотрю фильмы с запазданием лет в 5-10))
            4) нынче для просмотра «видео-торрентов» использую Popcorn Time и не маюсь с предзагрузкой, да, безлимитный круглосуточный интернет развращает.
              +1
              Много убивал времени на rtorrent. В итоге перешел на transmission. Уже года три проблем не знаю. Ничего собирать не надо, не надо прикручивать веб морду с бубном. Да и вообще, TR кажется хорошо продуманным продуктом, после набора костылей в RT.

              По вашим пунктам. Есть совершенно отличный cli которым легко многие ваши задачи можно автоматизировать. Стандартная веб морда нормально работает под всем устройствами, и сделана качественно. Она не навороченная, но посмотреть и добавить торрент на работе или с мобильного хватает. Для остального у меня например Transmission Remote GUI. Терминальные клиенты тоже есть.

              Автоперезакачка торрента — А как это вообще устроено? Как же авторизация, и т.д?
              п.с. А вам не страшно держать столько торрентов?
                +2
                Автоперезакачка торрента — А как это вообще устроено? Как же авторизация, и т.д?

                По крону раз в 10 минут плагин заходит на треккер и проверяет не изменилась ли контрольная сумма торрент файла, если изменилась — перекачивает. Авторизация реализована несколькими вариантами, как по логину и паролю от треккера, так и по куки. При этом еще и есть удобный поисковик по ряду треккеров прямо из вебморды.
                А вам не страшно держать столько торрентов?

                Держал 60000 раздач на 6 серверах в одном коммерческом проекте, тогда и познакомился с rtorrent и перековырял все доступные реализации, так его и стал использовать везде, включая домашний сервер, дома само-собой мне столько не надо.
                А так на вкус и цвет понятно все фломастеры разные, но для меня альтернативы нет, особенно в плане каталогизации коллекции, для того-же XBMC просто сказочно удобно, все другие качалки подразумевали ручную каталогизацию контента с ручной правкой имен.
                0
                1) Автоматический парсер дирректорий с поддиректориями с нахождением .torrent файлов и

                Для трансмишена когдато впилил

                там где стартует демон вписал
                nohup /root/scripts/notyfy.sh /opt/samba/torrent/video/ /opt/HDD/video/ &
                nohup /root/scripts/notyfy.sh /opt/samba/torrent/music/ /opt/HDD/music/ &
                nohup /root/scripts/notyfy.sh /opt/samba/torrent/distr/ /opt/HDD/distr/ &
                
                


                и сам скрипт
                #!/bin/bash
                #как запустить в фоне
                #nohup /root/scripts/notyfy.sh /opt/samba/torrent/video/ /opt/HDD/video/ &
                #inotify-tools не забудьте поставить
                
                [ $# -ne 2 ] && { echo Usage: $0 [/torrent/watch/dir/] [/when/torrent/download/]; exit; }
                DIR=$1
                DWN=$2
                
                ###Авторизация для трансмишеа
                AUTH=" 192.168.1.1:9091 -n user:password "
                
                while RES=$(inotifywait -e create $DIR --format %f .)
                do 
                 if [ ! -z `expr $RES : '.*\(torrent$\)'` ]; then
                
                    transmission-remote $AUTH -a $DIR/$RES --download-dir $DWN;
                    rm -f $DIR/$RES;
                
                  fi
                done
                
                


                как только появляется торрент файл в папке, он тут же скармливается и удаляется. inotifywait фича ядреная, так что не нагружает.
                  +1
                  Не совсем то, у вас надо каждый раз создавать для программы новую связку, если я например скачаю в /opt/samba/torrent/book/, но он не описан в вашем скрипте, то торрент на закачку либо не встанет, либо встанет в дефолтную директорию (в случае поддиректории описанной в скрипте). В моем случае сохраняется именно структура директорий, я могу на лету в .../autoload/ создавать или удалять любые каталоги и именно в таком виде они и перенесутся в download. Простой пример, на том же лосте я качаю сериалы, но они выходят по одной серии, создавать для каждого сериала каждый раз отдельный скрипт, чтоб он качался именно в .../autoload/serial/serial-name не совсем удобно, потом удалять, помнить что надо вычистить из скрипта, что добавить. В принципе ваш скрипт можно адаптировать и для такого варианта, добавив рекурсивный поиск торрент файлов от заданного пути, но остальной описанный мной функционал получить значительно сложнее, например, слежение за изменением раздач можно организовать через TorrentMonitor, а вот работу с RSS и поиск сразу на куче треккеров прямо из клиента уже так просто не выйдет. Я не говорю что это нереально, но сил по допиливанию и адаптации выйдет гарантированно не меньше чем настроить rtorrent.
                    0
                    Проблем-то нагенерировать связок, это первое, второе там можно подкрутить чтобы учитывались подпапки через рекурсию, ключ -r и просто другой формат отдачи поймого события и будет тоже что вы описали до RSS. Вообщем, под свою задачу — своё решение.

                      +1
                      А так, в итоге отказался этого мониторинга папки, у меня всё что требуется выполняет скрипт по завершению скачки:
                      «script-torrent-done-filename»: "/var/lib/transmission/.config/transmission/do.sh",

                      он вынимает ссылку из торрент файла на то место откуда был скачан( сейчас все любят в поле Comment URL страницы скидывать) если нет там url, то парсит выдачу с яндекса- ищется где файл аннонсирован.
                      Далее если кинцо, то кидает в кино, парсит страницу -> переименовывает, парсит кинопоиск -> вкидывает описание и прочее.
                      Всё.

                      Автокачем и докачем не занимался, сериалы смотрю уже когда вышли серии.
                        +1
                        Может скриптом поделитесь, думаю будет полезно не только вам, да и прикрутить его можно к любой качалке, а так чуток другой кейс использования клиента.
                        вкидывает описание и прочее.

                        Куда именно вкидывается описание? XBMC или какой-то свой каталогизатор?
                          +1
                          Сливает в бд, а с бд уже работает самописный сайт с которого тыкаю что воспроизводить на ТВ.
                          кусочек php
                          <?php
                          include_once("http.php");
                          
                          class KinoPoisk {
                          
                                  public function Parse($subject) {
                          
                                          $p = '#itemprop="name">(.*)</h1>#';
                                          preg_match($p, $subject, $matches);
                                          $name=strip_tags($matches[1]);
                          
                                          $altname="";
                                          $p = '#itemprop="alternativeHeadline">(.*)</span>#';
                                          preg_match($p, $subject, $matches);
                                          if(count ($altname)!=0)
                                                  $altname=$matches[1];
                          
                                          $p = '#<a href="/lists/m_act%5Byear%5D/(.*)/"#';
                                          preg_match($p, $subject, $matches);
                                          $year=$matches[1];
                          
                                          $p = '#<img width="205" src="(.*)" alt#';
                                          preg_match($p, $subject, $matches);
                                          $img=$matches[1];
                          
                          
                                          $p = '#itemprop="description">(.*)</div>#';
                                          preg_match($p, $subject, $matches);
                                          $desc=$matches[1];
                          
                                          $p = '#IMDb:(.*)</div>#';
                                          preg_match($p, $subject, $matches);
                                          $imdb=$matches[1];
                          
                                          $p = '#rating_ball">(.*)</span>#';
                                          preg_match($p, $subject, $matches);
                                          $rating=$matches[1];
                          
                          
                                          $p = '#itemprop="genre">(.*)#';
                                          preg_match($p, $subject, $matches);
                                          $genre=strip_tags($matches[1]);
                                          return array("name"=> mysql_real_escape_string(html_entity_decode($name)),
                                                                  "altname" => mysql_real_escape_string(html_entity_decode($altname)),
                                                                  "img"=>$img,
                                                                  "year"=>$year,
                                                                  "genre"=>mysql_real_escape_string(html_entity_decode($genre)),
                                                                  "desc"=>mysql_real_escape_string(html_entity_decode($desc)),
                                                                  "IDMb"=>mysql_real_escape_string(html_entity_decode($imdb)),
                                                                  "rate"=>mysql_real_escape_string(html_entity_decode($rating)));
                          
                                  }
                                  public function GetAndParse($film) {
                                          $curl = new HttpBurn();
                                          $html = $curl->Get($film);
                                          $data = $this->Parse(iconv('cp1251','utf-8',$html)) + array("URL"=>$film);
                                          return $data;
                                  }
                          
                                  public function Find($film) {
                                          $curl = new HttpBurn();
                                          $f = $curl->Get("www.kinopoisk.ru/index.php?first=no&what=&kp_query=".rawurlencode($film));
                                          $p = '#<p class="pic"><a href=\"(.*)\"><img#';
                                          preg_match($p, $f, $matches);
                                          $f = $matches[1];
                                          $p = '#film/(.*)/sr/#';
                                          preg_match($p, $f, $matches);
                                          $html = $curl->Get("http://www.kinopoisk.ru/film/".$matches[1]);
                                          $data = $this->Parse(iconv('cp1251','utf-8',$html)) + array("URL"=>"http://www.kinopoisk.ru/film/".$matches[1]);
                                          return $data;
                                  }
                          
                          
                          }
                          
                          

                          cat http.php
                          
                          
                          <?php
                          
                          
                          class HttpBurn {
                                  public $UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0";
                                  public $headers = array
                                  (
                                          'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*;q=0.8',
                                          'Accept-Language: ru,en-us;q=0.7,en;q=0.3',
                                          'Accept-Encoding: deflate',
                                          'Accept-Charset: utf-8,windows-1251;q=0.7,*;q=0.7'
                                  );
                                  public $refer = "http://ya.ru";
                          
                                  public function Get($URL){
                                          if($ch = curl_init($URL)){
                                                  curl_setopt ($ch, CURLOPT_USERAGENT, $this->UserAgent);
                                                  curl_setopt($ch, CURLOPT_HTTPHEADER,$this->headers);
                                                  curl_setopt($ch, CURLOPT_REFERER, $this->refer);
                                                  curl_setopt($ch, CURLOPT_COOKIEJAR, "kino_coo.txt");
                                                  curl_setopt($ch, CURLOPT_COOKIEFILE, "kino_coo.txt");
                                                  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                                                  $result = curl_exec($ch);
                                                  curl_close($ch);
                                                  return $result;
                                          }
                                          return null;
                                  }
                                  public function Post($url,$post){
                                          if( $curl = curl_init($url) ) {
                                                  curl_setopt ($curl, CURLOPT_USERAGENT, $this->UserAgent);
                                                  curl_setopt($curl, CURLOPT_HTTPHEADER,$this->headers);
                                                  curl_setopt($curl, CURLOPT_REFERER, $this->refer);
                                                  curl_setopt($curl, CURLOPT_RETURNTRANSFER,true);
                                                  curl_setopt($curl, CURLOPT_POST, true);
                                                  curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
                                                  $out = curl_exec($curl);
                                                  curl_close($curl);
                                                  return $out;
                                          }
                                          return null;
                                  }
                          
                          }
                          
                          



                          Там на целую статью, данный кусок просто ищет в кинопоиске запрошенный фильм,

                          $o = new KinoPoisk();
                          $film = $o->Find("а зори здесь тихие");
                          var_dump($film);
                          

                          Но момент,- на сайте кинопоиска лучше искать через гуглю. Весь обвес выложу статьей.
                  0
                  А не поделитесь своим конфигом, особенно инересует п.1 и п.2?
                    +1
                    П1 — плагин для rutorrent, пункт автодобавление.
                    П2- Плагин, тот что выше + этот плагин + клиент nativa для OS X, который умеет условия.
                      0
                      Спасибо большое.
                +6
                Ну и классика — transmission, но ИМХО, он сливает deluge по функционалу.

                А сам deluge сливает пасскеи, за что забанен на некоторых трекерах (пруф 1, пруф 2)
                +3
                Спасибо за статью.Тоже долгое время пользуюсь rtorrent-ом, знакомство с ним началось с его установки на роутере ASUS WL-500gP с 32 мегабайтами оперативки.
                Перепробовал все доступные torrent-клиенты под Linux, но так и остался на rtorrent+rutorrent из за его стабильности и нетребовательности к ресурсам.
                  +2
                  Для меня киллер-фича rutorrent — это возможность выбора директории для закачки на сервере, при добавлениии торрента.

                  Ни у transmission, ни у deluge, ни у utorrent такого не нашел — нужно писать путь ручками.
                    +1
                    Для меня киллер-фича rtorrent — это возможность выбора директории для закачки на сервере, при добавлениии торрента.

                    Поддерживаю. Самый простой интерфейс взаимодействия с пользователем, который напрочь отсутствует в других клиентах по непонятным причинам.
                    Альтернативные интерфейсы вроде rutorrent у меня как-то не прижились — ставить php только ради rutorrent неохота

                    В моём случае rtorrent и rutorrent живут на разных машинах, общаясь через xmlrpc (не хотелось мне обновлять php на NAS, поэтому веб-интерфейс поставил на ноутбук, благо LAMP на последнем есть всегда).
                  0
                  в копилку к мультиплатформеным торент-клиентам и небольшой патчик к нему с тех времён, когда трекеры любили банить за низкий аплоад и неизвестные торент-клиенты. к слову, умеет не только торрент, а ещё кучу p2p протоколов, в том числе и edonkey, из-за чего я на него лет 15 назад сел и менять не хочется.
                  • UFO just landed and posted this here
                      0
                      Сорсами не поделитесь? Скрин тот еще костыль.
                      • UFO just landed and posted this here
                          0
                          У меня 093, на 094 rutorrent нормально не работает, много надо допиливать, так что то, что нужно 092 и 093 не сильно отличаются, сам патч адаптирую. Спасибо.
                          • UFO just landed and posted this here
                      0
                      Кто поможет советом? Есть сервер, он же хранилище. Процессор с запасом — там Core i5. Есть десктоп с Kubuntu 14.04. Базовый торрент-клиент — ktorrent. Обычно я качаю в браузере торрент-файл и сразу открываю его в ktorrent, не сохраняя. Есть ли возможность аналогичного использования, но с подхватыванием файла сервером? Чтобы не лезть каждый раз в веб-интерфейс, не заливать файл. Я просто очень не люблю качать все в одну кучу, а лью сразу туда и с тем названием, которое будет в дальнейшем. В результате тот же xbmc сразу хватает название фильма, а торрент- клиент спокойно раздает, несмотря на другое название.
                        0
                        Да есть, тут варианта 3, первый автоматом сохранять торрент фаил в директорию для автозакачки сервером, для ubuntu — это будет однострочник на любом скриптовом языке. Второй вариант готовое приложение, например для OS X — это Nativa, для убунты сказать затрудняюсь, но должно быть. Третий — использовать API самой качалки и скрипт обвязку, тоже пару строк кода.
                          +1
                          Я просто думал, что есть десктопные клиенты для серверной части, с которыми можно файловую ассоциацию забить.
                            0
                            На сколько я знаю трансмиссия и делюга позволяет клиенту общаться с сервером не на локалхосте, а удаленным.
                              0
                              Посмотрю, спасибо. Хоть и gtk инородно в kde выглядит.
                                0
                                У Transmission есть qt клиент, а не только gtk.

                                Ну и при желании стиль gtk приложений можно дотюнинговать до кдешного состояния.
                                  0
                                  Нашёл. Transmission remote GUI. То, что нужно для меня.
                                    0
                                    Transmission Remote GUI как раз использует GTK, который вам не нравится.

                                    Чем вас transmission-qt не устроил? Он может как собственную сессию стартовать, так и управлять демоном по сети.
                                      0
                                      Может? Тогда его потыкаю. Спасибо.
                        +1
                        Хоть сам rtorrent-ом не пользуюсь, но автору за техническое наполнение статьи спасибо. Побольше бы подобной подачи материала.
                          +1
                          Я сам давний фанат rtorrent, однако до сих пор не сумел сделать в нем такое простое действие, как перенести загруженый файл/каталог в другое место (продолжая раздачу, разумеется). Кто нибудь?
                            +2
                            Я хардлинки для этого использую.

                            ln downloaded_file new_file

                            Когда с раздачи ухожу, downloaded_file удаляется, new_file на месте остается. Так как это именно линк, лишнее место на диске не занимается.
                              0
                              Плагин autotool для rutorrent переносит правильно и раздача продолжается, на чистом rtorrent либо линковать либо использовать внешний скрипт перемещения + api.
                                0
                                # Если качается в папку incomplete (по умолчанию) - переместить данные завершённой закачки в папку complete
                                
                                system.method.insert = finished_set4single,simple,"d.set_custom=incomplete,/home/torrents/incomplete"
                                
                                system.method.insert = finished_set4multi,simple,"d.set_custom=incomplete,$cat=\{/home/torrents/incomplete/\\,$d.get_base_filename=\}"
                                
                                system.method.insert = finished_if,simple,"equal={d.get_directory=,d.get_custom=incomplete}"
                                
                                system.method.insert = finished_do,simple,"d.set_directory=/home/torrents/complete/;execute=mv,-u,$d.get_base_path=,/home/torrents/complete/"
                                
                                system.method.set_key = event.download.finished,finished_event,"branch={$d.is_multi_file=,finished_set4multi=,finished_set4single=};branch={$finished_if=,finished_do=}"
                                
                                  0
                                  Фаил то переместится, а вот раздача отвалится.
                                    0
                                    а может для начала попробовать, а уже потом утверждать? :)
                                      0
                                      Опробовано, неоднократно, часть раздач потом не подхватывается при таком перемещении, особенно когда все не из корневой папки, а много подпапок.
                                        0
                                        и всё-таки я настаиваю попробовать банальным копи-пастом (только пути подправить) :)
                                        у меня с этим куском проработало более года: ни одной проблемы не было замечено
                                          0
                                          У меня путей править, как на всю эту заметку вместе с комментариями получится, говорю же разветвленная структура, куча подпапок, примонтированных удаленных шар и прочего. Когда все качаем в одну директорию, перемещаем в другую — это работает, а мне надо сохранять структуру, скачанный фильм переместить в фильмы, сериал в сериалы, образ залить в образы на удаленной шаре, музыку перелить на удаленный хостинг и т.п. Плагин нормально дружит с сохранением структуры, сам rtorrent — не очень. Попробуйте сами в папке для недокачанного создать несколько подпапок и с качать не в корень, а в них, перенесет ли ваша конструкция всю структуру?
                                            0
                                            дык, а в чём проблема вместо одной проверки на нахождение завершившейся закачки в «incomplete» сделать несколько проверок?
                                            например: если в incomplete/music — перемещаем в complete/music, если в incomplete/movies — перемещаем в complete/movies.

                                            в общем, я Вас услышал: не хотите морочиться и пользуете плагин к вэб-морде. Ваше право :)
                                              0
                                              Именно, просто если у меня появился новый подкаталог — он должен подхватиться автоматом и перенести структуру, а не я должен лезть каждый раз в конфиг и добавлять новый путь. Вот банальный пример, захотелось мне послушать классику, делаю подкаталог music и кидаю туда торрент файлы, они сразу начинают качаться в /torrent/incomplete/music/classic/ после закачки переместятся в /torrent/download/music/classic/ надоело — убил каталог, rtorrent увидел что файлов нет — удалил раздачу, все. В вашем случае путь займет примерно так:
                                              1) зашел в конфиг и добавил пути
                                              2) рестартнул rtorrent
                                              3) дальше как у меня
                                              4) зашел в конфиг удалил пути
                                              5) рестартнул rtorrent
                                              Не понятно зачем лишние телодвижения с правкой конфига под каждый новый подкаталог, я в начале примерно так же делал как вы, затем писал свой скрипт, который рекурсивно проверяет структуру и перемещает файлы, после чего через api меняет путь раздачи в rtorrent. В принципе работало, но потом поставил плагин, а оно уже все есть из коробки и работает как надо сразу, почесал репу и выкинул свои скрипты. Я смотрю некоторые сериалы с лоста, там выходят они по одной серии, обнаруживаются и качаются автоматом, представьте какая будет помойка если каждая новая серия будет качаться в общую директорию, мне их ручками разносить не улыбается совсем, а так пока сезон снимается создал каталог, все качается туда автоматом, сезон закончился удалил каталог, в конфиг при этом лазить не нужно.
                                                0
                                                Не понятно зачем лишние телодвижения

                                                У меня ничего лишнего :) меня лень-матушка пробивает не реже Вашего, просто не заморачиваюсь так сильно со структурой директорий на качалке. В моём понимании качалка — чтобы качать, а хранилка — чтобы хранить, и я их между собой не связывал.

                                                Поэтому утверждение
                                                Фаил то переместится, а вот раздача отвалится.

                                                было поспешным
                                0
                                Кто-нибудь видел фичу в каком-нибудь клиенте, чтобы просканировать оперделенные папки, найти в них файлы из имеющихся раздач, и поставить на раздачу (по имени и/или хэшу)? При условии, что файлы могут быть раскиданы не так, как в раздаче. Я было начал писать плагин к deluge, но не хватило терпения.
                                  0
                                  Для одиночных файлов реализация должна быть не очень сложной, что-то типа, вычисляем хеш всех файлов в директории, сравниваем с хешами мертвых раздач, если совпало, через апик меняем путь раздачи на путь к файлу, основной геморрой как мне видится будет с раздачами, где раздается целая папка (те же сериалы, игры, музыка и тп.) ведь если в директорию попадет хоть один «левый» файл, ее хеш уже не совпадет при пересчете и я даже на уровне логики не представляю как такой момент автоматизировать.
                                    0
                                    Да просто, главное понять, зачем (мне) это надо: есть несколько раздач, в которых файлы одни и те же, но разные имена и структура директорий. Если я выкачал (или уже имел) хотя бы часть файлов, хочется их «подтянуть», при чем во все из упомянутых раздач, а недостающие файлы докачать.
                                    Поэтому алгоритм такой: добавляем раздачу, ищем подходящие к ней имеющиеся файлы. Нашли — в торрент-клиенте меняется путь к каждому файлу по отдельности. При чем найденные файлы могут сами лежать в разных местах и иметь произвольные имена. То, что не нашлось, скачивается в папку с раздачей. Deluge нормально с этим работает, мне просто лень дописывать плагин :)
                                    Ну и удобно было бы взять старые .torrent'ы и натравить этот алгоритм на ~/downloads, чтобы автоматически встать на как можно большее число раздач, не мучаясь с «куда я это дел» и «ааа, я переименовал половину»
                                      +1
                                      Такой плагин написать невозможно.

                                      Битторрент при работе рассматривает все файлы в раздаче вместе, как один блок данных, разбивает его на блоки по 2^N байт и передаёт блоками.

                                      В торрент файле хранятся (и то, как я понял, не всегда) хэш суммы блоков, но не хэши отдельных файлов. (см.вики).

                                      Один и тот же файл в различных раздачах практически со 100% вероятностью будет разбит на блоки по-разному: если не из-за размера блока, так из-за различного набора файлов до него, что приведёт к разному смещению начала блока от начала файла. Ну а по набору хешей разных блоков невозможно установить, что это один и тот же файл.

                                      Но поставленную задачу можно решить, просто другим подходом. Для этого нужно или хранить раздачи на файловой системе с онлайн дедупликацией (ZFS) или регулярно делать оффлайн дедупликацию (например, встроенными средствами Btrfs или банально хардлинками с помощью Fslint или fdupes).
                                        0
                                        Файл можно представить как блоки, на которые он побит, плюс «хвосты» в начале и в конце. Поэтому его можно найти и поставить на раздачу, а хвосты, принадлежащие другим файлам, торрент-клиент скачает, перепроверит и запишет в соотв. файлы в других местах.
                                        А задачи найти одинаковые файлы по набору хешей не стоит, или я вас не понял, к чему это.
                                          0
                                          Смотрите, допустим 2 раздачи, размер блока одинаковый:

                                           ____________________
                                          |        |        |  |
                                          |cover.jp|gsong1.m|p3|
                                          |________|________|__|
                                          
                                           __________
                                          |        | |
                                          |song1.mp|3|
                                          |________|_|


                                          Вот вроде song1.mp3 общий для двух раздач файл, но совпадающих блоков не наблюдается.
                                            0
                                            Я то ли понял наконец вашу идею, то ли придумал сам возможный подход со стороны торрент-клиента.

                                            1) При добавлении раздачи для каждого файла F, на который приходится хотя бы один целый блок, ищем среди уже раздающихся файлов из других раздач совпадающие по размеру. Это кандидаты на то, чтобы считаться «тем же самым файлом»;
                                            2) Читаем из кандидатов куски, соответствующие целиком попавшим в наш F блокам и сверяем их хэши с хэшами блоков из F. Если хэши совпали, то считаем, что это «тот же самый файл» и меняем путь для сохранения F в добавляемой раздаче на путь к совпавшему кандидату.

                                            Всё же мне кажется, что средствами файловой системы дедуплицировать удобнее, но у такого подхода есть свой плюс: можно дедуплицировать между разными файловыми системами (но зачем?).
                                              0
                                              Да, как-то так я и начинал делать ;)
                                              Думал про дедупликацию, но не нашел как сделать для домашней винды.
                                    0
                                    Долго им пользовался, но пришлось отказаться и перейти на transmission, бо столкнулся с тем что начали попадаться торренты, которые он не качал от слова вообще. При этом другими клиентами они скачивались на ура…
                                      0
                                      Я настроил автозакачку при добавлении файла в директорию, как автор, и настроил NFS для этой директории на сервере и у клиентов. Таким образом для загрузки торрента клиенту нужно просто скачать файл в определённую директорию (ту, к которой примонтирован NFS). Со временем хочу доработать это решение так, чтобы когда NFS недоступен, файлы сохранялись локально, а при возобновлении связи копировались на сервер.
                                        0
                                        Большое спасибо за статью! Документации по rtorrent мало и она неполна, поэтому появление такого обзора — безусловно большая радость.

                                        Я тоже настраивал себе автоматическую закачку после копирования *.torrent файла в директорию и копирование загруженных файлов в целевую директорию в зависимости от местонахождения *.torrent файла.

                                        Но вот копирование файлов с магнет-линков у меня настроить так и не получилось. Когда магнет-линк скачан rtorrent теряет файлы с раздачи и считает их нескачанными. Происходит это, как я понимаю, из-за отсутствия соответствующего раздаче *.torrent файла. Может кто знает, как это побороть?
                                          0
                                          Возможно после добавления magnet-ссылки rtorrent создаёт .torrent-файл в каталоге session.path. В этом случае скорее всего его можно скопировать в обычный каталог по какому-то событию.

                                        Only users with full accounts can post comments. Log in, please.