require 'rubygems' require 'httparty' require 'mechanize' require 'nokogiri' require 'api_cache' require 'yaml' require 'pp' # Core extension stuff Dir[File.join(File.dirname(__FILE__), "ext/*.rb")].each { |f| require f } # Octopi stuff # By sorting them we ensure that api and base are loaded first on all sane operating systems Dir[File.join(File.dirname(__FILE__), "octopi/*.rb")].sort.each { |f| require f } # Include this into your app so you can access the child classes easier. # This is the root of all things Octopi. module Octopi # The authenticated methods are all very similar. # TODO: Find a way to merge them into something... better. def authenticated(options={}, &block) begin config = config = File.open(options[:config]) { |yf| YAML::load(yf) } if options[:config] config = read_gitconfig options[:login] = config["github"]["user"] options[:token] = config["github"]["token"] authenticated_with(options) do yield end ensure # Reset authenticated so if we were to do an anonymous call it would Just Work(tm) Api.authenticated = false Api.api = AnonymousApi.instance end end def authenticated_with(options, &block) begin if options[:token].nil? && !options[:password].nil? options[:token] = grab_token(options[:login], options[:password]) end begin User.find(options[:login]) # If the user cannot see themselves then they are not logged in, tell them so rescue Octopi::NotFound raise Octopi::InvalidLogin end Api.api = AuthApi.instance Api.api.trace_level = options[:trace] if options[:trace] Api.api.login = options[:login] Api.api.token = options[:token] trace("=> Trace on: #{options[:trace]}") yield ensure # Reset authenticated so if we were to do an anonymous call it would Just Work(tm) Api.authenticated = false Api.api = AnonymousApi.instance end end private def grab_token(username, password) a = Mechanize.new { |agent| # Fake out the agent agent.user_agent_alias = 'Mac Safari' } # Login with the provided a.get('http://github.com/login') do |page| user_page = page.form_with(:action => '/session') do |login| login.login = username login.password = password end.submit if Api.api.trace_level File.open("got.html", "w+") do |f| f.write user_page.body end `open got.html` end body = Nokogiri::HTML(user_page.body) error = body.xpath("//div[@class='error_box']").text raise error if error != "" # Should be clear to go if there is no errors. link = user_page.link_with(:text => "account") @account_page = a.click(link) if Api.api.trace_level File.open("account.html", "w+") do |f| f.write @account_page.body end `open account.html` end return Nokogiri::HTML(@account_page.body).xpath("//p").xpath("strong")[1].text end end def read_gitconfig config = {} group = nil File.foreach("#{ENV['HOME']}/.gitconfig") do |line| line.strip! if line[0] != ?# && line =~ /\S/ if line =~ /^\[(.*)\]$/ group = $1 config[group] ||= {} else key, value = line.split("=").map { |v| v.strip } config[group][key] = value end end end config end def trace(text) if Api.api.trace_level puts text end end end