
    >gM]                         d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	Z	ddl
 ddlmZ dZ G d d	e      Z G d
 de      Z G d de      Z G d de      Z G d de      Z G d de      Zy)a>  
.. module:: manager
   :synopsis: Python Interface for Asterisk Manager

This module provides a Python API for interfacing with the asterisk manager.

Example
-------

.. code-block:: python

   import asterisk.manager
   import sys

   def handle_shutdown(event, manager):
      print "Recieved shutdown event"
      manager.close()
      # we could analize the event and reconnect here

   def handle_event(event, manager):
      print "Recieved event: %s" % event.name

   manager = asterisk.manager.Manager()
   try:
       # connect to the manager
       try:
          manager.connect('host')
          manager.login('user', 'secret')

           # register some callbacks
           manager.register_event('Shutdown', handle_shutdown) # shutdown
           manager.register_event('*', handle_event)           # catch all

           # get a status report
           response = manager.status()

           manager.logoff()
       except asterisk.manager.ManagerSocketException as e:
          print "Error connecting to the manager: %s" % e.strerror
          sys.exit(1)
       except asterisk.manager.ManagerAuthException as e:
          print "Error logging in to the manager: %s" % e.strerror
          sys.exit(1)
       except asterisk.manager.ManagerException as e:
          print "Error: %s" % e.strerror
          sys.exit(1)

   finally:
      # remember to clean up
      manager.close()

Remember all header, response, and event names are case sensitive.

Not all manager actions are implmented as of yet, feel free to add them
and submit patches.

Specification
-------------
    N)PY3)queue)*)sleep
c                   6    e Zd ZdZd Zd Zd Zd	dZd Zd Z	y)

ManagerMsgzA manager interface messagec                 (   || _         d| _        i | _        | j                  |       d| j                  vr^d| j                  vrO| j	                  d      rd| j                  d<   y d| j                  v rd| j                  d<   y d| j                  d<   y y y )N EventResponseActionIDzGenerated Header--END COMMAND--NoClue)responsedataheadersparse
has_header)selfr   s     C/opt/asterisk_venv/lib/python3.12/site-packages/asterisk/manager.py__init__zManagerMsg.__init__O   s     	 	

8 $,,&:T\\+I z*+=Z("dii/(0W%+=Z( ,J&    c                    g }t        |      D ]  \  }}|j                  d      s|j                  ||d         n	 d |j                  dd      D        \  }}d|v rY| j                  j                  d      si | j                  d<   d |j                  dd      D        \  }}|| j                  d   |<   n|| j                  |<    d	j                  |      | _        y# t        $ r |j                  ||d        Y  7w xY w)
zParse a manager messager   Nc              3   <   K   | ]  }|j                           y wNstrip.0xs     r   	<genexpr>z#ManagerMsg.parse.<locals>.<genexpr>w   s     >a	>   :   ChanVariablec              3   <   K   | ]  }|j                           y wr   r   r   s     r   r"   z#ManagerMsg.parse.<locals>.<genexpr>}   s     "E1779"Er#   =r   )		enumerateendswithextendsplitr   has_key
ValueErrorjoinr   )	r   r   r   nlinekvnamevalues	            r   r   zManagerMsg.parsem   s      * 	GAt==(HQRL)>4::c1+=>1 "Q&<<//?57^4"Eaggc!n"EKD%7<DLL06&'DLLO	( GGDM		  HQRL)s   BCC>=C>c                     || j                   v S zCheck for a headerr   r   hnames     r   r   zManagerMsg.has_header       $$r   Nc                 :    | j                   j                  ||      S zReturn the specfied headerr   getr   r:   defvals      r   
get_headerzManagerMsg.get_header       ||v..r   c                      | j                   |   S r=   r8   r9   s     r   __getitem__zManagerMsg.__getitem__       ||E""r   c                 Z    d| j                   v r| j                   d   S | j                   d   S )Nr   r   r8   r   s    r   __repr__zManagerMsg.__repr__   s,    %<<
++<<((r   r   )
__name__
__module____qualname____doc__r   r   r   rB   rE   rI    r   r   r	   r	   M   s#    %><"4%/#)r   r	   c                   6    e Zd ZdZd Zd Zd	dZd Zd Zd Z	y)
r   z>Manager interface Events, __init__ expects and 'Event' messagec                     || _         |j                  | _        |j                  | _        |j                  d      st	        d      |j                  d      | _        y )Nr   z-Trying to create event from non event message)messager   r   r   ManagerExceptionrB   r4   )r   rQ   s     r   r   zEvent.__init__   sW     LL	 !!'*"?A A &&w/	r   c                     || j                   v S r7   r8   r9   s     r   r   zEvent.has_header   r;   r   Nc                 :    | j                   j                  ||      S r=   r>   r@   s      r   rB   zEvent.get_header   rC   r   c                      | j                   |   S r=   r8   r9   s     r   rE   zEvent.__getitem__   rF   r   c                      | j                   d   S )Nr   r8   rH   s    r   rI   zEvent.__repr__   s    ||G$$r   c                 :    | j                   j                  dd      S )Nr   r   r>   rH   s    r   get_action_idzEvent.get_action_id   s    ||
D11r   r   )
rJ   rK   rL   rM   r   r   rB   rE   rI   rX   rN   r   r   r   r      s#    H0%/#%2r   r   c            
           e Zd Zd Zd Zd Zd Zi fdZd Zd Z	d Z
d	 Zd
 Zd'dZd Zd Zd Zd Zd Zd(dZd)dZdddddddddi f
dZd Zd Zd Zd Zd Zd Zd Zd Zd Zd  Zd! Z d" Z!d# Z"d$ Z#d% Z$y&)*Managerc                    d | _         d | _        t        j                         | _        t        j                         | _        t        j                         | _        t        j                         | _        t        j                         | _        t        j                         | _        i | _        g | _        t        j                          | _        d| _        t        j&                  | j(                        | _        t        j&                  | j,                        | _        | j*                  j1                  d       | j.                  j1                  d       y )Nr   targetT)_socktitle	threadingr   
_connected_runningsocketgethostnamehostnamer   Queue_message_queue_response_queue_event_queue_event_callbacks_reswaitingLock_seqlock_seqThreadmessage_loopmessage_threadevent_dispatchevent_dispatch_thread	setDaemonrH   s    r   r   zManager.__init__   s    

#//+!) **, $kkm${{}!KKM !# "(	 (..d6G6GH%.%5%5&&&(" 	%%d+"",,T2r   c                 $    | j                          y r   )closerH   s    r   __del__zManager.__del__   s    

r   c                 6    | j                   j                         S )z3
        Check if we are connected or not.
        )ra   isSetrH   s    r   	connectedzManager.connected   s     $$&&r   c                    | j                   j                          	 | j                  | xj                  dz  c_        | j                   j                          S # | xj                  dz  c_        | j                   j                          w xY w)zAReturn the next number in the sequence, this is used for ActionIDr%   )rm   acquirern   releaserH   s    r   next_seqzManager.next_seq   s\    	$99IINIMM!!# IINIMM!!#s   A 1Bc                    | j                   j                         st        d      |j                  |       d|vr"d| j                  | j                         fz  |d<   g }|j                         D ]_  \  }}t        |t              r)|D ]#  }t        ||g      }|j                  d|z         % ?t        ||g      }|j                  d|z         a |j                  t               t        j                  |      }	 | j                  j                  |j                  dd             | j                  j!                          | j,                  j/                  dd	       | j0                  j3                         }	| j,                  j5                  d       |	st'        dd
      |	S # t"        j$                  $ r%}t'        |j(                  |j*                        d}~ww xY w)a  
        Send a command to the manager

        If a list is passed to the cdict argument, each item in the list will
        be sent to asterisk under the same header in the following manner:

        cdict = {"Action": "Originate",
                 "Variable": ["var1=value", "var2=value"]}
        send_action(cdict)

        ...

        Action: Originate
        Variable: var1=value
        Variable: var2=value
        zNot connectedr   z%s-%08xz%s: %sutf8ignoreNr   r%   zConnection Terminated)ra   ry   rR   updatere   r~   items
isinstancelisttupleappendEOLr/   r^   writeencodeflushrc   errorManagerSocketExceptionerrnostrerrorrk   insertrh   r?   pop)
r   cdictkwargsclistkeyr5   itemcommander   s
             r   send_actionzManager.send_action   s   $ $$&"?33 	V U" )T]]DMMO,L LE*  ++- 	.JC%&! 2D #t-DLLD12 c5\*X_-	. 	S((5/	>JJW^^F8<=JJ 	1%''++-Q(,CDD || 	>(!**==	>s   <AF" "G5 GGc                    d}d}d}d}| j                   j                         r| j                  j                         rd	 g }| j                  D ]  }|j	                  dd      }| j
                  s{d|v rwd|vrs|j                  d      d   j                         | _        |j                  d      d   j                         | _        |j                  d       |j                  |        n-|t        k(  r$|s"d}|s| j                  j                         s nd	|v rd
}d
}|j                  |       |j                  d      rd|vrd
}|s;|s9|j                  d      r(|j                  dd      d   j                         dk(  rd
}|r4|j                  d      s|j                         j                  d      rd}d}|rd|v rd}d}| j                  j                         r n5 | j                  j                          | j                  j                          |r6| j                  j                         r| j                  j!                  |       n| j                  j!                  d       | j                   j                         r| j                  j                         rbyyyy# t"        j$                  $ rR | j                  j                          | j                  j                          | j                  j!                  d       Y w xY w)z3
        Read the response from a command.
        Fr   r   r   /r$   r%   zResponse: Generated Header
zstatus will followTr   r   Followsr   StatusCompleteN)rb   ry   ra   r^   decoder_   r,   r   versionr   r   r*   
startswithrv   clearrg   putrc   r   )r   	multilinestatuswait_for_markereolcountlinesr1   s          r   _receive_datazManager._receive_data)  s   
 	mm!!#(=(=(?@. JJ 5,D;;vh7D::#+cTk%)ZZ_Q%7%=%=%?
'+zz#q'9'?'?'A%EFT* s{?$)	 (=(=(?!  ,t3!%*.LL&  ==0CtO$(	 &T__Z5P JJsA.q1779YF*. doo6G&HDJJLLaLabsLt*/$)	"2d":*/!&??002c5,h JJ$$&OO))+T__224''++E2''++D1{ mm!!#(=(=(?#(?#| << .

  "%%'##''-.s    FJ% !B
J% %A"L
	L
c                 |    | j                   j                  |g       }|j                  |       || j                   |<   y)z
        Register a callback for the specfied event.
        If a callback function returns True, no more callbacks for that
        event will be executed.
        N)rj   r?   r   r   eventfunctioncurrent_callbackss       r   register_eventzManager.register_eventv  s;     !1155eR@  *'8e$r   c                 |    | j                   j                  |g       }|j                  |       || j                   |<   y)z@
        Unregister a callback for the specified event.
        N)rj   r?   remover   s       r   unregister_eventzManager.unregister_event  s;     !1155eR@  *'8e$r   c                    t        j                  | j                        }|j                  d       |j	                          	 | j
                  j                         r| j                  j                         }|sH| j                  j                  d       | j                  D ]  }| j                  j                  d        nt        |      }|j                  d      r%| j                  j                  t        |             nE|j                  d      r| j                  j                  |       nt!        d|j"                  z         | j
                  j                         r|j%                          y# |j%                          w xY w)z
        The method for the event thread.
        This actually recieves all types of messages and places them
        in the proper queues.
        r\   TNr   r   zNo clue what we got
%s)r`   ro   r   rt   startrb   ry   rg   r?   ri   r   rk   rh   r	   r   r   printr   r/   )r   tr   waiterrQ   s        r   rp   zManager.message_loop  s,    D$6$67	D			--%%'**..0 %%))$/"&"2"2 7,,0067 %T* %%g.%%))%.9''
3((,,W53gllBC- --%%'2 FFHAFFHs   DE5 5Fc                 T   | j                   j                         r| j                  j                         }|sy| j                  j                  |j
                  g       | j                  j                  dg       z   }|D ]  } |||       s n | j                   j                         ryy)z1This thread is responsible for dispatching eventsr   N)rb   ry   ri   r?   rj   r4   )r   ev	callbackscallbacks       r   rr   zManager.event_dispatch  s     mm!!#""&&(B 
 ..22277B?0044S"=>I & B% mm!!#r   c                    | j                   j                         rt        d      t        |      t        u sJ t        |      }	 t        j                  t        j                  t        j                        }|j                  ||f       t        r|j                  dd      | _        n|j                         | _        |j                          | j                   j%                          | j&                  j%                          | j(                  j+                          | j,                  j+                          | j.                  j1                         S # t        j                  $ r%}t        |j                   |j"                        d}~ww xY w)z Connect to the manager interfacezAlready connected to managerrwbr   )mode	bufferingN)ra   ry   rR   typestrintrc   AF_INETSOCK_STREAMconnectr   makefiler^   rv   r   r   r   r   setrb   rq   r   rs   rh   r?   )r   hostportr^   r   s        r   r   zManager.connect  s&    ??  ""#ABB DzS   4y		>MM&..&2D2DEEMM4,'"^^!^D
"^^-
KKM
 	 	!!# 	""((* ##'')) || 	>(!**==	>s   B	E F# FFc                    | j                   j                         r*| j                  j                         r| j                          | j                   j                         rp| j                  j                  d       | j                  j                          t        j                         | j                  k7  r| j                  j                          | j                   j                          y)z&Shutdown the connection to the managerN)rb   ry   ra   logoffrg   r   rq   r/   r`   currentThreadrs   r   rH   s    r   rv   zManager.close  s     == T__%:%:%<KKM== ##D) $$& &&(D,F,FF**//1r   c                     ddi}||d<   ||d<   | j                  |      }|j                  d      dk(  rt        |j                  d            |S )zBLogin to the manager, throws ManagerAuthException when login falisActionLoginUsernameSecretr   ErrorMessage)r   rB   ManagerAuthException)r   usernamesecretr   r   s        r   loginzManager.login  s_     7#$j h##E*z*g5&x':':9'EFFr   c                 0    ddi}| j                  |      }|S )z!Send a ping action to the managerr   Pingr   r   r   r   s      r   pingzManager.ping  s!    6"##E*r   c                 0    ddi}| j                  |      }|S )zLogoff from the managerr   Logoffr   r   s      r   r   zManager.logoff  s#     8$##E*r   c                 :    ddi}||d<   | j                  |      }|S )zHangup the specified channelr   HangupChannelr   r   channelr   r   s       r   hangupzManager.hangup!  -     8$"i##E*r   r   c                 :    ddi}||d<   | j                  |      }|S )z"Get a status message from asteriskr   Statusr   r   r   s       r   r   zManager.status*  r   r   c                 j    ddi}||d<   ||d<   ||d<   |r||d<   |r||d<   | j                  |      }|S )zRedirect a channelr   Redirectr   ExtenPriorityContextExtraChannelr   )r   r   extenpriorityextra_channelcontextr   r   s           r   redirectzManager.redirect3  sZ     :&"ig$j&E)$1E.!##E*r   Ffalsec           
      d   ddi}||d<   ||d<   |r||d<   |r||d<   |r||d<   |r||d<   |r||d	<   |r||d
<   |	rd|d<   |
r|
|d<   |r||d<   |rI|j                         D cg c]*  \  }}dj                  t        |      t        |      f      , c}}|d<   | j                  |      }|S c c}}w )zOriginate a callr   	Originater   r   r   r   TimeoutApplicationDataCallerIDyesAsync
EarlyMediaAccountr(   Variable)r   r/   r   r   )r   r   r   r   r   timeoutapplicationr   	caller_id	run_async
earlymediaaccount	variablesr   r   r5   r   s                    r   	originatezManager.originateB  s     ;'"ig&E) (E*&E)#.E-  E&M )E*"E'N",E,&E) :C//:K!M,6C "%S3u:&"( !ME* ##E*!Ms   #/B,c                 :    ddi}||d<   | j                  |      }|S )z&Get the status of the specfied mailboxr   MailboxStatusMailboxr   r   mailboxr   r   s       r   mailbox_statuszManager.mailbox_statuse  s-     ?+"i##E*r   c                 :    ddi}||d<   | j                  |      }|S )zExecute a commandr   Commandr   )r   r   r   r   s       r   r   zManager.commandn  s-     9%"i##E*r   c                 D    ddi}||d<   ||d<   | j                  |      }|S )zGet the state of an extensionr   ExtensionStater   r   r   )r   r   r   r   r   s        r   extension_statezManager.extension_statew  s7     +,g"i##E*r   c                 D    ddi}||d<   ||d<   | j                  |      }|S )z+Plays a dtmf digit on the specified channelr   PlayDTMFr   Digitr   )r   r   digitr   r   s        r   playdtmfzManager.playdtmf  s6     :&"ig##E*r   c                 D    ddi}||d<   ||d<   | j                  |      }|S )z$Set an absolute timeout on a channelr   AbsoluteTimeoutr   r   r   )r   r   r   r   r   s        r   absolute_timeoutzManager.absolute_timeout  s8     ,-"i"i##E*r   c                 :    ddi}||d<   | j                  |      }|S )Nr   MailboxCountr  r   r	  s       r   mailbox_countzManager.mailbox_count  s+    >*"i##E*r   c                 0    ddi}| j                  |      }|S )Nr   Sippeersr   r   s      r   sippeerszManager.sippeers  s!    :&##E*r   c                 :    ddi}||d<   | j                  |      }|S )Nr   SIPshowpeerPeerr   )r   peerr   r   s       r   sipshowpeerzManager.sipshowpeer  s*    =)f##E*r   c                 0    ddi}| j                  |      }|S )Nr   SIPShowregistryr   r   s      r   sipshowregistryzManager.sipshowregistry  s"    ,-##E*r   c                 0    ddi}| j                  |      }|S )Nr   IAXregistryr   r   s      r   iaxregistryzManager.iaxregistry  s!    =)##E*r   c                 :    ddi}||d<   | j                  |      }|S )z# Reloads config for a given module r   ReloadModuler   )r   moduler   r   s       r   reloadzManager.reload  s,     8$ h##E*r   c                 D    ddi}||d<   ||d<   | j                  |      }|S )Nr   DBDelFamilyKeyr   r   familyr   r   r   s        r   dbdelzManager.dbdel  3    7# he##E*r   c                 D    ddi}||d<   ||d<   | j                  |      }|S )Nr   	DBDelTreer1  r2  r   r3  s        r   	dbdeltreezManager.dbdeltree  s3    ;' he##E*r   c                 D    ddi}||d<   ||d<   | j                  |      }|S )Nr   DBGetr1  r2  r   r3  s        r   dbgetzManager.dbget  r6  r   c                 N    ddi}||d<   ||d<   ||d<   | j                  |      }|S )Nr   DBPutr1  r2  Valr   )r   r4  r   valr   r   s         r   dbputzManager.dbput  s<    7# hee##E*r   N)i  )r   )1r   r   )%rJ   rK   rL   r   rw   rz   r~   r   r   r   r   rp   rr   r   rv   r   r   r   r   r   r   r  r  r   r  r  r  r  r  r#  r&  r)  r.  r5  r9  r<  rA  rN   r   r   rZ   rZ      s    3>'$ !# 7rK.Z99'R."*H. 13RY[bdpr  D  QX  bd  pr !F


r   rZ   c                       e Zd Zy)rR   NrJ   rK   rL   rN   r   r   rR   rR         r   rR   c                       e Zd Zy)r   NrD  rN   r   r   r   r     rE  r   r   c                       e Zd Zy)r   NrD  rN   r   r   r   r     rE  r   r   )rM   sysosrc   r`   sixr   	six.movesr   retypestimer   r   objectr	   r   rZ   	ExceptionrR   r   r   rN   r   r   <module>rQ     s~   :x  	     	  J) J)Z!2F !2HTf Tl	y 		- 		+ 	r   