summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/sip_accounts_controller.rb7
-rw-r--r--app/controllers/voicemail_accounts_controller.rb68
-rw-r--r--app/controllers/voicemail_settings_controller.rb85
-rw-r--r--app/helpers/voicemail_accounts_helper.rb2
-rw-r--r--app/models/sip_account.rb24
-rw-r--r--app/models/user.rb2
-rw-r--r--app/models/voicemail_account.rb20
-rw-r--r--app/models/voicemail_setting.rb52
-rw-r--r--app/views/sip_accounts/_form_core.html.haml1
-rw-r--r--app/views/sip_accounts/show.html.haml5
-rw-r--r--app/views/voicemail_accounts/_form.html.haml7
-rw-r--r--app/views/voicemail_accounts/_form_core.html.haml3
-rw-r--r--app/views/voicemail_accounts/_index_core.html.haml15
-rw-r--r--app/views/voicemail_accounts/edit.html.haml3
-rw-r--r--app/views/voicemail_accounts/index.html.haml6
-rw-r--r--app/views/voicemail_accounts/new.html.haml3
-rw-r--r--app/views/voicemail_accounts/show.html.haml19
-rw-r--r--app/views/voicemail_settings/_form.html.haml3
-rw-r--r--app/views/voicemail_settings/_form_core.html.haml17
-rw-r--r--app/views/voicemail_settings/_index_core.html.haml14
-rw-r--r--app/views/voicemail_settings/edit.html.haml2
-rw-r--r--app/views/voicemail_settings/index.html.haml6
-rw-r--r--app/views/voicemail_settings/new.html.haml3
-rw-r--r--app/views/voicemail_settings/show.html.haml33
-rw-r--r--config/locales/views/voicemail_accounts/de.yml65
-rw-r--r--config/locales/views/voicemail_accounts/en.yml65
-rw-r--r--config/locales/views/voicemail_settings/de.yml83
-rw-r--r--config/locales/views/voicemail_settings/en.yml91
-rw-r--r--config/routes.rb6
-rw-r--r--db/migrate/20130322081621_create_voicemail_accounts.rb17
-rw-r--r--db/migrate/20130322102533_add_voicemail_account_id_to_sip_accounts.rb5
-rw-r--r--db/migrate/20130326064557_create_voicemail_settings.rb16
-rw-r--r--misc/freeswitch/conf/freeswitch.xml136
-rw-r--r--misc/freeswitch/scripts/common/configuration_table.lua59
-rw-r--r--misc/freeswitch/scripts/dialplan/dialplan.lua16
-rw-r--r--misc/freeswitch/scripts/dialplan/functions.lua25
-rw-r--r--misc/freeswitch/scripts/dialplan/ivr.lua67
-rw-r--r--misc/freeswitch/scripts/dialplan/voicemail.lua378
-rw-r--r--misc/freeswitch/scripts/dialplan_default.lua7
-rw-r--r--test/unit/voicemail_account_test.rb7
40 files changed, 1133 insertions, 310 deletions
diff --git a/app/controllers/sip_accounts_controller.rb b/app/controllers/sip_accounts_controller.rb
index 0d34109..8208a29 100644
--- a/app/controllers/sip_accounts_controller.rb
+++ b/app/controllers/sip_accounts_controller.rb
@@ -36,6 +36,7 @@ class SipAccountsController < ApplicationController
break unless SipAccount.exists?(:auth_name => @sip_account.auth_name)
end
@sip_account.password = SecureRandom.hex(GsParameter.get('DEFAULT_LENGTH_SIP_PASSWORD'))
+ possible_voicemail_accounts
end
def create
@@ -61,6 +62,7 @@ class SipAccountsController < ApplicationController
end
def edit
+ possible_voicemail_accounts
end
def update
@@ -101,4 +103,9 @@ class SipAccountsController < ApplicationController
end
end
+ def possible_voicemail_accounts
+ @possible_voicemail_accounts = @sip_account.voicemail_accounts
+ @possible_voicemail_accounts = @possible_voicemail_accounts + @sip_account.sip_accountable.voicemail_accounts
+ end
+
end
diff --git a/app/controllers/voicemail_accounts_controller.rb b/app/controllers/voicemail_accounts_controller.rb
new file mode 100644
index 0000000..7e00131
--- /dev/null
+++ b/app/controllers/voicemail_accounts_controller.rb
@@ -0,0 +1,68 @@
+class VoicemailAccountsController < ApplicationController
+ load_resource :sip_account
+ load_resource :conference
+ load_resource :hunt_group
+ load_resource :automatic_call_distributor
+ load_resource :user
+ load_resource :tenant
+ load_resource :voicemail_account
+
+ load_and_authorize_resource :phone_number, :through => [:sip_account, :conference, :hunt_group, :automatic_call_distributor, :user, :tenant]
+
+ before_filter :set_and_authorize_parent
+
+ def index
+ @voicemail_accounts = @parent.voicemail_accounts
+ end
+
+ def show
+
+ end
+
+ def new
+ @voicemail_account = @parent.voicemail_accounts.build(:active => true)
+ if @parent.class == SipAccount && VoicemailAccount.where(:name => @parent.auth_name).count == 0
+ @voicemail_account.name = @parent.auth_name
+ else
+ @voicemail_account.name = SecureRandom.hex(GsParameter.get('DEFAULT_LENGTH_SIP_AUTH_NAME'))
+ end
+ end
+
+ def create
+ @voicemail_account = @parent.voicemail_accounts.new(params[:voicemail_account])
+ if @voicemail_account.save
+ m = method( :"#{@parent.class.name.underscore}_voicemail_accounts_url" )
+ redirect_to m.( @parent ), :notice => t('voicemail_accounts.controller.successfuly_created')
+ else
+ render :new
+ end
+ end
+
+ def edit
+ @voicemail_account = VoicemailAccount.find(params[:id])
+ end
+
+ def update
+ @voicemail_account = VoicemailAccount.find(params[:id])
+ if @voicemail_account.update_attributes(params[:voicemail_account])
+ m = method( :"#{@parent.class.name.underscore}_voicemail_accounts_url" )
+ redirect_to m.( @parent ), :notice => t('voicemail_accounts.controller.successfuly_updated')
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @voicemail_account = VoicemailAccount.find(params[:id])
+ @voicemail_account.destroy
+ m = method( :"#{@parent.class.name.underscore}_voicemail_accounts_url" )
+ redirect_to m.( @parent ), :notice => t('voicemail_accounts.controller.successfuly_destroyed')
+ end
+
+ private
+ def set_and_authorize_parent
+ @parent = @sip_account || @conference || @hunt_group || @automatic_call_distributor || @user || @tenant
+
+ authorize! :read, @parent
+ end
+end
diff --git a/app/controllers/voicemail_settings_controller.rb b/app/controllers/voicemail_settings_controller.rb
index 5de0c35..ee8e36b 100644
--- a/app/controllers/voicemail_settings_controller.rb
+++ b/app/controllers/voicemail_settings_controller.rb
@@ -1,92 +1,53 @@
class VoicemailSettingsController < ApplicationController
- load_resource :sip_account
- load_and_authorize_resource :voicemail_setting, :through => :sip_account, :singleton => true
-
- before_filter :set_and_authorize_parent
- before_filter :spread_breadcrumbs
- before_filter :voicemail_defaults, :only => [:index, :show, :new, :create, :edit]
+ load_and_authorize_resource :voicemail_account
+ load_and_authorize_resource :voicemail_setting, :through => [:voicemail_account]
def index
- render :edit
+ @voicemail_settings = @voicemail_account.voicemail_settings
end
def show
- render :edit
end
def new
- render :edit
end
def create
- @sip_account = SipAccount.where(:id => params[:sip_account_id]).first
- params[:voicemail_setting][:username] = @sip_account.auth_name
- params[:voicemail_setting][:domain] = @sip_account.sip_domain.try(:host)
- @voicemail_setting = VoicemailSetting.new(params[:voicemail_setting])
+ @voicemail_setting = @voicemail_account.voicemail_settings.build(params[:voicemail_setting])
+ @voicemail_setting.class_type = VoicemailSetting::VOICEMAIL_SETTINGS[@voicemail_setting.name]
if @voicemail_setting.save
- redirect_to sip_account_voicemail_settings_path(@sip_account), :notice => t('voicemail_settings.controller.successfuly_created')
+ m = method( :"#{@voicemail_account.voicemail_accountable.class.name.underscore}_voicemail_account_path" )
+ redirect_to m.( @voicemail_account.voicemail_accountable, @voicemail_account ), :notice => t('voicemail_settings.controller.successfuly_created')
else
- render :action => 'edit'
+ render :new
end
end
def edit
-
+ @voicemail_setting = @voicemail_account.voicemail_settings.find(params[:id])
+ @no_edit = {
+ :name => {
+ :input => VoicemailSetting::VOICEMAIL_SETTINGS[@voicemail_setting.name][:input],
+ :name => @voicemail_setting.name
+ },
+ :description => true
+ }
end
def update
+ @voicemail_setting = @voicemail_account.voicemail_settings.find(params[:id])
if @voicemail_setting.update_attributes(params[:voicemail_setting])
- redirect_to sip_account_voicemail_settings_path(@sip_account), :notice => t('voicemail_settings.controller.successfuly_updated')
+ m = method( :"#{@voicemail_account.voicemail_accountable.class.name.underscore}_voicemail_account_path" )
+ redirect_to m.( @voicemail_account.voicemail_accountable, @voicemail_account ), :notice => t('voicemail_settings.controller.successfuly_updated')
else
render :edit
end
end
def destroy
-
- end
-
- private
- def set_and_authorize_parent
- @parent = @sip_account
-
- authorize! :read, @parent
-
- @show_path_method = method( :"#{@parent.class.name.underscore}_voicemail_setting_path" )
- @index_path_method = method( :"#{@parent.class.name.underscore}_voicemail_settings_path" )
- @new_path_method = method( :"new_#{@parent.class.name.underscore}_voicemail_setting_path" )
- @edit_path_method = method( :"edit_#{@parent.class.name.underscore}_voicemail_setting_path" )
- end
-
- def spread_breadcrumbs
- if @parent.class == SipAccount
- if @sip_account.sip_accountable.class == User
- add_breadcrumb t("#{@sip_account.sip_accountable.class.name.underscore.pluralize}.index.page_title"), method( :"tenant_#{@sip_account.sip_accountable.class.name.underscore.pluralize}_path" ).(@sip_account.tenant)
- add_breadcrumb @sip_account.sip_accountable, method( :"tenant_#{@sip_account.sip_accountable.class.name.underscore}_path" ).(@sip_account.tenant, @sip_account.sip_accountable)
- end
- add_breadcrumb t("sip_accounts.index.page_title"), method( :"#{@sip_account.sip_accountable.class.name.underscore}_sip_accounts_path" ).(@sip_account.sip_accountable)
- add_breadcrumb @sip_account, method( :"#{@sip_account.sip_accountable.class.name.underscore}_sip_account_path" ).(@sip_account.sip_accountable, @sip_account)
- add_breadcrumb t("voicemail_settings.index.page_title"), sip_account_voicemail_settings_path(@sip_account)
- end
- end
-
- def voicemail_defaults
- storage_dir = GsParameter.where(:entity => 'voicemail', :section => 'parameters', :name => 'storage-dir').first.try(:value)
- path = "#{storage_dir}/#{@sip_account.sip_domain.host}/#{@sip_account.auth_name}/"
- @greeting_files = Dir.glob("#{path}*greeting*.wav").collect {|r| [ File.basename(r), File.expand_path(r) ] }
- @name_files = Dir.glob("#{path}*name*.wav").collect {|r| [ File.basename(r), File.expand_path(r) ] }
-
- if @voicemail_setting.blank? then
- @voicemail_setting = @sip_account.voicemail_setting
- end
-
- if @voicemail_setting.blank?
- @voicemail_setting = VoicemailSetting.new
- @voicemail_setting.notify = true
- @voicemail_setting.attachment = true
- @voicemail_setting.mark_read = true
- @voicemail_setting.purge = false
- end
+ @voicemail_setting = @voicemail_account.voicemail_settings.find(params[:id])
+ @voicemail_setting.destroy
+ m = method( :"#{@voicemail_account.voicemail_accountable.class.name.underscore}_voicemail_account_path" )
+ redirect_to m.( @voicemail_account.voicemail_accountable, @voicemail_account ), :notice => t('voicemail_settings.controller.successfuly_destroyed')
end
-
end
diff --git a/app/helpers/voicemail_accounts_helper.rb b/app/helpers/voicemail_accounts_helper.rb
new file mode 100644
index 0000000..5a75e18
--- /dev/null
+++ b/app/helpers/voicemail_accounts_helper.rb
@@ -0,0 +1,2 @@
+module VoicemailAccountsHelper
+end
diff --git a/app/models/sip_account.rb b/app/models/sip_account.rb
index 0c923be..77fe87a 100644
--- a/app/models/sip_account.rb
+++ b/app/models/sip_account.rb
@@ -6,7 +6,8 @@ class SipAccount < ActiveRecord::Base
attr_accessible :auth_name, :caller_name, :password, :voicemail_pin,
:tenant_id, :call_waiting, :clir, :clip_no_screening,
:clip, :description, :callforward_rules_act_per_sip_account,
- :hotdeskable, :gs_node_id, :language_code
+ :hotdeskable, :gs_node_id, :language_code, :voicemail_account_id
+
# Associations:
#
@@ -27,8 +28,6 @@ class SipAccount < ActiveRecord::Base
has_many :call_histories, :as => :call_historyable, :dependent => :destroy
- has_one :voicemail_setting, :class_name => "VoicemailSetting", :primary_key => 'auth_name', :foreign_key => 'username', :dependent => :destroy
-
belongs_to :gs_node
belongs_to :language, :foreign_key => 'language_code', :primary_key => 'code'
@@ -44,6 +43,9 @@ class SipAccount < ActiveRecord::Base
has_many :acd_agents, :as => :destination, :dependent => :destroy
has_many :switchboard_entries, :dependent => :destroy
+ has_many :voicemail_accounts, :as => :voicemail_accountable, :dependent => :destroy
+ belongs_to :voicemail_account
+
# Delegations:
#
delegate :host, :to => :sip_domain, :allow_nil => true
@@ -58,15 +60,11 @@ class SipAccount < ActiveRecord::Base
validate_sip_password :password
- validates_format_of :voicemail_pin, :with => /[0-9]+/,
- :allow_nil => true, :allow_blank => true
-
validates_uniqueness_of :auth_name, :scope => :sip_domain_id
# Before and after hooks:
#
before_save :save_value_of_to_s
- after_save :create_voicemail_setting, :if => :'voicemail_setting == nil'
before_validation :find_and_set_tenant_id
before_validation :set_sip_domain_id
before_validation :convert_umlauts_in_caller_name
@@ -279,18 +277,6 @@ class SipAccount < ActiveRecord::Base
end
end
- def create_voicemail_setting
- voicemail_setting = VoicemailSetting.new()
- voicemail_setting.username = self.auth_name
- voicemail_setting.domain = self.sip_domain.try(:host)
- voicemail_setting.password = self.voicemail_pin
- voicemail_setting.notify = true
- voicemail_setting.attachment = true
- voicemail_setting.mark_read = true
- voicemail_setting.purge = false
- voicemail_setting.save
- end
-
def create_default_group_memberships
default_groups = Hash.new()
templates = GsParameter.get('SipAccount', 'group', 'default')
diff --git a/app/models/user.rb b/app/models/user.rb
index b74fc06..81d1622 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -94,6 +94,8 @@ class User < ActiveRecord::Base
has_many :switchboards, :dependent => :destroy
+ has_many :voicemail_accounts, :as => :voicemail_accountable, :dependent => :destroy
+
# Avatar like photo
mount_uploader :image, ImageUploader
diff --git a/app/models/voicemail_account.rb b/app/models/voicemail_account.rb
new file mode 100644
index 0000000..02dc283
--- /dev/null
+++ b/app/models/voicemail_account.rb
@@ -0,0 +1,20 @@
+class VoicemailAccount < ActiveRecord::Base
+ attr_accessible :uuid, :name, :active, :gs_node_id, :voicemail_accountable_type, :voicemail_accountable_id
+
+ belongs_to :voicemail_accountable, :polymorphic => true
+ has_many :voicemail_settings
+
+ validates :name,
+ :presence => true,
+ :uniqueness => true
+
+ validates :voicemail_accountable_id,
+ :presence => true
+
+ validates :voicemail_accountable_type,
+ :presence => true
+
+ def to_s
+ "#{voicemail_accountable.to_s}: #{name}"
+ end
+end
diff --git a/app/models/voicemail_setting.rb b/app/models/voicemail_setting.rb
index a8bb304..4a9fbc9 100644
--- a/app/models/voicemail_setting.rb
+++ b/app/models/voicemail_setting.rb
@@ -1,12 +1,48 @@
-class VoicemailSetting < ActiveRecord::Base
- self.table_name = 'voicemail_prefs'
- self.primary_key = 'username'
+class VoicemailSetting < ActiveRecord::Base
+ CLASS_TYPES = ['String', 'Integer', 'Boolean']
+ VOICEMAIL_SETTINGS = {
+ 'password' => { :type => 'String', :characters => /[^0-9]/, :input => :password },
+ 'notify' => { :type => 'Boolean', :input => :boolean },
+ 'attachment' => { :type => 'Boolean', :input => :boolean },
+ 'mark_read' => { :type => 'Boolean', :input => :boolean },
+ 'purge' => { :type => 'Boolean', :input => :boolean },
+ 'record_length_max' => { :type => 'Integer', :input => :integer },
+ 'record_length_min' => { :type => 'Integer', :input => :integer },
+ 'records_max' => { :type => 'Integer', :input => :integer },
+ }
- attr_accessible :username, :domain, :name_path, :greeting_path, :password, :notify, :attachment, :mark_read, :purge, :sip_account
+ attr_accessible :voicemail_account_id, :name, :value, :class_type, :description
- has_one :sip_account, :foreign_key => 'auth_name'
+ belongs_to :voicemail_account
- validates_presence_of :username
- validates_presence_of :domain
- validates :username, :uniqueness => {:scope => :domain}
+ validates :name,
+ :presence => true,
+ :uniqueness => {:scope => :voicemail_account_id}
+
+ validates :class_type,
+ :presence => true,
+ :inclusion => { :in => CLASS_TYPES }
+
+ before_validation :set_class_type_and_value
+
+ def to_s
+ name
+ end
+
+ def set_class_type_and_value
+ seting_pref = VOICEMAIL_SETTINGS[self.name]
+ if seting_pref
+ self.class_type = seting_pref[:type]
+ case self.class_type
+ when 'String'
+ if seting_pref[:characters] && self.class_type == 'String'
+ self.value = self.value.to_s.gsub(seting_pref[:characters], '')
+ end
+ when 'Integer'
+ self.value = self.value.to_i
+ when 'Boolean'
+ self.value = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(self.value)
+ end
+ end
+ end
end
diff --git a/app/views/sip_accounts/_form_core.html.haml b/app/views/sip_accounts/_form_core.html.haml
index d7c65d0..2e4882e 100644
--- a/app/views/sip_accounts/_form_core.html.haml
+++ b/app/views/sip_accounts/_form_core.html.haml
@@ -14,3 +14,4 @@
= f.input :hotdeskable, :label => t('sip_accounts.form.hotdeskable.label'), :hint => conditional_hint('sip_accounts.form.hotdeskable.hint')
= f.input :clip_no_screening, :label => t('sip_accounts.form.clip_no_screening.label'), :hint => conditional_hint('sip_accounts.form.clip_no_screening.hint')
= f.input :language_code, :collection => Language.all.collect{|l| [l.to_s, l.code]}, :label => t('sip_accounts.form.language_code.label'), :hint => conditional_hint('sip_accounts.form.language_id.hint'), :include_blank => false
+ = f.input :voicemail_account_id, :collection => @possible_voicemail_accounts.collect{|l| [l.to_s, l.id]}, :label => t('sip_accounts.form.voicemail_account_id.label'), :hint => conditional_hint('voicemail_accounts.form.sip_account_id.hint'), :include_blank => true
diff --git a/app/views/sip_accounts/show.html.haml b/app/views/sip_accounts/show.html.haml
index e79907f..a7cd3ce 100644
--- a/app/views/sip_accounts/show.html.haml
+++ b/app/views/sip_accounts/show.html.haml
@@ -37,6 +37,11 @@
%strong= t('sip_accounts.show.hotdeskable') + ":"
%td
= @sip_account.hotdeskable == true ? t('simple_form.yes') : t('simple_form.no')
+ %tr
+ %td
+ %strong= t('sip_accounts.show.voicemail_account') + ":"
+ %td
+ = @sip_account.voicemail_account
- if @sip_account.registration.try(:network_ip) && @sip_account.registration.try(:network_port)
%tr
diff --git a/app/views/voicemail_accounts/_form.html.haml b/app/views/voicemail_accounts/_form.html.haml
new file mode 100644
index 0000000..1e5ffc0
--- /dev/null
+++ b/app/views/voicemail_accounts/_form.html.haml
@@ -0,0 +1,7 @@
+= simple_form_for([@parent, @voicemail_account]) do |f|
+ = f.error_notification
+
+ = render "form_core", :f => f
+
+ .form-actions
+ = f.button :submit, conditional_t('voicemail_accounts.form.submit')
diff --git a/app/views/voicemail_accounts/_form_core.html.haml b/app/views/voicemail_accounts/_form_core.html.haml
new file mode 100644
index 0000000..a13ae51
--- /dev/null
+++ b/app/views/voicemail_accounts/_form_core.html.haml
@@ -0,0 +1,3 @@
+.inputs
+ = f.input :name, :label => t('voicemail_accounts.form.name.label'), :hint => conditional_hint('voicemail_accounts.form.name.hint')
+ = f.input :active, :label => t('voicemail_accounts.form.active.label'), :hint => conditional_hint('voicemail_accounts.form.active.hint')
diff --git a/app/views/voicemail_accounts/_index_core.html.haml b/app/views/voicemail_accounts/_index_core.html.haml
new file mode 100644
index 0000000..908c2b4
--- /dev/null
+++ b/app/views/voicemail_accounts/_index_core.html.haml
@@ -0,0 +1,15 @@
+%table.table.table-striped
+ %tr
+ %th
+ %th= t('voicemail_accounts.index.name')
+
+
+ - for voicemail_account in voicemail_accounts
+ %tr
+ %td
+ - if voicemail_account.active
+ %i.icon-ok
+ - else
+ %i.icon-ban-circle
+ %td= voicemail_account.name
+ =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => voicemail_account.voicemail_accountable, :child => voicemail_account} \ No newline at end of file
diff --git a/app/views/voicemail_accounts/edit.html.haml b/app/views/voicemail_accounts/edit.html.haml
new file mode 100644
index 0000000..8d1518e
--- /dev/null
+++ b/app/views/voicemail_accounts/edit.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("voicemail_accounts.edit.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/voicemail_accounts/index.html.haml b/app/views/voicemail_accounts/index.html.haml
new file mode 100644
index 0000000..2bc8ae4
--- /dev/null
+++ b/app/views/voicemail_accounts/index.html.haml
@@ -0,0 +1,6 @@
+- content_for :title, t("voicemail_accounts.index.page_title")
+
+- if @voicemail_accounts && @voicemail_accounts.count > 0
+ = render "index_core", :voicemail_accounts => @voicemail_accounts
+
+= render :partial => 'shared/create_link', :locals => {:parent => @parent, :child_class => VoicemailAccount} \ No newline at end of file
diff --git a/app/views/voicemail_accounts/new.html.haml b/app/views/voicemail_accounts/new.html.haml
new file mode 100644
index 0000000..193779d
--- /dev/null
+++ b/app/views/voicemail_accounts/new.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("voicemail_accounts.new.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/voicemail_accounts/show.html.haml b/app/views/voicemail_accounts/show.html.haml
new file mode 100644
index 0000000..06b4d1a
--- /dev/null
+++ b/app/views/voicemail_accounts/show.html.haml
@@ -0,0 +1,19 @@
+- content_for :title, t("voicemail_accounts.show.page_title")
+
+%p
+ %strong= t('voicemail_accounts.show.uuid') + ":"
+ = @voicemail_account.uuid
+%p
+ %strong= t('voicemail_accounts.show.name') + ":"
+ = @voicemail_account.name
+%p
+ %strong= t('voicemail_accounts.show.active') + ":"
+ = @voicemail_account.active
+
+= render :partial => 'shared/show_edit_destroy_part', :locals => { :parent => @parent, :child => @voicemail_account }
+
+%h3= t('voicemail_settings.index.page_title')
+- if @voicemail_account.voicemail_settings.any?
+ = render "voicemail_settings/index_core", :voicemail_settings => @voicemail_account.voicemail_settings
+ %br
+= render :partial => 'shared/create_link', :locals => { :parent => @voicemail_account, :child_class => VoicemailSetting } \ No newline at end of file
diff --git a/app/views/voicemail_settings/_form.html.haml b/app/views/voicemail_settings/_form.html.haml
index cd43b2d..08fc37b 100644
--- a/app/views/voicemail_settings/_form.html.haml
+++ b/app/views/voicemail_settings/_form.html.haml
@@ -1,4 +1,5 @@
-= simple_form_for([@sip_account,@voicemail_setting]) do |f|
+
+= simple_form_for([@voicemail_account, @voicemail_setting]) do |f|
= f.error_notification
= render "form_core", :f => f
diff --git a/app/views/voicemail_settings/_form_core.html.haml b/app/views/voicemail_settings/_form_core.html.haml
index 08bdfc2..bf47e46 100644
--- a/app/views/voicemail_settings/_form_core.html.haml
+++ b/app/views/voicemail_settings/_form_core.html.haml
@@ -1,11 +1,10 @@
.inputs
+ - if !@no_edit or !@no_edit[:name]
+ = f.input :name, :collection => VoicemailSetting::VOICEMAIL_SETTINGS.keys.collect{|i, k| [t("voicemail_settings.settings.#{i}"), i]}, :label => t('voicemail_settings.form.name.label'), :hint => conditional_hint('voicemail_settings.form.name.hint'), :autofocus => true, :include_blank => false
+ = f.input :value, :label => t('voicemail_settings.form.value.label'), :hint => conditional_hint('voicemail_settings.form.value.hint')
+ - else
+ = f.input :value, :label => t("voicemail_settings.settings.#{@no_edit[:name][:name]}"), :hint => conditional_hint('voicemail_settings.form.value.hint'), :as => @no_edit[:name][:input]
- = f.input :greeting_path, :as => :select, :label => t('voicemail_settings.form.greeting.label'), :hint => conditional_hint('voicemail_settings.form.greeting.hint'), :collection => @greeting_files
- = f.input :name_path, :as => :select, :label => t('voicemail_settings.form.name.label'), :hint => conditional_hint('voicemail_settings.form.name.hint'), :collection => @name_files
-
- = f.input :password, :label => t('voicemail_settings.form.pin.label'), :hint => conditional_hint('voicemail_settings.form.pin.hint')
-
- = f.input :notify, :as => :boolean, :label => t('voicemail_settings.form.notify.label'), :hint => conditional_hint('voicemail_settings.form.notify.hint')
- = f.input :attachment, :as => :boolean, :label => t('voicemail_settings.form.attachment.label'), :hint => conditional_hint('voicemail_settings.form.attachment.hint')
- = f.input :mark_read, :as => :boolean, :label => t('voicemail_settings.form.mark_read.label'), :hint => conditional_hint('voicemail_settings.form.mark_read.hint')
- = f.input :purge, :as => :boolean, :label => t('voicemail_settings.form.purge.label'), :hint => conditional_hint('voicemail_settings.form.purge.hint')
+ - if !@no_edit or !@no_edit[:description]
+ = f.input :description, :label => t('voicemail_settings.form.description.label'), :hint => conditional_hint('voicemail_settings.form.description.hint')
+
diff --git a/app/views/voicemail_settings/_index_core.html.haml b/app/views/voicemail_settings/_index_core.html.haml
new file mode 100644
index 0000000..94ebfb1
--- /dev/null
+++ b/app/views/voicemail_settings/_index_core.html.haml
@@ -0,0 +1,14 @@
+%table.table.table-striped
+ %thead
+ %tr
+ %th= t('voicemail_settings.index.name')
+ %th= t('voicemail_settings.index.value')
+ %th= t('voicemail_settings.index.description')
+
+ %tbody
+ - for voicemail_setting in voicemail_settings
+ %tr
+ %td= voicemail_setting.name
+ %td= voicemail_setting.value
+ %td= voicemail_setting.description
+ =render :partial => 'shared/index_view_edit_destroy_part', :locals => {:parent => voicemail_setting.voicemail_account, :child => voicemail_setting}
diff --git a/app/views/voicemail_settings/edit.html.haml b/app/views/voicemail_settings/edit.html.haml
index 56e5765..cb9924b 100644
--- a/app/views/voicemail_settings/edit.html.haml
+++ b/app/views/voicemail_settings/edit.html.haml
@@ -1,3 +1,3 @@
- content_for :title, t("voicemail_settings.edit.page_title")
-= render "form"
+= render "form" \ No newline at end of file
diff --git a/app/views/voicemail_settings/index.html.haml b/app/views/voicemail_settings/index.html.haml
new file mode 100644
index 0000000..5eb9940
--- /dev/null
+++ b/app/views/voicemail_settings/index.html.haml
@@ -0,0 +1,6 @@
+- content_for :title, t("voicemail_settings.index.page_title")
+
+- if @voicemail_settings && @voicemail_settings.count > 0
+ = render "index_core", :voicemail_settings => @voicemail_settings
+
+= render :partial => 'shared/create_link', :locals => {:parent => @voicemail_account, :child_class => VoicemailSetting}
diff --git a/app/views/voicemail_settings/new.html.haml b/app/views/voicemail_settings/new.html.haml
new file mode 100644
index 0000000..6eddc39
--- /dev/null
+++ b/app/views/voicemail_settings/new.html.haml
@@ -0,0 +1,3 @@
+- content_for :title, t("voicemail_settings.new.page_title")
+
+= render "form" \ No newline at end of file
diff --git a/app/views/voicemail_settings/show.html.haml b/app/views/voicemail_settings/show.html.haml
index e156d7b..f1a3e61 100644
--- a/app/views/voicemail_settings/show.html.haml
+++ b/app/views/voicemail_settings/show.html.haml
@@ -1,26 +1,19 @@
- content_for :title, t("voicemail_settings.show.page_title")
%p
- %strong= t('voicemail_settings.show.greeting_path') + ":"
- = File.basename(@voicemail_setting.greeting_path.to_s)
-
+ %strong= t('voicemail_settings.show.voicemail_id') + ":"
+ = @voicemail_setting.voicemail
%p
- %strong= t('voicemail_settings.show.name_path') + ":"
- = File.basename(@voicemail_setting.name_path.to_s)
-
+ %strong= t('voicemail_settings.show.name') + ":"
+ = @voicemail_setting.name
+%p
+ %strong= t('voicemail_settings.show.value') + ":"
+ = @voicemail_setting.value
+%p
+ %strong= t('voicemail_settings.show.class_type') + ":"
+ = @voicemail_setting.class_type
%p
- %strong= t('voicemail_settings.show.flags') + ":"
- - if @voicemail_setting.notify
- %br
- = "- " + t('voicemail_settings.show.notify')
- - if @voicemail_setting.attachment
- %br
- = "- " + t('voicemail_settings.show.attachment')
- - if @voicemail_setting.mark_read
- %br
- = "- " + t('voicemail_settings.show.mark_read')
- - if @voicemail_setting.purge
- %br
- = "- " + t('voicemail_settings.show.purge')
+ %strong= t('voicemail_settings.show.description') + ":"
+ = @voicemail_setting.description
-= link_to t('voicemail_settings.actions.edit'), edit_sip_account_voicemail_setting_path(@sip_account, @voicemail_setting)
+= render :partial => 'shared/show_edit_destroy_part', :locals => {:parent => @voicemail_setting.voicemail_account, :child => @voicemail_setting} \ No newline at end of file
diff --git a/config/locales/views/voicemail_accounts/de.yml b/config/locales/views/voicemail_accounts/de.yml
new file mode 100644
index 0000000..989848b
--- /dev/null
+++ b/config/locales/views/voicemail_accounts/de.yml
@@ -0,0 +1,65 @@
+de:
+ voicemail_accounts:
+ name: 'Voicemailaccount'
+ controller:
+ successfuly_created: 'Voicemailaccount wurde angelegt.'
+ successfuly_updated: 'Voicemailaccount wurde aktualisiert.'
+ successfuly_destroyed: 'Voicemailaccount wurde gelöscht.'
+ index:
+ page_title: 'Ãœbersicht von Voicemailaccount'
+ uuid: 'Uuid'
+ name: 'Name'
+ active: 'Active'
+ gs_node_id: 'Gs node'
+ voicemail_accountable_type: 'Voicemail accountable type'
+ voicemail_accountable_id: 'Voicemail accountable'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass Sie folgendes löschen möchten: Voicemailaccount'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ show: 'Anzeigen'
+ create: 'Neu anlegen'
+ create_for: 'Voicemailaccount neu anlegen für %{resource}'
+ show:
+ page_title: 'Voicemailaccount bearbeiten'
+ uuid: 'Uuid'
+ name: 'Name'
+ active: 'Active'
+ gs_node_id: 'Gs node'
+ voicemail_accountable_type: 'Voicemail accountable type'
+ voicemail_accountable_id: 'Voicemail accountable'
+ actions:
+ confirm_destroy: 'Sind Sie sicher, dass die dieses Element löschen möchten?'
+ destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ new:
+ page_title: 'Voicemailaccount neu anlegen'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit:
+ page_title: 'Voicemailaccount bearbeiten'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
+ form:
+ uuid:
+ label: 'Uuid'
+ hint: ''
+ name:
+ label: 'Name'
+ hint: ''
+ active:
+ label: 'Active'
+ hint: ''
+ gs_node_id:
+ label: 'Gs node'
+ hint: ''
+ voicemail_accountable_type:
+ label: 'Voicemail accountable type'
+ hint: ''
+ voicemail_accountable_id:
+ label: 'Voicemail accountable'
+ hint: ''
+ submit: 'Absenden' \ No newline at end of file
diff --git a/config/locales/views/voicemail_accounts/en.yml b/config/locales/views/voicemail_accounts/en.yml
new file mode 100644
index 0000000..58491cd
--- /dev/null
+++ b/config/locales/views/voicemail_accounts/en.yml
@@ -0,0 +1,65 @@
+en:
+ voicemail_accounts:
+ name: 'Voicemailaccount'
+ controller:
+ successfuly_created: 'Successfully created Voicemailaccount.'
+ successfuly_updated: 'Successfully updated Voicemailaccount.'
+ successfuly_destroyed: 'Successfully destroyed Voicemailaccount.'
+ index:
+ page_title: 'Listing Voicemailaccount'
+ uuid: 'Uuid'
+ name: 'Name'
+ active: 'Active'
+ gs_node_id: 'Gs node'
+ voicemail_accountable_type: 'Voicemail accountable type'
+ voicemail_accountable_id: 'Voicemail accountable'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this Voicemailaccount?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ show: 'View'
+ create: 'New'
+ create_for: 'New Voicemailaccount for %{resource}'
+ show:
+ page_title: 'Show Voicemailaccount'
+ uuid: 'Uuid'
+ name: 'Name'
+ active: 'Active'
+ gs_node_id: 'Gs node'
+ voicemail_accountable_type: 'Voicemail accountable type'
+ voicemail_accountable_id: 'Voicemail accountable'
+ actions:
+ confirm_destroy: 'Are you sure you want to delete this element?'
+ destroy: 'Delete'
+ edit: 'Edit'
+ view_all: 'View All'
+ new:
+ page_title: 'New Voicemailaccount'
+ actions:
+ back_to_list: 'Back to Index'
+ edit:
+ page_title: 'Editing Voicemailaccount'
+ actions:
+ back_to_list: 'Back to Index'
+ edit: 'Edit'
+ view_all: 'View All'
+ form:
+ uuid:
+ label: 'Uuid'
+ hint: ''
+ name:
+ label: 'Name'
+ hint: ''
+ active:
+ label: 'Active'
+ hint: ''
+ gs_node_id:
+ label: 'Gs node'
+ hint: ''
+ voicemail_accountable_type:
+ label: 'Voicemail accountable type'
+ hint: ''
+ voicemail_accountable_id:
+ label: 'Voicemail accountable'
+ hint: ''
+ submit: 'Submit' \ No newline at end of file
diff --git a/config/locales/views/voicemail_settings/de.yml b/config/locales/views/voicemail_settings/de.yml
index 52edd4b..bb48720 100644
--- a/config/locales/views/voicemail_settings/de.yml
+++ b/config/locales/views/voicemail_settings/de.yml
@@ -1,52 +1,69 @@
de:
voicemail_settings:
- name: 'Anrufbeantworter Einstellungen'
+ name: 'Voicemail Einstellungen'
+ settigs:
+ password: 'PIN'
+ notify: 'Notify'
+ attachment: 'Attachment'
+ mark_read: 'Mark read'
+ purge: 'Purge'
+ record_length_max: 'Record max.'
+ record_length_min: 'Record min.'
+ records_max: 'Records max.'
controller:
- successfuly_destroyed: 'Einstellungen wurden gelöscht.'
- successfuly_created: 'Einstellungen wurden erstellt.'
- successfuly_updated: 'Einstellungen wurden aktuallisiert.'
+ successfuly_created: 'Voicemail Einstellung wurde angelegt.'
+ successfuly_updated: 'Voicemail Einstellung wurde aktualisiert.'
+ successfuly_destroyed: 'Voicemail Einstellung wurde gelöscht.'
index:
- page_title: 'Anrufbeantworter Einstellungen'
+ page_title: 'Voicemail Einstellungen'
+ voicemail_account_id: 'Voicemail'
+ name: 'Name'
+ value: 'Value'
+ class_type: 'Class type'
+ description: 'Beschreibung'
actions:
- confirm_destroy: 'Sind Sie sicher, dass Sie die Einstellungen löschen möchten?'
+ confirm_destroy: 'Sind Sie sicher, dass Sie folgendes löschen möchten: Voicemail Einstellungen'
destroy: 'Löschen'
+ edit: 'Bearbeiten'
+ show: 'Anzeigen'
+ create: 'Neu anlegen'
+ create_for: 'Voicemail Einstellungen neu anlegen für %{resource}'
show:
- page_title: 'Anrufbeantworter Einstellungen'
- greeting_path: 'Begrüßung'
- name_path: 'Name'
- flags: 'Flags'
- notify: 'Benachrichtigung'
- attachment: 'Datei anfügen'
- mark_read: 'Als gelesen markieren'
- purge: 'Löschen'
+ page_title: 'Voicemail Einstellungen bearbeiten'
+ voicemail_account_id: 'Voicemail'
+ name: 'Name'
+ value: 'Value'
+ class_type: 'Class type'
+ description: 'Beschreibung'
actions:
- confirm_destroy: 'Sind Sie sicher, dass Sie die Einstellungen löschen möchten?'
+ confirm_destroy: 'Sind Sie sicher, dass die dieses Element löschen möchten?'
destroy: 'Löschen'
edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
new:
- page_title: 'Anrufbeantworter Einstellungen'
+ page_title: 'Voicemail Einstellungen neu anlegen'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
edit:
- page_title: 'Anrufbeantworter Einstellungen'
+ page_title: 'Voicemail Einstellungen bearbeiten'
+ actions:
+ back_to_list: 'Zurück zur Übersicht'
+ edit: 'Bearbeiten'
+ view_all: 'Alle anzeigen'
form:
- greeting:
- label: 'Begrüßung'
+ voicemail_account_id:
+ label: 'Voicemail'
hint: ''
name:
label: 'Name'
hint: ''
- pin:
- label: 'Anrufbeantworter PIN'
+ value:
+ label: 'Value'
+ hint: ''
+ class_type:
+ label: 'Class type'
+ hint: ''
+ description:
+ label: 'Beschreibung'
hint: ''
- notify:
- label: 'Benachrichtigung'
- hint: 'Benachrichtigung per E-Mail'
- attachment:
- label: 'Datei anfügen'
- hint: 'Datei an E-Mail anfügen'
- mark_read:
- label: 'Als gelesen markieren'
- hint: 'Markieren als gelesen'
- purge:
- label: 'Löschen'
- hint: 'Nachricht löschen'
submit: 'Absenden' \ No newline at end of file
diff --git a/config/locales/views/voicemail_settings/en.yml b/config/locales/views/voicemail_settings/en.yml
index 5995544..1c8cad4 100644
--- a/config/locales/views/voicemail_settings/en.yml
+++ b/config/locales/views/voicemail_settings/en.yml
@@ -1,52 +1,69 @@
en:
voicemail_settings:
- name: 'Voicemail Settings'
+ name: 'Voicemailsetting'
+ settigs:
+ password: 'PIN'
+ notify: 'Notify'
+ attachment: 'Attachment'
+ mark_read: 'Mark read'
+ purge: 'Purge'
+ record_length_max: 'Record max.'
+ record_length_min: 'Record min.'
+ records_max: 'Records max.'
controller:
- successfuly_destroyed: 'Successfully destroyed voicemail settings.'
- successfuly_created: 'Successfully created voicemail settings.'
- successfuly_updated: 'Successfully updated voicemail settings.'
+ successfuly_created: 'Successfully created entry.'
+ successfuly_updated: 'Successfully updated entry.'
+ successfuly_destroyed: 'Successfully destroyed entry.'
index:
- page_title: 'Voicemail Settings'
+ page_title: 'Voicemail settings'
+ voicemail_account_id: 'Voicemail'
+ name: 'Name'
+ value: 'Value'
+ class_type: 'Class type'
+ description: 'Description'
actions:
- confirm_destroy: 'Are you sure you want to delete voicemail settings?'
+ confirm_destroy: 'Are you sure you want to delete this entry?'
destroy: 'Delete'
+ edit: 'Edit'
+ show: 'View'
+ create: 'New'
+ create_for: 'New settings entry for %{resource}'
show:
- page_title: 'Voicemail Settings'
- greeting_path: 'Greeting'
- name_path: 'Name'
- flags: 'Flags'
- notify: 'Notify by email'
- attachment: 'Attach file'
- mark_read: 'Mark read'
- purge: 'Delete'
+ page_title: 'Show Voicemailsetting'
+ voicemail_account_id: 'Voicemail'
+ name: 'Name'
+ value: 'Value'
+ class_type: 'Class type'
+ description: 'Description'
actions:
- confirm_destroy: 'Are you sure you want to delete voicemail settings?'
+ confirm_destroy: 'Are you sure you want to delete this element?'
destroy: 'Delete'
edit: 'Edit'
+ view_all: 'View All'
new:
- page_title: 'Voicemail Settings'
+ page_title: 'New Voicemail settings entry'
+ actions:
+ back_to_list: 'Back to Index'
edit:
- page_title: 'Voicemail Settings'
+ page_title: 'Editing Voicemail settings'
+ actions:
+ back_to_list: 'Back to Index'
+ edit: 'Edit'
+ view_all: 'View All'
form:
- greeting:
- label: 'Greeting'
- hint: 'Voicemail greeting'
+ voicemail_account_id:
+ label: 'Voicemail'
+ hint: ''
name:
label: 'Name'
- hint: 'Voicemail name'
- pin:
- label: 'Voicemail PIN'
- hint: 'Voicemail PIN'
- notify:
- label: 'Notify by email'
- hint: 'Notify user by email'
- attachment:
- label: 'Attach file'
- hint: 'Attach file to notification email'
- mark_read:
- label: 'Mark read'
- hint: 'Mark message read after notification is sent'
- purge:
- label: 'Delete'
- hint: 'Delete message after notification is sent'
- submit: 'Submit'
+ hint: ''
+ value:
+ label: 'Value'
+ hint: ''
+ class_type:
+ label: 'Class type'
+ hint: ''
+ description:
+ label: 'Description'
+ hint: ''
+ submit: 'Submit' \ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 69caf95..b123de4 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,5 +1,9 @@
Gemeinschaft42c::Application.routes.draw do
+ resources :voicemail_accounts do
+ resources :voicemail_settings
+ end
+
resources :switchboards do
resources :switchboard_entries do
collection { post :sort }
@@ -226,6 +230,7 @@ Gemeinschaft42c::Application.routes.draw do
resources :switchboards do
get :display
end
+ resources :voicemail_accounts
end
resources :user_groups do
@@ -295,6 +300,7 @@ Gemeinschaft42c::Application.routes.draw do
end
end
resources :voicemail_settings
+ resources :voicemail_accounts
end
resources :phones, :only => [] do
diff --git a/db/migrate/20130322081621_create_voicemail_accounts.rb b/db/migrate/20130322081621_create_voicemail_accounts.rb
new file mode 100644
index 0000000..8567adb
--- /dev/null
+++ b/db/migrate/20130322081621_create_voicemail_accounts.rb
@@ -0,0 +1,17 @@
+class CreateVoicemailAccounts < ActiveRecord::Migration
+ def self.up
+ create_table :voicemail_accounts do |t|
+ t.string :uuid
+ t.string :name
+ t.boolean :active
+ t.integer :gs_node_id
+ t.string :voicemail_accountable_type
+ t.integer :voicemail_accountable_id
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :voicemail_accounts
+ end
+end
diff --git a/db/migrate/20130322102533_add_voicemail_account_id_to_sip_accounts.rb b/db/migrate/20130322102533_add_voicemail_account_id_to_sip_accounts.rb
new file mode 100644
index 0000000..60f5883
--- /dev/null
+++ b/db/migrate/20130322102533_add_voicemail_account_id_to_sip_accounts.rb
@@ -0,0 +1,5 @@
+class AddVoicemailAccountIdToSipAccounts < ActiveRecord::Migration
+ def change
+ add_column :sip_accounts, :voicemail_account_id, :integer
+ end
+end
diff --git a/db/migrate/20130326064557_create_voicemail_settings.rb b/db/migrate/20130326064557_create_voicemail_settings.rb
new file mode 100644
index 0000000..45b6573
--- /dev/null
+++ b/db/migrate/20130326064557_create_voicemail_settings.rb
@@ -0,0 +1,16 @@
+class CreateVoicemailSettings < ActiveRecord::Migration
+ def self.up
+ create_table :voicemail_settings do |t|
+ t.integer :voicemail_account_id
+ t.string :name
+ t.string :value
+ t.string :class_type
+ t.string :description
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :voicemail_settings
+ end
+end
diff --git a/misc/freeswitch/conf/freeswitch.xml b/misc/freeswitch/conf/freeswitch.xml
index 5792e96..7283211 100644
--- a/misc/freeswitch/conf/freeswitch.xml
+++ b/misc/freeswitch/conf/freeswitch.xml
@@ -74,6 +74,70 @@
</match>
</input>
</macro>
+ <macro name="voicemail_message_play">
+ <input pattern="^(\d+):(\d+):(.+)$" break_on_match="true">
+ <match>
+ <action function="play-file" data="voicemail/vm-message_number.wav"/>
+ <action function="say" data="$1" method="pronounced" type="items"/>
+ <action function="play-file" data="voicemail/vm-received.wav"/>
+ <action function="say" data="$2" method="pronounced" type="short_date_time"/>
+ <action function="play-file" data="$3"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="voicemail_no_messages">
+ <input pattern="^(.*)$" break_on_match="true">
+ <match>
+ <action function="play-file" data="voicemail/vm-no_more_messages.wav"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="voicemail_message_menu_new">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-play_previous_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-delete_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-save_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$3" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-play_next_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$4" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-main_menu.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$5" method="pronounced" type="name_phonetic"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="voicemail_message_menu_saved">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-play_previous_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-delete_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-play_next_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$3" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-main_menu.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$4" method="pronounced" type="name_phonetic"/>
+ </match>
+ </input>
+ </macro>
<macro name="voicemail_menu">
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
<match>
@@ -250,6 +314,14 @@
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-record_message.wav"/>
+ <action function="play-file" data="tone_stream://%(1000,0,500)"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="voicemail_message_too_short">
+ <input pattern="^(.*)$">
+ <match>
+ <action function="play-file" data="voicemail/vm-too-small.wav"/>
</match>
</input>
</macro>
@@ -600,6 +672,70 @@
</match>
</input>
</macro>
+ <macro name="voicemail_message_play">
+ <input pattern="^(\d+):(\d+):(.+)$" break_on_match="true">
+ <match>
+ <action function="play-file" data="voicemail/vm-message_number.wav"/>
+ <action function="say" data="$1" method="pronounced" type="items"/>
+ <action function="play-file" data="voicemail/vm-received.wav"/>
+ <action function="say" data="$2" method="pronounced" type="short_date_time"/>
+ <action function="play-file" data="$3"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="voicemail_no_messages">
+ <input pattern="^(.*)$" break_on_match="true">
+ <match>
+ <action function="play-file" data="voicemail/vm-no_more_messages.wav"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="voicemail_message_menu_new">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-play_previous_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-delete_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-save_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$3" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-play_next_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$4" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-main_menu.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$5" method="pronounced" type="name_phonetic"/>
+ </match>
+ </input>
+ </macro>
+ <macro name="voicemail_message_menu_saved">
+ <input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
+ <match>
+ <action function="play-file" data="voicemail/vm-play_previous_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$1" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-delete_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$2" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-play_next_message.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$3" method="pronounced" type="name_spelled"/>
+ <action function="execute" data="sleep(100)"/>
+ <action function="play-file" data="voicemail/vm-main_menu.wav"/>
+ <action function="play-file" data="voicemail/vm-press.wav"/>
+ <action function="say" data="$4" method="pronounced" type="name_phonetic"/>
+ </match>
+ </input>
+ </macro>
<macro name="voicemail_menu">
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
<match>
diff --git a/misc/freeswitch/scripts/common/configuration_table.lua b/misc/freeswitch/scripts/common/configuration_table.lua
index 85bc014..1b8d8b7 100644
--- a/misc/freeswitch/scripts/common/configuration_table.lua
+++ b/misc/freeswitch/scripts/common/configuration_table.lua
@@ -4,12 +4,43 @@
module(...,package.seeall)
+
+function cast(variable_type, value, default)
+ require 'common.str';
+
+ if variable_type == 'boolean' then
+ return common.str.to_b(value);
+ elseif variable_type == 'integer' then
+ if default and not tonumber(value) then
+ return default;
+ end
+ return common.str.to_i(value);
+ elseif variable_type == 'float' then
+ if default and not tonumber(value) then
+ return default;
+ end
+ return common.str.to_n(value);
+ elseif variable_type == 'string' then
+ if default and not value then
+ return default;
+ end
+ return common.str.to_s(value);
+ elseif variable_type == 'array' then
+ if default and not value then
+ return default;
+ end
+ return common.str.to_a(value, ',');
+ end
+end
+
-- retrieve configuration from database
-function get(database, entity, section)
+function get(database, entity, section, defaults)
if not database or not entity then
return {};
end
+ defaults = defaults or {};
+
require 'common.str'
local sql_query = 'SELECT * FROM `gs_parameters` WHERE `entity` = "' .. entity .. '"';
@@ -17,7 +48,7 @@ function get(database, entity, section)
sql_query = sql_query .. ' AND `section` = "' .. section .. '"';
end
- local root = {}
+ local root = defaults[1] or {}
local parameter_class = '';
database:query(sql_query, function(parameters)
@@ -26,21 +57,27 @@ function get(database, entity, section)
local p_name = common.str.strip(parameters.name);
if not root[p_section] then
- root[p_section] = {};
+ root[p_section] = defaults[p_section] or {};
end
- if p_class_type == 'boolean' then
- root[p_section][p_name] = common.str.to_b(parameters.value);
- elseif p_class_type == 'integer' then
- root[p_section][p_name] = common.str.to_i(parameters.value);
- else
- root[p_section][p_name] = tostring(parameters.value);
- end
+ root[p_section][p_name] = cast(p_class_type, parameters.value);
end)
if section then
- return root[section];
+ return root[section] or defaults[section];
end
return root;
end
+
+
+function settings(database, table_name, key, value, defaults)
+ local sql_query = 'SELECT * FROM ' .. database:escape(table_name, '`') .. ' WHERE ' .. database:escape(key, '`') .. ' = ' .. database:escape(value, '"');
+
+ local settings_entries = defaults or {};
+ database:query(sql_query, function(record)
+ settings_entries[record.name] = cast(record.class_type:lower(), record.value, settings_entries[record.name]);
+ end);
+
+ return settings_entries;
+end
diff --git a/misc/freeswitch/scripts/dialplan/dialplan.lua b/misc/freeswitch/scripts/dialplan/dialplan.lua
index 5335328..7ed835b 100644
--- a/misc/freeswitch/scripts/dialplan/dialplan.lua
+++ b/misc/freeswitch/scripts/dialplan/dialplan.lua
@@ -590,19 +590,21 @@ end
function Dialplan.voicemail(self, destination)
- require 'dialplan.voicemail'
+ require 'dialplan.voicemail';
local voicemail_account = nil;
-
- local sip_account_id
- if not common.str.blank(destination.number) and false then
- voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database }:find_by_number(destination.number);
+ if common.str.to_i(destination.id) > 0 then
+ voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database, domain = self.domain }:find_by_id(destination.id);
+ elseif not common.str.blank(destination.number) then
+ voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database, domain = self.domain }:find_by_number(destination.number);
elseif self.caller.auth_account and self.caller.auth_account.class == 'sipaccount' then
- voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database }:find_by_sip_account_id(self.caller.auth_account.id);
+ voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database, domain = self.domain }:find_by_sip_account_id(self.caller.auth_account.id);
+ elseif self.caller.forwarding_number then
+ voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database, domain = self.domain }:find_by_number(self.caller.forwarding_number);
end
if not voicemail_account then
- self.log:error('VOICEMAIL - no mailbox');
+ self.log:error('VOICEMAIL - mailbox not found, ');
return { continue = false, code = 404, phrase = 'Mailbox not found' }
end
diff --git a/misc/freeswitch/scripts/dialplan/functions.lua b/misc/freeswitch/scripts/dialplan/functions.lua
index a47d9d3..6399c5e 100644
--- a/misc/freeswitch/scripts/dialplan/functions.lua
+++ b/misc/freeswitch/scripts/dialplan/functions.lua
@@ -756,31 +756,28 @@ function Functions.voicemail_message_leave(self, caller, phone_number)
end
-function Functions.voicemail_check(self, caller, phone_number)
+function Functions.voicemail_check(self, caller, number)
+ require 'dialplan.voicemail';
local voicemail_account = nil;
local voicemail_authorized = false;
-
- require 'dialplan.voicemail'
-
- if phone_number then
- voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database }:find_by_number(phone_number);
- else
- if caller.auth_account_type == 'SipAccount' then
- voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database }:find_by_sip_account_id(caller.auth_account.id);
- voicemail_authorized = true;
- end
+
+ if number then
+ voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database }:find_by_number(number);
+ elseif caller.auth_account and tostring(caller.auth_account.class):lower() == 'sipaccount' then
+ voicemail_account = dialplan.voicemail.Voicemail:new{ log = self.log, database = self.database }:find_by_sip_account_id(caller.auth_account.id);
+ voicemail_authorized = true;
end
if not voicemail_account then
+ self.log:notice('FUNCTION_VOICEMAIL_CHECK - mailbox not found');
return { continue = false, code = 404, phrase = 'Mailbox not found', no_cdr = true }
end
- voicemail_account:menu(caller, voicemail_authorized);
-
- return { continue = false, code = 200, phrase = 'OK', no_cdr = true }
+ return voicemail_account:menu_main(caller, voicemail_authorized);
end
+
function Functions.acd_membership_toggle(self, caller, agent_id, phone_number)
-- Find caller's SipAccount
local caller_sip_account = self:ensure_caller_sip_account(caller);
diff --git a/misc/freeswitch/scripts/dialplan/ivr.lua b/misc/freeswitch/scripts/dialplan/ivr.lua
index f8b8a2d..2a16e3b 100644
--- a/misc/freeswitch/scripts/dialplan/ivr.lua
+++ b/misc/freeswitch/scripts/dialplan/ivr.lua
@@ -21,29 +21,51 @@ function Ivr.new(self, arg)
end
-function Ivr.ivr_phrase(self, phrase, keys, timeout, ivr_repeat)
+function Ivr.ivr_break(self)
+ return self.exit or not self.caller:ready();
+end
+
+
+function Ivr.ivr_phrase(self, phrase, keys, timeout, ivr_repeat, phrase_data)
ivr_repeat = ivr_repeat or 3;
timeout = timeout or 30;
self.digit = '';
self.exit = false;
self.break_keys = {};
+ local query_keys = {};
+
for index=1, #keys do
- self.break_keys[keys[index]] = true;
+ if type(keys[index]) == 'table' then
+ if tostring(keys[index].key) ~= '' then
+ table.insert(query_keys, keys[index].key);
+ end
+ self.break_keys[keys[index].key] = keys[index];
+ else
+ if tostring(keys[index]) ~= '' then
+ table.insert(query_keys, keys[index]);
+ end
+ self.break_keys[keys[index]] = true;
+ end
end
global_callback:callback('dtmf', 'ivr_ivr_phrase', self.ivr_phrase_dtmf, self);
-
+ local continue = true;
for index=0, ivr_repeat do
- self.caller.session:sayPhrase(phrase, table.concat(keys, ':'));
- self.caller:sleep(timeout * 1000);
- if self.exit then
+ continue = self:ivr_break() or self.caller.session:sayPhrase(phrase, phrase_data or table.concat(query_keys, ':'));
+ continue = self:ivr_break() or self.caller:sleep(timeout * 1000);
+
+ if self:ivr_break() then
break;
end
end
global_callback:callback_unset('dtmf', 'ivr_ivr_phrase');
+ if type(self.break_keys[self.digit]) == 'table' then
+ return self.digit, self.break_keys[self.digit];
+ end
+
return self.digit;
end
@@ -66,8 +88,8 @@ function Ivr.read_phrase(self, phrase, phrase_data, max_keys, min_keys, timeout,
timeout = timeout or 30;
global_callback:callback('dtmf', 'ivr_read_phrase', self.read_phrase_dtmf, self);
- self.caller.session:sayPhrase(phrase, phrase_data or enter_key or '');
- self.caller:sleep(timeout * 1000);
+ local continue = self:ivr_break() or self.caller.session:sayPhrase(phrase, phrase_data or enter_key or '');
+ continue = self:ivr_break() or self.caller:sleep(timeout * 1000);
global_callback:callback_unset('dtmf', 'ivr_read_phrase');
return self.digits;
@@ -88,7 +110,7 @@ function Ivr.read_phrase_dtmf(self, dtmf)
end
-function Ivr.check_pin(self, phrase, pin, pin_timeout, pin_repeat, key_enter)
+function Ivr.check_pin(self, phrase_enter, phrase_incorrect, pin, pin_timeout, pin_repeat, key_enter)
if not pin then
return nil;
end
@@ -101,19 +123,42 @@ function Ivr.check_pin(self, phrase, pin, pin_timeout, pin_repeat, key_enter)
for i = 1, pin_repeat do
if digits == pin then
self.caller:send_display('PIN: OK');
- break
+ break;
elseif digits ~= "" then
self.caller:send_display('PIN: wrong');
+ self.caller.session:sayPhrase(phrase_incorrect, '');
+ elseif self:ivr_break() then
+ break;
end
self.caller:send_display('Enter PIN');
- digits = ivr:read_phrase(phrase, nil, 0, pin:len() + 1, pin_timeout, key_enter);
+ digits = ivr:read_phrase(phrase_enter, nil, 0, pin:len() + 1, pin_timeout, key_enter);
end
if digits ~= pin then
self.caller:send_display('PIN: wrong');
+ self.caller.session:sayPhrase(phrase_incorrect, '');
return false
end
self.caller:send_display('PIN: OK');
return true;
end
+
+
+function Ivr.record(self, file_name, phrase_record, phrase_too_short, record_length_max, record_length_min, record_repeat, silence_level, silence_lenght_abort)
+ local duration = nil;
+ for index=1, record_repeat do
+ if (duration and duration >= record_length_min) or not self.caller:ready() then
+ break;
+ elseif duration then
+ self.caller:send_display('Recording too short');
+ self.caller.session:sayPhrase(phrase_too_short);
+ end
+ self.caller.session:sayPhrase(phrase_record);
+ self.caller:send_display('Recording...');
+ local result = self.caller.session:recordFile(file_name, record_length_max, silence_level, silence_lenght_abort);
+ duration = self.caller:to_i('record_seconds');
+ end
+
+ return duration or 0;
+end
diff --git a/misc/freeswitch/scripts/dialplan/voicemail.lua b/misc/freeswitch/scripts/dialplan/voicemail.lua
index caeeb48..4fd5612 100644
--- a/misc/freeswitch/scripts/dialplan/voicemail.lua
+++ b/misc/freeswitch/scripts/dialplan/voicemail.lua
@@ -1,17 +1,39 @@
-- Gemeinschaft 5 module: voicemail class
--- (c) AMOOMA GmbH 2012-2013
+-- (c) AMOOMA GmbH 2013
--
module(...,package.seeall)
Voicemail = {}
-MESSAGE_LENGTH_MIN = 3;
-MESSAGE_LENGTH_MAX = 120;
-SILENCE_LENGTH_ABORT = 5;
-SILENCE_LEVEL = 500;
-BEEP = 'tone_stream://%(1000,0,500)';
-RECORD_FILE_PREFIX = '/var/spool/freeswitch/voicemail_';
+DEFAULT_SETTINGS = {
+ pin_length_max = 10,
+ pin_length_min = 2,
+ pin_timeout = 20,
+ key_new_messages = '1',
+ key_saved_messages = '2',
+ key_config_menu = '0',
+ key_terminator = '#',
+ key_previous = '4',
+ key_next = '6',
+ key_delete = '7',
+ key_save = '2',
+ key_main_menu = '#',
+ record_length_max = 300,
+ record_length_min = 4,
+ records_max = 100,
+ silence_lenght_abort = 3,
+ silence_level = 500,
+ beep = 'tone_stream://%(1000,0,500)',
+ record_file_prefix = 'voicemail_',
+ record_file_suffix = '.wav',
+ record_file_path = '/var/spool/freeswitch/',
+ record_repeat = 3,
+ notify = true,
+ attachment = true,
+ mark_read = true,
+ purge = false,
+}
-- create voicemail object
function Voicemail.new(self, arg)
@@ -23,93 +45,313 @@ function Voicemail.new(self, arg)
self.log = arg.log;
self.database = arg.database;
self.record = arg.record;
+ self.domain = arg.domain;
return object
end
--- find voicemail account by sip account id
-function Voicemail.find_by_sip_account_id(self, id)
- local sql_query = 'SELECT `a`.`id`, `a`.`uuid`, `a`.`auth_name`, `a`.`caller_name`, `b`.`name_path`, `b`.`greeting_path`, `a`.`voicemail_pin`, `b`.`password`, `c`.`host` AS `domain` \
- FROM `sip_accounts` `a` LEFT JOIN `voicemail_prefs` `b` ON `a`.`auth_name` = `b`.`username` \
- JOIN `sip_domains` `c` ON `a`.`sip_domain_id` = `c`.`id` \
- WHERE `a`.`id` = ' .. tonumber(id);
+function Voicemail.find_by_sql(self, sql_query)
local voicemail_account = nil;
self.database:query(sql_query, function(entry)
voicemail_account = Voicemail:new(self);
voicemail_account.record = entry;
voicemail_account.id = tonumber(entry.id);
voicemail_account.uuid = entry.uuid;
- end)
+ voicemail_account.name = entry.name;
+ voicemail_account.settings = self:settings_get(entry.id);
+ end);
return voicemail_account;
end
--- Find Voicemail account by name
-function Voicemail.find_by_name(self, account_name)
- id = tonumber(id) or 0;
- local sql_query = string.format('SELECT * FROM `voicemail_prefs` WHERE `username`= "%s" LIMIT 1', account_name)
- local record = nil
- self.database:query(sql_query, function(voicemail_entry)
- record = voicemail_entry
- end)
+function Voicemail.find_by_name(self, name)
+ local sql_query = 'SELECT * FROM `voicemail_accounts` \
+ WHERE `name` = ' .. self.database:escape(name, '"') .. ' LIMIT 1';
+
+ return self:find_by_sql(sql_query);
+end
+
+
+function Voicemail.find_by_id(self, id)
+ local sql_query = 'SELECT * FROM `voicemail_accounts` \
+ WHERE `id` = ' .. self.database:escape(id, '"') .. ' LIMIT 1';
+
+ return self:find_by_sql(sql_query);
+end
+
+
+function Voicemail.find_by_sip_account_id(self, id)
+ local sql_query = 'SELECT `a`.* FROM `voicemail_accounts` `a` \
+ JOIN `sip_accounts` `b` ON `a`.`id` = `b`.`voicemail_account_id` \
+ WHERE `b`.`id` = ' .. self.database:escape(id, '"') .. ' LIMIT 1';
+
+ return self:find_by_sql(sql_query);
+end
+
+
+function Voicemail.find_by_number(self, number)
+ local sql_query = 'SELECT `a`.* FROM `voicemail_accounts` `a` \
+ JOIN `sip_accounts` `b` ON `a`.`id` = `b`.`voicemail_account_id` \
+ JOIN `phone_numbers` `c` ON `b`.`id` = `c`.`phone_numberable_id` \
+ WHERE `c`.`number` = ' .. self.database:escape(number, '"') .. ' \
+ AND `c`.`phone_numberable_type` = "SipAccount" LIMIT 1';
+
+ return self:find_by_sql(sql_query);
+end
+
+
+function Voicemail.settings_get(self, id)
+ require 'common.configuration_table';
+ local parameters = common.configuration_table.get(self.database, 'voicemail', 'settings', { settings = DEFAULT_SETTINGS });
- if voicemail_account then
- voicemail_account.account_name = account_name;
- if record then
- voicemail_account.name_path = record.name_path;
- voicemail_account.greeting_path = record.greeting_path;
- voicemail_account.password = record.password;
+ return common.configuration_table.settings(self.database, 'voicemail_settings', 'voicemail_account_id', id or self.id, parameters)
+end
+
+
+function Voicemail.messages_get(self, status)
+ local sql_query = 'SELECT * FROM `voicemail_msgs` WHERE `username` = ' .. self.database:escape(self.name, '"');
+
+ status = status or 'all';
+
+ if status == 'read' then
+ sql_query = sql_query .. ' AND `read_epoch` > 0';
+ elseif status == 'unread' then
+ sql_query = sql_query .. ' AND (`read_epoch` = 0 OR `read_epoch` IS NULL)';
+ elseif status == 'new' then
+ sql_query = sql_query .. ' AND `in_folder` != "save" AND `flags` != "save"';
+ elseif status == 'saved' then
+ sql_query = sql_query .. ' AND (`in_folder` = "save" OR `flags` = "save")';
+ end
+
+ return self.database:query_return_all(sql_query);
+end
+
+
+function Voicemail.check_pin(self, pin)
+ self.caller:answer();
+ self.caller:sleep(1000);
+
+ require 'dialplan.ivr';
+ local ivr = dialplan.ivr.Ivr:new{ caller = self.caller, log = self.log };
+
+ local digits = '';
+ for i = 1, 3 do
+ if digits == pin then
+ self.caller:send_display('PIN: OK');
+ break
+ elseif digits ~= "" then
+ self.caller:send_display('PIN: wrong');
end
+ self.caller:send_display('Enter PIN');
+ digits = ivr:read_phrase('voicemail_enter_pass', nil, self.settings.pin_length_min, self.settings.pin_length_max, self.settings.pin_timeout, self.settings.terminator_key);
+ end
+
+ if digits ~= pin then
+ return false
+ end
+
+ return true;
+end
+
+
+function Voicemail.menu_main(self, caller, authorized)
+ self.caller = caller;
+
+ require 'dialplan.ivr';
+ self.ivr = dialplan.ivr.Ivr:new{ caller = self.caller, log = self.log };
+
+ if not authorized then
+ if common.str.blank(self.pin) then
+ self.log:notice('VOICEMAIL_MAIN_MENU - unaunthorized, no PIN, ', self.class, '=', self.id, '/', self.uuid, '|', self.name);
+ return { continue = false, code = 500, phrase = 'Unauthorized', no_cdr = true }
+ end
+
+ self.caller:answer();
+ self.caller:sleep(1000);
+
+ if not self.ivr:check_pin('voicemail_enter_pass', 'voicemail_fail_auth', self.pin) then
+ self.log:notice('VOICEMAIL_MAIN_MENU - wrong PIN, ', self.class, '=', self.id, '/', self.uuid, '|', self.name);
+ caller.session:sayPhrase('voicemail_goodbye');
+ return { continue = false, code = 500, phrase = 'Unauthorized', no_cdr = true }
+ end
+ end
+
+ local messages_new = self:messages_get('unread');
+ local messages_saved = self:messages_get('read');
+
+ if not caller:answered() then
+ self.caller:answer();
+ self.caller:sleep(1000);
end
- return voicemail_account
+ if self.settings.voicemail_hello then
+ caller.session:sayPhrase('voicemail_hello');
+ end
+
+ if self.settings.voicemail_message_count then
+ caller.session:sayPhrase('voicemail_message_count', #messages_new .. ':new');
+ end
+
+ while true do
+ self.log:info('VOICEMAIL_MAIN_MENU - ', self.class, '=', self.id, '/', self.uuid, '|', self.name, ', messages: ', #messages_new, ':', #messages_saved);
+ self.caller:send_display(#messages_new .. ' new messages');
+
+ local main_menu = {
+ { key = self.settings.key_new_messages, method = self.menu_messages, parameters = { self, 'new', messages_new } },
+ { key = self.settings.key_saved_messages, method = self.menu_messages, parameters = { self, 'saved', messages_saved } },
+ { key = self.settings.key_config_menu, method = self.menu_options, parameters = { self } },
+ { key = self.settings.key_terminator, exit = true },
+ { key = '', exit = true },
+ };
+
+ local digits, key = self.ivr:ivr_phrase('voicemail_menu', main_menu);
+ self.log:debug('VOICEMAIL_MAIN_MENU - digit: ', digits);
+ if key.exit then
+ break;
+ end
+
+ key.method(unpack(key.parameters));
+
+ messages_new = self:messages_get('unread');
+ messages_saved = self:messages_get('read');
+ end
+ self.caller:send_display('Goodbye');
+ caller.session:sayPhrase('voicemail_goodbye');
end
--- Find Voicemail account by number
-function Voicemail.find_by_number(self, phone_number)
- local sip_account = nil;
- require "common.phone_number"
- local destination_number_object = common.phone_number.PhoneNumber:new{ log = self.log, database = self.database }:find_by_number(phone_number);
- if destination_number_object and destination_number_object.record.phone_numberable_type:lower() == "sipaccount" then
- return self:find_by_sip_account_id(destination_number_object.record.phone_numberable_id);
+function Voicemail.menu_messages(self, folder, messages)
+ self.log:info('VOICEMAIL_MESSAGES_MENU - ', folder,' messages: ', #messages);
+
+ local digits = nil;
+ local key = nil;
+
+ local message_menu = {
+ { key = self.settings.key_previous, action = 'previous' },
+ { key = self.settings.key_delete, action = 'delete' },
+ { key = self.settings.key_save, action = 'save' },
+ { key = self.settings.key_next, action = 'next' },
+ { key = self.settings.key_main_menu, exit = true },
+ };
+
+ if folder == 'saved' then
+ message_menu = {
+ { key = self.settings.key_previous, action = 'previous' },
+ { key = self.settings.key_delete, action = 'delete' },
+ { key = self.settings.key_next, action = 'next' },
+ { key = self.settings.key_main_menu, exit = true },
+ };
+ end
+
+ if #messages == 0 then
+ digits, key = self.ivr:ivr_phrase('voicemail_no_messages', message_menu, 0, 0);
+ return;
end
- return false;
+ local index = 1;
+ while index <= #messages do
+ local message = messages[index];
+ self.caller:send_display(index .. ': ' .. message.cid_name .. ' ' .. message.cid_number);
+ digits, key = self.ivr:ivr_phrase('voicemail_message_play', message_menu, 0, 0,
+ index .. ':' .. message.created_epoch .. ':' .. message.file_path
+ );
+ if digits == '' then
+ if common.str.to_i(message.read_epoch) == 0 then
+ self:message_mark_read(message);
+ end
+ digits, key = self.ivr:ivr_phrase('voicemail_message_menu_' .. folder, message_menu, 15, 0);
+ end
+
+ if not key or key.exit then
+ break;
+ end
+
+ if key.action == 'previous' then
+ if index > 1 then
+ index = index - 1;
+ end
+ else
+ index = index + 1;
+ end
+
+ if index > #messages then
+ digits, key = self.ivr:ivr_phrase('voicemail_no_messages', message_menu, 0, 0);
+ return;
+ end
+
+ if key.action == 'delete' and self:message_delete(message) then
+ self.caller:send_display('Message deleted');
+ digits = self.caller.session:sayPhrase('voicemail_ack', 'deleted');
+ elseif key.action == 'save' and self:message_save(message) then
+ self.caller:send_display('Message saved');
+ digits = self.caller.session:sayPhrase('voicemail_ack', 'saved');
+ end
+ end
end
-function Voicemail.leave(self, caller, phone_number)
- require 'common.str'
+function Voicemail.menu_options(self)
+ self.log:info('VOICEMAIL_OPTIONS_MENU');
+ self.caller:send_display('Voicemail options');
+end
+
+
+function Voicemail.message_delete(self, message)
+ self.log:debug('VOICEMAIL_MESSAGE_DELETE - message: ', message.uuid);
+ require 'common.fapi';
+ return common.fapi.FApi:new{ log = self.log }:execute('vm_delete', message.username .. '@' .. message.domain .. ' ' .. message.uuid);
+end
+
+function Voicemail.message_mark_read(self, message)
+ self.log:debug('VOICEMAIL_MESSAGE_MARK_READ - message: ', message.uuid);
+ require 'common.fapi';
+ return common.fapi.FApi:new{ log = self.log }:execute('vm_read', message.username .. '@' .. message.domain .. ' read ' .. message.uuid);
+end
- self.log:info('VOICEMAIL_LEAVE - account=', self.record.id, '/', self.record.uuid, ', auth_name: ', self.record.auth_name, ', caller_name: ', self.record.caller_name);
- caller:set_callee_id(phone_number, self.record.caller_name);
+function Voicemail.message_save(self, message)
+ self.log:debug('VOICEMAIL_MESSAGE_SAVE - message: ', message.uuid);
+ require 'common.fapi';
+ return common.fapi.FApi:new{ log = self.log }:execute('vm_fsdb_msg_save', 'default ' .. message.domain .. ' ' .. message.username .. ' ' .. message.uuid);
+end
+
+
+function Voicemail.leave(self, caller, greeting)
+ local forwarding_number = caller.forwarding_number;
+ self.log:info('VOICEMAIL_LEAVE - voicemail_account=', self.record.id, '/', self.record.uuid, '|', self.record.name, ', forwarding_number: ', forwarding_number);
+
+ caller:set_callee_id(forwarding_number, common.array.try(caller, 'auth_account.caller_name') or common.array.try(caller, 'auth_account.name'));
caller:answer();
- caller:send_display(common.str.to_s(self.record.caller_name), common.str.to_s(phone_number));
+ caller:send_display(common.array.try(caller, 'auth_account.caller_name') or common.array.try(caller, 'auth_account.name'));
caller:sleep(1000);
- if not common.str.blank(self.record.greeting_path) then
- caller.session:sayPhrase('voicemail_play_greeting', 'greeting:' .. tostring(self.record.greeting_path));
- elseif not common.str.blank(self.record.name_path) then
- caller.session:sayPhrase('voicemail_play_greeting', 'name:' .. tostring(self.record.name_path));
- elseif not common.str.blank(phone_number) then
- caller.session:sayPhrase('voicemail_play_greeting', (tostring(phone_number):gsub('[%D]', '')));
+ if not common.str.blank(forwarding_number) then
+ caller.session:sayPhrase('voicemail_play_greeting', (tostring(forwarding_number):gsub('[%D]', '')));
end
- local record_file_name = RECORD_FILE_PREFIX .. caller.uuid .. '.wav';
- caller.session:streamFile(BEEP);
+ local record_file_name = self.settings.record_file_path ..self.settings.record_file_prefix .. caller.uuid .. self.settings.record_file_suffix;
self.log:info('VOICEMAIL_LEAVE - recording to file: ', tostring(record_file_name));
- local result = caller.session:recordFile(record_file_name, MESSAGE_LENGTH_MAX, SILENCE_LEVEL, SILENCE_LENGTH_ABORT);
- local duration = caller:to_i('record_seconds');
+
+ require 'dialplan.ivr';
+ local ivr = dialplan.ivr.Ivr:new{ caller = caller, log = self.log };
+
+ local duration = ivr:record(
+ record_file_name,
+ 'voicemail_record_message',
+ 'voicemail_message_too_short',
+ self.settings.record_length_max,
+ self.settings.record_length_min,
+ self.settings.record_repeat,
+ self.settings.silence_level,
+ self.settings.silence_lenght_abort);
- if duration >= MESSAGE_LENGTH_MIN then
+ if duration >= self.settings.record_length_min then
self.log:info('VOICEMAIL_LEAVE - saving recorded message to voicemail, duration: ', duration);
require 'common.fapi'
common.fapi.FApi:new{ log = self.log, uuid = caller.uuid }:execute('vm_inject',
- self.record.auth_name ..
- '@' .. self.record.domain .. " '" ..
+ self.record.name ..
+ '@' .. self.domain .. " '" ..
record_file_name .. "' '" ..
caller.caller_id_number .. "' '" ..
caller.caller_id_name .. "' '" ..
@@ -121,32 +363,14 @@ function Voicemail.leave(self, caller, phone_number)
caller:set_variable('voicemail_message_len');
end
os.remove(record_file_name);
- return true;
+ caller:send_display('Goodbye');
+ caller.session:sayPhrase('voicemail_goodbye');
end
function Voicemail.trigger_notification(self, caller)
- local command = 'http_request.lua ' .. caller.uuid .. ' http://127.0.0.1/trigger/voicemail?sip_account_id=' .. tostring(self.id);
+ local command = 'http_request.lua ' .. caller.uuid .. ' http://127.0.0.1/trigger/voicemail?voicemail_account_id=' .. tostring(self.id);
- require 'common.fapi'
+ require 'common.fapi';
return common.fapi.FApi:new():execute('luarun', command);
end
-
-
-function Voicemail.menu(self, caller, authorized)
- self.log:info('VOICEMAIL_MENU - account: ', self.record.auth_name);
-
- if authorized then
- caller:set_variable('voicemail_authorized', true);
- end
-
- caller:set_callee_id(phone_number, self.record.caller_name);
- caller:answer();
- caller:send_display(common.str.to_s(self.record.caller_name), common.str.to_s(phone_number));
-
- caller:sleep(1000);
- caller:set_variable('skip_greeting', true);
- caller:set_variable('skip_instructions', true);
-
- caller:execute('voicemail', 'check default ' .. self.record.domain .. ' ' .. self.record.auth_name);
-end
diff --git a/misc/freeswitch/scripts/dialplan_default.lua b/misc/freeswitch/scripts/dialplan_default.lua
index 2b651c5..ba51ed3 100644
--- a/misc/freeswitch/scripts/dialplan_default.lua
+++ b/misc/freeswitch/scripts/dialplan_default.lua
@@ -29,6 +29,9 @@ function input_call_back_callee(s, object_type, object_data, arg)
end
end
+function global_callback_handler(...)
+ return global_callback:run({...});
+end
-- initialize logging
require 'common.log'
@@ -90,6 +93,10 @@ else
end
end
+require 'dialplan.callback';
+global_callback = dialplan.callback.Callback:new{ session = session, log = log };
+
+
if start_caller.from_node then
log:debug('AUTHENTICATION_REQUIRED_NODE - node_id: ', start_caller.node_id, ', domain: ', start_dialplan.domain);
start_dialplan:hangup(407, start_dialplan.domain);
diff --git a/test/unit/voicemail_account_test.rb b/test/unit/voicemail_account_test.rb
new file mode 100644
index 0000000..b878c67
--- /dev/null
+++ b/test/unit/voicemail_account_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class VoicemailAccountTest < ActiveSupport::TestCase
+ def test_should_be_valid
+ assert VoicemailAccount.new.valid?
+ end
+end