Skip to content

Instantly share code, notes, and snippets.

@RobertKim
Last active October 25, 2016 16:24
Show Gist options
  • Save RobertKim/5fb95d9bddc3d3e63214247d468ff286 to your computer and use it in GitHub Desktop.
Save RobertKim/5fb95d9bddc3d3e63214247d468ff286 to your computer and use it in GitHub Desktop.
Module used to consume AWR Cloud API (for processing domain name rankings on various search engines)
module RankingsAPI
NoDateError = Class.new(StandardError)
NoRankingError = Class.new(StandardError)
ProjectExistsError = Class.new(StandardError)
def self.get_latest_rankings(project, api=nil)
api = api || AWRCloud::API.new(project.awr_account.token)
project.update got_rankings_at: Time.now
date = get_latest_ranking_report_date project, api
ranking_data = get_ranking project, date, api
simplified_ranking_data = simplify_ranking_data project.domain, project.domain, date, ranking_data
end
def self.create_project user
begin
retries ||= 1
project_name = user.domain.sub(/^https?\:\/\//, '').sub(/^www./,'')
puts "TRY ##{ retries } OF 5 FOR \'RankingsAPI.create_project\' | '#{project_name}'"
website = user.domain.sub(/^https?\:\/\//, '').sub(/^www./,'')
keywords = []
10.times do |i|
kw = user.send("keyword_#{i+1}")
kw.if true: ->{ keywords << kw }
end
awr_account = AwrAccount.find(5)
api = AWRCloud::API.new awr_account.token
project = AWRCloud::Project.new project_name.sub(/^https?\:\/\//, '').sub(/^www./,'')
project.frequency = "monthly"
project.websites.add name: website, aliases: create_website_alias(website)
project.search_engines.add awr_id: "1481189791" #bing
project.search_engines.add awr_id: "2138589785" #google
project.search_engines.add awr_id: "85186592" #yahoo
keywords.each{|keyword| project.keywords.add(name: keyword)}
api.create_project project
p = Project.where(domain: website.sub(/^https?\:\/\//, '').sub(/^www./,'')).first_or_create
p.update(awr_account_id: awr_account.id)
rescue => e
puts "Exception => #{e} ... retrying '#{project_name}'"
puts "#{Time.now} | First attempt creating project for #{project_name} unsuccessful for #{project_name}."
sleep 45
retry if (retries +=1) < 3
ensure
log_api_call "create_project"
end
}, ->{
exit
end
def self.get_latest_ranking_report_date project, api
log_api_call "get_dates"
project.update got_dates_at: Time.now
date = api.get_dates(project.domain)["dates"][-1]["date"]
date
rescue NoMethodError, JSON::ParserError
raise NoDateError.new "Could not get a ranking report date from response."
end
def self.get_ranking project, date, api
log_api_call "get_ranking"
project.update got_rankings_at: Time.now
api.get_ranking(project.domain, date)
rescue
raise NoRankingError.new "Ranking could not be retrieved from AWRCloud with the given project name and date."
end
private
def self.simplify_ranking_data project_name, domain, date, response
response.map{|segment| extract_valuable_ranking_data(project_name, domain, date, segment)}.reject{|segment| segment.nil?}
end
def self.extract_valuable_ranking_data project_name, domain, date, segment
output = {"date" => nil, "search_engine" => nil, "keyword" => nil, "keyword_group" => nil, "website" => nil, "url" => nil, "position" => nil, "best" => nil, "competition" => nil, "average" => nil, "cpc" => nil, "page" => nil, "ranking_type" => nil}
rank = segment["rankdata"].select{|rank| rank["url"].include?(domain)}.first
output["date"] = date
output["search_engine"] = segment["searchengine"].try{|y|y.ascii_only!}
output["keyword"] = segment["keyword"].try{|y|y.ascii_only!}
output["website"] = domain.try{|y|y.ascii_only!}
output["url"] = rank.try{|x|x["url"]}.try{|y|y.ascii_only!}
output["position"] = rank.try{|y|y["position"]}
output["page"] = rank.try{|z|z["page"]}
output["ranking_type"] = rank.try{|w|w["type"]}
output
end
def self.create_website_alias domain
"*.#{domain}"
end
def self.log_api_call name
AwrcloudApiCall.create method: name
end
def self.make_call_when_ready &block
sleep 1.minute until AwrcloudApiCall.free_api_calls?
yield
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment