voicemail 0.2.0 → 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/README.md +57 -2
  4. data/lib/voicemail.rb +15 -8
  5. data/lib/voicemail/{application_controller.rb → call_controllers/application_controller.rb} +14 -1
  6. data/lib/voicemail/call_controllers/authentication_controller.rb +60 -0
  7. data/lib/voicemail/call_controllers/mailbox_controller.rb +46 -0
  8. data/lib/voicemail/{mailbox_main_menu_controller.rb → call_controllers/mailbox_main_menu_controller.rb} +9 -4
  9. data/lib/voicemail/call_controllers/mailbox_messages_controller.rb +48 -0
  10. data/lib/voicemail/{mailbox_play_message_controller.rb → call_controllers/mailbox_play_message_controller.rb} +26 -10
  11. data/lib/voicemail/call_controllers/mailbox_play_message_intro_controller.rb +72 -0
  12. data/lib/voicemail/{mailbox_set_greeting_controller.rb → call_controllers/mailbox_set_greeting_controller.rb} +2 -2
  13. data/lib/voicemail/{mailbox_set_pin_controller.rb → call_controllers/mailbox_set_pin_controller.rb} +0 -0
  14. data/lib/voicemail/call_controllers/voicemail_controller.rb +57 -0
  15. data/lib/voicemail/localization_loader.rb +28 -0
  16. data/lib/voicemail/matcher.rb +14 -0
  17. data/lib/voicemail/plugin.rb +40 -15
  18. data/lib/voicemail/storage_pstore.rb +49 -2
  19. data/lib/voicemail/version.rb +1 -1
  20. data/spec/voicemail/call_controllers/application_controller_spec.rb +31 -0
  21. data/spec/voicemail/call_controllers/authentication_controller_spec.rb +59 -0
  22. data/spec/voicemail/call_controllers/mailbox_controller_spec.rb +107 -0
  23. data/spec/voicemail/{mailbox_main_menu_controller_spec.rb → call_controllers/mailbox_main_menu_controller_spec.rb} +9 -2
  24. data/spec/voicemail/call_controllers/mailbox_messages_controller_spec.rb +110 -0
  25. data/spec/voicemail/call_controllers/mailbox_play_message_controller_spec.rb +97 -0
  26. data/spec/voicemail/call_controllers/mailbox_play_message_intro_controller_spec.rb +81 -0
  27. data/spec/voicemail/{mailbox_set_greeting_controller_spec.rb → call_controllers/mailbox_set_greeting_controller_spec.rb} +24 -6
  28. data/spec/voicemail/{mailbox_set_pin_controller_spec.rb → call_controllers/mailbox_set_pin_controller_spec.rb} +0 -0
  29. data/spec/voicemail/call_controllers/voicemail_controller_spec.rb +97 -0
  30. data/spec/voicemail/localization_loader_spec.rb +21 -0
  31. data/spec/voicemail/storage_pstore_spec.rb +64 -2
  32. data/templates/en.yml +67 -0
  33. data/voicemail.gemspec +2 -2
  34. metadata +42 -26
  35. data/lib/voicemail/mailbox_controller.rb +0 -56
  36. data/lib/voicemail/mailbox_messages_controller.rb +0 -55
  37. data/lib/voicemail/voicemail_controller.rb +0 -33
  38. data/spec/voicemail/mailbox_controller_spec.rb +0 -79
  39. data/spec/voicemail/mailbox_messages_controller_spec.rb +0 -71
  40. data/spec/voicemail/mailbox_play_message_controller_spec.rb +0 -70
  41. data/spec/voicemail/voicemail_controller_spec.rb +0 -76
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ece901d2e7597ad7c46d21892c1c18860366229
4
- data.tar.gz: 5179e5142890487aafe759b21d459212f90e8170
3
+ metadata.gz: fb2e43cb58958f29572591333898ac974619e7b9
4
+ data.tar.gz: db211cf3e65e54e4863d08d098a64229183630c6
5
5
  SHA512:
6
- metadata.gz: f741bdf352fb6c34412461e81a1ce85810d01d2ad680248e41d54c3d2dc033dd817edcc0d025a50147b7115c85a9220d77ea46e5171b3e5bf1a6180e84f18d3a
7
- data.tar.gz: bbc20bd448644acb1b896835f09f28254f5730d3d1a8579207c981bd83b4cff4ca49120987c079ec7f729e0b415350776ef1f36a6815d0ceda6be4686ebec692
6
+ metadata.gz: f2167ad8cf793941cb4abfde3a9daaab8d0bbdf84a5da10993980d6cd2e11e2d49d6edb87e7979bb4ccef275834cdce12cac193e3d8264f61156a12bfdf4f42b
7
+ data.tar.gz: 4020fc20353a8ce76e16e911272113876bd21e3570bd4b036c80ce85bacff270ba9610083cdedc51f7eed800e6070b4c5f7dc172290b83b13e078659f333349d
@@ -0,0 +1,44 @@
1
+ #v1.0.0..
2
+ * FEATURE - Optional per-mailbox override of default recording hash
3
+ * FEATURE - Optional rerecording of voicemail messages
4
+ * FEATURE - I18n numeric methods
5
+ * FEATURE - I18n support for keys
6
+ * FEATURE - Seperate pin_checking into seperate matcher class, so that it can be overriden if desired
7
+ * FEATURE - Allow `pin_tries` to be set to 0 for infinite loop
8
+ * FEATURE - Pass the complete recording complete object to `#save_recording`, giving the storage more information; `PStore` only uses the uri, but now you have access to more information (such as duration) if desired for your own storage adapter
9
+ * FEATURE - Seperate weclome/authentication from `MailboxController`, for those that wish to use their own.
10
+ * FEATURE - Add saved count to `MailboxController`
11
+ * FEATURE - Allow overriding `MailboxMainMenuController` with your own custom menu class
12
+ * FEATURE - Ability to listen to new OR saved messages, and archive/unarchive at will.
13
+ * FEATURE - Improved passing of a storage mechanism between controllers
14
+ * FEATURE - Customizable method for using TTS/ahn_say for things like "You have #{x} new messages"
15
+ * CS - Rename config option for when to answer
16
+ * CS - DRY up duplicated `#mailbox_not_found` method
17
+ * CS - Move all the call controllers to their own call_controller directory, to avoid clutter
18
+ * CS - Remove unused `#section_menu` in `MailboxMessagesController`
19
+ * CS - Remove specs for `#main_menu` in `AuthenticationController` since that controller never calls it
20
+ * BUGFIX - Calls passed to `VoicemailController` were never formally hungup
21
+ * BUGFIX - Don't strip extensions or `file://'` - punchblock will do that if needed
22
+ * BUGFIX - Apply datetime formatting to ahnsaid dates
23
+ * DOC - Add Justin Aiken to authors
24
+
25
+ # v0.2.0 - 2012-08-30
26
+ ## Require adhearsion 2.4 or higher
27
+ * FEATURE - Put more `#record` options into the config instead of hardcoded
28
+ * FEATURE - Freeswitch support
29
+ * FEATURE - Add MIT license to gemspec
30
+ * FEATURE - Add optional location setting for `#answer`
31
+ * CS - Refactoring
32
+
33
+
34
+ # v0.1.0 - 2013-08-28
35
+ * BUGFIX - typo in `#load_message`
36
+ * BUGFIX - `#load_message` not actually called
37
+ * BUGFIX - Pass mailbox id to `MailboxPlayMessageController`
38
+ * BUGFIX - Remove calls to nonexistant `#message_loop`
39
+ * FEATURE - Allow passing in storage adapter
40
+ * FEATURE - Only record one end of voicemail - save 50% of storage costs!
41
+ * FEATURE - TravisCI status added to README
42
+
43
+ # v0.0.1
44
+ * First release!
data/README.md CHANGED
@@ -20,6 +20,12 @@ To allow access by users to the mailboxes, `invoke MailboxController`. You will
20
20
  invoke Voicemail::MailboxController, mailbox: mailbox_id
21
21
  ```
22
22
 
23
+ If you want the users to go through pin-based authentication first, pass to the `AuthenticationController` instead:
24
+ ```ruby
25
+ # inside a CallController method
26
+ invoke Voicemail::AuthenticationController, mailbox: mailbox_id
27
+ ```
28
+
23
29
  ## Storage
24
30
 
25
31
  Mailbox metadata is stored in a PStore hash on disk for easy drop-in functionality.
@@ -39,9 +45,58 @@ Alternatively, you can pass in a storage layer dynamically when invoking the con
39
45
  # etc.
40
46
  ```
41
47
 
42
- ## Author
48
+ ## Method Overrides
49
+
50
+ If you prefer to use your own main menu instead of the [one provided](https://github.com/adhearsion/voicemail/blob/develop/lib/voicemail/call_controllers/mailbox_main_menu_controller.rb#L10-L13), you can set the class to use like so:
51
+ ```ruby
52
+ config.voicemail.main_menu_class = MyMenuController
53
+ ```
54
+
55
+ Another override provided is the [pin matcher](https://github.com/adhearsion/voicemail/blob/develop/lib/voicemail/call_controllers/authentication_controller.rb#L43-L45) used to verify authentication - if you want to use your own match-checker (to check against an API or some use), you can also override it:
56
+ ```ruby
57
+ config.voicemail.matcher_class = MyMatcher
58
+ ```
59
+
60
+ ## Numeric Methods
61
+
62
+ When you have something like `You have -x- new messages` or `message received on -x-` you can either use the default setting, which will fill the x with TTS, or to use [ahnsay](https://www.github.com/polysics/ahnsay) to use audio files for each digit.
63
+ ```ruby
64
+ config.voicemail.numeric_method = :play_numeric #default
65
+ "You have two new messages"
66
+
67
+ config.voicemail.numeric_method = :ahn_say
68
+ "You have" + "file://...two.ul" + "new messages"
69
+ ```
70
+
71
+ ## Internationalization
72
+
73
+ This plugin also provides support for internationalization:
74
+
75
+ ```ruby
76
+ # Enable I18n support in the plugin
77
+ config.voicemail.use_i18n = true
78
+
79
+ # Tell your application where your local files are, and set a default
80
+ I18n.load_path += Dir[File.join(config.platform.root, 'config', 'locales', '*.{rb,yml}').to_s]
81
+ I18n.default_locale = :en
82
+ ```
83
+
84
+ Either run `rake voicemail:i18n_init` to copy a starting `en.yml` file from the plugin into your application (default location is `#{ahn_root}/config/locales/en.yml`), or [look at the template](https://github.com/adhearsion/voicemail/blob/develop/templates/en.yml) to get an idea of what translation keys to add to your app's existing localization files.
85
+
86
+ You can also use I18n to handle the numeric methods:
87
+
88
+ ```ruby
89
+ config.voicemail.numeric_method = :i18n_string
90
+ "You have two new messages"
91
+ "You have one new message"
92
+ ```
93
+
94
+ Using I18n for the numeric method will nicely handle pluralizing message counts and formating the datetime messages were received on.
95
+
96
+ ## Authors
43
97
 
44
- Original author: [Luca Pradovera](https://github.com/polysics)
98
+ * Original author: [Luca Pradovera](https://github.com/polysics)
99
+ * Also contributed: [Justin Aiken](https://github.com/JustinAiken)
45
100
 
46
101
  ## Links
47
102
 
@@ -1,14 +1,21 @@
1
+ require 'adhearsion'
2
+
1
3
  module Voicemail; end
2
4
  require "voicemail/version"
3
5
  require "voicemail/storage_pstore"
4
6
  require "voicemail/storage"
5
- require "voicemail/application_controller"
6
- require "voicemail/voicemail_controller"
7
- require "voicemail/mailbox_controller"
8
- require "voicemail/mailbox_main_menu_controller"
9
- require "voicemail/mailbox_messages_controller"
10
- require "voicemail/mailbox_play_message_controller"
11
- require "voicemail/mailbox_set_greeting_controller"
12
- require "voicemail/mailbox_set_pin_controller"
7
+ require "voicemail/matcher"
8
+ require "voicemail/localization_loader"
9
+ require "voicemail/call_controllers/application_controller"
10
+ require "voicemail/call_controllers/voicemail_controller"
11
+ require "voicemail/call_controllers/mailbox_controller"
12
+ require "voicemail/call_controllers/authentication_controller"
13
+ require "voicemail/call_controllers/mailbox_main_menu_controller"
14
+ require "voicemail/call_controllers/mailbox_messages_controller"
15
+ require "voicemail/call_controllers/mailbox_play_message_intro_controller"
16
+ require "voicemail/call_controllers/mailbox_play_message_controller"
17
+ require "voicemail/call_controllers/mailbox_set_greeting_controller"
18
+ require "voicemail/call_controllers/mailbox_set_pin_controller"
19
+
13
20
 
14
21
  require "voicemail/plugin"
@@ -1,7 +1,7 @@
1
1
  module Voicemail
2
2
  class ApplicationController < ::Adhearsion::CallController
3
3
  def main_menu
4
- pass MailboxMainMenuController, mailbox: mailbox[:id]
4
+ pass config.main_menu_class, mailbox: mailbox[:id], storage: storage
5
5
  end
6
6
 
7
7
  private
@@ -23,5 +23,18 @@ module Voicemail
23
23
  raise ArgumentError, "Voicemail needs a mailbox specified in metadata" unless mailbox_id
24
24
  storage.get_mailbox mailbox_id
25
25
  end
26
+
27
+ def record_options
28
+ if config.use_mailbox_opts_for_recording
29
+ config.recording.to_hash.merge mailbox[:record_options]
30
+ else
31
+ config.recording.to_hash
32
+ end
33
+ end
34
+
35
+ def mailbox_not_found
36
+ play config.mailbox_not_found
37
+ hangup
38
+ end
26
39
  end
27
40
  end
@@ -0,0 +1,60 @@
1
+ module Voicemail
2
+ class AuthenticationController < ApplicationController
3
+
4
+ attr_accessor :tries, :auth_ok, :input
5
+
6
+ def initialize(call, metadata={})
7
+ @tries = 0
8
+ @auth_ok = false
9
+
10
+ super call, metadata
11
+ end
12
+
13
+ def run
14
+ if mailbox
15
+ play_greeting
16
+ authenticate
17
+ fail_auth unless auth_ok
18
+ pass MailboxController, mailbox: mailbox[:id]
19
+ else
20
+ mailbox_not_found
21
+ end
22
+ end
23
+
24
+ def authenticate
25
+ while still_going?
26
+ @tries += 1
27
+ get_input
28
+ if matches?
29
+ @auth_ok = true
30
+ else
31
+ play config.mailbox.pin_wrong
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def still_going?
39
+ return false if auth_ok
40
+ config.mailbox.pin_tries == 0 || tries < config.mailbox.pin_tries
41
+ end
42
+
43
+ def matches?
44
+ config.matcher_class.new(input, mailbox[:pin]).matches?
45
+ end
46
+
47
+ def get_input
48
+ @input = ask config.mailbox.please_enter_pin, terminator: "#", timeout: config.prompt_timeout
49
+ end
50
+
51
+ def play_greeting
52
+ play config.mailbox.greeting_message
53
+ end
54
+
55
+ def fail_auth
56
+ play config.mailbox.could_not_auth
57
+ hangup
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,46 @@
1
+ module Voicemail
2
+ class MailboxController < ApplicationController
3
+
4
+ attr_accessor :new_or_saved
5
+
6
+ def run
7
+ if mailbox
8
+ play_number_of_messages :new
9
+ play_number_of_messages :saved
10
+ main_menu
11
+ else
12
+ mailbox_not_found
13
+ end
14
+ end
15
+
16
+ def play_number_of_messages(new_or_saved)
17
+ @new_or_saved = new_or_saved
18
+ get_count
19
+
20
+ if @number > 0
21
+ play_message_count
22
+ else
23
+ play config.messages["no_#{new_or_saved}_messages".to_sym]
24
+ end
25
+ end
26
+
27
+ def play_message_count
28
+ case config.numeric_method
29
+ when :i18n_string
30
+ play I18n.t("voicemail.mailbox.x_#{new_or_saved}_messages", count: @number)
31
+ when :play_numeric
32
+ play config.mailbox.number_before
33
+ play_numeric @number
34
+ play config.mailbox["number_after_#{new_or_saved}".to_sym]
35
+ when :ahn_say
36
+ play config.mailbox.number_before
37
+ play *sounds_for_number(@number)
38
+ play config.mailbox["number_after_#{new_or_saved}".to_sym]
39
+ end
40
+ end
41
+
42
+ def get_count
43
+ @number = storage.send "count_#{new_or_saved}_messages", mailbox[:id]
44
+ end
45
+ end
46
+ end
@@ -7,9 +7,10 @@ module Voicemail
7
7
  def main_menu
8
8
  menu config.mailbox.menu_greeting,
9
9
  timeout: config.menu_timeout, tries: config.menu_tries do
10
- match(1) { listen_to_messages }
11
- match(2) { set_greeting }
12
- match(3) { set_pin }
10
+ match(1) { listen_to_new_messages }
11
+ match(2) { listen_to_saved_messages }
12
+ match(3) { set_greeting }
13
+ match(4) { set_pin }
13
14
 
14
15
  timeout do
15
16
  play config.mailbox.menu_timeout_message
@@ -34,8 +35,12 @@ module Voicemail
34
35
  invoke MailboxSetPinController, mailbox: mailbox[:id]
35
36
  end
36
37
 
37
- def listen_to_messages
38
+ def listen_to_new_messages
38
39
  invoke MailboxMessagesController, mailbox: mailbox[:id]
39
40
  end
41
+
42
+ def listen_to_saved_messages
43
+ invoke MailboxMessagesController, mailbox: mailbox[:id], new_or_saved: :saved
44
+ end
40
45
  end
41
46
  end
@@ -0,0 +1,48 @@
1
+ module Voicemail
2
+ class MailboxMessagesController < ApplicationController
3
+
4
+ attr_accessor :new_or_saved
5
+
6
+ def initialize(call, metadata={})
7
+ @new_or_saved = metadata[:new_or_saved] || :new
8
+
9
+ super call, metadata
10
+ end
11
+
12
+ def run
13
+ message_loop
14
+ end
15
+
16
+ def message_loop
17
+ if messages_remaining > 0
18
+ next_message
19
+ else
20
+ bail_out
21
+ end
22
+ end
23
+
24
+ def next_message
25
+ handle_message current_message
26
+ message_loop
27
+ end
28
+
29
+ def handle_message(message)
30
+ invoke MailboxPlayMessageController, message: message, mailbox: mailbox[:id], new_or_saved: new_or_saved, storage: storage
31
+ end
32
+
33
+ private
34
+
35
+ def messages_remaining
36
+ storage.send "count_#{new_or_saved}_messages", mailbox[:id]
37
+ end
38
+
39
+ def current_message
40
+ storage.send "next_#{new_or_saved}_message", mailbox[:id]
41
+ end
42
+
43
+ def bail_out
44
+ play config.messages["no_#{new_or_saved}_messages"]
45
+ main_menu
46
+ end
47
+ end
48
+ end
@@ -1,6 +1,14 @@
1
1
  module Voicemail
2
2
  class MailboxPlayMessageController < ApplicationController
3
3
 
4
+ attr_accessor :new_or_saved
5
+
6
+ def initialize(call, metadata={})
7
+ @new_or_saved = metadata[:new_or_saved] || :new
8
+
9
+ super call, metadata
10
+ end
11
+
4
12
  def run
5
13
  load_message
6
14
  intro_message
@@ -8,9 +16,9 @@ module Voicemail
8
16
  end
9
17
 
10
18
  def play_message
11
- menu message_uri, config.messages.menu, timeout: config.menu_timeout, tries: config.menu_tries do
19
+ menu message_uri, play_message_menu, timeout: config.menu_timeout, tries: config.menu_tries do
12
20
  match 1 do
13
- archive_message
21
+ archive_or_unarchive_message
14
22
  end
15
23
 
16
24
  match 5 do
@@ -36,19 +44,27 @@ module Voicemail
36
44
  end
37
45
 
38
46
  def intro_message
39
- play config.messages.message_received_on
40
- play_time current_message[:received], format: config.datetime_format
41
- play config.messages.from
42
- from_digits = current_message[:from].scan(/\d/).join
43
- say_characters from_digits unless from_digits.empty?
47
+ invoke MailboxPlayMessageIntroController, message: current_message, mailbox: mailbox[:id], storage: storage
48
+ end
49
+
50
+ def play_message_menu
51
+ if new_or_saved == :new
52
+ config.messages.menu_new
53
+ else
54
+ config.messages.menu_saved
55
+ end
44
56
  end
45
57
 
46
58
  def rewind_message
47
59
  play_message
48
60
  end
49
61
 
50
- def archive_message
51
- storage.archive_message mailbox[:id], current_message[:id]
62
+ def archive_or_unarchive_message
63
+ if new_or_saved == :new
64
+ storage.archive_message mailbox[:id], current_message[:id]
65
+ else
66
+ storage.unarchive_message mailbox[:id], current_message[:id]
67
+ end
52
68
  end
53
69
 
54
70
  def delete_message
@@ -65,7 +81,7 @@ module Voicemail
65
81
  end
66
82
 
67
83
  def message_uri
68
- current_message[:uri].gsub(/\.wav/, '')
84
+ current_message[:uri]
69
85
  end
70
86
  end
71
87
  end
@@ -0,0 +1,72 @@
1
+ module Voicemail
2
+ class MailboxPlayMessageIntroController < ApplicationController
3
+
4
+ def run
5
+ load_message
6
+ intro_message
7
+ end
8
+
9
+ def intro_message
10
+ play_time_message
11
+ play_from_message
12
+ end
13
+
14
+ def play_time_message
15
+ case config.numeric_method
16
+ when :i18n_string
17
+ play I18n.t("voicemail.messages.message_received_on_x", received_on: I18n.localize(current_message[:received]))
18
+ when :play_numeric
19
+ play config.messages.message_received_on
20
+ play_time current_message[:received], format: config.datetime_format
21
+ when :ahn_say
22
+ play config.messages.message_received_on
23
+ play *sounds_for_time(current_message[:received], format: config.datetime_format)
24
+ end
25
+ end
26
+
27
+ def play_from_message
28
+ case config.numeric_method
29
+ when :i18n_string
30
+ play I18n.t("voicemail.messages.message_received_from_x", from: from_string)
31
+ when :play_numeric
32
+ play config.messages.from
33
+ say_characters from_digits unless from_digits.empty?
34
+ when :ahn_say
35
+ play config.messages.from
36
+ play *sounds_for_digits(from_digits)
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def from_digits
43
+ current_message[:from].scan(/\d/).join
44
+ end
45
+
46
+ def from_string
47
+ "".tap do |string|
48
+ from_digits.each_char do |char|
49
+ digit_word = I18n.t "numbers.#{char}"
50
+ if digit_word =~ /missing/
51
+ string << char
52
+ else
53
+ string << digit_word
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ def current_message
60
+ @message
61
+ end
62
+
63
+ def load_message
64
+ @message = metadata[:message] || nil
65
+ raise ArgumentError, "MailboxPlayMessageIntroController needs a valid message passed to it" unless @message
66
+ end
67
+
68
+ def message_uri
69
+ current_message[:uri]
70
+ end
71
+ end
72
+ end