diff options
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 |