first commit

This commit is contained in:
Benjamin Dauvergne 2016-01-06 14:49:17 +01:00
commit 84c303a0c7
6 changed files with 284 additions and 0 deletions

35
vxml/README Normal file
View File

@ -0,0 +1,35 @@
Accueil téléphonique eo
-----------------------
Il nécessite un serveur vocal acceptant des scripts VXML, comme celui d'OVH.
Script WSGI
-----------
Le script vxml.wsgi est basé sur flask et requests, il propose deux vues:
/play?text=<utf-8 texte>
synthèse vocale du texte envoyé, les fichiers wav généré sont mis en cache en utilisant le hash SHA1
du texte comme clé. Ils sont conservé dans le répertoire `sounds` du répertoire courant.
/vxml/<path>
transforme le fichier VXML donné qui doit se trouver dans le chemin courant de lors de l'exécution
du script WSGI, il modifie toutes les balices `voice` pour les faire pointer vers la vue de
synthèse vocale.
Le script record.wsgi est conçu pour recevoir les fichiers wav généré par les balises `record` du
VXML sur le serveur vocal d'OVH.
Script VXML
-----------
entrouvert.vxml
script VXML principal pour l'accueil téléphonique entrouvert
record.vxml
sous script pour la fonctionnalité répondeur, il permet principalement de conserver le
numéro de l'appelant dans le nom du fichier wav généré.

116
vxml/entrouvert.vxml Normal file
View File

@ -0,0 +1,116 @@
<?xml version="1.0"?>
<vxml xmlns="http://www.w3.org/2001/vxml" version="2.0" xml:lang="fr-FR">
<var name="callDuration"/>
<var name="number"/>
<property name="inputmodes" value="dtmf"/>
<form id="startMenu">
<field name="level1" type="digits?length=1">
<audio>
Bienvenue chez Entr'ouvert.
Vous souhaitez parler à une personne en particulier, tapez 1.
Vous souhaitez laisser un message au service su porc, tapez 2.
Vous souhaitez une information sur nos services, tapez 3.
Pour réécouter ce message, tapez 4.
</audio>
</field>
<filled>
<if cond="level1 == 1">
<goto next="#workers"/>
<elseif cond="level1 == 2"/>
<audio>
Votre demande de support va être enregistrée après le bip; vous pouvez également utiliser l'adresse électronique qui vous a été communiquée.
</audio>
<goto next="#support"/>
<elseif cond="level1 == 3"/>
<goto next="#sales"/>
</if>
<goto next="#startMenu"/>
</filled>
</form>
<form id="workers">
<field name="level2" type="digits?length=1">
<audio>
Pour Mikael Atès, tapez 1.
Pour Victor Claudet, le 2.
Pierre Crosse, le 3.
</audio>
<audio>
Brice Mallet, le 4.
une personne du siège, le 5.
et revenir à l'accueil, le 6.
</audio>
</field>
<filled>
<if cond="level2 == 3">
<goto next="#pierre"/>
</if>
<if cond="level2 == 2">
<goto next="#totor"/>
</if>
<if cond="level2 == 1">
<goto next="#mike"/>
</if>
<if cond="level2 == 4">
<goto next="#brice"/>
</if>
<if cond="level2 == 5">
<goto next="#bureau"/>
</if>
<goto next="#startMenu"/>
</filled>
</form>
<form id="returnFromTransfer">
<block> Au revoir. Dur&#xE9;e de l'appel : <value expr="callDuration"/> secondes
</block>
</form>
<form id="bureau">
<transfer name="callResult" bridge="true" dest="number/0185098350">
<filled>
<assign name="callDuration" expr="services$.duration"/>
<goto next="#returnFromTransfer"/>
</filled>
</transfer>
</form>
<form id="pierre">
<transfer name="callResult" bridge="true" dest="number/0184162456">
<filled>
<assign name="callDuration" expr="services$.duration"/>
<goto next="#returnFromTransfer"/>
</filled>
</transfer>
</form>
<form id="mike">
<transfer name="callResult" bridge="true" dest="number/0184162451">
<filled>
<assign name="callDuration" expr="services$.duration"/>
<goto next="#returnFromTransfer"/>
</filled>
</transfer>
</form>
<form id="totor">
<transfer name="callResult" bridge="true" dest="number/0184162452">
<filled>
<assign name="callDuration" expr="services$.duration"/>
<goto next="#returnFromTransfer"/>
</filled>
</transfer>
</form>
<form id="brice">
<transfer name="callResult" bridge="true" dest="number/0184162454">
<filled>
<assign name="callDuration" expr="services$.duration"/>
<goto next="#returnFromTransfer"/>
</filled>
</transfer>
</form>
<form id="sales">
<transfer name="callResult" bridge="true" dest="number/0185098351">
</transfer>
</form>
<form id="support">
<block>
<assign name="number" expr="session.connection.remote.uri"/>
<submit method="post" next="record.vxml" namelist="number" />
</block>
</form>
</vxml>

9
vxml/record.vxml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<vxml xmlns="http://www.w3.org/2001/vxml" version="2.0" xml:lang="fr-FR">
<var name="callDuration"/>
<property name="inputmodes" value="dtmf"/>
<form>
<record name="awaymessage" beep="true" maxtime="600s" dest="{number[0]}" finalsilence="20s" dtmfterm="true">
</record>
</form>
</vxml>

37
vxml/record.wsgi Executable file
View File

@ -0,0 +1,37 @@
import site
import sys
import os
prev_sys_path = list(sys.path)
site.addsitedir('/home/bdauvergne/venv/lib/python2.7/site-packages/')
# Reorder sys.path so new directories at the front.
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
from flask import Flask, request, Response, __version__
from werkzeug.debug import DebuggedApplication
from werkzeug.urls import url_encode
import os
import hashlib
import requests
import subprocess
secret = 'secret'
app = Flask(__name__)
app.debug = True
application = DebuggedApplication(app, evalex=True) # The trick is HERE! Add this extra line!
@app.route("/", methods=['GET', 'POST'])
def record():
if request.method == 'POST':
f = request.files['file']
path = '/tmp/'
f.save(os.path.join(path, f.filename))
return Response('OK')

21
vxml/scriptvocal.xml Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" ?>
<vxml version="2.0" xmlns="http://www.w3.org/2001/vxml" xml:lang="fr-FR">
<property name="inputmodes" value="dtmf"/>
<var name="numappelant"/>
<form id="guessNumber">
<field name="guess1" type="digits?length=1" >
<prompt>
Guess what the computer is thinking! Pick a number between 0 and 9.
</prompt>
</field>
<field name="guess2" type="digits?length=1" >
<prompt>
Guess what the computer is thinking now! Pick a number between 0 and 9.
</prompt>
<filled>
You guessed <value expr="guess1"/> and <value expr="guess2"/>.
</filled>
</field>
</form>
</vxml>

66
vxml/vxml.wsgi Executable file
View File

@ -0,0 +1,66 @@
import site
import sys
prev_sys_path = list(sys.path)
site.addsitedir('/home/bdauvergne/venv/lib/python2.7/site-packages/')
# Reorder sys.path so new directories at the front.
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
from flask import Flask, request, Response, __version__
from werkzeug.debug import DebuggedApplication
from werkzeug.urls import url_encode
import os
import hashlib
import requests
import subprocess
secret = 'secret'
app = Flask(__name__)
app.debug = True
application = DebuggedApplication(app, evalex=True) # The trick is HERE! Add this extra line!
default_voice = 'Emma' # 'Agnes' # 'Becool' # 'Moussa' # 'Agnes'
@app.route("/play")
def play():
text = request.args.get('text')
voice = request.args.get('voice', default_voice)
key_prehash = secret + voice + text
key = hashlib.md5(key_prehash.encode('utf8')).hexdigest()
path = os.path.join('sounds', key+'.wav')
if not os.path.exists(path):
r = requests.get('http://voxygen.fr/sites/all/modules/voxygen_voices/assets/proxy/index.php',
params=dict(method='redirect', text=text, voice=voice))
p = subprocess.Popen('/usr/bin/sox -t mp3 - -r 8k -c 1 -t wav -'.split(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate(input=r.content)
with file(path, 'w') as f:
f.write(out)
return Response(file(path), mimetype="audio/x-wav")
import xml.etree.ElementTree as ET
@app.route("/vxml/<path:path>", methods=['GET', 'POST'])
def vxml(path, voice=default_voice):
tree = ET.parse(path)
root = tree.getroot()
if request.form:
for node in root.iter():
for key in node.attrib:
node.attrib[key] = node.attrib[key].format(**request.form)
for audio in root.findall('.//{http://www.w3.org/2001/vxml}audio'):
play_voice = voice
if 'voice' in audio.attrib:
play_voice = audio.attrib['voice']
del audio.attrib['voice']
q = dict(voice=play_voice, text=audio.text)
url = '/~bdauvergne/vxml.wsgi/play?%s' % url_encode(q)
audio.attrib['src'] = url
return Response(ET.tostring(root), mimetype='application/xml')