Skip to content

Instantly share code, notes, and snippets.

@bpinto
Created August 25, 2012 03:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bpinto/3459843 to your computer and use it in GitHub Desktop.
Save bpinto/3459843 to your computer and use it in GitHub Desktop.
Screencast Downloader
# Forcing the app to load the dynamic libxml2 library instead of the older system version of libxml2 loaded by gems that failed to specify which library to load.
require 'nokogiri'
require 'open-uri'
Bundler.setup
Bundler.require(:default)
require 'ostruct'
ROOT_URL = 'https://www.URL.com'
def download_screencasts
login
all_screencasts do |screencast|
download screencast unless File.exists? screencast.filename
end
end
def all_screencasts(&block)
screencasts_links do |link|
download_page = Nokogiri::HTML(open url(link))
download_link = ios_download_link download_page
filename = "#{link.split('/').last}.mov"
yield OpenStruct.new filename: filename, download_link: download_link
end
end
def authenticity_token
page = Nokogiri::HTML(open url('/screencasts/users/sign_in'))
page.css('input[name=authenticity_token]').first[:value]
end
def download(screencast)
link = screencast.download_link
filename = screencast.filename
Curl::Easy.new(link) do |curl|
curl.follow_location = true
curl.cookies = @cookies.join " "
progress_bar = nil
curl.on_header do |header|
if header =~ /Content-Length: (\d*)/
length = $1.to_i
progress_bar = ProgressBar.create title: filename, total: length, format: '%a |%b>>%i| %p%% %t'
end
header.length
end
curl.on_body do |data|
File.open(filename, 'a') { |f| f.write data }
progress_bar.progress += data.length
data.length
end
curl.perform
end
end
def login
curl = Curl::Easy.new(url '/screencasts/users/sign_in')
curl.follow_location = true
curl.enable_cookies = true
# Extract cookies in response.
@cookies = []
curl.on_header { |header|
# Parse cookies from the headers (yes, this is a naive implementation but it's fast).
@cookies << "#{$1}=#{$2}" if header =~ /^Set-Cookie: ([^=]*)=([^;]+;)/
header.length
}
curl.http_post(
Curl::PostField.content('authenticity_token', authenticity_token),
Curl::PostField.content('user[email]', 'EMAIL'),
Curl::PostField.content('user[password]', 'PASSWORD')
)
# Reset the on_header handler.
curl.on_header
end
def ios_download_link(page)
links = page.css('.downloads a').map { |link| url(link[:href]) }
links.find { |link| link =~ /ios/ }
end
def screencasts_links(&block)
page = Nokogiri::HTML(open url('/screencasts'))
page.css('.screencast a').each { |link| yield link[:href] }
end
def url(link)
"#{ROOT_URL}#{link}"
end
download_screencasts
source :rubygems
gem 'curb'
gem 'nokogiri'
gem 'ruby-progressbar'
group :test, :development do
gem 'pry'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment