public
Last active

Fetch iTunes finance reports for your iPhone apps

  • Download Gist
fetch_finance_reports.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
#!/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

Information about this can be found on my blog.

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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.