Skip to content

Instantly share code, notes, and snippets.

@akinsgre
Created January 22, 2015 13:20
Show Gist options
  • Select an option

  • Save akinsgre/94c2d22b64d801d8bd96 to your computer and use it in GitHub Desktop.

Select an option

Save akinsgre/94c2d22b64d801d8bd96 to your computer and use it in GitHub Desktop.

Revisions

  1. akinsgre created this gist Jan 22, 2015.
    117 changes: 117 additions & 0 deletions contact.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,117 @@
    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
    #
    37 changes: 37 additions & 0 deletions email.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    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
    #
    61 changes: 61 additions & 0 deletions messages_controller.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,61 @@
    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
    69 changes: 69 additions & 0 deletions phone.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,69 @@
    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
    #