Example #1
1
def queue_status():
    MANAGER = Manager(loop=asyncio.get_event_loop(), host='127.0.0.1', username='******', secret='password')
    yield from MANAGER.connect()
    queues_details = yield from MANAGER.send_action({'Action': 'QueueStatus', 'Queue': 'queue_name'})
    pprint(queues_details)
Example #2
0
def main():
    """Função principal da aplicação."""
    manager = Manager(
        loop=asyncio.get_event_loop(),
        host=ASTERISK_IP,
        port=ASTERISK_PORT,
        username=ASTERISK_USER,
        secret=ASTERISK_PASSWORD,
    )

    @manager.register_event("QueueCallerLeave")
    @manager.register_event("AgentCalled")
    @manager.register_event("AgentConnect")
    @manager.register_event("AgentComplete")
    @manager.register_event("AgentDump")
    # @manager.register_event("AgentRingNoAnswer")
    @manager.register_event("MessageWaiting")
    # @manager.register_event('UserEvent')
    async def callback_agent(manager, message):
        fire(message)

    @manager.register_event("Hangup")
    async def callback_hangup(manager, message):
        # hangup from queue, external only
        if message.context == "ext-queues":
            fire(message)

    manager.connect()
    try:
        manager.loop.run_forever()
    except KeyboardInterrupt:
        manager.loop.close()
Example #3
0
    def attach(self, amihost):
        """
        attach amihost to a ChannelManager.

        Args:
            amihost (dict): A dictionary containing the connection settings for
                an AMI host.
        """
        # Create Panoramisk asterisk AMI manager.
        amimgr = Manager(loop=self.loop,
                         host=amihost['host'],
                         port=amihost['port'],
                         username=amihost['username'],
                         secret=amihost['password'],
                         ssl=False,
                         encoding='utf8',
                         log=self.logger)

        # Create our own channel manager.
        channel_manager = self.channel_manager(reporter=self.reporter, )

        # Tell Panoramisk to which events we want to listen.
        for event_name in channel_manager.INTERESTING_EVENTS:
            amimgr.register_event(event_name, self.on_event)

        # Record them for later use.
        self.amimgrs[amimgr] = channel_manager

        # Tell asyncio what to work on.
        asyncio.ensure_future(amimgr.connect())
def extension_status():
    manager = Manager(loop=asyncio.get_event_loop(), host='127.0.0.1', username='******', secret='password')
    yield from manager.connect()
    extension = yield from manager.send_action_via_manager({'Action': 'ExtensionState',
                                                            'Exten': '2001',
                                                            'Context': 'default'})
    pprint(extension)
Example #5
0
    def attach(self, amihost):
        """
        attach amihost to a ChannelManager.

        Args:
            amihost (dict): A dictionary containing the connection settings for
                an AMI host.
        """
        # Create Panoramisk asterisk AMI manager.
        amimgr = Manager(
            loop=self.loop, host=amihost['host'], port=amihost['port'],
            username=amihost['username'], secret=amihost['password'],
            ssl=False, encoding='utf8')

        # Create our own channel manager.
        channel_manager = self.channel_manager(
            reporter=self.reporter,
        )

        # Tell Panoramisk to which events we want to listen.
        channel_manager._pre_connect(amimgr)

        # Record them for later use.
        self.amimgrs.append(amimgr)
        self.channel_managers.append(channel_manager)

        # Tell asyncio what to work on.
        asyncio.async(amimgr.connect())
Example #6
0
class Bridge:
    def __init__(self, options, filters, push_configs):
        self.loop = asyncio.get_event_loop()

        max_queues = options.pop("max_size", DEFAULT_MAX_QUEUES)
        max_queue_size = options.pop("max_queue_size", DEFAULT_MAX_QUEUE_SIZE)
        self.controller = Controller(self.loop, max_queues, max_queue_size)
        self.controller.load_configs(filters, push_configs)

        options.pop("loop", None)  # discard invalid argument
        self.manager = Manager(loop=self.loop, **options)
        self.manager.log.addHandler(logging.NullHandler())
        self.manager.register_event("*", self.handle_events)

    @asyncio.coroutine
    def handle_events(self, manager, message):
        wrapper = MessageWrapper(message)
        yield from self.controller.handle(wrapper)

    @asyncio.coroutine
    def connect(self):
        yield from self.manager.connect()

    def run(self):
        try:
            self.loop.run_until_complete(self.connect())
            self.loop.run_forever()
        finally:
            self.loop.close()
Example #7
0
def queue_status():
    manager = Manager(loop=asyncio.get_event_loop(),
                      host='127.0.0.1', port=5039,
                      username='******', secret='mysecret')
    yield from manager.connect()
    queues_details = yield from manager.send_action({'Action': 'QueueStatus', 'Queue': 'queue_name'})
    manager.close()
    pprint(queues_details)
def extension_status():
    manager = Manager(loop=asyncio.get_event_loop(),
                      host='127.0.0.1', port=5039,
                      username='******', secret='password')
    yield from manager.connect()
    extension = yield from manager.send_action({'Action': 'ExtensionState',
                                                'Exten': '2001',
                                                'Context': 'default'})
    manager.close()
    pprint(extension)
Example #9
0
def originate():
    manager = Manager(loop=asyncio.get_event_loop(), host='127.0.0.1', username='******', secret='password')
    yield from manager.connect()
    result = yield from manager.send_action_via_manager({'Action': 'Originate',
                                                            'Channel': 'SIP/gawel',
                                                            'WaitTime': 20,
                                                            'CallerID': 'gawel',
                                                            'Exten': '0299999999',
                                                            'Context': 'default',
                                                            'Priority': 1,})
    pprint(result)
Example #10
0
def ping(lp, username, secret):
    manager = Manager(loop=lp,
                      host='127.0.0.1', port=5038,
                      username=username, secret=secret,
                      forgetable_actions=('login',))
    yield from manager.connect()
    while True:
        p = yield from manager.send_action({'Action': 'ping'})
        # p = yield from manager.send_action({'Action': 'SIPpeers'})
        pprint(p)
        yield from asyncio.sleep(1)
    manager.close()
Example #11
0
def queue_status():
    MANAGER = Manager(loop=asyncio.get_event_loop(),
                      host='127.0.0.1',
                      username='******',
                      secret='password')
    yield from MANAGER.connect()
    queues_details = yield from MANAGER.send_action_via_manager({
        'Action':
        'QueueStatus',
        'Queue':
        'queue_name'
    })
    pprint(queues_details)
Example #12
0
def ping(lp, username, secret):
    manager = Manager(loop=lp,
                      host='127.0.0.1',
                      port=5038,
                      username=username,
                      secret=secret,
                      forgetable_actions=('login', ))
    yield from manager.connect()
    while True:
        p = yield from manager.send_action({'Action': 'ping'})
        # p = yield from manager.send_action({'Action': 'SIPpeers'})
        pprint(p)
        yield from asyncio.sleep(1)
    manager.close()
Example #13
0
def test_reconnection_without_lost(event_loop, unused_tcp_port_factory):
    unused_tcp_port = unused_tcp_port_factory()

    print('Start server on %s' % unused_tcp_port)
    manager = Manager(loop=event_loop,
                      host='127.0.0.1',
                      port=unused_tcp_port,
                      username='******',
                      secret='secret')
    server = Asterisk(event_loop, unused_tcp_port)

    yield from server.start()
    yield from manager.connect()
    yield from server.data_received()
    login = server.actions[0]
    assert login['action'] == 'Login'
    unused_tcp_port = unused_tcp_port_factory()

    print('Restart server on %s' % unused_tcp_port)
    server.port = unused_tcp_port
    manager.config['port'] = unused_tcp_port
    yield from server.stop()

    manager.send_action({'Action': 'Ping'})
    f = manager.send_action({'Action': 'Test', 'Command': 'test'})
    fully_booted = Event('FullyBooted')

    yield from asyncio.sleep(.1)
    assert manager.awaiting_actions
    yield from server.start()
    yield from asyncio.sleep(2)
    assert manager.awaiting_actions
    manager.dispatch(fully_booted)
    yield from asyncio.sleep(.5)
    assert not manager.awaiting_actions
    resp = yield from f
    yield from server.stop()

    login2 = server.actions[0]
    assert login2['action'] == 'Login'
    assert login['actionid'] != login2['actionid']

    test_action = server.actions[-1]
    assert test_action.id == resp.id
    assert test_action['action'] == 'Test'
Example #14
0
def test_reconnection_without_lost(event_loop):
    unused_tcp_port = unused_tcp_port_factory()

    print('Start server on %s' % unused_tcp_port)
    manager = Manager(loop=event_loop,
                      host='127.0.0.1',
                      port=unused_tcp_port,
                      username='******',
                      secret='secret')
    server = Asterisk(event_loop, unused_tcp_port)

    yield from server.start()
    yield from manager.connect()
    yield from server.data_received()
    login = server.actions[0]
    assert login['action'] == 'Login'
    unused_tcp_port = unused_tcp_port_factory()

    print('Restart server on %s' % unused_tcp_port)
    server.port = unused_tcp_port
    manager.config['port'] = unused_tcp_port
    yield from server.stop()

    manager.send_action({'Action': 'Ping'})
    f = manager.send_action({'Action': 'Test', 'Command': 'test'})
    fully_booted = Event('FullyBooted')

    yield from asyncio.sleep(.1)
    assert manager.awaiting_actions
    yield from server.start()
    yield from asyncio.sleep(2)
    assert manager.awaiting_actions
    manager.dispatch(fully_booted)
    yield from asyncio.sleep(.5)
    assert not manager.awaiting_actions
    resp = yield from f
    yield from server.stop()

    login2 = server.actions[0]
    assert login2['action'] == 'Login'
    assert login['actionid'] != login2['actionid']

    test_action = server.actions[-1]
    assert test_action.id == resp.id
    assert test_action['action'] == 'Test'
Example #15
0
    def attach(self, asterisk):
        """
        Set up a connection to the specified Asterisk

        Args:
            asterisk (str): A connection string
        """
        ami_host = urlparse(asterisk)

        # Create Panoramisk asterisk AMI manager.
        manager = Manager(loop=self.loop,
                          host=ami_host.hostname,
                          port=ami_host.port,
                          username=ami_host.username,
                          secret=ami_host.password,
                          ssl=ami_host.scheme in ('ssl', 'tls'),
                          encoding='utf8',
                          log=self.logger)

        # Create our own channel manager.
        event_handler = self.event_handler(
            reporter=self.reporter,
            hostname=ami_host.hostname,
            logger=self.logger,
        )

        # Tell Panoramisk to which events we want to listen.
        if event_handler.FILTER_EVENTS:
            for event_name in event_handler.event_handlers().keys():
                manager.register_event(event_name, self.on_event)
        else:
            manager.register_event('*', self.on_event)

        # Record them for later use.
        self.ami_managers[manager] = event_handler

        # Tell asyncio what to work on.
        asyncio.ensure_future(manager.connect())
Example #16
0
def putCids(lp, args, config):
    auth = HTTPBasicAuth(config['carddav']['user'], config['carddav']['pass'])
    url = config['carddav']['url']

    # connect to asterisk
    ami = Manager(host=config['ami']['host'],
                  port=config['ami']['port'],
                  username=config['ami']['user'],
                  secret=config['ami']['pass'])
    yield from ami.connect()

    # get phone numbers from vcard
    for vurl in getAllVcardLinks(url, auth):
        r = requests.request("GET", vurl, auth=auth)
        try:
            vcard = vobject.readOne(r.text)
        except ParseError as e:
            print(e)
            continue
        if "tel" in vcard.contents:
            for telno in vcard.contents['tel']:
                num = tidyPhoneNumber(config, telno.value)
                if num and "fn" in vcard.contents:
                    name = vcard.fn.value
                    print("Adding/updating Number: %s Name: %s" % (num, name),
                          end="... ")
                    if not args.no_update:
                        ami_result = yield from ami.send_action({
                            "Action": "DBPut",
                            "Family": "cidname",
                            "Key": num,
                            "Val": name
                        })
                        print(ami_result.Response)
                    else:
                        print("no-update")
    ami.close()
Example #17
0
class Asterisk(object):

    requires = ['irc3.plugins.command']

    def __init__(self, bot):
        self.bot = bot
        self.bot.asterirc = self
        self.config = config = dict(
            host='127.0.0.1',
            port=5038,
            http_port='8088',
            protocol='http',
            debug=True,
        )
        config.update(bot.config.get('asterisk', {}))
        self.log = logging.getLogger('irc3.ast')
        self.ilog = logging.getLogger('irc.asterirc')
        self.ilog.set_irc_targets(bot, self.config['channel'])
        self.log.info('Channel is set to {channel}'.format(**config))
        self.rooms = defaultdict(dict)
        self.http = None
        self.resolver = irc3.utils.maybedotted(self.config['resolver'])
        self.manager = Manager(log=logging.getLogger('irc3.ast.manager'),
                               **config)
        self.manager.register_event('Shutdown', self.handle_shutdown)
        self.manager.register_event('Meet*', self.handle_meetme)
        if config.get('debug'):
            self.manager.register_event('*', self.handle_event)
        if isinstance(self.resolver, type):
            self.resolver = self.resolver(bot)

    def connection_made(self):
        self.bot.loop.call_later(1, self.connect)

    def post_connect(self):
        self.log.debug('post_connect')
        resp = self.send_action({'Action': 'Status'})
        if resp.success:
            self.update_meetme()
        else:  # pragma: no cover
            self.log.error(resp.text)
            self.bot.loop.call_later(1, self.post_connect)

    def update_meetme(self):
        resp = self.send_command('meetme list')
        if resp.success:
            if 'No active MeetMe conferences.' in resp.text:
                self.rooms = defaultdict(dict)
            for line in resp.lines[1:-2]:
                room = line.split(' ', 1)[0]
                if not room or not room.isdigit():
                    continue
                resp = self.send_command('meetme list ' + room)
                if resp.success and resp.iter_lines():
                    room = self.rooms[room]
                    for line in resp.lines:
                        if not line.startswith('User '):
                            continue
                        line = line.split('Channel:')[0]
                        splited = [s for s in line.split() if s][2:]
                        uid = splited.pop(0)
                        caller = ' '.join(splited[1:])
                        if 'external call ' in caller.lower():
                            e, c, n = caller.split(' ')[:4]
                            caller = ' '.join([e, c, n[:6]])
                        room[caller] = uid

    def connect(self):
        if self.manager is not None:
            self.manager.close()
            self.bot.loop.call_later(5, self.post_connect)
        try:
            self.manager.connect()
        except Exception as e:
            self.log.exception(e)
            self.log.info('connect retry in 5s')
            self.bot.loop.call_later(1, self.connect)
            return False
        else:
            return True

    def handle_shutdown(self, event, manager):
        self.manager.close()
        self.bot.loop.call_later(2, self.connect)

    def handle_event(self, event, manager):
        self.log.debug('handle_event %s %s', event, '')  # , event.headers)

    def handle_meetme(self, event, manager):
        self.log.debug('handle_meetme %s %s', event, event.headers)
        lower_header_keys(event)
        name = event.name.lower()
        room = event['meetme']

        if name == 'meetmeend':
            if room in self.rooms:  # pragma: no cover
                del self.rooms[room]
            self.ilog.info('room {} is closed.'.format(room))
            return

        action = None
        caller = event['calleridname']
        if 'external call ' in caller.lower():
            e, c, n = caller.split(' ')[:4]
            caller = ' '.join([e, c, n[:6]])
        elif 'external call' in caller.lower():  # pragma: no cover
            caller += event['calleridnum'][:6]

        if 'join' in name:
            action = 'join'
            self.rooms[room][caller] = event['usernum']
        elif 'leave' in name:
            action = 'leave'
            if caller in self.rooms.get(room, []):
                del self.rooms[room][caller]

        if action:
            # log
            args = dict(caller=caller, action=action,
                        room=room, total=len(self.rooms[room]))
            self.ilog.info((
                '{caller} has {action} room {room} '
                '(total in this room: {total})').format(**args))

    def send_action(self, *args, **kwargs):
        try:
            res = self.manager.send_action(*args, **kwargs)
            return res
        except Exception as e:
            self.log.error('send_action(%r, **%r)', args, kwargs)
            self.log.exception(e)
            return Message('response',
                           'Sorry an error occured. ({})'.format(repr(e)),
                           headers={'Response': 'Failed'})

    def send_command(self, command, debug=False):
        resp = self.send_action({'Action': 'Command', 'Command': command})
        if debug:  # pragma: no cover
            self.log.debug('Command "%s" => Succeed: %s, Data:\n%s',
                           command, resp.success, getattr(resp, 'text', resp))
        if resp.success:
            resp.lines = []
            if resp['response'].lower() == 'follows':
                resp.lines = resp.text.split('\n')
        return resp

    @command(permission='voip')
    def call(self, mask, target, args):
        """Call someone. Destination and from can't contains spaces.

            %%call <destination> [<from>]

        """
        if 'nick' not in args:
            args['nick'] = mask.nick

        callee = self.resolver(mask, args['<destination>'])
        if args['<from>']:
            caller = self.resolver(mask, args['<from>'])
        else:
            caller = self.resolver(mask, mask.nick)

        if caller is None or caller.get('channel') is None:
            return '{nick}: Your caller is invalid.'.format(**args)
        if callee is None or callee.get('exten') is None:
            return '{nick}: Your destination is invalid.'.format(**args)

        action = {
            'Action': 'Originate',
            'Channel': caller['channel'],
            'WaitTime': 20,
            'CallerID': caller.get('fullname', caller['channel']),
            'Exten': callee['exten'],
            'Context': caller.get('context', 'default'),
            'Priority': 1,
        }
        resp = self.send_action(action)
        if resp.success:
            return '{nick}: Call to {<destination>} done.'.format(**args)
        else:
            return resp.text

    @command(permission='voip')
    def room(self, mask, target, args):
        """Invite/kick someone in a room. You can use more than one
        destination. Destinations can't contains spaces.

            %%room (list|invite|kick) [<room>] [<destination>...]

        """
        args['nick'] = mask.nick
        room = args['<room>']
        if args['invite']:

            callees = args['<destination>']
            message = '{nick}: {<from>} has been invited to room {<room>}.'
            if not callees:
                # self invite
                callees = [mask.nick]
                message = '{nick}: You have been invited to room {<room>}.'

            resolved = [self.resolver(mask, c) for c in callees]
            if None in resolved:
                # show invalid arguments and quit
                callees = zip(resolved, callees)
                invalid = [c for r, c in callees if r is None]
                yield (
                    "{0}: I'm not able to resolve {1}. Please fix it!"
                ).format(mask.nick, ', '.join(invalid))
                raise StopIteration()

            for callee in callees:
                # call each
                args['<destination>'] = args['<room>']
                args['<from>'] = callee
                msg = self.call(mask, target, args)
                if 'Call to' in msg:
                    yield message.format(**args)
                else:
                    yield msg

        if room and room not in self.rooms:
            yield 'Invalid room'
            raise StopIteration()

        if args['list']:
            def fmt(room, users):
                amount = len(users)
                users = ', '.join([u for u in sorted(users)])
                return 'Room {0} ({1}): {2}'.format(room, amount, users)

            if room:
                yield fmt(room, self.rooms[room])
            elif self.rooms:
                for room, users in self.rooms.items():
                    yield fmt(room, self.rooms[room])
            else:
                yield 'Nobody here.'

        elif args['kick']:
            users = self.rooms[room]
            commands = []
            for victim in args['<destination>']:
                for user in users:
                    if victim.lower() in user.lower():
                        peer = users[user]
                        commands.append((
                            user,
                            'meetme kick {0} {1}'.format(room, peer)))

            if not commands:
                yield 'No user matching query'
                raise StopIteration()

            for user, cmd in commands:
                resp = self.send_command(cmd)
                if resp.success:
                    del self.rooms[room][user]
                    if not self.rooms[room]:
                        del self.rooms[room]
                    yield '{0} kicked from {1}.'.format(user, room)
                else:  # pragma: no cover
                    yield 'Failed to kick {0} from {1}.'.format(user, room)

    @command(permission='voip')
    def asterisk(self, mask, target, args):
        """Show voip status

            %%asterisk status [<id>]
        """
        self.log.info('voip %s %s %s', mask, target, args)
        args['nick'] = mask.nick
        if args['<id>']:
            peer = self.resolver(mask.nick, args['<id>'])
        else:
            peer = self.resolver(mask, mask.nick)
        if peer is None:
            return '{nick}: Your id is invalid.'.format(**args)
        action = {'Action': 'SIPshowpeer', 'peer': peer['login']}
        resp = self.send_action(action)
        if resp.success:
            print(resp.lheaders)
            return ('{nick}: Your VoIP phone is registered. '
                    '(User Agent: {sip-useragent} on {address-ip})'
                    ).format(nick=mask.nick, **resp.lheaders)

    @command(permission='admin', venusian_category='irc3.debug')
    def asterisk_command(self, mask, target, args):  # pragma: no cover
        """Send a raw command to asterisk. Use "help" to list core commands.

            %%asterisk_command <command>...
        """
        cmd = ' '.join(args['<command>'])
        cmd = dict(
            help='core show help',
        ).get(cmd, cmd)
        resp = self.send_command(cmd, debug=True)
        return resp.success

    @command(permission='admin', venusian_category='irc3.debug')
    def asterisk_originate(self, mask, target, args):  # pragma: no cover
        """Send raw originate

            %%asterisk_originate <Channel> <CallerID> <Exten> <Context>
        """
        action = {
            'Action': 'Originate',
            'WaitTime': 20,
            'Priority': 1,
        }
        for k, v in list(args.items()):
            if k.startswith('<'):
                action[k.strip('<>')] = v
        self.send_action(action)
        return 'Action {} sent'.format(repr(action))

    def SIGINT(self):
        if self.manager is not None:
            self.manager.close()
        self.log.info('SIGINT: connection closed')
Example #18
0
class Asterisk(object):

    requires = ['irc3.plugins.command']

    def __init__(self, bot):
        self.bot = bot
        self.bot.asterirc = self
        self.config = config = dict(
            host='127.0.0.1',
            port=5038,
            http_port='8088',
            protocol='http',
            debug=True,
        )
        config.update(bot.config.get('asterisk', {}))
        self.log = logging.getLogger('irc3.ast')
        self.ilog = logging.getLogger('irc.asterirc')
        self.ilog.set_irc_targets(bot, self.config['channel'])
        self.log.info('Channel is set to {channel}'.format(**config))
        self.rooms = defaultdict(dict)
        self.http = None
        self.resolver = irc3.utils.maybedotted(self.config['resolver'])
        self.manager = Manager(log=logging.getLogger('irc3.ast.manager'),
                               **config)
        self.manager.register_event('Shutdown', self.handle_shutdown)
        self.manager.register_event('Meet*', self.handle_meetme)
        if config.get('debug'):
            self.manager.register_event('*', self.handle_event)
        if isinstance(self.resolver, type):
            self.resolver = self.resolver(bot)

    def connection_made(self):
        self.bot.loop.call_later(1, self.connect)

    def post_connect(self):
        self.log.debug('post_connect')
        resp = self.send_action({'Action': 'Status'})
        if resp.success:
            self.update_meetme()
        else:  # pragma: no cover
            self.log.error(resp.text)
            self.bot.loop.call_later(1, self.post_connect)

    def update_meetme(self):
        resp = self.send_command('meetme list')
        if resp.success:
            if 'No active MeetMe conferences.' in resp.text:
                self.rooms = defaultdict(dict)
            for line in resp.lines[1:-2]:
                room = line.split(' ', 1)[0]
                if not room or not room.isdigit():
                    continue
                resp = self.send_command('meetme list ' + room)
                if resp.success and resp.iter_lines():
                    room = self.rooms[room]
                    for line in resp.lines:
                        if not line.startswith('User '):
                            continue
                        line = line.split('Channel:')[0]
                        splited = [s for s in line.split() if s][2:]
                        uid = splited.pop(0)
                        caller = ' '.join(splited[1:])
                        if 'external call ' in caller.lower():
                            e, c, n = caller.split(' ')[:4]
                            caller = ' '.join([e, c, n[:6]])
                        room[caller] = uid

    def connect(self):
        if self.manager is not None:
            self.manager.close()
            self.bot.loop.call_later(5, self.post_connect)
        try:
            self.manager.connect()
        except Exception as e:
            self.log.exception(e)
            self.log.info('connect retry in 5s')
            self.bot.loop.call_later(1, self.connect)
            return False
        else:
            return True

    def handle_shutdown(self, event, manager):
        self.manager.close()
        self.bot.loop.call_later(2, self.connect)

    def handle_event(self, event, manager):
        self.log.debug('handle_event %s %s', event, '')  # , event.headers)

    def handle_meetme(self, event, manager):
        self.log.debug('handle_meetme %s %s', event, event.headers)
        lower_header_keys(event)
        name = event.name.lower()
        room = event['meetme']

        if name == 'meetmeend':
            if room in self.rooms:  # pragma: no cover
                del self.rooms[room]
            self.ilog.info('room {} is closed.'.format(room))
            return

        action = None
        caller = event['calleridname']
        if 'external call ' in caller.lower():
            e, c, n = caller.split(' ')[:4]
            caller = ' '.join([e, c, n[:6]])
        elif 'external call' in caller.lower():  # pragma: no cover
            caller += event['calleridnum'][:6]

        if 'join' in name:
            action = 'join'
            self.rooms[room][caller] = event['usernum']
        elif 'leave' in name:
            action = 'leave'
            if caller in self.rooms.get(room, []):
                del self.rooms[room][caller]

        if action:
            # log
            args = dict(caller=caller,
                        action=action,
                        room=room,
                        total=len(self.rooms[room]))
            self.ilog.info(('{caller} has {action} room {room} '
                            '(total in this room: {total})').format(**args))

    def send_action(self, *args, **kwargs):
        try:
            res = self.manager.send_action(*args, **kwargs)
            return res
        except Exception as e:
            self.log.error('send_action(%r, **%r)', args, kwargs)
            self.log.exception(e)
            return Message('response',
                           'Sorry an error occured. ({})'.format(repr(e)),
                           headers={'Response': 'Failed'})

    def send_command(self, command, debug=False):
        resp = self.send_action({'Action': 'Command', 'Command': command})
        if debug:  # pragma: no cover
            self.log.debug('Command "%s" => Succeed: %s, Data:\n%s', command,
                           resp.success, getattr(resp, 'text', resp))
        if resp.success:
            resp.lines = []
            if resp['response'].lower() == 'follows':
                resp.lines = resp.text.split('\n')
        return resp

    @command(permission='voip')
    def call(self, mask, target, args):
        """Call someone. Destination and from can't contains spaces.

            %%call <destination> [<from>]

        """
        if 'nick' not in args:
            args['nick'] = mask.nick

        callee = self.resolver(mask, args['<destination>'])
        if args['<from>']:
            caller = self.resolver(mask, args['<from>'])
        else:
            caller = self.resolver(mask, mask.nick)

        if caller is None or caller.get('channel') is None:
            return '{nick}: Your caller is invalid.'.format(**args)
        if callee is None or callee.get('exten') is None:
            return '{nick}: Your destination is invalid.'.format(**args)

        action = {
            'Action': 'Originate',
            'Channel': caller['channel'],
            'WaitTime': 20,
            'CallerID': caller.get('fullname', caller['channel']),
            'Exten': callee['exten'],
            'Context': caller.get('context', 'default'),
            'Priority': 1,
        }
        resp = self.send_action(action)
        if resp.success:
            return '{nick}: Call to {<destination>} done.'.format(**args)
        else:
            return resp.text

    @command(permission='voip')
    def room(self, mask, target, args):
        """Invite/kick someone in a room. You can use more than one
        destination. Destinations can't contains spaces.

            %%room (list|invite|kick) [<room>] [<destination>...]

        """
        args['nick'] = mask.nick
        room = args['<room>']
        if args['invite']:

            callees = args['<destination>']
            message = '{nick}: {<from>} has been invited to room {<room>}.'
            if not callees:
                # self invite
                callees = [mask.nick]
                message = '{nick}: You have been invited to room {<room>}.'

            resolved = [self.resolver(mask, c) for c in callees]
            if None in resolved:
                # show invalid arguments and quit
                callees = zip(resolved, callees)
                invalid = [c for r, c in callees if r is None]
                yield (
                    "{0}: I'm not able to resolve {1}. Please fix it!").format(
                        mask.nick, ', '.join(invalid))
                raise StopIteration()

            for callee in callees:
                # call each
                args['<destination>'] = args['<room>']
                args['<from>'] = callee
                msg = self.call(mask, target, args)
                if 'Call to' in msg:
                    yield message.format(**args)
                else:
                    yield msg

        if room and room not in self.rooms:
            yield 'Invalid room'
            raise StopIteration()

        if args['list']:

            def fmt(room, users):
                amount = len(users)
                users = ', '.join([u for u in sorted(users)])
                return 'Room {0} ({1}): {2}'.format(room, amount, users)

            if room:
                yield fmt(room, self.rooms[room])
            elif self.rooms:
                for room, users in self.rooms.items():
                    yield fmt(room, self.rooms[room])
            else:
                yield 'Nobody here.'

        elif args['kick']:
            users = self.rooms[room]
            commands = []
            for victim in args['<destination>']:
                for user in users:
                    if victim.lower() in user.lower():
                        peer = users[user]
                        commands.append(
                            (user, 'meetme kick {0} {1}'.format(room, peer)))

            if not commands:
                yield 'No user matching query'
                raise StopIteration()

            for user, command in commands:
                resp = self.send_command(command)
                if resp.success:
                    del self.rooms[room][user]
                    if not self.rooms[room]:
                        del self.rooms[room]
                    yield '{0} kicked from {1}.'.format(user, room)
                else:  # pragma: no cover
                    yield 'Failed to kick {0} from {1}.'.format(user, room)

    @command(permission='voip')
    def asterisk(self, mask, target, args):
        """Show voip status

            %%asterisk status [<id>]
        """
        self.log.info('voip %s %s %s', mask, target, args)
        args['nick'] = mask.nick
        if args['<id>']:
            peer = self.resolver(mask.nick, args['<id>'])
        else:
            peer = self.resolver(mask, mask.nick)
        if peer is None:
            return '{nick}: Your id is invalid.'.format(**args)
        action = {'Action': 'SIPshowpeer', 'peer': peer['login']}
        resp = self.send_action(action)
        if resp.success:
            print(resp.lheaders)
            return ('{nick}: Your VoIP phone is registered. '
                    '(User Agent: {sip-useragent} on {address-ip})').format(
                        nick=mask.nick, **resp.lheaders)

    @command(permission='admin', venusian_category='irc3.debug')
    def asterisk_command(self, mask, target, args):  # pragma: no cover
        """Send a raw command to asterisk. Use "help" to list core commands.

            %%asterisk_command <command>...
        """
        cmd = ' '.join(args['<command>'])
        cmd = dict(help='core show help', ).get(cmd, cmd)
        resp = self.send_command(cmd, debug=True)
        return resp.success

    @command(permission='admin', venusian_category='irc3.debug')
    def asterisk_originate(self, mask, target, args):  # pragma: no cover
        """Send raw originate

            %%asterisk_originate <Channel> <CallerID> <Exten> <Context>
        """
        action = {
            'Action': 'Originate',
            'WaitTime': 20,
            'Priority': 1,
        }
        for k, v in list(args.items()):
            if k.startswith('<'):
                action[k.strip('<>')] = v
        self.send_action(action)
        return 'Action {} sent'.format(repr(action))

    def SIGINT(self):
        if self.manager is not None:
            self.manager.close()
        self.log.info('SIGINT: connection closed')
Example #19
0
                                    server_side=True)
    try:
        server.serve_forever()
    except Exception as e:
        print("error on starting web server {0}".format(e))


if __name__ == '__main__':

    if DEBUG:
        print('DEBUG enabled')

    if DEBUG:
        handler = logging.StreamHandler(sys.stdout)
        # handler.setLevel(logging.DEBUG)
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler.setFormatter(formatter)
        logger.addHandler(handler)
    else:
        logging.basicConfig(level=logging.INFO)
        Thread(target=serve_on_port, args=[SERVE_PORT]).start()
    bx24 = Bitrix24(BX_INC_HOOK)
    bx_users = grab_bx_users(bx24)
    manager.on_connect = on_connect
    manager.on_login = on_login
    manager.on_disconnect = on_disconnect
    manager.connect(run_forever=True,
                    on_startup=on_startup,
                    on_shutdown=on_shutdown)
Example #20
0
class AsteriskClient:
    def __init__(self, loop):
        self.manager = Manager(loop=loop,
                               host='178.248.87.116',
                               port=1709,
                               username='******',
                               secret='100')
        self.callManager = CallBaseManager()
        self.httpclient = HttpClientTornado()

        self.manager.register_event('FullyBooted', self.FullyBooted)
        self.manager.register_event('BridgeEnter', self.BridgeEnter)
        self.manager.register_event('Hangup', self.Hangup)

        self.manager.connect()
        try:
            self.manager.loop.run_forever()
        except KeyboardInterrupt:
            self.manager.loop.close()

    def FullyBooted(self, manager, message):
        print(message)
        resp = yield from manager.send_action({'Action': 'SIPpeers'})
        self.callManager.FillSIPpeers(resp)
        resp = yield from manager.send_action({'Action': 'QueueStatus'})
        pprint(resp)
        result = self.httpclient.QueueStatus(resp, method='connect')
        self.httpclient.SendRequest(result)

    def BridgeEnter(self, manager, message):
        # global isDial
        # isDial=False
        print(message)
        Bridge = self.callManager.CallBegin(
            CallerNumber=message.CallerIDNum,
            ConnectedNumber=message.ConnectedLineNum)
        if isinstance(Bridge, dict):
            resp = yield from manager.send_action({'Action': 'QueueStatus'})
            pprint(resp)
            result = self.httpclient.QueueStatus(resp,
                                                 method='call_begin',
                                                 call=Bridge)
            self.httpclient.SendRequest(result)

    def Hangup(self, manager, message):
        print(message)
        Call = self.callManager.CallEnd(CallerNumber=message.CallerIDNum)
        if isinstance(Call, dict):
            resp = yield from manager.send_action({'Action': 'QueueStatus'})
            pprint(resp)
            result = self.httpclient.QueueStatus(resp,
                                                 method='call_end',
                                                 call=Call)
            self.httpclient.SendRequest(result)

    def ChanSpy(self, channel_from: str, channel_to: str, type: str):
        call = yield from self.manager.send_action({
            'Action':
            'Originate',
            'Channel':
            'SIP/' + channel_from,
            'Application':
            'ChanSpy',
            'Data':
            'SIP/' + channel_to + ',' + type,
            'Priority':
            1,
            'Callerid':
            'Spy-{%s} <{%s}>'.format(channel_to),
            'Variable':
            'SIPADDHEADER="Call-Info:\;answer-after=0"',
        })
        pprint(call)

    def PickUp(self, channel: str):
        call = yield from self.manager.send_action({
            'Action':
            'Originate',
            'Channel':
            'SIP/' + channel,
            'Application':
            'PickupChan',
            'Data':
            'SIP/' + channel,
            'Priority':
            1,
            'Callerid':
            channel,
            'Variable':
            'SIPADDHEADER="Call-Info:\;answer-after=0"',
        })
        pprint(call)

    def Originate(self, channel_from, channel_to):
        call = yield from self.manager.send_action({
            'Action':
            'Originate',
            'Channel':
            'SIP/' + channel_from,
            'Exten':
            channel_to,
            'Priority':
            1,
            'Callerid':
            channel_from,
            'Variable':
            'SIPADDHEADER="Call-Info:\;answer-after=0"',
        })
        pprint(call)

    def Redirect(self, channel_from, channel_to):
        call = yield from self.manager.send_action({
            'Action': 'Redirect',
            # 'Channel': 'SIP/' + channel_from,
            # 'Exten': channel_to,
            'Priority': 1,
            'Context': 'from-internal',
        })
        pprint(call)

    def QueueAdd(self, channel):
        call = yield from self.manager.send_action({
            'Action': 'QueueAdd',
            'Queue': 'operator',
            'Interface': 'SIP/' + channel,
            'Penalty': 0,
        })
        pprint(call)

    def QueueRemove(self, channel):
        call = yield from self.manager.send_action({
            'Action':
            'QueueRemove',
            'Queue':
            'operator',
            'Interface':
            'SIP/' + channel,
        })
        pprint(call)

    def Queue(self, worker: str, action: int):
        if action == 1:
            self.QueueAdd(worker)
        else:
            self.QueueRemove(worker)

    def Parse(self, message: dict):
        method = message['method']
        if method == 'call_abonent':
            self.Originate(message['from'], message['to'])
        elif method == 'transfer_call':
            self.Redirect(message['from'], message['to'])
        elif method == 'connect_with_abonent':
            self.ChanSpy(message['from'], message['to'], 'qBx')
        elif method == 'connect_without_abonent':
            self.ChanSpy(message['from'], message['to'], 'wx')
        elif method == 'connect_without_microphone':
            self.ChanSpy(message['from'], message['to'], 'qx')
        elif method == 'queue':
            self.Queue(message['worker'], message['action'])


# if __name__ == '__main__':
#     main()