Skip to content

Instantly share code, notes, and snippets.

@lukeredpath
Created July 28, 2010 15:00
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save lukeredpath/494798 to your computer and use it in GitHub Desktop.
Fetch iTunes finance reports for your iPhone apps
#!/usr/bin/env ruby
require 'mechanize'
require 'open-uri'
require 'pathname'
require 'fileutils'
require 'pp'
### BEGIN CUSTOMIZATION
# set this to where you would like the reports to be stored
REPORT_FOLDER = Pathname.new('/Users/luke/Documents/Business/Accounts/iTunes Finance Reports')
ITUNES_CONNECT_USER = 'yourusername'
ITUNES_CONNECT_PASS = 'yourpassword'
OPEN_FOLDER_ON_DOWNLOAD = true
### END CUSTOMIZATION
module ITunesConnect
ROOT_URL = "https://itunesconnect.apple.com/"
LOGIN_PAGE = "#{ROOT_URL}/WebObjects/iTunesConnect.woa"
class Agent
attr_reader :current_page
def initialize
@current_page = nil
@agent = Mechanize.new
@agent.user_agent_alias = 'Mac Safari'
@agent.follow_meta_refresh = false
@agent.gzip_enabled = true
end
def sign_in!(username, password)
get(LOGIN_PAGE)
login_form = current_page.form('appleConnectForm')
login_form.theAccountName = username
login_form.theAccountPW = password
submit(login_form, 2)
end
def sign_out!
if logout_form = signed_in?
submit(logout_form)
end
end
def signed_in?
return nil unless current_page.respond_to?(:form)
current_page.form('signOutForm')
end
def click_link(link_text)
if links = current_page.links_with(:text => link_text)
click(links.first)
end
end
def finance_reports
link_text = 'Payments and Financial Reports'
if finance_link = (current_page.links_with(:text => link_text).first rescue nil)
click(finance_link)
current_page.form_with(:name => /mainForm/) do |nav|
nav.button_with(:value => /Earnings/) do |earnings|
submit_with_button(nav, earnings)
end
end
else
return_home
click_link(link_text)
end
FinanceReports.new(@agent, current_page)
end
def return_home
click_link('Home')
end
def download(form, button, output_dir)
submit_with_button(form, button)
if current_page.respond_to?(:filename)
filename = current_page.filename.gsub(/.gz$/, '')
File.open(output_dir + filename, 'w+') do |io|
gzipped = Zlib::GzipReader.new(StringIO.new(current_page.body))
io.write(gzipped.read)
end
@agent.back
@current_page = @agent.page
end
end
private
def click(link)
@current_page = @agent.click(link)
end
def get(url)
@current_page = @agent.get(url)
end
def submit(form, button_index = 0)
@current_page = @agent.submit(form, form.buttons[button_index])
end
def submit_with_button(form, button)
@current_page = form.submit(button)
end
end
class FinanceReports
def initialize(agent, page)
@agent, @page = agent, page
Mechanize::Form::Button.class_eval do
def src
node['src']
end
end
end
def available_reports
form = @page.form_with(:name => /mainForm/)
form.buttons_with(:src => /download-report/).map do |button|
date = button.node.parent.parent.children[0].children[0].text
Report.new(date, form, button)
end
end
class Report
def initialize(date, form, button)
@date, @form, @button = date, form, button
end
def fetch_to(root, agent)
FileUtils.mkdir_p(output_directory(root))
agent.download(@form, @button, output_directory(root))
end
private
def output_directory(root)
root + Date.parse(@date).strftime("%Y-%m-%b")
end
end
end
end
@agent = ITunesConnect::Agent.new
@agent.sign_in!(ITUNES_CONNECT_USER, ITUNES_CONNECT_PASS)
begin
if @agent.signed_in?
@downloaded = 0
@finance_reports = @agent.finance_reports
@finance_reports.available_reports.reverse.each do |report|
report.fetch_to(REPORT_FOLDER, @agent)
@downloaded += 1
end
puts "Downloaded #{@downloaded} financial reports."
system("open \"#{REPORT_FOLDER}\"") if OPEN_FOLDER_ON_DOWNLOAD
else
STDERR.puts "Couldn't sign in to iTunes Connect! Check your credentials."
exit 1
end
ensure
@agent.sign_out!
end
@lukeredpath
Copy link
Author

Information about this can be found on my blog.

@lukeredpath
Copy link
Author

Updated to work with the new iTunes Connect finance module (August 2010).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment