Skip to content

Commit

Permalink
almost there with a real conversational scheduling with wit.ai
Browse files Browse the repository at this point in the history
  • Loading branch information
cromulus committed May 26, 2016
1 parent 369c5f4 commit d8e7c20
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 54 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ GEM
will_paginate (3.1.0)
will_paginate-bootstrap (0.2.5)
will_paginate (>= 3.0.3)
wit (3.3.1)
wit (3.4.0)
wuparty (1.2.6)
httparty (>= 0.6.1)
mime-types (~> 1.16)
Expand Down
4 changes: 3 additions & 1 deletion Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ Vagrant.configure(2) do |config|
nginx-full \
openjdk-7-jre \
phantomjs \
elasticsearch
elasticsearch\
redis-server
mysqladmin -u root -ppassword password '';
sudo update-rc.d elasticsearch defaults;
Expand Down
13 changes: 6 additions & 7 deletions app/controllers/v2/event_invitations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,27 @@ def create_event(event_invitation)
end

def send_notifications(event_invitation)
event = event_invitation.event
event_invitation.invitees.each do |invitee|
case invitee.preferred_contact_method.upcase
when 'SMS'
send_sms(invitee, event)
send_sms(invitee, event_invitation)
when 'EMAIL'
send_email(invitee, event)
send_email(invitee, event_invitation)
end
end
end

def send_email(person, event)
def send_email(person, event_invitation)
EventInvitationMailer.invite(
email_address: person.email_address,
event: event,
event: event_invitation,
person: person
).deliver_later
end

def send_sms(person, event)
def send_sms(person, event_invitation)
# we send a bunch at once, delay it. Plus this has extra logic
Delayed::Job.enqueue SendEventInvitationsSmsJob.new(person, event)
Delayed::Job.enqueue(SendEventInvitationsSmsJob.new(person, event_invitation))
end

# TODO: add a nested :event
Expand Down
17 changes: 6 additions & 11 deletions app/controllers/v2/sms_reservations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ def create
if remove?
# do the remove people thing.
person.deactivate!
elsif declined? # currently not used.
#send_decline_notifications(person, event)
::RemoveSms.new(to: person).send
elsif confirm? # confirmation for the days reservations
if person.v2_reservations.for_today_and_tomorrow.size > 0
person.v2_reservations.for_today_and_tomorrow.each(&:confirm!)
Expand All @@ -43,9 +42,11 @@ def create
# we don't know what event_id we're talking about here
send_error_notification && return if str_context.nil?
context = JSON.parse(str_context)
new_context = ::WitClient.run_actions "#{person.id}_#{context['event_id']}", message, context
Redis.current.set("wit_context:#{person.id}", new_context.to_json)
Redis.current.expire("wit_context:#{person.id}", 3600)
puts "in sms_reservation_controller"
pp context
puts message
puts "!!!!!!!!!!!!!!!!!!!!!!!"
::WitClient.run_actions "#{person.id}_#{context['event_id']}", message, context
end
render text: 'OK'
end
Expand Down Expand Up @@ -90,12 +91,6 @@ def resend_available_slots(person, event)
::TimeSlotNotAvailableSms.new(to: person, event: event).send
end

def declined?
# this is no longer in use. still might be handt though...
# up to 10k events.
message.downcase =~ /^\d{1,5}-decline?/
end

def confirm?
message.downcase.include?('confirm')
end
Expand Down
15 changes: 9 additions & 6 deletions app/jobs/send_event_invitations_sms_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class SendEventInvitationsSmsJob < Struct.new(:to, :event)
def enqueue(job)
# job.delayed_reference_id =
# job.delayed_reference_type = ''
Rails.logger.info '[TwilioSender] job enqueued'
Rails.logger.info '[SendEventInvitationsSms] job enqueued'
job.save!
end

Expand All @@ -30,11 +30,14 @@ def perform

# context = Redis.current.get("wit_context:#{to.id}")
# if context.nil? && !time_requeue? # no context, free to send
# context is symbols here, but will be string keys after json.
context = { person_id: to.id, event_id: event.id, state: 'yes_no' }.to_json
Redis.current.set("wit_context:#{to.id}", context)
Redis.current.expire("wit_context:#{to.id}", 7200) # two hours
EventInvitationSms.new(to: to, event: event).send
# context is symbols here, but will be string keys after json.
context = { person_id: to.id,
event_id: event.id,
'reference_time' => event.start_datetime,
'reference_time_slot' => event.bot_duration }.to_json
Redis.current.set("wit_context:#{to.id}", context)
Redis.current.expire("wit_context:#{to.id}", 7200) # two hours
EventInvitationSms.new(to: to, event: event).send
# elsif time_requeue?
# Delayed::Job.enqueue(SendEventInvitationsSmsJob.new(to, event), run_at: run_in_business_hours)
# else # we have a context, wait till we time out.
Expand Down
10 changes: 5 additions & 5 deletions app/models/concerns/calendarable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@ def end_datetime
end

def to_time_and_weekday
"#{start_datetime.strftime('%l:%M %p')} - #{end_datetime.strftime('%l:%M %p')} #{start_datetime.strftime('%A %d')}"
"#{start_datetime.strftime('%l:%M %p').lstrip} - #{end_datetime.strftime('%l:%M %p').lstrip} #{start_datetime.strftime('%a %d')}"
end

def to_weekday_and_time
"#{start_datetime.strftime('%l:%M %p')} #{start_datetime.strftime('%l:%M %p')} - #{end_datetime.strftime('%H:%M')}"
"#{start_datetime.strftime('%a %d')} #{start_datetime.strftime('%l:%M %p').lstrip} - #{end_datetime.strftime('%l:%M %p').lstrip}"
end

def start_datetime_human
"#{start_datetime.strftime('%l:%M%p, %a %b')} #{start_datetime.strftime('%d').to_i.ordinalize}"
"#{start_datetime.strftime('%l:%M%p, %a %b').lstrip} #{start_datetime.strftime('%d').to_i.ordinalize}"
end

def slot_time_human
"#{start_datetime.strftime('%l:%M%p')}-#{end_datetime.strftime('%l:%M%p, %a %b')} #{start_datetime.strftime('%d').to_i.ordinalize}"
"#{start_datetime.strftime('%l:%M%p').lstrip}-#{end_datetime.strftime('%l:%M%p, %a %b').lstrip} #{start_datetime.strftime('%d').to_i.ordinalize}"
end

def bot_duration
"#{start_datetime.strftime('%A')} from #{start_datetime.strftime('%l:%M%p')} to #{end_datetime.strftime('%l:%M%p')}"
"from #{start_datetime.strftime('%l:%M%p').lstrip} to #{end_datetime.strftime('%l:%M%p').lstrip}"
end

private
Expand Down
2 changes: 1 addition & 1 deletion app/models/person.rb
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def deactivate(method = nil)
end

def update_neighborhood
n = Neighborhood.zip_to_neighborhood(postal_code)
n = zip_to_neighborhood(postal_code)
unless n.blank?
self.neighborhood = n
save
Expand Down
6 changes: 3 additions & 3 deletions app/sms/event_invitation_sms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ def initialize(to:, event:)
# TODO: Chunk this into 160 characters and send individualls
def body
body = "#{event.description}\n"
body << "If you're available for #{event.duration / 60} minutes"
body << ' during that time please'
body << " text back 'Yes'. If not, 'No'\n"
body << "If you're available for #{event.duration / 60} minutes at "
body << "#{event.slot_time_human} please"
body << " text back 'Yes'.\nIf not, 'No'\n"
body << "You can text 'remove me' to unsubscribe"
end
end
14 changes: 14 additions & 0 deletions app/sms/remove_sms.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# TODO: needs a spec. The spec for SmsReservationsController covers it,
# but a unit test would make coverage more robust
class RemoveSms < ApplicationSms
attr_reader :to

def initialize(to:)
super
@to = to # only really people here.
end

def body
"You have been removed from this list. If you think this is in error, please contact #{ENV['MAIL_ADMIN']}"
end
end
Loading

0 comments on commit d8e7c20

Please sign in to comment.