#! /usr/bin/env ruby # usage: # $ das_download.rb email password # based on various gists from this thread https://gist.github.com/maca/1798070 require "mechanize" require "nokogiri" require "fileutils" class DasDownloader attr_reader :agent, :email, :password def initialize(email, password) @agent = Mechanize.new @email, @password = email, password end def screencasts screencasts = [] screencasts_metadata_html.each do |html| next unless (meta = html.at("h1.season_title")) season = meta.at("a").attr("name") html.search(".episode").each do |episode| #title = replace episode.at(".title").text.gsub("/", "-") title_node = Nokogiri::HTML.parse(episode.to_s).css('.title') title_node.css('.tag').remove title = replace title_node.text number = episode.at(".number").text.gsub("/", "-").rjust(3, "0") url = episode.at("a").attr("href") download_url = url + "/download" description = replace episode.at(".subtitle").text duration = episode.at(".duration").text screencasts << Screencast.new(season, title, number, description, duration, download_url) end end screencasts end def run screencasts.each do |screencast| if screencast.season != "Classic season 1" && screencast.season != "Classic season 2" puts "#{screencast.season}" download screencast end end end private def replace(name) name.gsub!(":", " ") name.gsub!("/", " ") name.gsub!("\\", " ") name.gsub!("<", " ") name.gsub!(">", " ") name.gsub!("|", " ") name.gsub!("?", " ") name.gsub!("*", " ") name.gsub!("\"", " ") name.gsub!(/\s+/, ' ') name end def login agent.get "https://www.destroyallsoftware.com/screencasts/users/sign_in" if (form = agent.page.forms.first) form["user[email]"] = email form["user[password]"] = password form.submit agent.pluggable_parser.default = Mechanize::Download end end def download(screencast) puts "Downloading #{screencast.season} - #{screencast.title}" FileUtils::mkdir_p(replace screencast.season) Dir.chdir(replace screencast.season) do title = replace "#{screencast.number} #{screencast.title}" FileUtils::mkdir_p(title) Dir.chdir(title) do File.open("metadata.txt", "w") do |metadata| metadata.puts "Number: #{screencast.number}" metadata.puts "Title: #{screencast.title}" metadata.puts "Description: #{screencast.description}" metadata.puts "Duration: #{screencast.duration}" end agent.get("https://destroyallsoftware.com#{screencast.url}").save("screencast.mp4") end end end def screencasts_metadata_html login agent.get "https://www.destroyallsoftware.com/screencasts/catalog" agent.page.search(".season").reverse end Screencast = Struct.new(:season, :title, :number, :description, :duration, :url) end email = ARGV[0] or raise("Please provide the email address for your account") password = ARGV[1] or raise("Please provide the password for your account") DasDownloader.new(email, password).run