Ejemplo n.º 1
0
def help(client, topic='', *, H=False, h=False, domain=''):
    """ The command for receiving in-game help. Searches through commands,
    subscribers, and active_services and returns either a list of available
    matching helpfiles, or the docstring of the single match.

        :param client:      The client issuing the help command. (That'd be
                            you.) **This isn't part of the command you enter.**
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.
        :param topic:       None by default, otherwise the name of the
                            command/service/subscriber you're looking to get
                            help with.
        :param domain:      Optionally limit where you're looking for help to
                            either cmds, subscribers, or services.

        For example, you might enter ``help talker`` to learn more about qtMUD's
        talker system. You would be prompted to enter either
        ``help --domain=cmds talker`` to learn about the in-game talker
        command or ``help --domain=services talker`` to learn about the
        Talker service`.
    """
    output = ''
    brief = ('help [-Hh] [--domain=$domain] [topic]\n\n'
             'Search for help for *topic*. Use *--domain=* to limit where you '
             'search to cmds, subscribers, or services.')
    matches = []
    help_locations = {
        'cmds': [client.commands],
        'subscribers': [qtmud.subscribers],
        'services': [qtmud.active_services]
    }
    if H:
        output += help.__doc__
    elif h:
        output += brief
    elif topic:
        topic = topic.lower()
        for _domain, locations in help_locations.items():
            if domain == _domain or not domain:
                for location in locations:
                    if topic in location:
                        # TODO Warning Expected type 'Union[Integral,
                        # slice]', got 'str' instead
                        matches.append(location[topic])
        if matches:
            if len(matches) == 1:
                output += matches[0].__doc__
            else:
                output += (
                    'Multiple matches found, try "help '
                    '--domain=*domain* {}" where *domain* is one of : {}'
                    ''.format(
                        topic, ', '.join(
                            m.__module__.split('.')[-1] for m in matches)))
    else:
        output += help.__doc__
    if not output:
        output = 'No help found. Try looking at https://qtmud.rtfd.io'
    qtmud.schedule('send', recipient=client, text=output)
    return output
Ejemplo n.º 2
0
def options(client, value, *, H=False, h=False, attr=None):
    """ Command to set client options.

        :param client:      The client issuing the command. (That'd be you.)
                            **This isn't part of the command you enter.**
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.

    """
    output = ''
    brief = ('syntax: options [-Hh]\n\n'
             'Sets options for the client. `This command is a work in '
             'progress.`')
    if H:
        output += options.__doc__
    elif h:
        output += brief
    elif attr:
        try:
            setattr(client, attr, value)
            output += 'You set your `{attr}` to `{value}`.'.format(**locals())
        except AttributeError as err:
            output += 'You don\'t have a `{attr}` attribute.'.format(
                **locals())
            qtmud.log.warning('{client.name} failed to set {attr}: {err}'
                              ''.format(**locals()),
                              exc_info=True)
    else:
        output += (
            'This command is for setting options about your player '
            'account. Since it isn\'t really intended for you to use if '
            'you don\'t know what you\'re doing, I\'m not going to '
            'explain it further.')
    qtmud.schedule('send', recipiennt=client, text=output)
Ejemplo n.º 3
0
def foo(client, *, H=False, h=False, p=False):
    """ The dedicated test command

        :param client:      The client issuing the foo command. (That'd be
                            you.) **This isn't part of the command you enter.**
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.

        This is a testing command, so you should check the source itself for
        information on what it actually does.
    """
    output = ''
    brief = ('syntax: foo [-Hh]\n\n'
             'Check source for real information, this is a testing command.')
    if H:
        output += foo.__doc__
    elif h:
        output = brief
    elif p:
        line = ('You can also use %^RED%^nesting %^GREEN%^Pinkfish-style '
                '%^B_YELLOW%^markup tags%^, though they%^ become less%^ '
                'readable.')
        output += ('You test the pinkfish_parser with the following line:\n\n'
                   '{}\n\nIt returns: {}'.format(line,
                                                 qtmud.pinkfish_parse(line)))
    else:
        output = 'You foo, to no effect. (`this is a development command`)'
    if output:
        qtmud.schedule('send', recipient=client, text=output)
    return True
Ejemplo n.º 4
0
 def broadcast(self, channel, speaker, message):
     for listener in self.channels[channel]:
         qtmud.schedule('send',
                        recipient=listener,
                        text='`(`{}`)` {}: {}'.format(
                            channel, speaker, message))
     self.history[channel].append('{}: {}'.format(speaker, message))
Ejemplo n.º 5
0
 def tune_channel(self, client, channel):
     if channel not in self.channels:
         self.new_channel(channel)
     self.channels[channel].append(client)
     client.channels.append(channel)
     qtmud.schedule('send',
                    recipient=client,
                    text='You tune into the {} channel'.format(channel))
Ejemplo n.º 6
0
def talker(client,
           channel=None,
           *,
           H=False,
           h=False,
           l=False,
           t=False,
           d=False):
    """ Command for interacting with the Talker service.

        :param client:      The client issuing the talker command. (That'd be
                            you.) **This isn't part of the command you enter.**
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.
        :param channel:     The channel you're getting information on.
        :param l:           Show the channel's history.
        :param t:           Tune into a channel
        :param d:           Drop a channel

        .. todo:: --depth argument to specify how much history to show
    """
    output = ''
    brief = ('syntax: talker [-Hhltd] [channel]\n\n'
             'If entered without argument, lists the channels you\'re tuned '
             'into. If a channel is given, shows information about that '
             'channel. If the -l flag is given, shows that channel\'s logs.')
    talker_service = qtmud.active_services['talker']
    if H:
        output += talker.__doc__
    elif h:
        output = brief
    else:
        if not channel:
            output += ('you\'re listening to {}'
                       ''.format([c for c in client.channels]))
        else:
            if d:
                for _channel in channel.split(','):
                    talker_service.drop_channel(client, _channel)
            elif t:
                for _channel in channel.split(','):
                    talker_service.tune_channel(client=client,
                                                channel=_channel)
            elif l:
                output += ('({}) channel log:\n{}'
                           ''.format(
                               channel, '\n'.join(
                                   m for m in qtmud.active_services['talker'].
                                   history[channel])))
            else:
                # TODO output += talker_service.summarize(channel)
                output += ('This will show you output about that channel '
                           'and its listeners, in the future.')

    if output:
        qtmud.schedule('send', recipient=client, text=output)
        return True
Ejemplo n.º 7
0
 def tick(self):
     read, write, error = select.select(self.connections, [
         conn for conn, client in self.clients.items()
         if client.send_buffer != ''
     ], [], 0)
     if read:
         for conn in read:
             if conn is self.ip4_socket or conn is self.ip6_socket:
                 new_conn, addr = conn.accept()
                 qtmud.log.debug('new connection accepted from %s',
                                 format(addr))
                 client = qtmud.Client()
                 client.update({
                     'addr': addr,
                     'send_buffer': '',
                     'recv_buffer': ''
                 })
                 self.connections.append(new_conn)
                 self.clients[new_conn] = client
                 client.input_parser = 'client_login_parser'
                 qtmud.schedule('send', recipient=client, text=qtmud.SPLASH)
             else:
                 try:
                     data = conn.recv(1024)
                 except ConnectionResetError as err:
                     qtmud.log.debug('lost connection from: {}:\n'
                                     '{}'.format(self.clients[conn].addr,
                                                 err),
                                     exc_info=True)
                     qtmud.schedule('client_disconnect',
                                    client=self.clients[conn])
                     return
                 if data == b'':
                     qtmud.log.debug('disconnected from %s',
                                     format(self.clients[conn].addr))
                     qtmud.schedule('client_disconnect',
                                    client=self.clients[conn])
                 else:
                     client = self.clients[conn]
                     client.recv_buffer += data.decode('utf8', 'ignore')
                     if '\n' in client.recv_buffer:
                         split = client.recv_buffer.rstrip().split('\n', 1)
                         if len(split) == 2:
                             line, client.recv_buffer = split
                         else:
                             line, client.recv_buffer = split[0], ''
                         qtmud.schedule('send',
                                        recipient=client,
                                        text='> {}'.format(line))
                         qtmud.schedule('client_input_parser',
                                        client=client,
                                        line=line)
     if write:
         for conn in write:
             conn.send(self.clients[conn].send_buffer.encode('utf8'))
             self.clients[conn].send_buffer = ''
Ejemplo n.º 8
0
def whatami(client, *, H=False, h=False):
    output = ''
    brief = ('syntax: whatami [-Hh]\n\n' 'Shows what sort of object you are.')
    if H:
        output += who.__doc__
    elif h:
        output = brief
    else:
        output += ('{}'.format(client.__class__.__name__))
    qtmud.schedule('send', recipient=client, text=output)
Ejemplo n.º 9
0
def broadcast(channel, speaker, message):
    """ Send a message from speaker to everyone on the channel. """
    if not message:
        qtmud.schedule('send',
                       recipient=speaker,
                       text='syntax: {0} <message>\n'
                       'Sends `message` to everyone tuned into `{0}`'
                       ''.format(channel))
    else:
        qtmud.active_services['talker'].broadcast(channel=channel,
                                                  speaker=speaker.name,
                                                  message=message)
    return True
Ejemplo n.º 10
0
def whoami(client, *, H=False, h=False):
    """ Command to quit qtMUD

        :param client:      The client issuing the whoami command. (That'd be
                            you.) **This isn't part of the command you enter.**
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.
    """
    output = ''
    brief = ('syntax: whoami [-Hh]\n\n' 'Shows your own name.')
    if H:
        output += whoami.__doc__
    elif h:
        output = brief
    else:
        output = ('You are {}'.format(client.name))
    qtmud.schedule('send', recipient=client, text=output)
    return True
Ejemplo n.º 11
0
def client_disconnect(client):
    """ Handle removing a client from qtMUD

        .. warning:: This is likely buggy and going to change
    """
    mudsocket = qtmud.active_services['mudsocket']
    qtmud.log.debug('disconnecting %s from qtmud.', client.name)
    for other in qtmud.connected_clients:
        qtmud.schedule('send',
                       recipient=other,
                       text='{} disconnected.'.format(client.name))
    try:
        qtmud.connected_clients.remove(client)
    except ValueError:
        pass
    socket = mudsocket.get_socket_by_thing(client)
    if socket:
        mudsocket.clients.pop(socket)
        mudsocket.connections.remove(socket)
    return True
Ejemplo n.º 12
0
def who(client, *, H=False, h=False):
    """ Command to check your name

        :param client:      The client issuing the who command. (That'd be
                            you.) **This isn't part of the command you enter.**
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.
    """
    output = ''
    brief = ('syntax: who [-Hh]\n\n'
             'Shows a list of the currently connected clients.')
    if H:
        output += who.__doc__
    elif h:
        output = brief
    else:
        output = ('The following clients are currently connected:\n'
                  '{}'.format('\n'.join(
                      [c.name for c in qtmud.connected_clients])))
    qtmud.schedule('send', recipient=client, text=output)
    return True
Ejemplo n.º 13
0
def tell(client, *payload, H=False, h=False):
    """ Command for private messaging other players.

        :param client:      The client issuing the command. (That'd be you.)
                            **This isn't part of the command you enter.**
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.
    """
    output = ''
    brief = ('syntax: tell [-Hh] <recipient> <message>\n\n'
             'Sends `message` to `recipient`.')
    if H:
        output += tell.__doc__
    elif h:
        output += brief
    elif payload:
        payload = [w for w in payload]
        if len(payload) > 1:
            recipients = qtmud.search_connected_clients_by_name(payload.pop(0))
            if len(recipients) == 1:
                recipient = recipients[0]
                message = ' '.join(payload)
                if client == recipient:
                    output += 'You tell `yourself`: {}'.format(message)
                else:
                    output += 'You tell `{}`: {}'.format(
                        recipient.name, message)
                    qtmud.schedule('send',
                                   recipient=recipient,
                                   text='`{}` tells you: {}'.format(
                                       client.name, message))
            elif len(recipients) > 1:
                output += ('More than one match: {}'
                           ''.format(', '.join([r.name for r in recipients])))
            else:
                output += 'Couldn\'t find that client.'
    if not output:
        output += brief
    qtmud.schedule('send', recipient=client, text=output)
Ejemplo n.º 14
0
def shutdown():
    """ Handles qtMUD shutting down. """
    qtmud.log.debug('shutdown() occurring')
    for client in qtmud.connected_clients:
        qtmud.schedule('client_disconnect', client=client)
    while True:
        if qtmud.events:
            qtmud.log.debug('processing final events %s', qtmud.events)
            qtmud.tick()
        else:
            break
    for service in qtmud.active_services:
        service = qtmud.active_services[service]
        qtmud.log.debug('shutdown()ing %s', service.__class__.__name__)
        try:
            service.shutdown()
            qtmud.log.debug('shutdown() %s successfully',
                            service.__class__.__name__)
        except Exception as err:
            qtmud.log.warning('%s failed to shutdown: %s',
                              service.__class__.__name__, err)
    qtmud.log.info('shutdown() finished, raising SystemExit')
    raise SystemExit
Ejemplo n.º 15
0
def commands(client, *, H=False, h=False):
    """ Sends a list of the client's commands to the client.

        :param client:      The client issuing the command command. (That'd be
                            you.) This isn't part of the command you enter.
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.

        Creates a ``send`` event to tell the client a list of their commands.
    """
    output = ''
    brief = ('commands [-Hh]\n\n'
             'If entered without argument, lists all your valid commands.')
    if H:
        output += commands.__doc__
    elif h:
        output += brief
    else:
        output += ('Your commands are: {}'
                   ''.format(', '.join([c for c in client.commands.keys()])))
    if output:
        qtmud.schedule('send', recipient=client, text=output)
        return True
Ejemplo n.º 16
0
def client_command_parser(client, line):
    """ Once a client has logged in, this method handles parsing their input.
    """
    if line:
        spl = line.split(' ')
        command = spl[0]
        if command in client.commands:
            if len(spl) > 1:
                targs = spl[1:]
            else:
                targs = []
            kwargs = {}
            args = []
            for arg in targs:
                if arg.startswith('--'):
                    if '=' in arg:
                        targ = arg[2:].split('=', 1)
                        if len(targ) == 2:
                            kwargs[targ[0]] = targ[1]
                elif arg.startswith('-'):
                    for char in arg[1:]:
                        kwargs[char] = True
                else:
                    args.append(arg)
            try:
                client.commands[command](*args, **kwargs)
            except (SyntaxWarning, SyntaxError, TypeError) as err:
                qtmud.schedule('send',
                               recipient=client,
                               text='{} command failed: {}'
                               ''.format(command, err))
                client.commands[command](h=True)
                qtmud.log.warning('%s\'s %s command failed: %s',
                                  client.name,
                                  command,
                                  err,
                                  exc_info=True)
        elif command in client.channels:
            message = ' '.join(spl[1:])
            qtmud.schedule('broadcast',
                           channel=command,
                           speaker=client,
                           message=message)
        else:
            qtmud.schedule('send',
                           recipient=client,
                           text=('{} is not a valid command; check '
                                 '"commands" for your commands.'
                                 ''.format(command)))
    return True
Ejemplo n.º 17
0
def quit(client, *, H=False, h=False):
    """ Command to quit qtMUD

        :param client:      The client issuing the quit command. (That'd be
                            you.) **This isn't part of the command you enter.**
        :param H:           Shows the client this docstring.
        :param h:           Shows the client a brief help.
    """
    output = ''
    brief = ('syntax: help [-Hh]\n\n' 'Causes the client to leave the game.')
    if H:
        output += quit.__doc__
    elif h:
        output = brief
    else:
        qtmud.schedule('send', recipient=client, text='you quit goodbye')
        qtmud.schedule('client_disconnect', client=client)
    if output:
        qtmud.schedule('send', recipient=client, text=output)
    return True
Ejemplo n.º 18
0
def client_login_parser(client, line):
    """ Handle logs-in for arriving players - right now, just a basic check
    against qtmud.client_accounts to see if the client is there already.
    """
    output = ''
    #####
    #
    # start login process
    #
    #####
    if not hasattr(client, 'login_stage'):
        client.login_stage = 0
        output = 'Input [desired] client name and press <enter>.'
    #####
    #
    # check if client exits
    #
    #####
    elif client.login_stage == 0:
        if line in qtmud.client_accounts.keys():
            output = ('There\'s a client named {}, if you\'re them, type your '
                      'password and press <enter>'.format(line))
            client.login_stage = 2
        elif line:
            output = ('No client named {}, going to make an account with that '
                      'name. Type your desired password and press <enter>.'
                      ''.format(line))
            client.login_stage = 1
        else:
            output = ('Your client name can\'t be blank. Input what name '
                      'you\'d like to use and press <enter>.')
        client.name = line
    #####
    #
    # register new client
    #
    #####
    elif client.login_stage == 1:
        qtmud.client_accounts[client.name] = {'password': line}
        qtmud.save_client_accounts()
        client.login_stage = 9
        output = ('Client account registered with name {}, press '
                  '<enter> to finish logging in.'.format(client.name))
    #####
    #
    # login existing account
    #
    #####
    elif client.login_stage == 2:
        if line == qtmud.client_accounts[client.name]['password']:
            client.login_stage = 9
            output = ('That\'s the correct password, press <enter> to finish '
                      'logging in.')
        else:
            client.login_stage = 0
            output = ('That\'s not the right password for that account - '
                      'type your [desired] client name and press <enter>.')
    elif client.login_stage == 9:
        if qtmud.MUDLIB:
            client.input_parser = 'client_mudlib_login_parser'
        else:
            client.input_parser = 'client_command_parser'
        qtmud.active_services['talker'].tune_channel(client=client,
                                                     channel='one')
        qtmud.connected_clients.append(client)
        for c in qtmud.connected_clients:
            qtmud.schedule('send',
                           recipient=c,
                           text='`{}` has connected'.format(client.name))
    if output:
        qtmud.schedule('send', recipient=client, text=output)
    return True
Ejemplo n.º 19
0
def client_input_parser(client, line):
    """ Pushes a client's input to their designated parser subscription.
    """
    qtmud.schedule('{}'.format(client.input_parser), client=client, line=line)
    return True