Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save davidpfahler/2971503 to your computer and use it in GitHub Desktop.
Save davidpfahler/2971503 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment