applications/luci-asterisk: initial dialplan voicemail box support
This commit is contained in:
parent
dd267f9457
commit
2c7a761054
5 changed files with 266 additions and 11 deletions
|
@ -310,6 +310,46 @@ function idd.idd(c)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Populate given CBI field with IDD codes.
|
||||||
|
-- @param field CBI option object
|
||||||
|
-- @return (nothing)
|
||||||
|
function idd.cbifill(o)
|
||||||
|
for i, v in ipairs(cc_idd.CC_IDD) do
|
||||||
|
o:value("_%i" % i, util.pcdata(v[1]))
|
||||||
|
end
|
||||||
|
|
||||||
|
o.formvalue = function(...)
|
||||||
|
local val = luci.cbi.Value.formvalue(...)
|
||||||
|
if val:sub(1,1) == "_" then
|
||||||
|
val = tonumber((val:gsub("^_", "")))
|
||||||
|
if val then
|
||||||
|
return type(cc_idd.CC_IDD[val][3]) == "table"
|
||||||
|
and cc_idd.CC_IDD[val][3] or { cc_idd.CC_IDD[val][3] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
|
||||||
|
o.cfgvalue = function(...)
|
||||||
|
local val = luci.cbi.Value.cfgvalue(...)
|
||||||
|
if val then
|
||||||
|
val = tools.parse_list(val)
|
||||||
|
for i, v in ipairs(cc_idd.CC_IDD) do
|
||||||
|
if type(v[3]) == "table" then
|
||||||
|
if v[3][1] == val[1] then
|
||||||
|
return "_%i" % i
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if v[3] == val[1] then
|
||||||
|
return "_%i" % i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- LuCI Asterisk - Country Code Prefixes
|
--- LuCI Asterisk - Country Code Prefixes
|
||||||
-- @type module
|
-- @type module
|
||||||
|
@ -363,6 +403,46 @@ function cc.cc(c)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Populate given CBI field with CC codes.
|
||||||
|
-- @param field CBI option object
|
||||||
|
-- @return (nothing)
|
||||||
|
function cc.cbifill(o)
|
||||||
|
for i, v in ipairs(cc_idd.CC_IDD) do
|
||||||
|
o:value("_%i" % i, util.pcdata(v[1]))
|
||||||
|
end
|
||||||
|
|
||||||
|
o.formvalue = function(...)
|
||||||
|
local val = luci.cbi.Value.formvalue(...)
|
||||||
|
if val:sub(1,1) == "_" then
|
||||||
|
val = tonumber((val:gsub("^_", "")))
|
||||||
|
if val then
|
||||||
|
return type(cc_idd.CC_IDD[val][2]) == "table"
|
||||||
|
and cc_idd.CC_IDD[val][2] or { cc_idd.CC_IDD[val][2] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
|
||||||
|
o.cfgvalue = function(...)
|
||||||
|
local val = luci.cbi.Value.cfgvalue(...)
|
||||||
|
if val then
|
||||||
|
val = tools.parse_list(val)
|
||||||
|
for i, v in ipairs(cc_idd.CC_IDD) do
|
||||||
|
if type(v[2]) == "table" then
|
||||||
|
if v[2][1] == val[1] then
|
||||||
|
return "_%i" % i
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if v[2] == val[1] then
|
||||||
|
return "_%i" % i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- LuCI Asterisk - Dialzone
|
--- LuCI Asterisk - Dialzone
|
||||||
-- @type module
|
-- @type module
|
||||||
|
@ -432,6 +512,101 @@ function dialzone.ucisection(i)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- LuCI Asterisk - Voicemailbox
|
||||||
|
-- @type module
|
||||||
|
voicemail = luci.util.class()
|
||||||
|
|
||||||
|
--- Parse a voicemail section
|
||||||
|
-- @param zone Table containing the mailbox info
|
||||||
|
-- @return Table with parsed information
|
||||||
|
function voicemail.parse(z)
|
||||||
|
if z.number and #z.number > 0 then
|
||||||
|
local v = {
|
||||||
|
id = '%s@%s' %{ z.number, z.context or 'default' },
|
||||||
|
number = z.number,
|
||||||
|
context = z.context or 'default',
|
||||||
|
name = z.name or z['.name'] or 'OpenWrt',
|
||||||
|
zone = z.zone or 'homeloc',
|
||||||
|
password = z.password or '0000',
|
||||||
|
email = z.email or '',
|
||||||
|
page = z.page or '',
|
||||||
|
dialplans = { }
|
||||||
|
}
|
||||||
|
|
||||||
|
uci:foreach("asterisk", "dialplanvoice",
|
||||||
|
function(s)
|
||||||
|
if s.dialplan and #s.dialplan > 0 and
|
||||||
|
s.voicebox == v.number
|
||||||
|
then
|
||||||
|
v.dialplans[#v.dialplans+1] = s.dialplan
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a list of known voicemail boxes
|
||||||
|
-- @return Associative table of boxes and table of box numbers
|
||||||
|
function voicemail.boxes()
|
||||||
|
local vboxes = { }
|
||||||
|
local vnames = { }
|
||||||
|
uci:foreach("asterisk", "voicemail",
|
||||||
|
function(z)
|
||||||
|
local v = voicemail.parse(z)
|
||||||
|
if v then
|
||||||
|
local n = '%s@%s' %{ v.number, v.context }
|
||||||
|
vboxes[n] = v
|
||||||
|
vnames[#vnames+1] = n
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return vboxes, vnames
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a specific voicemailbox
|
||||||
|
-- @param number Number of the voicemailbox
|
||||||
|
-- @return Table containing mailbox information
|
||||||
|
function voicemail.box(n)
|
||||||
|
local box
|
||||||
|
n = n:gsub("@.+$","")
|
||||||
|
uci:foreach("asterisk", "voicemail",
|
||||||
|
function(z)
|
||||||
|
if z.number == tostring(n) then
|
||||||
|
box = voicemail.parse(z)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return box
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Find all voicemailboxes within the given dialplan
|
||||||
|
-- @param plan Dialplan name or table
|
||||||
|
-- @return Associative table containing extensions mapped to mailbox info
|
||||||
|
function voicemail.in_dialplan(p)
|
||||||
|
local plan = type(p) == "string" and p or p.name
|
||||||
|
local boxes = { }
|
||||||
|
uci:foreach("asterisk", "dialplanvoice",
|
||||||
|
function(s)
|
||||||
|
if s.extension and #s.extension > 0 and s.dialplan == plan then
|
||||||
|
local box = voicemail.box(s.voicebox)
|
||||||
|
if box then
|
||||||
|
boxes[s.extension] = box
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
return boxes
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove voicemailbox and associated extensions from config
|
||||||
|
-- @param box Voicemailbox number or table
|
||||||
|
-- @return Boolean indicating success
|
||||||
|
function voicemail.remove(v)
|
||||||
|
local box = type(v) == "string" and v or v.number
|
||||||
|
local ok1 = uci:delete_all("asterisk", "voicemail", {number=box})
|
||||||
|
local ok2 = uci:delete_all("asterisk", "dialplanvoice", {voicebox=box})
|
||||||
|
return ( ok1 or ok2 ) and true or false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- LuCI Asterisk - Dialplan
|
--- LuCI Asterisk - Dialplan
|
||||||
-- @type module
|
-- @type module
|
||||||
dialplan = luci.util.class()
|
dialplan = luci.util.class()
|
||||||
|
@ -447,6 +622,7 @@ function dialplan.parse(z)
|
||||||
description = z.description or z['.name']
|
description = z.description or z['.name']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- dialzones
|
||||||
for _, name in ipairs(tools.parse_list(z.include)) do
|
for _, name in ipairs(tools.parse_list(z.include)) do
|
||||||
local zone = dialzone.zone(name)
|
local zone = dialzone.zone(name)
|
||||||
if zone then
|
if zone then
|
||||||
|
@ -454,6 +630,9 @@ function dialplan.parse(z)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- voicemailboxes
|
||||||
|
plan.voicemailboxes = voicemail.in_dialplan(plan)
|
||||||
|
|
||||||
return plan
|
return plan
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -103,6 +103,31 @@ function handle_dialplan()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(luci.http.formvaluetable("delvbox")) do
|
||||||
|
local plan = ast.dialplan.plan(k)
|
||||||
|
if #v > 0 and plan then
|
||||||
|
uci:delete_all("asterisk", "dialplanvoice",
|
||||||
|
{ extension=v, dialplan=plan.name })
|
||||||
|
uci:save("asterisk")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for k, v in pairs(luci.http.formvaluetable("addvbox")) do
|
||||||
|
local plan = ast.dialplan.plan(k)
|
||||||
|
local vbox = ast.voicemail.box(v)
|
||||||
|
if plan and vbox then
|
||||||
|
local vext = luci.http.formvalue("addvboxext.%s" % plan.name)
|
||||||
|
vext = ( vext and #vext > 0 ) and vext or vbox.number
|
||||||
|
uci:section("asterisk", "dialplanvoice", nil, {
|
||||||
|
dialplan = plan.name,
|
||||||
|
extension = vext,
|
||||||
|
voicebox = vbox.number,
|
||||||
|
voicecontext = vbox.context
|
||||||
|
})
|
||||||
|
uci:save("asterisk")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local aname = luci.http.formvalue("addplan")
|
local aname = luci.http.formvalue("addplan")
|
||||||
if aname and #aname > 0 then
|
if aname and #aname > 0 then
|
||||||
if aname:match("^[a-zA-Z0-9_]+$") then
|
if aname:match("^[a-zA-Z0-9_]+$") then
|
||||||
|
|
|
@ -120,7 +120,10 @@ if arg[1] then
|
||||||
end
|
end
|
||||||
|
|
||||||
aprefix = entry:option(Value, "addprefix", "Add prefix to dial out (optional)")
|
aprefix = entry:option(Value, "addprefix", "Add prefix to dial out (optional)")
|
||||||
|
--ast.idd.cbifill(aprefix)
|
||||||
|
|
||||||
ccode = entry:option(Value, "countrycode", "Effective countrycode (optional)")
|
ccode = entry:option(Value, "countrycode", "Effective countrycode (optional)")
|
||||||
|
ast.cc.cbifill(ccode)
|
||||||
|
|
||||||
lzone = entry:option(ListValue, "localzone", "Dialzone for local numbers")
|
lzone = entry:option(ListValue, "localzone", "Dialzone for local numbers")
|
||||||
lzone:value("", "no special treatment of local numbers")
|
lzone:value("", "no special treatment of local numbers")
|
||||||
|
|
|
@ -33,6 +33,10 @@ $Id$
|
||||||
function format_matches(z)
|
function format_matches(z)
|
||||||
local html = { }
|
local html = { }
|
||||||
|
|
||||||
|
if type(z) ~= "table" then
|
||||||
|
z = { matches = { z } }
|
||||||
|
end
|
||||||
|
|
||||||
if z.localprefix then
|
if z.localprefix then
|
||||||
for _, m in ipairs(z.matches) do
|
for _, m in ipairs(z.matches) do
|
||||||
html[#html+1] =
|
html[#html+1] =
|
||||||
|
@ -41,7 +45,7 @@ $Id$
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if #z.intlmatches > 0 then
|
if z.intlmatches and #z.intlmatches > 0 then
|
||||||
for _, i in ipairs(z.intlmatches) do
|
for _, i in ipairs(z.intlmatches) do
|
||||||
for _, m in ipairs(z.matches) do
|
for _, m in ipairs(z.matches) do
|
||||||
html[#html+1] = "%s %s" %{
|
html[#html+1] = "%s %s" %{
|
||||||
|
@ -71,7 +75,10 @@ $Id$
|
||||||
<div class="cbi-map" id="cbi-asterisk">
|
<div class="cbi-map" id="cbi-asterisk">
|
||||||
<h2><a id="content" name="content">Outgoing Call Routing</a></h2>
|
<h2><a id="content" name="content">Outgoing Call Routing</a></h2>
|
||||||
<div class="cbi-map-descr">
|
<div class="cbi-map-descr">
|
||||||
Here you can manage your dial plans which are used to route outgoing calls from your local extensions.
|
Here you can manage your dial plans which are used to route outgoing calls from your local extensions.<br /><br />
|
||||||
|
Related tasks:<br />
|
||||||
|
<a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans/zones')%>" class="cbi-title-ref">Manage dialzones</a> |
|
||||||
|
<a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans/zones')%>" class="cbi-title-ref">Manage voicemailboxes</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- tblsection -->
|
<!-- tblsection -->
|
||||||
<fieldset class="cbi-section" id="cbi-asterisk-sip">
|
<fieldset class="cbi-section" id="cbi-asterisk-sip">
|
||||||
|
@ -93,9 +100,9 @@ $Id$
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<!-- dialzones -->
|
<!-- dialzones -->
|
||||||
<% local zones_used = { } %>
|
<% local zones_used = { }; local row = 0 %>
|
||||||
<% for i, zone in ipairs(plan.zones) do zones_used[zone.name] = true %>
|
<% for i, zone in ipairs(plan.zones) do zones_used[zone.name] = true %>
|
||||||
<tr class="cbi-section-table-row <%=rowstyle(i)%>">
|
<tr class="cbi-section-table-row <%=rowstyle(row)%>">
|
||||||
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell">
|
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell">
|
||||||
<strong>└ Dialzone <em><%=zone.name%></em></strong> (<%=zone.description%>)
|
<strong>└ Dialzone <em><%=zone.name%></em></strong> (<%=zone.description%>)
|
||||||
<p style="padding-left: 1em; margin-bottom:0">
|
<p style="padding-left: 1em; margin-bottom:0">
|
||||||
|
@ -118,25 +125,65 @@ $Id$
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
<% row = row + 1; end %>
|
||||||
|
<!-- /dialzones -->
|
||||||
|
|
||||||
|
<!-- voicemail -->
|
||||||
|
<% local boxes_used = { } %>
|
||||||
|
<% for ext, box in luci.util.kspairs(plan.voicemailboxes) do boxes_used[box.id] = true %>
|
||||||
|
<tr class="cbi-section-table-row <%=rowstyle(row)%>">
|
||||||
|
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell">
|
||||||
|
<strong>└ Voicemailbox <em><%=box.id%></em></strong> (<%=box.name%>)
|
||||||
|
<p style="padding-left: 1em; margin-bottom:0">
|
||||||
|
Owner: <%=box.name%> |
|
||||||
|
eMail: <%=#box.email > 0 and box.email or 'n/a'%> |
|
||||||
|
Pager: <%=#box.page > 0 and box.page or 'n/a'%><br />
|
||||||
|
Matches: <%=format_matches(ext)%>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td style="width:5%" class="cbi-value-field">
|
||||||
|
<a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans', 'out', box.name)%>">
|
||||||
|
<img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" />
|
||||||
|
</a>
|
||||||
|
<a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans')%>?delvbox.<%=plan.name%>=<%=ext%>">
|
||||||
|
<img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% row = row + 1; end %>
|
||||||
|
<!-- /voicemail -->
|
||||||
|
|
||||||
<tr class="cbi-section-table-row">
|
<tr class="cbi-section-table-row">
|
||||||
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell" colspan="2">
|
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell" colspan="2">
|
||||||
<hr style="margin-bottom:0.5em; border-width:0 0 1px 0" />
|
<hr style="margin-bottom:0.5em; border-width:0 0 1px 0" />
|
||||||
|
|
||||||
|
Add Dialzone:<br />
|
||||||
<select style="width:30%" name="addzone.<%=plan.name%>">
|
<select style="width:30%" name="addzone.<%=plan.name%>">
|
||||||
<option value="">-- Add dialzone --</option>
|
<option value="">-- please select --</option>
|
||||||
<% for _, zone in pairs(ast.dialzone.zones()) do %>
|
<% for _, zone in pairs(ast.dialzone.zones()) do %>
|
||||||
<% if not zones_used[zone.name] then %>
|
<% if not zones_used[zone.name] then %>
|
||||||
<option value="<%=zone.name%>"><%=zone.name%> (<%=zone.description%>)</option>
|
<option value="<%=zone.name%>"><%=zone.name%> (<%=zone.description%>)</option>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</select>
|
</select>
|
||||||
<input type="submit" class="cbi-button cbi-button-add" value=" » " title="Add Zone ..."/>
|
<br /><br />
|
||||||
|
|
||||||
<a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans/zones')%>" class="cbi-title-ref">Manage dialzones</a>
|
Add Voicemailbox:<br />
|
||||||
|
<select style="width:20%" name="addvbox.<%=plan.name%>" onchange="this.form['addvboxext.<%=plan.name%>'].value=this.options[this.selectedIndex].value.split('@')[0]">
|
||||||
|
<option value="">-- please select --</option>
|
||||||
|
<% for ext, box in pairs(ast.voicemail.boxes()) do %>
|
||||||
|
<% if not boxes_used[box.id] then %>
|
||||||
|
<option value="<%=box.id%>"><%=box.id%> (<%=box.name%>)</option>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</select>
|
||||||
|
as extension
|
||||||
|
<input type="text" style="width:5%" name="addvboxext.<%=plan.name%>" />
|
||||||
|
<br /><br />
|
||||||
|
|
||||||
|
<input type="submit" class="cbi-button cbi-button-add" value="Add item »" title="Add item ..."/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- /dialzones -->
|
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,8 @@ config 'iax' 'sam'
|
||||||
config 'voicegeneral'
|
config 'voicegeneral'
|
||||||
option 'serveremail' 'voice@sip.mydomain.net'
|
option 'serveremail' 'voice@sip.mydomain.net'
|
||||||
|
|
||||||
config 'voicemail' '1001'
|
config 'voicemail'
|
||||||
|
option 'number' '1001'
|
||||||
option 'context' 'default'
|
option 'context' 'default'
|
||||||
option 'password' '0000'
|
option 'password' '0000'
|
||||||
option 'name' 'Family'
|
option 'name' 'Family'
|
||||||
|
|
Loading…
Reference in a new issue