#!/usr/bin/env python

#***************************************************************************
#                         dialAsterisk  -  description
#                             -------------------
#    copyright            : (c) 2007 by Robert Penz
#    email                : robert@penz.name
#***************************************************************************
#
#***************************************************************************
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU General Public License as published by  *
#*   the Free Software Foundation; either version 2 of the License, or     *
#*   (at your option) any later version.                                   *
#*                                                                         *
#***************************************************************************

""" this script takes the number to dial from Kontact and forwards it to
    an asterisk server, which makes than the phone ring. ;-)
    
    Written by Robert Penz <robert@penz.name>
"""

import socket
import sys
import string

yourNumber = "sip/YOUR_EXTENTION"
user = "YOUR_USER"
password = "YOUR_PASSWORD"
context = user  # may differ, if so specify
callerid = "Kontact"

asteriskHost = "ASTERISK_SERVER_IP"
asteriskPort = 5038
asteriskAreaCode = "0512" 
asteriskCountryCode = "0043"
asteriskCombinedCode = asteriskCountryCode + asteriskAreaCode[1:]

def prepareNumber(rawNumber):
    """ this function prepares the given Number in
        a way asterisk is able to use it like I've just
        typed it into my phone
    """

    # remove (0)
    s = rawNumber.replace("(0)", "")
    
    # replace + by 00
    s = s.replace("+", "00")
    
    # remove all non digit chars
    s = s.translate(string.maketrans("",""), string.printable.replace(string.digits,""))

    # remove country and area code if the match
    if s.startswith(asteriskCombinedCode):
        s = s[len(asteriskCombinedCode):]
    
    # remove country code and at a zero
    if s.startswith(asteriskCountryCode):
        s = "0" + s[len(asteriskCountryCode):]
    
    # we're done
    return s

    
def dial(numberToDial):
    """ talks via TCP with the asterisk server """
    
    aSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    aSocket.settimeout(30)
    aSocket.connect((asteriskHost, asteriskPort))
    fd = aSocket.makefile('rw', 0)
    
    # are we connected to an asterisk?
    
    s = fd.readline()
    if not s.startswith("Asterisk Call Manager"):
        print "Not matched (1): " + s
        sys.exit(2)
    
    # we authenticated ourself
    
    fd.write("action: login\r\nusername: %s\r\nsecret: %s\r\nevents: off\r\n\r\n" % (user, password))
    fd.flush()
    
    for line in ["Response: Success",
                 "Message: Authentication accepted",
                 "\r\n"]:
        s = fd.readline()
        if not s.startswith(line):
            print "Not matched (2): " + s
            sys.exit(2)

    # we dial the number ....
            
    fd.write("action: originate\r\nchannel: %s\r\nexten: %s\r\ncontext: %s\r\ncallerid: %s\r\npriority: 1\r\n\r\n"
                % (yourNumber, numberToDial, context, callerid))
    fd.flush()

    # now we wait for the user to pickup the phone
    
    for line in ["Response: Success",
                 "Message: Originate successfully queued",
                 "\r\n"]:
        s = fd.readline()
        if not s.startswith(line):
            print "Not matched (3): " + s
            sys.exit(2)
            
    fd.write("action: logoff\r\n\r\n")
    fd.flush()
    aSocket.shutdown(1)
    
def main():
    if len(sys.argv) != 2:
        print "Usage: ./dialAsterisk.py [numberToDial]"
        sys.exit(-1)
    dial(prepareNumber(sys.argv[1]))
    
if __name__ == '__main__':
    main()
