[ruby] 続ruby with mechanizeでニコニコ動画のダウンローダーを作ってみた

id:hsurコメントでバグを指摘されたのでちょっと修正。

require 'yaml'
require 'rubygems'
require 'mechanize'
require 'uri'
require 'tempfile'

class NicoVideo
  attr_reader :email, :password
  AGENT_ALIAS = 'Windows Mozilla'
  
  def initialize(*args)
    case args.length
    when 1
      fname = args[0]
      raise unless File.exists?(fname)
      YAML.load_file(fname).each do |sym, value|
        instance_variable_set('@' + sym, value)
      end
    end
    @agent = WWW::Mechanize.new
    @agent.user_agent_alias = AGENT_ALIAS
  end

  def login
    if @agent.post("https://secure.nicovideo.jp/secure/login?site=niconico", {'mail' => @email, 'password' => @password}).header['x-niconico-authflag'] == '1'
      @login = true
    else
      raise LOGIN_FAILURE
    end
  end

  def login?
    @login
  end

  def get_flv(id)
    api = { }
    login unless login?
    URI.decode(@agent.get("http://www.nicovideo.jp/api/getflv?v=" + id).body).split('&').each do |query|
      query =~ /^([^=]+)=(.+)/
      api[$1.to_sym] = $2
    end
    
    raise VIDEO_NOT_FOUND unless api[:url]
    
    @agent.get("http://www.nicovideo.jp/watch/#{id}")
    dir = "/tmp/nicovideo"
    Dir.mkdir dir unless File.exists?(dir)
    path = "#{dir}/#{id}.flv"
    
    File.open(path, 'w') do |f|
      f.write @agent.get(api[:url]).body
    end unless File.exists?(path)

    Video.new(path)
  end

  class VIDEO_NOT_FOUND < StandardError; end
  class LOGIN_FAILURE < StandardError; end
  
  class Video
    attr_reader :tmpfile
    def initialize(path)
      @tmpfile = path
    end
  end
end

if $0 == __FILE__
  NicoVideo.new(File.expand_path(File.dirname(__FILE__) + '/account.yml')).get_flv(ARGV[0])
end