]>
git.ipfire.org Git - ipfire.org.git/blob - src/backend/asterisk.py
11 from .decorators
import *
13 # Make this less verbose
14 logging
.getLogger("panoramisk").setLevel(logging
.INFO
)
16 class Asterisk(misc
.Object
):
20 loop
= asyncio
.get_event_loop()
22 # Connect as soon as the event loop starts
23 loop
.create_task(self
.connect())
27 if not self
.__manager
:
28 raise RuntimeError("Asterisk is not connected")
32 async def connect(self
):
36 manager
= panoramisk
.Manager(
37 host
= self
.settings
.get("asterisk-ami-host"),
38 username
= self
.settings
.get("asterisk-ami-username"),
39 secret
= self
.settings
.get("asterisk-ami-secret"),
41 on_connect
=self
._on
_connect
,
45 await manager
.connect()
49 def _on_connect(self
, manager
):
50 logging
.debug("Connection to Asterisk established")
52 # Close any existing connections
54 self
.__manager
.close()
56 self
.__manager
= manager
58 async def _fetch(self
, cls
, action
, filter=None, data
={}):
62 args
= { "Action" : action
} | data
64 # Run the action and parse all messages
65 for data
in await self
.manager
.send_action(args
):
66 if not "Event" in data
or not data
.Event
== cls
.event
:
69 # Create the object and append it to the list
70 o
= cls(self
.backend
, data
)
72 # Filter out anything unwanted
73 if filter and not o
.matches(filter):
80 async def get_sip_channels(self
, filter=None):
81 return await self
._fetch
(Channel
, "CoreShowChannels", filter=filter)
83 async def get_registrations(self
, filter=None):
84 return await self
._fetch
(Registration
, "PJSIPShowContacts", filter=filter)
86 async def get_outbound_registrations(self
):
87 return await self
._fetch
(OutboundRegistration
, "PJSIPShowRegistrationsOutbound")
89 async def get_queues(self
):
91 queues
= { q
.name
: q
for q
in await self
._fetch
(Queue
, "QueueSummary") }
94 for member
in await self
._fetch
(QueueMember
, "QueueStatus"):
95 # Append to the matching queue
97 queues
[member
.queue
].members
.append(member
)
101 return queues
.values()
103 async def get_conferences(self
):
104 conferences
= await self
._fetch
(Conference
, "ConfbridgeListRooms")
106 # Fetch everything else
107 async with asyncio
.TaskGroup() as tasks
:
108 for c
in conferences
:
109 tasks
.create_task(c
._fetch
())
114 class Channel(misc
.Object
):
115 event
= "CoreShowChannel"
117 def init(self
, data
):
121 return self
.connected_line
124 def account_code(self
):
125 return self
.data
.AccountCode
128 def connected_line(self
):
129 return self
.data
.ConnectedLineName
or self
.data
.ConnectedLineNum
131 def matches(self
, filter):
133 self
.data
.CallerIDNum
,
138 h
, m
, s
= self
.data
.Duration
.split(":")
141 h
, m
, s
= int(h
), int(m
), int(s
)
145 return datetime
.timedelta(hours
=h
, minutes
=m
, seconds
=s
)
147 def is_connected(self
):
148 return self
.data
.ChannelStateDesc
== "Up"
150 def is_ringing(self
):
151 return self
.data
.ChannelStateDesc
== "Ringing"
154 class Registration(misc
.Object
):
155 event
= "ContactList"
157 def init(self
, data
):
160 def __lt__(self
, other
):
161 if isinstance(other
, self
.__class
__):
162 if isinstance(self
.user
, accounts
.Account
):
163 if isinstance(other
.user
, accounts
.Account
):
164 return self
.user
< other
.user
166 return self
.user
.name
< other
.user
168 if isinstance(other
.user
, accounts
.Account
):
169 return self
.user
< other
.user
.name
171 return self
.user
< other
.user
173 return NotImplemented
176 return self
.user_agent
178 def matches(self
, filter):
179 return self
.data
.Endpoint
== filter
183 return urllib
.parse
.urlparse(self
.data
.Uri
)
186 def uri_params(self
):
189 for param
in self
.uri
.params
.split(";"):
190 key
, _
, value
= param
.partition("=")
198 return self
.uri_params
.get("transport")
202 return self
.backend
.accounts
.get_by_sip_id(self
.data
.Endpoint
) or self
.data
.Endpoint
207 user
, _
, address
= self
.uri
.path
.partition("@")
210 address
, _
, port
= address
.rpartition(":")
215 def user_agent(self
):
216 return self
.data
.UserAgent
.replace("_", " ")
221 return int(self
.data
.RoundtripUsec
) / 1000
226 class OutboundRegistration(misc
.Object
):
227 event
= "OutboundRegistrationDetail"
229 def init(self
, data
):
232 def __lt__(self
, other
):
233 if isinstance(other
, self
.__class
__):
234 return self
.server
< other
.server
or self
.username
< other
.username
236 return NotImplemented
240 return urllib
.parse
.urlparse(self
.data
.ClientUri
)
244 username
, _
, server
= self
.uri
.path
.partition("@")
250 username
, _
, server
= self
.uri
.path
.partition("@")
256 return self
.data
.Status
259 class Queue(misc
.Object
):
260 event
= "QueueSummary"
262 def init(self
, data
):
272 return self
.data
.Queue
274 def is_available(self
):
275 return self
.data
.Available
== "1"
279 return int(self
.data
.Callers
)
282 class QueueMember(misc
.Object
):
283 event
= "QueueMember"
285 def init(self
, data
):
293 return self
.data
.Name
297 return self
.data
.Queue
300 def calls_taken(self
):
301 return int(self
.data
.CallsTaken
)
303 def is_in_call(self
):
304 return self
.data
.InCall
== "1"
307 def last_call_at(self
):
308 return datetime
.datetime
.fromtimestamp(int(self
.data
.LastCall
))
311 def logged_in_at(self
):
312 return datetime
.datetime
.fromtimestamp(int(self
.data
.LoginTime
))
317 class Conference(misc
.Object
):
318 event
= "ConfbridgeListRooms"
320 def init(self
, data
):
328 return self
.data
.Conference
330 async def _fetch(self
):
332 self
.members
= await self
.backend
.asterisk
._fetch
(
333 ConferenceMember
, "ConfbridgeList", data
={ "Conference" : self
.name
, })
336 class ConferenceMember(misc
.Object
):
337 event
= "ConfbridgeList"
339 def init(self
, data
):
345 def __lt__(self
, other
):
346 if isinstance(other
, self
.__class
__):
347 return not self
.duration
< other
.duration
349 return NotImplemented
353 return "%s <%s>" % (self
.data
.CallerIDName
, self
.data
.CallerIDNum
)
356 return self
.data
.Admin
== "Yes"
359 return self
.data
.Muted
== "Yes"
363 return datetime
.timedelta(seconds
=int(self
.data
.AnsweredTime
))