Last active
August 8, 2017 10:40
-
-
Save lightman76/2357338dcca65fd390e2 to your computer and use it in GitHub Desktop.
Class to interface with Google Contacts API in Ruby. Adapted from https://gist.github.com/cantino/d1a63045fbfe5fc55a94 . Initialize the class with client which is a hurley client and auth is a Signet::OAuth2::Client - I'm using the versions from the google-api-ruby-client 0.9.x series. Hurley client can be one created straight up or prebuilt fro…
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
#Adapted from https://gist.github.com/cantino/d1a63045fbfe5fc55a94 | |
module ContactList | |
class GoogleContactsApi | |
MAX_RESULTS = "250" | |
attr_reader :client | |
def initialize(client, auth) | |
@client = client | |
@auth = auth | |
end | |
def all_contacts | |
process_contacts_list(fetch_contacts['feed']['entry']) | |
end | |
def query_contacts(search_text) | |
process_contacts_list(fetch_contacts({q: search_text})['feed']['entry']) | |
end | |
def all_groups | |
process_group_list(fetch_groups['feed']['entry']) | |
end | |
def group_members(group) | |
group_data = fetch_contacts({group: group.id}) | |
process_contacts_list(group_data['feed']['entry']) | |
end | |
protected | |
def execute(uri, options = {}) | |
client.get(uri, options[:parameters]) do |req| | |
req.header['GData-Version'] = '3.0' | |
req.header['Content-Type'] = 'application/json' | |
@auth.apply!(req.header) | |
end | |
end | |
def fetch_contacts(options = {}) | |
params = { 'alt' => 'json', | |
'max-results' => MAX_RESULTS } | |
params[:q] = options[:q] if options[:q] | |
params[:group] = options[:group] if options[:group] | |
response = execute("https://www.google.com/m8/feeds/contacts/default/full", | |
parameters: params) | |
JSON.parse(response.body) | |
end | |
def fetch_groups(options = {}) | |
params = { 'alt' => 'json', | |
'max-results' => '200' } | |
params[:q] = options[:q] if options[:q] | |
response = execute("https://www.google.com/m8/feeds/groups/default/full", | |
parameters: params) | |
JSON.parse(response.body) | |
end | |
def process_group_list(group_list) | |
(group_list || []).map do |group| | |
group_cleansed = cleanse_gdata(group) #TODO: do I want to filter out anything? | |
GoogleGroup.new(group_cleansed) | |
end | |
end | |
def process_contacts_list(contact_list) | |
(contact_list || []).map do |contact| | |
contact_raw_data = { | |
emails: extract_schema(contact['gd$email']), | |
phone_numbers: extract_schema(contact['gd$phoneNumber']), | |
handles: extract_schema(contact['gd$im']), | |
addresses: extract_schema(contact['gd$structuredPostalAddress']), | |
name_data: cleanse_gdata(contact['gd$name']), | |
nickname: contact['gContact$nickname'] && contact['gContact$nickname']['$t'], | |
websites: extract_schema(contact['gContact$website']), | |
organizations: extract_schema(contact['gd$organization']), | |
events: extract_schema(contact['gContact$event']), | |
birthday: contact['gContact$birthday'].try(:[], "when") | |
}.tap do |basic_data| | |
# Extract a few useful bits from the basic data | |
basic_data[:full_name] = basic_data[:name_data].try(:[], :full_name) | |
primary_email_data = basic_data[:emails].find { |type, email| email[:primary] } | |
if primary_email_data | |
basic_data[:primary_email] = primary_email_data.last[:address] | |
end | |
end | |
GoogleContact.new(contact_raw_data) | |
end | |
end | |
# Turn an array of hashes into a hash with keys based on the original hash's 'rel' values, flatten, and cleanse. | |
def extract_schema(records) | |
(records || []).inject({}) do |memo, record| | |
key = (record['rel'] || 'unknown').split('#').last.to_sym | |
value = cleanse_gdata(record.except('rel')) | |
value[:primary] = true if value[:primary] == 'true' # cast to a boolean for primary entries | |
value[:protocol] = value[:protocol].split('#').last if value[:protocol].present? # clean namespace from handle protocols | |
value = value[:$t] if value[:$t].present? # flatten out entries with keys of '$t' | |
value = value[:href] if value.is_a?(Hash) && value.keys == [:href] # flatten out entries with keys of 'href' | |
memo[key] = value | |
memo | |
end | |
end | |
# Transform this | |
# {"gd$fullName"=>{"$t"=>"Bob Smith"}, | |
# "gd$givenName"=>{"$t"=>"Bob"}, | |
# "gd$familyName"=>{"$t"=>"Smith"}} | |
# into this | |
# { :full_name => "Bob Smith", | |
# :given_name => "Bob", | |
# :family_name => "Smith" } | |
def cleanse_gdata(hash) | |
(hash || {}).inject({}) do |m, (k, v)| | |
k = k.gsub(/\Agd\$/, '').underscore # remove leading 'gd$' on key names and switch to underscores | |
v = v['$t'] if v.is_a?(Hash) && v.keys == ['$t'] # flatten out { '$t' => "value" } results | |
m[k.to_sym] = v | |
m | |
end | |
end | |
end | |
class GoogleContact | |
attr_accessor :first_name, :last_name, :email_address, :raw_data | |
def initialize(raw_data) | |
@raw_data = raw_data | |
@first_name = raw_data && raw_data[:name_data] ? raw_data[:name_data][:given_name] : nil | |
@last_name = raw_data && raw_data[:name_data] ? raw_data[:name_data][:family_name] : nil | |
@email_address = raw_data[:primary_email] | |
end | |
def full_name | |
"#{@first_name} #{@last_name}" | |
end | |
end | |
class GoogleGroup | |
attr_accessor :title, :id, :raw_data | |
def initialize(raw_data) | |
@raw_data = raw_data | |
@title = raw_data[:title] | |
@id = raw_data[:id] | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based upon this code https://github.com/msp/promo-sender