Asterisk - "monitor" file küldése e-mailen (script)

Sziasztok!

Keresgéltem a neten, de nem találtam kész megoldást arra, hogy az Asterisk által gyártott felvételeket el tudjam küldeni e-mailen, megadott címre.
Kicsit pontosabban a gombnyomásra indítható "One Touch Record", ill. "Touch Monitor" funkció által gyártott hangfelvételek elküldését szerettem volna megoldani.

A legközelebbi megoldás, amit találtam "írj egy scriptet hozzá" jellegű válasz volt.
Mivel a file alapértelmezett neve beszédesnek látszott, elkezdtem összerakni magamnak egy használható változatot.

Mivel nem vagyok gyakorlott "bash programozásban", könnyen lehet, hogy sokkal szebben és jobban is megírható a dolog.
Írjátok meg nyugodtan az észrevételeiteket, legfeljebb tanulok belőle. :)

A levélküldéshez is kerestem használható megoldást, amivel el tudom küldeni a levéltestet és azzal együtt a csatolmányt is korrekt formában.
Ehhez találtam a neten egy scriptet, ami szépen megcsinálja, amit kell - kicsit módosítottam rajta, hogy a másik scriptből fel tudjam paraméterezni, ill. hogy a levéltestben is hasznos, ill. megfelelő információk jelenjenek meg. Tulajdonképpen ez a script sok helyen megtalálható a neten, ez csak az egyik közülük.

Mit is csinál a "scriptem"?

Kigyűjti az asterisk monitor könyvtárából a .wav fileok neveit (erre valakinek esetleg szebb megoldás?), ezután a filenévből kinyeri a hívó és a hívott számát.
Ha nem olyan fileról van szó, amit az Asterisk éppen felvesz és a hívó számát sikerült kinyerni, megnézi, a szamok.txt fileban szerepel-e ez a szám és ha igen, milyen e-mail cím van megadva mellé.
Ha valamilyen oknál fogva nem sikerült e-mail címet kinyerni, az alapértelmezettet használja.

Ezután megnézi, milyen hosszú a .wav file és ha 35-percnél hosszabb, két részre vágja - egy harminc perces és egy a maradéknak (egy óra után amúgyis bontom a vonalat), majd betömöríti bzip2-vel és elküldi őket a célcímre és törli az ideiglenes fileokat.
Ha 20 és 35 perc közötti a file, akkor ugyanezt csinálja, de nem darabol.
20 percnél rövidebb fileokat egyben elküldi.

Küldés után az eredeti fileokat elmozgatja egy monitor_sent nevű könyvtárba.

...nagyjából ennyi az egész. :)

Remélem, sikerült minden nem odavaló elemet átalakítani az idézett fileokban, hogy rendesen megjelenjenek.

send_monitor.sh file tartalma:

#!/bin/bash
PHNUM=/etc/asterisk/monitor/szamok.txt          #E-mail addresses assigned to which service registration numbers
DIRECTORY=/var/spool/asterisk                   #Asterisk's spool directory
TMP=/tmp/asterisk_tmp                           #Temporary folder - have to create it before use!
SENDMAIL=/etc/asterisk/monitor/sendmail.sh      #Sendmail script
FILENAME=$TMP/file_$RANDOM.txt                  #Random filename for search results
DEFAULT_MAIL="yourmail@here"                    #Default e-mail address in case we haven't found one in PHNUM
MIME_BZ2="application/x-bzip2"                  #Mime type for bz2 files for e-mail attachment
MIME_WAV="audio/x-wav"                          #Mime type for wav files for e-mail attachment

function send_parts
{
    local subject="Asterisk felvétel ($(echo $name | cut -d- -f2))"
    local length=$(printf "%.0f" $(soxi -D $attach))      #Gets length of .wav file and converts this float to integer

#Note: at 8000Hz bitrate, 1 second = 8000 samples in sox's trim
if [ $length -gt 2100 ] #If length is greater than 35 minutes
then
  first_part=$TMP/$name-part1.wav
  second_part=$TMP/$name-part2.wav
  sox $attach $first_part trim 0 14400000s      #Cut first 30 minutes
  sox $attach $second_part trim 14400000s       #Leading part
  bzip2 $first_part                             #Compress it using bzip2
  bzip2 $second_part
  $SENDMAIL $mail $hivo $hivott $first_part.bz2  "$subject Part1" $MIME_BZ2 "recorded_part1.wav.bz2"   #Invoke sendmail script
  $SENDMAIL $mail $hivo $hivott $second_part.bz2 "$subject Part2" $MIME_BZ2 "recorded_part2.wav.bz2"
  rm -f $first_part.bz2                         #Delete sent file
  rm -f $second_part.bz2
  mv $attach $DIRECTORY/monitor_sent/           #Move original file to sent folder, so script will not send it again
else

 if [ $length -gt 1200 ] #If length is greater than 20 minutes (so it is between 20 and 35 minutes) - no need of parting
 then
   cp $attach $TMP                              #Copy original file to temp directory
   bzip2 $TMP/$name.wav                         #Compress it using bzip2
   $SENDMAIL $mail $hivo $hivott $TMP/$name.wav.bz2 "$subject" $MIME_BZ2 "recorded.wav.bz2"
   rm -f $TMP/$name.wav.bz2
   mv $attach $DIRECTORY/monitor_sent/

 else #Otherwise - if length is less than 20 minutes, send wav file as is
   $SENDMAIL $mail $hivo $hivott $attach "$subject" $MIME_WAV "recorded.wav"
   mv $attach $DIRECTORY/monitor_sent/
 fi
fi
}

#Locate which mail address belongs to the phone number
function pairing()
{
    local mail
    local szam

while read result <&7
do

  szam=$(echo $result | cut -d\  -f1)
  mail=$(echo $result | cut -d\  -f2)

  #If numbers match => found --> give back corresponding mail address, then brake the cycle
  if [ $szam =  $1 ] ; then
    echo $mail
    break
  fi

done \
    7< $PHNUM
}

#Cut filename to parts to get phone numbers
function send()
{
    name=$(echo $1 | grep .wav | sed -e 's/^.*\///' -e 's/.wav$//')
    hivo=$(echo $name | cut -d- -f3)
    hivott=$(echo $name | cut -d- -f4)
    attach=$1

#Check if the file is not currently under recording - fifth parameter (in/out) does not exists
if [ -z $(echo $name | cut -d- -f5) ]
then
  #If caller is not blank, locate the corresponding mail address
  if [ -n "$hivo" ]
  then 
    mail=$(pairing "$hivo")
    #If no mail address found, use default one
    if [ -z "$mail" ]
    then
      mail=$DEFAULT_MAIL
    fi
    send_parts
  fi
fi
}


#Main part

#Find files and write results to a temporary file
find $DIRECTORY/monitor > $FILENAME

# Read file and send to examine /and then send/ it
while read results <&7
do
    send "$results"
done \
    7< $FILENAME \

rm -f $FILENAME

Az alábbi a neten talált levélküldő script.

sendmail.sh file tartalma:

#!/bin/bash
#requires: basename,date,md5sum,sed,sendmail,uuencode
function fappend {
     echo "$2">>$1;
}
 YYYYMMDD=`date +%Y%m%d`

# CHANGE THESE
 TOEMAIL=$1;
 HIVO=$2;
 HIVOTT=$3;
 FREMAIL="Asterisk <noreply@localhost>";
# MSGBODY="Hello this is the message body";
 ATTACHMENT=$4;
 SUBJECT="$5";
 MIMETYPE="$6" #if not sure, use http://www.webmaster-toolkit.com/mime-types.shtml

# DON'T CHANGE ANYTHING BELOW
 TMP="/tmp/tmpfil_$RANDOM";
 BOUNDARY=`date +%s|md5sum`
 BOUNDARY=${BOUNDARY:0:32}
# FILENAME=`basename $ATTACHMENT`
 FILENAME="$7"

 rm -rf $TMP;
 cat $ATTACHMENT|uuencode --base64 $FILENAME>$TMP;
 sed -i -e '1,1d' -e '$d' $TMP; #removes first & last lines from $TMP
 DATA=`cat $TMP`

 rm -rf $TMP;
 fappend $TMP "From: $FREMAIL";
 fappend $TMP "To: $TOEMAIL";
 fappend $TMP "Reply-To: $FREMAIL";
 fappend $TMP "Subject: $SUBJECT";
 fappend $TMP "Content-Type: multipart/mixed; boundary=\""$BOUNDARY"\"";
 fappend $TMP "";
 fappend $TMP "This is a MIME formatted message.  If you see this text it means that your";
 fappend $TMP "email software does not support MIME formatted messages.";
 fappend $TMP "";
 fappend $TMP "--$BOUNDARY";
 fappend $TMP "Content-Type: text/html; charset=UTF-8; format=flowed";
 fappend $TMP "Content-Transfer-Encoding: 7bit";
 fappend $TMP "Content-Disposition: inline";
 fappend $TMP "";
# fappend $TMP "$MSGBODY";
 fappend $TMP "<html>";
 fappend $TMP "<head>";
 fappend $TMP "<meta content=\"text/html; charset=UTF-8\"";
 fappend $TMP "<http-equiv=\"content-type\">";
 fappend $TMP "<title>Felvétel</title>";
 fappend $TMP "</head>";
 fappend $TMP "<body>";
 fappend $TMP "Hangfelvétel érkezett!<br>";
 fappend $TMP "<br>";
 fappend $TMP "A hívó/hívott fél kapcsolási száma: <span style=\"font-weight: bold;\">$HIVOTT</span><br>";
 fappend $TMP "A készülék SIP regisztrációs száma: <span style=\"font-weight: bold;\">$HIVO</span><br>";
# fappend $TMP "Időpont: <span style=\"font-weight: bold;\">$YYYYMMDD</span><br>";
 fappend $TMP "<br>";
 fappend $TMP "Üdvözlettel: Rendszer<br>";
 fappend $TMP "</body>";
 fappend $TMP "</html>";
 fappend $TMP "";
 fappend $TMP "";
 fappend $TMP "--$BOUNDARY";
 fappend $TMP "Content-Type: $MIMETYPE; name=\"$FILENAME\"";
 fappend $TMP "Content-Transfer-Encoding: base64";
 fappend $TMP "Content-Disposition: attachment; filename=\"$FILENAME\";";
 fappend $TMP "";
 fappend $TMP "$DATA";
 fappend $TMP "";
 fappend $TMP "";
 fappend $TMP "--$BOUNDARY--";
 fappend $TMP "";
 fappend $TMP "";
#cat $TMP>out.txt
 cat $TMP|/usr/sbin/sendmail -t;
 rm $TMP;

A szám - e-mail cím hozzárendelés nem túl bonyolult referenciája:

Egy példa szamok.txt file tartalmára:

32 local1@localhost
9822 local2@localhost
03221 local3@localhost
89098 local4@localhost

Remélem, nem olyan hajmeresztő az elgondolás ill. megoldás és lesz, akinek még hasznára válik.
Ha valamit nagyon rosszul használnék, szóljatok rám, mert eddig nem igazán foglalkoztam ilyesmivel - az meg nem sokat jelent, hogy amúgy működik. :)

Gondolkoztam rajt, hogy esetleg a hangfilet érdemes volna átalakítani (hogy kisebb legyen), de nem tudom, mi volna a leginkább célravezető - ahol a minőség is jó marad, méret is csökken és mindenki boldog...

Talán a legközelebbi google-játékos könnyebben talál működőképes megoldást mint én. :D

Update:
Kicsit változtattam a scripten, mert rájöttem, hogy az mp3 tömörítvényt az mplayer vacakul játsza le nekem (nyeklik-nyaklik a hang), de VLC vagy mpg123 tökéletesen játsza.

A tömörítvény kb. tizede a .wav filenak, így inkább kivettem a darabolós részt és ehelyett inkább tömörítem őket mp3-ba.

Betettem viszont egy lockfile-kezelést (lehet, hogy fölöslegesen túlbonyolítva), ami addig nem engedi lefutni a scriptet, amíg ez a file nincs törölve, de a beállított intervallum lejárta után törli azt és engedi futni (bár ezt lehet, még kicsit át kellene gondolni).

A tömörítést ffmpeg-gel végzi, de a Debian változata nem támogat mp3-mat, így ezt azért meg kell oldani előtte.

Jelenleg így néz ki:
monitor_send.sh file tartalma:

#!/bin/bash
PHNUM=/etc/asterisk/monitor/szamok.txt          #E-mail addresses assigned to which service registration numbers
DIRECTORY=/var/spool/asterisk                   #Asterisk's spool directory
TMP=/tmp/asterisk_tmp                           #Temporary folder - have to create it before use!
SENDMAIL=/etc/asterisk/monitor/sendmail.sh      #Sendmail script
FILENAME=$TMP/file_$RANDOM.txt                  #Random filename for search results
LOCKFILE=$TMP/.lock                             #Lockfile's name
LOCK_TIMEOUT=20                                 #Timeout before delete stale lock file in minutes
DEFAULT_MAIL="yourmail@here"                   #Default e-mail address in case we haven't found one in PHNUM
MIME_MP3="audio/mpeg"                           #Mime type for mp3 files for e-mail attachment
deleted=0

function lockfile_check()
{
    local f_e_mins      #When will timeout over - calculated by elapsed minutes since file creation (from midnight) + lock_timeout
    local fdate         #File creation day
    local e_mins        #Elapsed minutes since midnight of today
    local cdate         #Current day of the month

  hours=$(printf "%.0f" $(stat -c %y $LOCKFILE | cut -d\  -f2 | cut -d: -f1))
  minutes=$(printf "%.0f" $(stat -c %y $LOCKFILE | cut -d:  -f2))
  let f_e_mins=($hours*60 + $minutes+$LOCK_TIMEOUT)
  fdate=$(printf "%.0f" $(stat -c %y $LOCKFILE | cut -d-  -f3 | cut -d\  -f1))

  hours=$(printf "%.0f" $(date +%k))
  minutes=$(printf "%.0f" $(date +%M))
  let e_mins=($hours*60 + $minutes)
  cdate=$(printf "%.0f" $(date +%d))

let tmp=1439-$LOCK_TIMEOUT
if [[ $f_e_mins -gt 1439 && $e_mins -lt $tmp ]]         #If file creation time + timeout is over 23:59 and current time is over 00:00 (not before 23:59)
then

   let f_e_mins=(f_e_mins - 1440)                       #Substract 24:00 from f_e_mins
   fdate=$cdate                                         #Set file date to current one, since midnight was over during timeout (or too old lockfile)

fi

if [ $fdate -eq $cdate ]                                #If this is the same day the file was created or substraction happened /see above/ (most likely the next day)
then
    if [ $e_mins -gt $f_e_mins ]                        #Check if we reached lock timeout
    then
        rm -f $LOCKFILE                                 #Delete lockfile - seems to be remained there
        deleted=1                                       #File deleted --> let the script run below
    fi

 else
        rm -f $LOCKFILE                                 #Else - delete lock file - seems to be an older one
        deleted=1
fi
}

#Locate which mail address belongs to the phone number
function pairing()
{
    local mail
    local szam

while read result <&7
do

  szam=$(echo $result | cut -d\  -f1)
  mail=$(echo $result | cut -d\  -f2)

  #If numbers match => found --> give back corresponding mail address, then brake the cycle
  if [ $szam =  $1 ] ; then
    echo $mail
    break
  fi

done \
    7< $PHNUM
}

#Cut filename to parts to get phone numbers
function send()
{
    name=$(echo $1 | grep .wav | sed -e 's/^.*\///' -e 's/.wav$//')
    hivo=$(echo $name | cut -d- -f3)
    hivott=$(echo $name | cut -d- -f4)
    local subject="Asterisk felvétel ($(echo $name | cut -d- -f2))"
    attach=$1

#Check if the file is not currently under recording - fifth parameter (in/out) does not exists
if [ -z $(echo $name | cut -d- -f5) ]
then
  #If caller is not blank, locate the corresponding mail address
  if [ -n "$hivo" ]
  then 
    mail=$(pairing "$hivo")
    #If no mail address found, use default one
    if [ -z "$mail" ]
    then
      mail=$DEFAULT_MAIL
    fi

    nice -n 19 ffmpeg -i $attach -y -vn -aq 40 -ac 1 $TMP/$name.mp3 2>/dev/null         #Compress wav file to mp3 - ffmpeg needs to be installed with mp3 support
    $SENDMAIL $mail $hivo $hivott "$TMP/$name.mp3" "$subject" $MIME_MP3 "recorded.mp3"  #Invoke sendmail script
    rm -f $TMP/$name.mp3                                                                #Delete sent file
    mv $attach $DIRECTORY/monitor_sent/                                                 #Move original file to sent folder, so script will not send it again

  fi
fi
}


#Main part

if [ -e $LOCKFILE ]         #If LOCKFILE exists
then
    lockfile_check          #Check if timeout reached
    if [ $deleted -ne 1 ]   #If timeout not reached
    then
        exit                #Abort script
    fi
fi

touch $LOCKFILE            #Create lockfile

#Find files and write results to a temporary file
find $DIRECTORY/monitor > $FILENAME

# Read file and send to examine /and then send/ it
while read results <&7
do
    send "$results"
done \
    7< $FILENAME \

rm -f $FILENAME             #Remove temporary search results file
rm -f $LOCKFILE             #Remove lockfile

Így mp3-ban egy kicsit használhatóbbnak tűnik a dolog.
Egy óra beszélgetés ~6MB-ot emészt fel, ami sokkal barátibb azért egy csatolmány esetén.

Hozzászólások

Helló.

Szép munka!
Ha esetleg adatbázisból szeretnéd kinyerni a monitor file unique id-je alapján a fájlhoz tartalmazó egyéb információkat (ez ugye akkor érdekes, ha minden adatbázisba megy, és a hangfájlok nevei nem egyértelműek, hanem a unique id-val azonosíthatóak), arra van kész megoldásom!

<= Powered By Ubuntu & Gentoo Linux =>

'Software is like sex: It's better when it's free!'
By Linus Torvalds

Köszönöm. :)

Adatbázis ismereteim sajnos még nincsenek, de terveim között szerepel - mint sok más dolog is. Szeretnék majd ebben a témában is elmélyedni kicsit a nem túl távoli jövőben, mert van néhány ötletem, amihez kelleni fog még...

Érdekelne a megoldásod, mert ha közvetlenül most nem is, később biztosan hasznát veszem.