Route inbound PSTN calls through FlowerCore IVR, add missing star codes

from-twilio: Changed from Dial(PJSIP/100) to Stasis(flowercore-pbx,inbound-pstn)
so inbound calls go through the FlowerCore IVR workflow engine instead
of directly ringing extensions.

Added missing star codes: *43 (echo test), *80 (intercom), *88 (conference),
*41/*411 (directory). Added catch-all _*X. pattern for future star codes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andrew M. Stoltz
2026-03-20 10:51:28 -05:00
parent 8611fe521a
commit 92792cdc50

View File

@@ -1,260 +1,269 @@
apiVersion: v1 apiVersion: v1
kind: ConfigMap kind: ConfigMap
metadata: metadata:
name: asterisk-config name: asterisk-config
namespace: telephony namespace: telephony
data: data:
modules.conf: | modules.conf: |
[modules] [modules]
autoload=yes autoload=yes
noload=chan_sip.so noload=chan_sip.so
noload=res_hep.so noload=res_hep.so
noload=res_hep_pjsip.so noload=res_hep_pjsip.so
noload=res_hep_rtcp.so noload=res_hep_rtcp.so
http.conf: | http.conf: |
[general] [general]
enabled=yes enabled=yes
bindaddr=0.0.0.0 bindaddr=0.0.0.0
bindport=8088 bindport=8088
ari.conf: | ari.conf: |
[general] [general]
enabled=yes enabled=yes
pretty=yes pretty=yes
allowed_origins=* allowed_origins=*
[flowercore] [flowercore]
type=user type=user
read_only=no read_only=no
password=bluejay-asterisk-ari password=bluejay-asterisk-ari
password_format=plain password_format=plain
manager.conf: | manager.conf: |
[general] [general]
enabled=no enabled=no
pjsip.conf: | pjsip.conf: |
; ===== Transports ===== ; ===== Transports =====
[transport-udp] [transport-udp]
type=transport type=transport
protocol=udp protocol=udp
bind=0.0.0.0:5060 bind=0.0.0.0:5060
; NAT: internal phones see node IP, Twilio sees public IP ; NAT: internal phones see node IP, Twilio sees public IP
local_net=10.0.0.0/8 local_net=10.0.0.0/8
local_net=172.16.0.0/12 local_net=172.16.0.0/12
local_net=192.168.0.0/16 local_net=192.168.0.0/16
external_media_address=74.40.140.28 external_media_address=74.40.140.28
external_signaling_address=74.40.140.28 external_signaling_address=74.40.140.28
; ===== Twilio SIP Trunk ===== ; ===== Twilio SIP Trunk =====
[twilio-trunk] [twilio-trunk]
type=endpoint type=endpoint
context=from-twilio context=from-twilio
transport=transport-udp transport=transport-udp
disallow=all disallow=all
allow=ulaw allow=ulaw
allow=alaw allow=alaw
allow=g722 allow=g722
aors=twilio-trunk aors=twilio-trunk
from_domain=sip.twilio.com from_domain=sip.twilio.com
direct_media=no direct_media=no
ice_support=no ice_support=no
rtp_symmetric=yes rtp_symmetric=yes
force_rport=yes force_rport=yes
rewrite_contact=yes rewrite_contact=yes
trust_id_inbound=yes trust_id_inbound=yes
[twilio-trunk] [twilio-trunk]
type=aor type=aor
contact=sip:bluejay.pstn.twilio.com contact=sip:bluejay.pstn.twilio.com
[twilio-trunk] [twilio-trunk]
type=identify type=identify
endpoint=twilio-trunk endpoint=twilio-trunk
; Twilio North America signaling IPs ; Twilio North America signaling IPs
match=54.172.60.0/30 match=54.172.60.0/30
match=54.172.60.4/30 match=54.172.60.4/30
match=54.244.51.0/30 match=54.244.51.0/30
match=54.244.51.4/30 match=54.244.51.4/30
match=34.203.250.0/23 match=34.203.250.0/23
match=54.171.127.192/26 match=54.171.127.192/26
match=35.156.191.128/25 match=35.156.191.128/25
match=54.65.63.192/26 match=54.65.63.192/26
match=54.169.127.128/26 match=54.169.127.128/26
match=54.252.254.64/26 match=54.252.254.64/26
match=177.71.206.192/26 match=177.71.206.192/26
; ===== Yealink Phone Template ===== ; ===== Yealink Phone Template =====
[phone-template](!) [phone-template](!)
type=endpoint type=endpoint
context=from-internal context=from-internal
transport=transport-udp transport=transport-udp
disallow=all disallow=all
allow=opus allow=opus
allow=g722 allow=g722
allow=ulaw allow=ulaw
allow=alaw allow=alaw
direct_media=no direct_media=no
dtmf_mode=rfc4733 dtmf_mode=rfc4733
rtp_symmetric=yes rtp_symmetric=yes
force_rport=yes force_rport=yes
rewrite_contact=yes rewrite_contact=yes
; Extension 100 - Reception ; Extension 100 - Reception
[100](phone-template) [100](phone-template)
auth=auth100 auth=auth100
aors=100 aors=100
callerid="Reception" <100> callerid="Reception" <100>
[auth100] [auth100]
type=auth type=auth
auth_type=userpass auth_type=userpass
username=100 username=100
password=bluejay-ext-100 password=bluejay-ext-100
[100] [100]
type=aor type=aor
max_contacts=1 max_contacts=1
remove_existing=yes remove_existing=yes
qualify_frequency=60 qualify_frequency=60
; Extension 101 - Office 1 ; Extension 101 - Office 1
[101](phone-template) [101](phone-template)
auth=auth101 auth=auth101
aors=101 aors=101
callerid="Office 1" <101> callerid="Office 1" <101>
[auth101] [auth101]
type=auth type=auth
auth_type=userpass auth_type=userpass
username=101 username=101
password=bluejay-ext-101 password=bluejay-ext-101
[101] [101]
type=aor type=aor
max_contacts=1 max_contacts=1
remove_existing=yes remove_existing=yes
qualify_frequency=60 qualify_frequency=60
; Extension 102 - Office 2 ; Extension 102 - Office 2
[102](phone-template) [102](phone-template)
auth=auth102 auth=auth102
aors=102 aors=102
callerid="Office 2" <102> callerid="Office 2" <102>
[auth102] [auth102]
type=auth type=auth
auth_type=userpass auth_type=userpass
username=102 username=102
password=bluejay-ext-102 password=bluejay-ext-102
[102] [102]
type=aor type=aor
max_contacts=1 max_contacts=1
remove_existing=yes remove_existing=yes
qualify_frequency=60 qualify_frequency=60
; Extension 103 - Office 3 ; Extension 103 - Office 3
[103](phone-template) [103](phone-template)
auth=auth103 auth=auth103
aors=103 aors=103
callerid="Office 3" <103> callerid="Office 3" <103>
[auth103] [auth103]
type=auth type=auth
auth_type=userpass auth_type=userpass
username=103 username=103
password=bluejay-ext-103 password=bluejay-ext-103
[103] [103]
type=aor type=aor
max_contacts=1 max_contacts=1
remove_existing=yes remove_existing=yes
qualify_frequency=60 qualify_frequency=60
extensions.conf: | extensions.conf: |
[general] [general]
static=yes static=yes
writeprotect=no writeprotect=no
[from-twilio] [from-twilio]
; Inbound calls from Twilio SIP trunk ; Inbound calls from Twilio SIP trunk -> FlowerCore IVR workflow
; Ring reception (100) for 30s, then try all extensions in ring group exten => _+X.,1,Answer()
exten => _+X.,1,Answer() same => n,Wait(1)
same => n,Playback(silence/1) same => n,Stasis(flowercore-pbx,inbound-pstn,${EXTEN})
same => n,Dial(PJSIP/100,30,t) same => n,Hangup()
same => n,Dial(PJSIP/101&PJSIP/102&PJSIP/103,30,t)
same => n,Playback(vm-goodbye) exten => _X.,1,Answer()
same => n,Hangup() same => n,Wait(1)
same => n,Stasis(flowercore-pbx,inbound-pstn,${EXTEN})
exten => _X.,1,Answer() same => n,Hangup()
same => n,Playback(silence/1)
same => n,Dial(PJSIP/100,30,t) [from-internal]
same => n,Dial(PJSIP/101&PJSIP/102&PJSIP/103,30,t) ; Internal extension-to-extension dialing
same => n,Playback(vm-goodbye) exten => _1XX,1,Dial(PJSIP/${EXTEN},30)
same => n,Hangup() same => n,Hangup()
[from-internal] ; Outbound via Twilio SIP trunk (11-digit US)
; Internal extension-to-extension dialing exten => _1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529)
exten => _1XX,1,Dial(PJSIP/${EXTEN},30) same => n,Dial(PJSIP/+${EXTEN}@twilio-trunk,60)
same => n,Hangup() same => n,Hangup()
; Outbound via Twilio SIP trunk (11-digit US) ; Outbound via Twilio SIP trunk (+1 format)
exten => _1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529) exten => _+1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529)
same => n,Dial(PJSIP/+${EXTEN}@twilio-trunk,60) same => n,Dial(PJSIP/${EXTEN}@twilio-trunk,60)
same => n,Hangup() same => n,Hangup()
; Outbound via Twilio SIP trunk (+1 format) ; IVR access from internal phones (when ARI is connected)
exten => _+1NXXNXXXXXX,1,Set(CALLERID(num)=+13202332529) exten => *100,1,Stasis(flowercore-pbx,internal,ivr)
same => n,Dial(PJSIP/${EXTEN}@twilio-trunk,60) same => n,Hangup()
same => n,Hangup()
; Star codes routed to FlowerCore Stasis app for handling
; IVR access from internal phones (when ARI is connected) exten => *0,1,Stasis(flowercore-pbx,starcode,*0)
exten => *100,1,Stasis(flowercore-pbx,internal,ivr) same => n,Hangup()
same => n,Hangup() exten => *30,1,Stasis(flowercore-pbx,starcode,*30)
same => n,Hangup()
; Star codes routed to FlowerCore Stasis app for handling exten => *69,1,Stasis(flowercore-pbx,starcode,*69)
exten => *0,1,Stasis(flowercore-pbx,starcode,*0) same => n,Hangup()
same => n,Hangup() exten => *70,1,Stasis(flowercore-pbx,starcode,*70)
exten => *30,1,Stasis(flowercore-pbx,starcode,*30) same => n,Hangup()
same => n,Hangup() exten => _*70X.,1,Stasis(flowercore-pbx,starcode,${EXTEN})
exten => *69,1,Stasis(flowercore-pbx,starcode,*69) same => n,Hangup()
same => n,Hangup() exten => *71,1,Stasis(flowercore-pbx,starcode,*71)
exten => *70,1,Stasis(flowercore-pbx,starcode,*70) same => n,Hangup()
same => n,Hangup() exten => _*71X.,1,Stasis(flowercore-pbx,starcode,${EXTEN})
exten => _*70X.,1,Stasis(flowercore-pbx,starcode,${EXTEN}) same => n,Hangup()
same => n,Hangup() exten => *72,1,Stasis(flowercore-pbx,starcode,*72)
exten => *71,1,Stasis(flowercore-pbx,starcode,*71) same => n,Hangup()
same => n,Hangup() exten => *73,1,Stasis(flowercore-pbx,starcode,*73)
exten => _*71X.,1,Stasis(flowercore-pbx,starcode,${EXTEN}) same => n,Hangup()
same => n,Hangup() exten => *75,1,Stasis(flowercore-pbx,starcode,*75)
exten => *72,1,Stasis(flowercore-pbx,starcode,*72) same => n,Hangup()
same => n,Hangup() exten => *77,1,Stasis(flowercore-pbx,starcode,*77)
exten => *73,1,Stasis(flowercore-pbx,starcode,*73) same => n,Hangup()
same => n,Hangup() exten => *78,1,Stasis(flowercore-pbx,starcode,*78)
exten => *75,1,Stasis(flowercore-pbx,starcode,*75) same => n,Hangup()
same => n,Hangup() exten => *79,1,Stasis(flowercore-pbx,starcode,*79)
exten => *77,1,Stasis(flowercore-pbx,starcode,*77) same => n,Hangup()
same => n,Hangup() exten => *86,1,Stasis(flowercore-pbx,starcode,*86)
exten => *78,1,Stasis(flowercore-pbx,starcode,*78) same => n,Hangup()
same => n,Hangup() exten => *87,1,Stasis(flowercore-pbx,starcode,*87)
exten => *79,1,Stasis(flowercore-pbx,starcode,*79) same => n,Hangup()
same => n,Hangup() exten => *97,1,Stasis(flowercore-pbx,starcode,*97)
exten => *86,1,Stasis(flowercore-pbx,starcode,*86) same => n,Hangup()
same => n,Hangup() exten => *43,1,Stasis(flowercore-pbx,starcode,*43)
exten => *87,1,Stasis(flowercore-pbx,starcode,*87) same => n,Hangup()
same => n,Hangup() exten => *80,1,Stasis(flowercore-pbx,starcode,*80)
exten => *97,1,Stasis(flowercore-pbx,starcode,*97) same => n,Hangup()
same => n,Hangup() exten => *88,1,Stasis(flowercore-pbx,starcode,*88)
same => n,Hangup()
[default] exten => *41,1,Stasis(flowercore-pbx,starcode,*41)
exten => _X.,1,NoOp(Unhandled call to ${EXTEN}) same => n,Hangup()
same => n,Hangup() exten => *411,1,Stasis(flowercore-pbx,starcode,*411)
same => n,Hangup()
rtp.conf: |
[general] ; Catch-all for any other star codes
rtpstart=10000 exten => _*X.,1,Stasis(flowercore-pbx,starcode,${EXTEN})
rtpend=20000 same => n,Hangup()
strictrtp=yes
icesupport=no [default]
exten => _X.,1,NoOp(Unhandled call to ${EXTEN})
same => n,Hangup()
rtp.conf: |
[general]
rtpstart=10000
rtpend=20000
strictrtp=yes
icesupport=no