--- /dev/null
+#!/usr/bin/ruby
+# download from bowlroll.net
+# http://bowlroll.net/up/
+
+$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
+require 'bowl'
+
+require 'net/http'
+require 'rss'
+
+def read_atom
+ body = ''
+ http = Net::HTTP.new('bowlroll.net')
+ http.start do
+ http.request_get('/Php/upRssAtom.php?feed=ATOM&count=20&tab=MikuMikuDance') do |response|
+ body = response.body
+ end
+ end
+ body
+end
+
+def each_code
+ feed = RSS::Parser.parse(read_atom)
+ feed.items.each do |item|
+ code = /(dl\d+)\z/.match(item.link.href)[1]
+ yield code
+ end
+end
+
+each_code do |code|
+ bowl = Bowl.new(code)
+ if bowl.save_src
+ puts "saved src #{code}"
+ else
+ puts "PASS: src #{code} exists"
+ end
+ bowl.load
+ if bowl.save_arc
+ puts "saved arc #{code}"
+ else
+ puts "PASS: arc #{code} exists (or locked or removed)"
+ end
+end
--- /dev/null
+require 'net/http'
+
+class Bowl
+ attr_reader :code
+
+ def src_path
+ "/Volumes/uploader/src/mmdbowl/#{code}.html"
+ end
+
+ def save_src_0
+ http = Net::HTTP.new('bowlroll.net')
+ http.start do
+ http.request_get("/up/#{code}") do |response|
+ open(src_path(code), 'wb') { |f|
+ response.read_body { |buf| f.write buf }
+ }
+ end
+ end
+ end
+
+ def save_src
+ if File.exist? src_path
+ return false
+ end
+ save_src_0
+ true
+ end
+
+ def initialize(code)
+ @code = code
+ end
+
+ def load
+ @source = IO.read(src_path)
+ end
+
+ def removed?
+ !!/削除され/.match(@source)
+ end
+
+ def locked?
+ !!/認証キー/.match(@source)
+ end
+
+ def summary
+ description.split(/,/)[0]
+ end
+
+ def tabs
+ description.split(/,/)[1..-1]
+ end
+
+ def description
+ %r(<meta name="description" content="(.+?)">).match(@source)[1]
+ end
+
+ def extname
+ File.extname(origname)[1..-1]
+ end
+
+ def origname
+ %r(<p>ファイル名 : (.+?)</p>).match(@source)[1]
+ end
+
+ def boundary
+ "myboundary"
+ end
+
+ def request_header
+ header = {}
+ header["user-agent"] = "Mozilla/5.0 (Windows; U; Windows NT 6.0; ja; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 (.NET CLR 3.5.30729)"
+ header["accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
+ header["accept-language"] = "ja,en-us;q=0.7,en;q=0.3"
+ header["accept-charset"] = "Shift_JIS,utf-8;q=0.7,*;q=0.7"
+ header["referer"] = "http://bowlroll.net/up/#{code}"
+ header["content-type"] = "multipart/form-data; boundary=#{boundary}"
+ header
+ end
+
+ def request_body
+ body = ''
+ body.concat "--#{boundary}\r\n"
+ body.concat "content-disposition: form-data; name=\"upDlBrowser\";\r\n"
+ body.concat "\r\n"
+ body.concat "OTHER\r\n"
+ body.concat "--#{boundary}--\r\n"
+ body
+ end
+
+ def arc_path
+ "/Volumes/uploader/arc/mmdbowl/#{code}.#{extname}"
+ end
+
+ def save_arc_0
+ http = Net::HTTP.new('bowlroll.net')
+ http.start do
+ request = Net::HTTP::Post.new('/Php/upDlDownload.php')
+
+ request_header.each do |key, value|
+ request[key] = value
+ end
+ request.body = request_body
+
+ http.request(request) do |response|
+ p response.code
+ p response['content-type']
+ open(arc_path, 'wb') { |f|
+ response.read_body { |buf| f.write buf }
+ }
+ end
+ end
+ end
+
+ def save_arc
+ if removed?
+ return false
+ end
+ if locked?
+ return false
+ end
+ if File.exist? arc_path
+ return false
+ end
+ save_arc_0
+ true
+ end
+end
--- /dev/null
+require 'lib/bowl'
+$KCODE = 'U'
+
+describe 'Bowl', 'arc dl140' do
+ subject { Bowl.new('dl140') }
+ before do
+ subject.load
+ end
+ it "should be removed" do
+ should be_removed
+ end
+end
+
+describe 'Bowl', 'arc dl391' do
+ subject { Bowl.new('dl391') }
+ before do
+ subject.load
+ end
+ it "should not be removed" do
+ should_not be_removed
+ end
+ it "should be locked" do
+ should be_locked
+ end
+ its "code" do
+ should == 'dl391'
+ end
+ its "extname" do
+ should == 'zip'
+ end
+ its "summary" do
+ should == 'アイギス Ver. 0.951'
+ end
+ its "tabs" do
+ should == %w[ MikuMikuDance MMDモデル ]
+ end
+ its "origname" do
+ should == 'アイギス v0951.zip'
+ end
+end
+
+describe 'Bowl', 'arc dl392' do
+ subject { Bowl.new('dl392') }
+ before do
+ subject.load
+ end
+ it "should not be removed" do
+ should_not be_removed
+ end
+ it "should not be locked" do
+ should_not be_locked
+ end
+ its "code" do
+ should == 'dl392'
+ end
+ its "extname" do
+ should == 'rar'
+ end
+ its "summary" do
+ should == 'サテンサン'
+ end
+ its "tabs" do
+ should == %w[ MikuMikuDance MMDモデル ]
+ end
+ its "origname" do
+ should == 'サテンサン.rar'
+ end
+end