Скачиваем Torrent файлы с помощью ruby и transmission



Сегодня я расскажу вам как я решил несложную, но очень акутальную для меня задачу, а именно скачивание файлов с торрентов. Я приследовал в первую очередь цель скачивать файлы с помощью айпеда, в котором очень сложно с торрент клиентами. Задача свелась к тому, что с айпеда отправляю задание на скачку с торрентов, жду некоторое время и забирая скаченный файл. Сначала хотел реализовать вариант сложнее, а именно, чтобы скаченный файл отправлялся в дропбокс (ничего сложного тут нет, есть удобный и понятный гем), но понял что для меня задача решена и вместо того, чтобы делать какие-то «плюшки», займусь чем-нибудь другим.

Инструментарий

Нам понадобится дешевенький vps сервер, я взял у reg.ru за 128 рублей в месяц с 128 мегабайтами оперативной памяти и 2 гигабайтами жестким и хорошим интернет каналом на XEN. Для данной задачи за глаза хватит такого слабенького сервера.

Демон transmission-daemon для быстрого и удобного скачивания файлов через торрент. Самое сложное тут будет правильно настроить конфиг (но и это просто).

Rails бекенд (unicorn, nginx) для сообщения transmission, что пока заканчивать прохлаждаться и начинать скачивать файлы.

Поэтапная реализация

В данной заметке я не буду рассказывать вам, как устанавливать rvm (в данном проекте я применял его), настраивать nginx + unicorn + capistrano, мануалов полно в инете, я лишь заострю внимание на ключевых моментах. Допустим приложение, чтобы не путаться в путях у вас также как у меня находится в папке /home/deployer/apps/my_site_current.

Давайте разберемся с конфигом transmission-daemon’а, который будет лежать в ~/.config/transmission-daemon/settings.json.
{
    "dht-enabled": true, 
    "download-dir": "/home/deployer/apps/my_site/current/public/attachment/complete-downloads", 
    "download-queue-enabled": true, 
    "download-queue-size": 5, 
    "encryption": 1, 
    "idle-seeding-limit": 30, 
    "idle-seeding-limit-enabled": false, 
    "incomplete-dir": "/home/deployer/apps/my_site/current/public/attachment/incomplete-downloads", 
    "watch-dir": "/home/deployer/apps/my_site/current/public/attachment/incomplete-dir", 
    "watch-dir-enabled": true,
    "incomplete-dir-enabled": true, 
    "lpd-enabled": false, 
    "message-level": 2, 
    "peer-congestion-algorithm": "", 
    "script-torrent-done-enabled": false, 
    "script-torrent-done-filename": "", 
    "start-added-torrents": true, 
    "trash-original-torrent-files": false, 
    "umask": 18, 
    "upload-slots-per-torrent": 14, 
    "utp-enabled": true
}

Большинство опций использунется по умолчанию, но есть некоторые которые стоит пояснить.

«download-dir» — указывает в какую папку сохранять скаченные файлы
«incomplete-dir» — куда будет качать
«incomplete-dir-enabled» чтобы отделить котлеты от мух (скачиваемое и скаченное будут лежать отдельно, дабы не путаться)
«watch-dir» — за какой папкой будем следить, т.е. если в этой папке появляются торрент файлы, то автоматически начинаем их скачивать
«watch-dir-enabled» — включаем опцию «слежения»
Для эксперимента будем скачивать торрент файл с tfile.ru, чтобы без регистрации. Чтобы скачать файл, необходимо поставить куку, которая ставится javascript’ом, но тут нет ничего сложного.

Скачивать будем wget’ом, чтобы проще, а чтобы еще проще взаимодействовать с консольными утилитами будет использовать гем Cocaine от создателей Paperclip’а и FacoryGirl’ы.
class Attachment < ActiveRecord::Base
  validates_presence_of :name, :url 

  attr_accessible :name, :status, :file, :url 

  before_create :download_torrent_file

  private
  def download_torrent_file
    response = open(self.url).read
    
    cookie = response[/tmbx=[^"]*/]

    torrent_url = response[/http:\/\/[^"]*/]

    output_path = '/home/deployer/apps/my_site/current/public/attachment/incomplete-dir/'

    output_file = "#{ output_path }#{ Date.today.to_s }-#{ self.name }.torrent"

    # wget 'http://tfile.ru/forum/download.php?id=549501&attempt=1#r' --no-cookies --header "Cookie: tmbx=6df9fc90ad02d5bdf2ca7449d0cc44
    line = Cocaine::CommandLine.new('wget', ":torrent_url --no-cookies --header 'Cookie: #{ cookie }' -O :output_file",
                                    :torrent_url => torrent_url,
                                    :output_file => output_file)

    line.run
  end  
end

Так мы будем скачивать наши торрент файлы. Первый запуск transmission-daemon’а попробуем не в режиме демона, чтобы не ждать до ишачьей пасхи, а видеть все ошибки воочию. Для этого запустим transmission-daemon с ключом **-f** и все ошибки посыпятся в stdout и мы легко их сможем исправить, если все пойдет по плану, то наш первый файл будет скачен. Если все прошло тип-топ, то можем запускать transmission-daemon без параметров и озадачивать его новыми закачками.

Для того, чтобы отобразить результат и использовал следующее костальное решение в контроллере Attachments#index, я написал следующее:
def index
  @files = Dir.glob("public/attachment/complete-downloads/*")
end

во вьюхе уже выводил список файлов
  <ul>
    <% @files.each do |f| %>
      <li><%= link_to f, f.sub('public', '') %></li>
    <% end %>
  </ul>

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

Заключение

Данное решение служит мне верой и правдой уже где-то с месяц и не вызывало никаких нареканий, процессы не отваливаются, журнальчики скачиваются. Было бы неплохо, наверное, сделать так, что при скачивании торрент файла, мы получаем список файлов, которые в нем содержатся и каким-нибудь демоном проверяем все ли файлы скачались, если да, то оповещаем по имейлу пользователя. Но данная «плюшка» выходит за рамки данной заметки. Надеюсь, вам было интересно, до новых встреч.
Теги:
Torrent, transmission
Добавлено: 21 Сентября 2013 10:08:59 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...