Skip to main content

Async agi client/server framework (asyncio)

Project description

Aioagi

Async agi client/server framework. The project based on “aiohttp” framework.

Key Features

  • Supports both client and server side of AGI protocol.

  • AGI-server has middlewares and pluggable routing.

Getting started

Server

Simple AGI server:

import asyncio

from aiohttp.web import Application, AppRunner, TCPSite, Response

from aioagi import runner
from aioagi.app import AGIApplication
from aioagi.log import agi_server_logger
from aioagi.urldispathcer import AGIView
from aiohttp.web_runner import GracefulExit


async def hello(request):
    message = await request.agi.stream_file('hello-world')
    await request.agi.verbose('Hello handler: {}.'.format(request.rel_url.query))
    agi_server_logger.debug(message)


async def http_hello(request):
    return Response(text="Hello, world")


class HelloView(AGIView):
    async def sip(self):
        message = await self.request.agi.stream_file('hello-world')
        await self.request.agi.verbose('HelloView handler: {}.'.format(self.request.rel_url.query))
        agi_server_logger.debug(message)


if __name__ == '__main__':
    app = AGIApplication()
    app.router.add_route('SIP', '/', hello)
    runner.run_app(app)

# OR
if __name__ == '__main__':
    apps = []

    app = AGIApplication()
    app.router.add_route('SIP', '/', hello)

    http_app = Application()
    http_app.router.add_route('GET', '/', http_hello)

    loop = asyncio.get_event_loop()

    runners = []
    sites = []
    for _app in [app, http_app]:
        app_runner = AppRunner(_app)
        loop.run_until_complete(app_runner.setup())
        if isinstance(_app, AGIApplication):
            sites.append(runner.AGISite(app_runner, port=8081))
        else:
            sites.append(TCPSite(app_runner, port=8080))

        runners.append(app_runner)

    for site in sites:
        loop.run_until_complete(site.start())

    uris = sorted(str(s.name) for runner in runners for s in runner.sites)
    print("======== Running on {} ========\n"
          "(Press CTRL+C to quit)".format(', '.join(uris)))

    try:
        loop.run_forever()
    except (GracefulExit, KeyboardInterrupt):  # pragma: no cover
        pass

    finally:
        for runner in reversed(runners):
            loop.run_until_complete(runner.cleanup())

    if hasattr(loop, 'shutdown_asyncgens'):
        loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close()

Client

To set AGI connection as Asterisk:

import asyncio
import logging.config

from aioagi.log import agi_client_logger
from aioagi.client import AGIClientSession
from aioagi.parser import AGIMessage, AGICode


async def test_request(loop):
    headers = {
        'agi_channel': 'SIP/100-00000001',
        'agi_language': 'ru',
        'agi_uniqueid': '1532375920.8',
        'agi_version': '14.0.1',
        'agi_callerid': '100',
        'agi_calleridname': 'test',
        'agi_callingpres': '0',
        'agi_callingani2': '0',
        'agi_callington': '0',
        'agi_callingtns': '0',
        'agi_dnid': '101',
        'agi_rdnis': 'unknown',
        'agi_context': 'from-internal',
        'agi_extension': '101',
        'agi_priority': '1',
        'agi_enhanced': '0.0',
        'agi_accountcode': '',
        'agi_threadid': '139689736754944',
    }
    async with AGIClientSession(headers=headers, loop=loop) as session:
        async with session.sip('agi://localhost:8080/hello/?a=test1&b=var1') as response:
            async for message in response:
                client_logger.debug(message)
                await response.send(AGIMessage(AGICode.OK, '0', {}))

        async with session.sip('agi://localhost:8080/hello-view/?a=test2&b=var2') as response:
            async for message in response:
                client_logger.debug(message)
                await response.send(AGIMessage(AGICode.OK, '0', {}))
agi_type: SIP
agi_network: yes
agi_network_script: hello/
agi_request: agi://localhost:8080/hello/

AMI

import asyncio

from aioagi.ami.action import AMIAction
from aioagi.ami.manager import AMIManager


async def callback(manager, message):
    print(message)


async def main(app):
    manager = AMIManager(
        app=app, title='myasterisk',
        host='127.0.0.1',
        port=5038,
        username='username',
        secret='secret',
    )
    manager.register_event('*', callback)
    app['manager'] = manager
    await manager.connect()

    await asyncio.sleep(2)

    message = await manager.send_action(AMIAction({
        'Action': 'Command',
        'Command': 'database show',
    }))
    print(message)
    print(message.body)


async def cleanup(app):
    app['manager'].close()


if __name__ == '__main__':
    app = {}
    _loop = asyncio.get_event_loop()
    try:
        _loop.run_until_complete(main(app))
    except KeyboardInterrupt:
        _loop.run_until_complete(cleanup(app))
        _loop.close()

Install

pip install aioagi

Thanks

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aioagi_ik-1.3.1.tar.gz (35.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aioagi_ik-1.3.1-py3-none-any.whl (40.2 kB view details)

Uploaded Python 3

File details

Details for the file aioagi_ik-1.3.1.tar.gz.

File metadata

  • Download URL: aioagi_ik-1.3.1.tar.gz
  • Upload date:
  • Size: 35.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.3

File hashes

Hashes for aioagi_ik-1.3.1.tar.gz
Algorithm Hash digest
SHA256 598ec75ebb00ea7260d245a6d9203edeb08dcbf5a1217136e4aafc00987b000d
MD5 11018d2884e7f9c1a0101070847b4634
BLAKE2b-256 581b5f20b8a5e16312efd1042b8fe35ffd3db1086d9fa5ba0955de79b9529bad

See more details on using hashes here.

File details

Details for the file aioagi_ik-1.3.1-py3-none-any.whl.

File metadata

  • Download URL: aioagi_ik-1.3.1-py3-none-any.whl
  • Upload date:
  • Size: 40.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.12.3

File hashes

Hashes for aioagi_ik-1.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5e2be285f1ce6479efc6746512c8c649978f5ec7082ea944b086064afd447122
MD5 1dd23861236e4ca3afe1299591f7b359
BLAKE2b-256 e35750e85064727111b9dcceee44a9e111380403fe28b7cbd8fa829bbedea73b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page