lib/flapjack/gateways/sms_twilio.rb in flapjack-1.6.0 vs lib/flapjack/gateways/sms_twilio.rb in flapjack-2.0.0b1

- old
+ new

@@ -1,15 +1,20 @@ #!/usr/bin/env ruby -require 'em-synchrony' -require 'em-synchrony/em-http' +require 'net/http' +require 'uri' +require 'uri/https' + require 'active_support/inflector' -require 'flapjack/redis_pool' +require 'flapjack/redis_proxy' +require 'flapjack/record_queue' +require 'flapjack/utility' +require 'flapjack/exceptions' require 'flapjack/data/alert' -require 'flapjack/utility' +require 'flapjack/data/check' module Flapjack module Gateways class SmsTwilio @@ -17,120 +22,132 @@ # --data-urlencode 'To=+61414123456' \ # --data-urlencode 'From=+61414123456' \ # --data-urlencode 'Body=Sausage' \ # -u [AccountSid]:[AuthToken] + TWILIO_DEFAULT_HOST = 'api.twilio.com' + + attr_accessor :sent + include Flapjack::Utility def initialize(opts = {}) + @lock = opts[:lock] + @config = opts[:config] - @logger = opts[:logger] - @redis_config = opts[:redis_config] || {} - @redis = Flapjack::RedisPool.new(:config => @redis_config, :size => 1, :logger => @logger) - @logger.info("starting") - @logger.debug("new sms_twilio gateway pikelet with the following options: #{@config.inspect}") + # TODO support for config reloading + @queue = Flapjack::RecordQueue.new(@config['queue'] || 'sms_twilio_notifications', + Flapjack::Data::Alert) @sent = 0 - end - def stop - @logger.info("stopping") - @should_quit = true - - redis_uri = @redis_config[:path] || - "redis://#{@redis_config[:host] || '127.0.0.1'}:#{@redis_config[:port] || '6379'}/#{@redis_config[:db] || '0'}" - shutdown_redis = EM::Hiredis.connect(redis_uri) - shutdown_redis.rpush(@config['queue'], Flapjack.dump_json('notification_type' => 'shutdown')) + Flapjack.logger.debug("new sms_twilio gateway pikelet with the following options: #{@config.inspect}") end def start - queue = @config['queue'] + begin + Zermelo.redis = Flapjack.redis - until @should_quit - begin - @logger.debug("sms_twilio gateway is going into blpop mode on #{queue}") - alert = Flapjack::Data::Alert.next(queue, :redis => @redis, :logger => @logger) - deliver(alert) unless alert.nil? - rescue => e - @logger.error "Error generating or dispatching SMS Twilio message: #{e.class}: #{e.message}\n" + - e.backtrace.join("\n") + loop do + @lock.synchronize do + @queue.foreach {|alert| handle_alert(alert) } + end + + @queue.wait end + ensure + Flapjack.redis.quit end end - def deliver(alert) + def stop_type + :exception + end + + private + + def handle_alert(alert) account_sid = @config["account_sid"] - auth_token = @config["auth_token"] - from = @config["from"] - endpoint = @config["endpoint"] || "https://api.twilio.com/2010-04-01/Accounts/#{account_sid}/Messages.json" + auth_token = @config["auth_token"] + from = @config["from"] - address = alert.address - notification_id = alert.notification_id - message_type = alert.rollup ? 'rollup' : 'alert' + endpoint_host = @config["endpoint_host"] || TWILIO_DEFAULT_HOST + endpoint_path = @config["endpoint_path"] || "/2010-04-01/Accounts/#{account_sid}/Messages.json" + address = alert.medium.address + notification_id = alert.id + message_type = alert.rollup ? 'rollup' : 'alert' + + sms_dir = File.join(File.dirname(__FILE__), 'sms_twilio') sms_template_erb, sms_template = - load_template(@config['templates'], message_type, 'text', - File.join(File.dirname(__FILE__), 'sms_twilio')) + load_template(@config['templates'], message_type, 'text', sms_dir) - @alert = alert - bnd = binding + @alert = alert + bnd = binding begin message = sms_template_erb.result(bnd).chomp rescue => e - @logger.error "Error while executing the ERB for an sms: " + + Flapjack.logger.error "Error while executing the ERB for an sms: " + "ERB being executed: #{sms_template}" raise end if @config.nil? || (@config.respond_to?(:empty?) && @config.empty?) - @logger.error "sms_twilio config is missing" + Flapjack.logger.error "sms twilio config is missing" return end errors = [] - safe_message = truncate(message, 159) - [[account_sid, "Twilio account_sid is missing"], [auth_token, "Twilio auth_token is missing"], - [from, "SMS from address is missing"], - [address, "SMS address is missing"], + [from, "SMS from address is missing"], + [address, "SMS address is missing"], [notification_id, "Notification id is missing"]].each do |val_err| next unless val_err.first.nil? || (val_err.first.respond_to?(:empty?) && val_err.first.empty?) errors << val_err.last end unless errors.empty? - errors.each {|err| @logger.error err } + errors.each {|err| Flapjack.logger.error err } return end - body_data = {'To' => address, - 'From' => from, - 'Body' => safe_message} - @logger.debug "body_data: #{body_data.inspect}" - @logger.debug "authorization: [#{account_sid}, #{auth_token[0..2]}...#{auth_token[-3..-1]}]" + body_data = { + 'To' => address, + 'From' => from, + 'Body' => truncate(message, 159) + } - http = EM::HttpRequest.new(endpoint).post(:body => body_data, :head => {'authorization' => [account_sid, auth_token]}) + Flapjack.logger.debug "body_data: #{body_data.inspect}" + Flapjack.logger.debug "authorization: [#{account_sid}, #{auth_token[0..2]}...#{auth_token[-3..-1]}]" - @logger.debug "server response: #{http.response}" + req = Net::HTTP::Post.new(endpoint_path) + req.set_form_data(body_data) + req['Authorization'] = [account_sid, auth_token] - status = (http.nil? || http.response_header.nil?) ? nil : http.response_header.status - if (status >= 200) && (status <= 206) + http_response = Net::HTTP.start(endpoint_host, 443, :use_ssl => true) do |http| + http.request(req) + end + + Flapjack.logger.debug "server response: #{http_response.inspect}" + + status = http_response.code + + if (status.to_i >= 200) && (status.to_i <= 206) @sent += 1 - alert.record_send_success! - @logger.debug "Sent SMS via Twilio, response status is #{status}, " + - "notification_id: #{notification_id}" + Flapjack.logger.info "Sent SMS via Twilio, response status is #{status}, " + + "alert id: #{alert.id}" else - @logger.error "Failed to send SMS via Twilio, response status is #{status}, " + - "notification_id: #{notification_id}" + Flapjack.logger.error "Failed to send SMS via Twilio, response status is #{status}, " + + "alert id: #{alert.id}" end rescue => e - @logger.error "Error generating or delivering sms to #{alert.address}: #{e.class}: #{e.message}" - @logger.error e.backtrace.join("\n") + Flapjack.logger.error "Error generating or delivering twilio sms to #{alert.medium.address}: #{e.class}: #{e.message}" + Flapjack.logger.error e.backtrace.join("\n") raise end end end