lib/madmimi.rb in madmimi-1.0.6 vs lib/madmimi.rb in madmimi-1.0.8
- old
+ new
@@ -1,6 +1,6 @@
-# Mad Mimi - v.0.0.1 the incredibly basic, and barely usable version, in my opinion. (too many stinkin' dependencies!)
+# Mad Mimi for Ruby
# License
# Copyright (c) 2010 Mad Mimi (nicholas@madmimi.com)
@@ -27,188 +27,193 @@
# THE SOFTWARE.
require 'uri'
require 'net/http'
require 'net/https'
-require 'active_support'
+require 'crack'
+require 'csv'
class MadMimi
-
- BASE_URL = "api.madmimi.com"
- NEW_LISTS_PATH = "/audience_lists"
- AUDIENCE_MEMBERS_PATH = "/audience_members"
- AUDIENCE_LISTS_PATH = "/audience_lists/lists.xml"
- MEMBERSHIPS_PATH = "/audience_members/%email%/lists.xml"
- SUPPRESSED_SINCE_PATH = "/audience_members/suppressed_since/%timestamp%.txt"
- PROMOTIONS_PATH = "/promotions.xml"
- MAILING_STATS_PATH = "/promotions/%promotion_id%/mailings/%mailing_id%.xml"
- SEARCH_PATH = "/audience_members/search.xml"
-
- @@api_settings = {}
+ class MadMimiError < StandardError; end
+
+ BASE_URL = 'api.madmimi.com'
+ NEW_LISTS_PATH = '/audience_lists'
+ AUDIENCE_MEMBERS_PATH = '/audience_members'
+ AUDIENCE_LISTS_PATH = '/audience_lists/lists.xml'
+ MEMBERSHIPS_PATH = '/audience_members/%email%/lists.xml'
+ SUPPRESSED_SINCE_PATH = '/audience_members/suppressed_since/%timestamp%.txt'
+ PROMOTIONS_PATH = '/promotions.xml'
+ MAILING_STATS_PATH = '/promotions/%promotion_id%/mailings/%mailing_id%.xml'
+ SEARCH_PATH = '/audience_members/search.xml'
+ MAILER_PATH = '/mailer'
+ MAILER_TO_LIST_PATH = '/mailer/to_list'
+
def initialize(username, api_key)
- @@api_settings[:username] = username
- @@api_settings[:api_key] = api_key
+ @api_settings = { :username => username, :api_key => api_key }
end
-
+
def username
- @@api_settings[:username]
+ @api_settings[:username]
end
-
+
def api_key
- @@api_settings[:api_key]
+ @api_settings[:api_key]
end
-
+
def default_opt
- { 'username' => username, 'api_key' => api_key }
+ { :username => username, :api_key => api_key }
end
-
- # Refactor this method asap
- def do_request(path, req_type = :get, options = {}, transactional = false)
- resp = href = "";
- case req_type
- when :get then
- begin
- http = Net::HTTP.new(BASE_URL, 80)
- http.start do |http|
- req = Net::HTTP::Get.new(path)
- req.set_form_data(options)
- response = http.request(req)
- resp = response.body
- end
- resp
- rescue SocketError
- raise "Host unreachable."
- end
- when :post then
- begin
- if transactional == true
- http = Net::HTTP.new(BASE_URL, 443)
- http.use_ssl = true
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
- else
- http = Net::HTTP.new(BASE_URL, 80)
- end
- http.start do |http|
- req = Net::HTTP::Post.new(path)
- req.set_form_data(options)
- response = http.request(req)
- resp = response.body
- end
- rescue SocketError
- raise "Host unreachable."
- end
- end
- end
-
+
def lists
- request = do_request(AUDIENCE_LISTS_PATH, :get, default_opt)
- Hash.from_xml(request)
+ request = do_request(AUDIENCE_LISTS_PATH, :get)
+ Crack::XML.parse(request)
end
-
+
def memberships(email)
- request = do_request((MEMBERSHIPS_PATH.gsub('%email%', email)), :get, default_opt)
- Hash.from_xml(request)
+ request = do_request(MEMBERSHIPS_PATH.gsub('%email%', email), :get)
+ Crack::XML.parse(request)
end
-
+
def new_list(list_name)
- options = { 'name' => list_name }
- do_request(NEW_LISTS_PATH, :post, options.merge(default_opt))
+ do_request(NEW_LISTS_PATH, :post, :name => list_name)
end
-
+
def delete_list(list_name)
- options = { '_method' => 'delete' }
- do_request(NEW_LISTS_PATH + "/" + URI.escape(list_name), :post, options.merge(default_opt))
+ do_request("#{NEW_LISTS_PATH}/#{URI.escape(list_name)}", :post, :'_method' => 'delete')
end
-
+
def csv_import(csv_string)
- options = { 'csv_file' => csv_string }
- do_request(AUDIENCE_MEMBERS_PATH, :post, options.merge(default_opt))
+ do_request(AUDIENCE_MEMBERS_PATH, :post, :csv_file => csv_string)
end
-
- def build_csv(hash)
- csv = ""
- hash.keys.each do |key|
- csv << "#{key},"
- end
- # strip out one char at the end
- csv << "\n"
- csv = csv[0..-1]
- hash.values.each do |value|
- csv << "#{value},"
- end
- csv = csv[0..-1]
- csv << "\n"
- end
-
+
def add_user(options)
csv_data = build_csv(options)
- opt = { 'csv_file' => csv_data }
- do_request(AUDIENCE_MEMBERS_PATH, :post, opt.merge(default_opt))
+ do_request(AUDIENCE_MEMBERS_PATH, :post, :csv_file => csv_data)
end
-
+
def add_to_list(email, list_name)
- options = { 'email' => email }
- do_request(NEW_LISTS_PATH + "/" + URI.escape(list_name) + "/add", :post, options.merge(default_opt))
+ do_request("#{NEW_LISTS_PATH}/#{URI.escape(list_name)}/add", :post, :email => email)
end
-
+
def remove_from_list(email, list_name)
- options = { 'email' => email }
- do_request(NEW_LISTS_PATH + "/" + URI.escape(list_name) + "/remove", :post, options.merge(default_opt))
+ do_request("#{NEW_LISTS_PATH}/#{URI.escape(list_name)}/remove", :post, :email => email)
end
-
+
def suppressed_since(timestamp)
- do_request((SUPPRESSED_SINCE_PATH.gsub('%timestamp%', timestamp)), :get, default_opt)
+ do_request(SUPPRESSED_SINCE_PATH.gsub('%timestamp%', timestamp), :get)
end
-
+
def promotions
- request = do_request(PROMOTIONS_PATH, :get, default_opt)
- Hash.from_xml(request)
+ request = do_request(PROMOTIONS_PATH, :get)
+ Crack::XML.parse(request)
end
-
+
def mailing_stats(promotion_id, mailing_id)
- path = (MAILING_STATS_PATH.gsub('%promotion_id%', promotion_id).gsub('%mailing_id%', mailing_id))
- request = do_request(path, :get, default_opt)
- Hash.from_xml(request)
+ path = MAILING_STATS_PATH.gsub('%promotion_id%', promotion_id).gsub('%mailing_id%', mailing_id)
+ request = do_request(path, :get)
+ Crack::XML.parse(request)
end
-
+
def audience_search(query_string, raw = false)
- options = { 'raw' => raw, 'query' => query_string }
- request = do_request(SEARCH_PATH, :get, options.merge(default_opt))
- Hash.from_xml(request)
+ request = do_request(SEARCH_PATH, :get, :raw => raw, :query => query_string)
+ Crack::XML.parse(request)
end
-
+
def send_mail(opt, yaml_body)
- opt['body'] = yaml_body.to_yaml
- if opt['list_name']
- do_request('/mailer/to_list', :post, opt.merge(default_opt), true)
+ options = opt.dup
+ options[:body] = yaml_body.to_yaml
+ if !options[:list_name].nil?
+ do_request(MAILER_TO_LIST_PATH, :post, options, true)
else
- do_request('/mailer', :post, opt.merge(default_opt), true)
+ do_request(MAILER_PATH, :post, options, true)
end
end
-
+
def send_html(opt, html)
+ options = opt.dup
if html.include?('[[tracking_beacon]]') || html.include?('[[peek_image]]')
- opt['raw_html'] = html
- if opt['list_name']
- do_request('/mailer/to_list', :post, opt.merge(default_opt), true)
+ options[:raw_html] = html
+ if !options[:list_name].nil?
+ unless html.include?('[[unsubscribe]]') || html.include?('[[opt_out]]')
+ raise MadMimiError, "When specifying list_name, include the [[unsubscribe]] or [[opt_out]] macro in your HTML before sending."
+ end
+ do_request(MAILER_TO_LIST_PATH, :post, options, true)
else
- do_request('/mailer', :post, opt.merge(default_opt), true)
+ do_request(MAILER_PATH, :post, options, true)
end
else
- raise StandardError, "You'll need to include either the [[tracking_beacon]] or [[peek_image]] tag in your HTML before sending."
+ raise MadMimiError, "You'll need to include either the [[tracking_beacon]] or [[peek_image]] macro in your HTML before sending."
end
end
-
+
def send_plaintext(opt, plaintext)
- if plaintext.include?('[[unsubscribe]]')
- opt['raw_plain_text'] = plaintext
- if opt['list_name']
- do_request('/mailer/to_list', :post, opt.merge(default_opt), true)
+ options = opt.dup
+ options[:raw_plain_text] = plaintext
+ if !options[:list_name].nil?
+ if plaintext.include?('[[unsubscribe]]') || plaintext.include?('[[opt_out]]')
+ do_request(MAILER_TO_LIST_PATH, :post, options, true)
else
- do_request('/mailer', :post, opt.merge(default_opt), true)
+ raise MadMimiError, "You'll need to include either the [[unsubscribe]] or [[opt_out]] macro in your text before sending."
end
else
- raise StandardError, "You'll need to include either the [[unsubscribe]] tag in your text before sending."
+ do_request(MAILER_PATH, :post, options, true)
end
end
-end
\ No newline at end of file
+
+ private
+
+ # Refactor this method asap
+ def do_request(path, req_type = :get, options = {}, transactional = false)
+ options = options.merge(default_opt)
+ form_data = options.inject({}) { |m, (k, v)| m[k.to_s] = v; m }
+ resp = href = ""
+ case req_type
+ when :get then
+ begin
+ http = Net::HTTP.new(BASE_URL, 80)
+ http.start do |http|
+ req = Net::HTTP::Get.new(path)
+ req.set_form_data(form_data)
+ response = http.request(req)
+ resp = response.body.strip
+ end
+ resp
+ rescue SocketError
+ raise "Host unreachable."
+ end
+ when :post then
+ begin
+ if transactional == true
+ http = Net::HTTP.new(BASE_URL, 443)
+ http.use_ssl = true
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ else
+ http = Net::HTTP.new(BASE_URL, 80)
+ end
+ http.start do |http|
+ req = Net::HTTP::Post.new(path)
+ req.set_form_data(form_data)
+ response = http.request(req)
+ resp = response.body.strip
+ end
+ rescue SocketError
+ raise "Host unreachable."
+ end
+ end
+ end
+
+ def build_csv(hash)
+ if CSV.respond_to?(:generate_row) # before Ruby 1.9
+ buffer = ''
+ CSV.generate_row(hash.keys, hash.keys.size, buffer)
+ CSV.generate_row(hash.values, hash.values.size, buffer)
+ buffer
+ else # Ruby 1.9 and after
+ CSV.generate do |csv|
+ csv << hash.keys
+ csv << hash.values
+ end
+ end
+ end
+
+end