-
-
Save davidpfahler/2971503 to your computer and use it in GitHub Desktop.
Fetch iTunes finance reports for your iPhone apps
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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