Skip to content

Instantly share code, notes, and snippets.

@akinsgre
Created January 22, 2015 13:20
Show Gist options
  • Save akinsgre/94c2d22b64d801d8bd96 to your computer and use it in GitHub Desktop.
Save akinsgre/94c2d22b64d801d8bd96 to your computer and use it in GitHub Desktop.
class Contact < ActiveRecord::Base
has_many :groups, :through => :group_contacts
has_many :group_contacts
has_many :messages
belongs_to :user
validates_presence_of :entry
require_dependency 'phone'
require_dependency 'sms'
require_dependency 'email'
require_dependency 'fb_group'
#GAK 11/4/2011
# Email is a virtual attribute so it can be captured in a form_for but then assigned to the User to whom the contact belongs
# rather than being saved on the Contact record (which breaks for those contacts created by group_owners and not associated
# with a user account.. Got to think about this some.
def email
@email
end
def email=(email)
@email = email
end
def self.hide?(user,group)
false
end
def self.select_options(user, group)
Rails.logger.debug "##### User owns group (#{user.id} == #{group.user.id}) #{user == group.user}" unless user.nil?
descendants.reject { |d| d.hide?(user, group ) }.collect { |d| [d.identify,d.to_s] }
end
def to_s
"Contact => #{self.name}, #{self.entry}"
end
def self.determine_type(params)
contact = nil
contactType = params[:contact][:type]
normalized_entry = Phone.normalize_number(params[:contact][:entry], :default_country_number => '01')
contactExists = Contact.exists?(params[:id]) ||
( !normalized_entry.nil? && Contact.exists?(:normalized_entry => normalized_entry, :type => contactType) ) ||
Contact.exists?(:entry => params[:contact][:entry], :type => contactType)
if contactExists
Rails.logger.info "###### Contact Exists"
ActiveRecord::Base.transaction do
contact = Contact.find(params[:id]) unless params[:id].nil?
Rails.logger.info "###### Contact found by ID is #{contact.inspect}"
contact ||= Contact.find_by(:normalized_entry => normalized_entry, :type => contactType) unless normalized_entry.nil?
Rails.logger.info "###### Contact found by normalized_entry is #{contact.inspect}"
contact ||= Contact.find_by(:entry => params[:contact][:entry], :type => contactType) unless params[:contact][:entry].empty?
Rails.logger.info "###### Contact found by entry is #{contact.inspect}"
Rails.logger.info "###### Contact is #{contact.inspect}"
if contact.type != contactType
contact.type = contactType
contact.save
end
Rails.logger.info "###### After setting contact type Contact is #{contact.inspect}"
case contactType
when 'Phone'
contact = contact.becomes(Phone)
when 'Sms'
contact = contact.becomes(Sms)
when 'Email'
contact = contact.becomes(Email)
when 'FbGroup'
contact = contact.becomes(FbGroup)
else
raise "Not a supported type"
end
Rails.logger.info "###### After become Contact is #{contact.inspect}"
contact = Contact.find(contact.id)
unless contact.update_attributes(params[:contact].permit(:name, :user_id, :entry))
Rails.logger.error "##### Had to rollback transaction because #{contact.errors.full_messages}"
raise ActiveRecord::Rollback
end
Rails.logger.info "###### Completed contact modification #{contact.inspect}"
end
else
puts "##### The contact does not exist"
case contactType
when'Phone'
contact = Phone.new(params[:contact].permit(:name, :user_id, :entry, :type))
when 'Sms'
contact = Sms.new(params[:contact].permit(:name, :user_id, :entry, :type))
when 'Email'
contact = Email.new(params[:contact].permit(:name, :user_id, :entry, :type))
when 'FbGroup'
contact = FbGroup.new(params[:contact].permit(:name, :user_id, :entry, :type))
else
raise "Not a supported type"
end
contact.save
end
Rails.logger.info "##### Returning contact #{contact.inspect}"
return contact
end
end
# == Schema Information
#
# Table name: contacts
#
# id :integer not null, primary key
# name :string(255)
# created_at :datetime
# updated_at :datetime
# user_id :integer
# type :string(255)
# entry :string(255)
# identifier :string(255)
# normalized_entry :text
#
class Email < Contact
include ActiveModel::Naming
validates :entry, :email => { :message => I18n.t('validations.errors.models.email.invalid_email')}
def self.identify
"Email"
end
def identify
"Email"
end
def self.long_description
"Valid email address"
end
def deliver(contact, message, advertisement, options = {})
MessageMailer.send_message(contact,message, advertisement).deliver
sent_message = advertisement.html_message
rescue => e
Rails.logger.error "####### There was a problem #{e.message} "
raise e
end
end
# == Schema Information
#
# Table name: contacts
#
# id :integer not null, primary key
# name :string(255)
# created_at :datetime
# updated_at :datetime
# user_id :integer
# type :string(255)
# entry :string(255)
# identifier :string(255)
# normalized_entry :text
#
require 'twilio-ruby'
class MessagesController < ApplicationController
include MessageHelper
def new
@message = Message.new
@group = Group.find(params[:group_id])
@message.group = @group
end
def deliver
@message = Message.new(params[:message].permit(:message, :group_id, :phone_message))
@contacts = Group.find(@message.group_id).contacts
@group = Group.find(@message.group_id)
if @contacts.size == 0
flash[:alert] = "The message was not sent because the group doesn't have any contacts."
redirect_to @group and return
end
render(:file => File.join(Rails.root, 'public/404'), :status => 404, :layout => false, content_type: "text/html" ) and return if @group.nil?
@account_sid = ENV['TW_SID']
@auth_token = ENV['TW_TOKEN']
Rails.logger.debug "##### Set up a client to talk to the Twilio REST API using Twilio gem with #{@account_sid} #{@auth_token}"
@client = Twilio::REST::Client.new(@account_sid, @auth_token)
@message.group = @group
if @group.exceed_messages?
flash[:alert] = "The message cannot be sent because you have already sent #{@group.membership_level.allowed_messages} this month. You must upgrade to a 'Premium' or 'Sponsored' level to be able to send additional messages."
redirect_to @group and return
end
if @message.save
Rails.logger.info "##### Sending #{@message.inspect} to each contact"
# Check membership, on Group model (ie., Group.messages_exceeded?) level before sending message
# abort if number of messages exceeds threshhold
errors = 0
# because localhost can't host the Twilio services
if Rails.env.development?
app_url = "http://nmc-demo.herokuapp.com"
else
app_url = "#{request.protocol + request.host_with_port}"
end
@contacts.each do |c|
advertisement = Sponsor.getAd
sent_message = c.deliver(c, @message, advertisement, {:client => @client, :group => @group, :app_url => app_url})
record_message(sent_message, @group, c, advertisement ) unless c.type == "FbGroup"
end
flash.now[:notice] = "Message sent successfully to #{@contacts.size - errors } contacts."
render "groups/show", id: @group.id
end
rescue => e
Rails.logger.warn "##### There was a problem sending this message. #{e.message}"
flash.now[:alert] = "There was a problem sending this message. #{e.message}"
render "groups/show", id: @group.id
end
end
class Phone < Contact
include ActiveModel::Naming
phony_normalize :entry, as: :normalized_entry, :default_country_code => 'US'
validates_plausible_phone :entry, :normalized_country_code => 'US', :message => I18n.t('validations.errors.models.phone.invalid_number')
def self.identify
"Phone"
end
def identify
"Phone"
end
def self.long_description
"Phone number (10 digit)"
end
def self.normalize_number(number, options = {})
return if number.nil?
number = number.clone # Just to be sure, we don't want to change the original.
number.gsub!(/[^\d\+]/, '') # Strips weird stuff from the number
return if number.blank?
if default_country_number = options[:default_country_number]
# Add default_country_number if missing
number = "#{default_country_number}#{number}" if not number =~ /\A(00|\+|#{default_country_number})/
end
Phony.normalize(number)
rescue => e
number # If all goes wrong .. we still return the original input.
end
def deliver(contact, message, advertisement, options = {})
client = options[:client]
group = options[:group]
sponsor_msg = Rack::Utils.escape(advertisement.phone_message)
if message.phone_message.blank?
message = Rack::Utils.escape(message.message)
else
message = Rack::Utils.escape(message.phone_message)
end
sent_message = sponsor_msg
group_name = Rack::Utils.escape(group.name)
url = "#{options[:app_url]}/twiml/say.xml?secret=#{ ENV['NMC_API_KEY'] }&IfMachine=Continue&message=#{message}&sponsor_msg=#{sponsor_msg}&group=#{group_name}"
@call = client.account.calls.create( :from => group.twilio_number, :to => contact.entry, :url => url, :method => 'GET' )
rescue => e
Rails.logger.info "####### An error occurred #{e.message}"
end
end
# == Schema Information
#
# Table name: contacts
#
# id :integer not null, primary key
# name :string(255)
# created_at :datetime
# updated_at :datetime
# user_id :integer
# type :string(255)
# entry :string(255)
# identifier :string(255)
# normalized_entry :text
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment