houdini/lib/mailchimp.rb

156 lines
5.8 KiB
Ruby

require 'httparty'
require 'digest/md5'
module Mailchimp
include HTTParty
format :json
def self.base_uri(key)
dc = get_datacenter(key)
return "https://#{dc}.api.mailchimp.com/3.0"
end
# Run the configuration from an initializer
# data: {:api_key => String}
def self.config(hash)
@options = {
:headers => {
'Content-Type' => 'application/json',
'Accept' => 'application/json'
}
}
@body = {
:apikey => hash[:api_key]
}
end
# Given a nonprofit mailchimp oauth2 key, return its current datacenter
def self.get_datacenter(key)
metadata = HTTParty.get('https://login.mailchimp.com/oauth2/metadata', {
headers: {
'User-Agent' => 'oauth2-draft-v10',
'Host' => 'login.mailchimp.com',
'Accept' => 'application/json',
'Authorization' => "OAuth #{key}"
}
})
return metadata['dc']
end
def self.signup email, mailchimp_list_id
body_hash = @body.merge({
:id => mailchimp_list_id,
:email => {:email => email}
})
post("/lists/subscribe", @options.merge(:body => body_hash.to_json)).parsed_response
end
def self.get_mailchimp_token(npo_id)
mailchimp_token = QueryNonprofitKeys.get_key(npo_id, 'mailchimp_token')
throw RuntimeError.new("No Mailchimp connection for this nonprofit: #{npo_id}") if mailchimp_token.nil?
return mailchimp_token
end
# Given a nonprofit id and a list of tag master ids that they make into email lists,
# create those email lists on mailchimp and return an array of hashes of mailchimp list ids, names, and tag_master_id
def self.create_mailchimp_lists(npo_id, tag_master_ids)
mailchimp_token = get_mailchimp_token(npo_id)
uri = base_uri(mailchimp_token)
puts "URI #{uri}"
puts "KEY #{mailchimp_token}"
npo = Qx.fetch(:nonprofits, npo_id).first
tags = Qx.select("DISTINCT(tag_masters.name) AS tag_name, tag_masters.id")
.from(:tag_masters)
.where({"tag_masters.nonprofit_id" => npo_id})
.and_where("tag_masters.id IN ($ids)", ids: tag_master_ids)
.join(:nonprofits, "tag_masters.nonprofit_id = nonprofits.id")
.execute
tags.map do |h|
list = post(uri+'/lists', {
basic_auth: {username: '', password: mailchimp_token},
headers: {'Content-Type' => 'application/json'},
body: {
name: 'CommitChange-'+h['tag_name'],
contact: {
company: npo['name'],
address1: npo['address'] || '',
city: npo['city'] || '',
state: npo['state_code'] || '',
zip: npo['zip_code'] || '',
country: npo['state_code'] || '',
phone: npo['phone'] || ''
},
permission_reminder: 'You are a registered supporter of our nonprofit.',
campaign_defaults: {
from_name: npo['name'] || '',
from_email: npo['email'].blank? ? "support@commichange.com" : npo['email'],
subject: "Enter your subject here...",
language: 'en'
},
email_type_option: false,
visibility: 'prv'
}.to_json
})
if list.code != 200
raise Exception.new("Failed to create list: #{list}")
end
{id: list['id'], name: list['name'], tag_master_id: h['id']}
end
end
# Given a nonprofit id and post_data, which is an array of batch operation hashes
# See here: http://developer.mailchimp.com/documentation/mailchimp/guides/how-to-use-batch-operations/
# Perform all the batch operations and return a status report
def self.perform_batch_operations(npo_id, post_data)
return if post_data.empty?
mailchimp_token = get_mailchimp_token(npo_id)
uri = base_uri(mailchimp_token)
batch_job_id = post(uri + '/batches', {
basic_auth: {username: "CommitChange", password: mailchimp_token},
headers: {'Content-Type' => 'application/json'},
body: {operations: post_data}.to_json
})['id']
check_batch_status(npo_id, batch_job_id)
end
def self.check_batch_status(npo_id, batch_job_id)
mailchimp_token = get_mailchimp_token(npo_id)
uri = base_uri(mailchimp_token)
batch_status = get(uri+'/batches/'+batch_job_id, {
basic_auth: {username: "CommitChange", password: mailchimp_token},
headers: {'Content-Type' => 'application/json'}
})
end
def self.delete_mailchimp_lists(npo_id, mailchimp_list_ids)
mailchimp_token = get_mailchimp_token(npo_id)
uri = base_uri(mailchimp_token)
mailchimp_list_ids.map do |id|
delete(uri + "/lists/#{id}", {basic_auth: {username: "CommitChange", password: mailchimp_token}})
end
end
# `removed` and `added` are arrays of tag join ids that have been added or removed to a supporter
def self.sync_supporters_to_list_from_tag_joins(npo_id, supporter_ids, tag_data)
emails = Qx.select(:email).from(:supporters).where("id IN ($ids)", ids: supporter_ids).execute.map{|h| h['email']}
to_add = get_mailchimp_list_ids(tag_data.select{|h| h['selected']}.map{|h| h['tag_master_id']})
to_remove = get_mailchimp_list_ids(tag_data.reject{|h| h['selected']}.map{|h| h['tag_master_id']})
return if to_add.empty? && to_remove.empty?
bulk_post = emails.map{|em| to_add.map{|ml_id| {method: 'POST', path: "lists/#{ml_id}/members", body: {email_address: em, status: 'subscribed'}.to_json}}}.flatten
bulk_delete = emails.map{|em| to_remove.map{|ml_id| {method: 'DELETE', path: "lists/#{ml_id}/members/#{Digest::MD5.hexdigest(em.downcase).to_s}"}}}.flatten
perform_batch_operations(npo_id, bulk_post.concat(bulk_delete))
end
def self.get_mailchimp_list_ids(tag_master_ids)
return [] if tag_master_ids.empty?
to_insert_data = Qx.select("email_lists.mailchimp_list_id")
.from(:tag_masters)
.where("tag_masters.id IN ($ids)", ids: tag_master_ids)
.join("email_lists", "email_lists.tag_master_id=tag_masters.id")
.execute.map{|h| h['mailchimp_list_id']}
end
end