Exemple #1
0
def handle_listmode(cli, chan, mode, target, setter, timestamp):
    """Handle and store list modes."""

    ch = channels.add(chan, cli)
    if mode not in ch.modes:
        ch.modes[mode] = {}
    ch.modes[mode][target] = (setter, int(timestamp))
Exemple #2
0
def mode_change(cli, rawnick, chan, mode, *targets):
    """Update the channel and user modes whenever a mode change occurs.

    Ordering and meaning of arguments for a MODE change:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick of the mode setter/actor
    2 - The channel (target) of the mode change
    3 - The mode changes
    * - The targets of the modes (if any)

    This takes care of properly updating all relevant users and the
    channel modes to make sure we remain internally consistent.

    """

    actor = users._add(cli, nick=rawnick)  # FIXME
    if chan == users.Bot.nick:  # we only see user modes set to ourselves
        users.Bot.modes.update(mode)
        return

    target = channels.add(chan, cli)
    target.queue("mode_change", {
        "mode": mode,
        "targets": targets
    }, (var, actor, target))
Exemple #3
0
def mode_change(cli, rawnick, chan, mode, *targets):
    """Update the channel and user modes whenever a mode change occurs.

    Ordering and meaning of arguments for a MODE change:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick of the mode setter/actor
    2 - The channel (target) of the mode change
    3 - The mode changes
    * - The targets of the modes (if any)

    This takes care of properly updating all relevant users and the
    channel modes to make sure we remain internally consistent.

    """

    if chan == users.Bot.nick: # we only see user modes set to ourselves
        users.Bot.modes.update(mode)
        return

    if "!" not in rawnick:
        # Only sync modes if a server changed modes because
        # 1) human ops probably know better
        # 2) other bots might start a fight over modes
        # 3) recursion; we see our own mode changes.
        evt = Event("sync_modes", {})
        evt.dispatch(var)
        return

    actor = users._get(rawnick, allow_none=True) # FIXME
    target = channels.add(chan, cli)
    target.queue("mode_change", {"mode": mode, "targets": targets}, (var, actor, target))
Exemple #4
0
def mode_change(cli, rawnick, chan, mode, *targets):
    """Update the channel and user modes whenever a mode change occurs.

    Ordering and meaning of arguments for a MODE change:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick of the mode setter/actor
    2 - The channel (target) of the mode change
    3 - The mode changes
    * - The targets of the modes (if any)

    This takes care of properly updating all relevant users and the
    channel modes to make sure we remain internally consistent.

    """

    if chan == users.Bot.nick:  # we only see user modes set to ourselves
        users.Bot.modes.update(mode)
        return

    if "!" not in rawnick:
        # Only sync modes if a server changed modes because
        # 1) human ops probably know better
        # 2) other bots might start a fight over modes
        # 3) recursion; we see our own mode changes.
        evt = Event("sync_modes", {})
        evt.dispatch(var)
        return

    actor = users._get(rawnick, allow_none=True)  # FIXME
    target = channels.add(chan, cli)
    target.queue("mode_change", {
        "mode": mode,
        "targets": targets
    }, (var, actor, target))
Exemple #5
0
def handle_listmode(cli, chan, mode, target, setter, timestamp):
    """Handle and store list modes."""

    ch = channels.add(chan, cli)
    if mode not in ch.modes:
        ch.modes[mode] = {}
    ch.modes[mode][target] = (setter, int(timestamp))
Exemple #6
0
    def prepare_stuff(cli, prefix, *args):
        from src import lagcheck
        alog("Received end of MOTD from {0}".format(prefix))

        # This callback only sets up event listeners
        wolfgame.connect_callback()

        # just in case we haven't managed to successfully auth yet
        if botconfig.PASS and not botconfig.SASL_AUTHENTICATION:
            cli.ns_identify(botconfig.USERNAME or botconfig.NICK,
                            botconfig.PASS,
                            nickserv=var.NICKSERV,
                            command=var.NICKSERV_IDENTIFY_COMMAND)

        # give bot operators an opportunity to do some custom stuff here if they wish
        event = Event("irc_connected", {})
        event.dispatch(var, cli)

        # don't join any channels if we're just doing a lag check
        if not lagcheck:
            channels.Main = channels.add(botconfig.CHANNEL, cli)
            channels.Dummy = channels.add("*", cli)

            if botconfig.ALT_CHANNELS:
                for chan in botconfig.ALT_CHANNELS.split(","):
                    channels.add(chan, cli)

            if botconfig.DEV_CHANNEL:
                channels.Dev = channels.add(botconfig.DEV_CHANNEL, cli)

            if var.LOG_CHANNEL:
                channels.add(var.LOG_CHANNEL, cli)
        else:
            alog("Preparing lag check")
            # if we ARE doing a lagcheck, we need at least our own host or things break
            users.Bot.who()

        users.Bot.change_nick(botconfig.NICK)

        if var.SERVER_PING_INTERVAL > 0:

            def ping_server_timer(cli):
                ping_server(cli)

                t = threading.Timer(var.SERVER_PING_INTERVAL,
                                    ping_server_timer,
                                    args=(cli, ))
                t.daemon = True
                t.start()

            ping_server_timer(cli)

        hook.unhook(294)
Exemple #7
0
def who_reply(cli, bot_server, bot_nick, chan, ident, host, server, nick, status, hopcount_gecos):
    """Handle WHO replies for servers without WHOX support.

    Ordering and meaning of arguments for a bare WHO response:

    0 - The IRCClient instance (like everywhere else)
    1 - The server the requester (i.e. the bot) is on
    2 - The nickname of the requester (i.e. the bot)
    3 - The channel the request was made on
    4 - The ident of the user in this reply
    5 - The hostname of the user in this reply
    6 - The server the user in this reply is on
    7 - The nickname of the user in this reply
    8 - The status (H = Not away, G = Away, * = IRC operator, @ = Opped in the channel in 4, + = Voiced in the channel in 4)
    9 - The hop count and realname (gecos)

    This fires off the "who_result" event, and dispatches it with three
    arguments, the game state namespace, a Channel, and a User. Less
    important attributes can be accessed via the event.params namespace.

    """

    hop, realname = hopcount_gecos.split(" ", 1)
    hop = int(hop)
    # We throw away the information about the operness of the user, but we probably don't need to care about that
    # We also don't directly pass which modes they have, since that's already on the channel/user
    is_away = ("G" in status)

    modes = {Features["PREFIX"].get(s) for s in status} - {None}

    user = users._add(cli, nick=nick, ident=ident, host=host, realname=realname) # FIXME
    ch = None
    if not channels.predicate(chan): # returns True if it's not a channel
        ch = channels.add(chan, cli)

        if ch not in user.channels:
            user.channels[ch] = modes
            ch.users.add(user)
            for mode in modes:
                if mode not in ch.modes:
                    ch.modes[mode] = set()
                ch.modes[mode].add(user)

    event = Event("who_result", {}, away=is_away, data=0, ip_address=None, server=server, hop_count=hop, idle_time=None, extended_who=False)
    event.dispatch(var, ch, user)

    if ch is channels.Main and not users.exists(nick): # FIXME
        users.add(nick, ident=ident, host=host, account="*", inchan=True, modes=modes, moded=set())
Exemple #8
0
def join_chan(cli, rawnick, chan, account=None, realname=None):
    """Handle a user joining a channel, which may be the bot itself.

    Ordering and meaning of arguments for a channel JOIN:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick (nick!ident@host) of the user joining the channel
    2 - The channel the user joined

    The following two arguments are optional and only present if the
    server supports the extended-join capability (we will have requested
    it when we connected if it was supported):

    3 - The account the user is identified to, or "*" if none
    4 - The realname (gecos) of the user, or "" if none

    """

    if account == "*":
        account = None

    if realname == "":
        realname = None

    ch = channels.add(chan, cli)

    user = users.get(nick=rawnick,
                     account=account,
                     allow_bot=True,
                     allow_none=True,
                     allow_ghosts=True)
    if user is None:
        user = users.add(cli, nick=rawnick, account=account)
    if account:
        # ensure we work for the case when user left, changed accounts, then rejoined as a different account
        user.account = account
        user = users.get(nick=rawnick, account=account)
    ch.users.add(user)
    user.channels[ch] = set()
    # mark the user as here, in case they used to be connected before but left
    user.disconnected = False

    Event("chan_join", {}).dispatch(ch, user)

    if user is users.Bot:
        ch.mode()
        ch.mode(Features["CHANMODES"][0])
        ch.who()
Exemple #9
0
def current_modes(cli, server, bot_nick, chan, mode, *targets):
    """Update the channel modes with the existing ones.

    Ordering and meaning of arguments for a bare MODE response:

    0 - The IRCClient instance (like everywhere else)
    1 - The server the requester (i.e. the bot) is on
    2 - The nickname of the requester (i.e. the bot)
    3 - The channel holding the modes
    4 - The modes of the channel
    * - The targets to the modes (if any)

    """

    ch = channels.add(chan, cli)
    ch.update_modes(server, mode, targets)
Exemple #10
0
def current_modes(cli, server, bot_nick, chan, mode, *targets):
    """Update the channel modes with the existing ones.

    Ordering and meaning of arguments for a bare MODE response:

    0 - The IRCClient instance (like everywhere else)
    1 - The server the requester (i.e. the bot) is on
    2 - The nickname of the requester (i.e. the bot)
    3 - The channel holding the modes
    4 - The modes of the channel
    * - The targets to the modes (if any)

    """

    ch = channels.add(chan, cli)
    ch.update_modes(server, mode, targets)
Exemple #11
0
    def prepare_stuff(cli, prefix, *args):
        from src import lagcheck
        alog("Received end of MOTD from {0}".format(prefix))

        # This callback only sets up event listeners
        wolfgame.connect_callback()

        # just in case we haven't managed to successfully auth yet
        if botconfig.PASS and not botconfig.SASL_AUTHENTICATION:
            cli.ns_identify(botconfig.USERNAME or botconfig.NICK,
                            botconfig.PASS,
                            nickserv=var.NICKSERV,
                            command=var.NICKSERV_IDENTIFY_COMMAND)

        # don't join any channels if we're just doing a lag check
        if not lagcheck:
            channels.Main = channels.add(botconfig.CHANNEL, cli)
            channels.Dummy = channels.add("*", cli)

            if botconfig.ALT_CHANNELS:
                for chan in botconfig.ALT_CHANNELS.split(","):
                    channels.add(chan, cli)

            if botconfig.DEV_CHANNEL:
                channels.Dev = channels.add(botconfig.DEV_CHANNEL, cli)

            if var.LOG_CHANNEL:
                channels.add(var.LOG_CHANNEL, cli)

        #if var.CHANSERV_OP_COMMAND: # TODO: Add somewhere else if needed
        #    cli.msg(var.CHANSERV, var.CHANSERV_OP_COMMAND.format(channel=botconfig.CHANNEL))

        users.Bot.change_nick(botconfig.NICK)

        if var.SERVER_PING_INTERVAL > 0:

            def ping_server_timer(cli):
                ping_server(cli)

                t = threading.Timer(var.SERVER_PING_INTERVAL,
                                    ping_server_timer,
                                    args=(cli, ))
                t.daemon = True
                t.start()

            ping_server_timer(cli)

        if lagcheck:
            cli.command_handler["privmsg"] = on_privmsg
            run_lagcheck(cli)
Exemple #12
0
def chan_created(cli, server, bot_nick, chan, timestamp):
    """Update the channel timestamp with the server's information.

    Ordering and meaning of arguments for a bare MODE response end:

    0 - The IRCClient instance (like everywhere else)
    1 - The server the requester (i.e. the bot) is on
    2 - The nickname of the requester (i.e. the bot)
    3 - The channel in question
    4 - The UNIX timestamp of when the channel was created

    We probably don't need to care about this at all, but it doesn't
    hurt to keep it around. If we ever need it, it will be there.

    """

    channels.add(chan, cli).timestamp = int(timestamp)
Exemple #13
0
def chan_created(cli, server, bot_nick, chan, timestamp):
    """Update the channel timestamp with the server's information.

    Ordering and meaning of arguments for a bare MODE response end:

    0 - The IRCClient instance (like everywhere else)
    1 - The server the requester (i.e. the bot) is on
    2 - The nickname of the requester (i.e. the bot)
    3 - The channel in question
    4 - The UNIX timestamp of when the channel was created

    We probably don't need to care about this at all, but it doesn't
    hurt to keep it around. If we ever need it, it will be there.

    """

    channels.add(chan, cli).timestamp = int(timestamp)
Exemple #14
0
    def prepare_stuff(cli, prefix, *args):
        from src import lagcheck
        alog("Received end of MOTD from {0}".format(prefix))

        # This callback only sets up event listeners
        wolfgame.connect_callback()

        # just in case we haven't managed to successfully auth yet
        if botconfig.PASS and not botconfig.SASL_AUTHENTICATION:
            cli.ns_identify(botconfig.USERNAME or botconfig.NICK,
                            botconfig.PASS,
                            nickserv=var.NICKSERV,
                            command=var.NICKSERV_IDENTIFY_COMMAND)

        # don't join any channels if we're just doing a lag check
        if not lagcheck:
            channels.Main = channels.add(botconfig.CHANNEL, cli)
            channels.Dummy = channels.add("*", cli)

            if botconfig.ALT_CHANNELS:
                for chan in botconfig.ALT_CHANNELS.split(","):
                    channels.add(chan, cli)

            if botconfig.DEV_CHANNEL:
                channels.Dev = channels.add(botconfig.DEV_CHANNEL, cli)

            if var.LOG_CHANNEL:
                channels.add(var.LOG_CHANNEL, cli)
        else:
            alog("Preparing lag check")
            # if we ARE doing a lagcheck, we need at least our own host or things break
            users.Bot.who()

        #if var.CHANSERV_OP_COMMAND: # TODO: Add somewhere else if needed
        #    cli.msg(var.CHANSERV, var.CHANSERV_OP_COMMAND.format(channel=botconfig.CHANNEL))

        users.Bot.change_nick(botconfig.NICK)

        if var.SERVER_PING_INTERVAL > 0:
            def ping_server_timer(cli):
                ping_server(cli)

                t = threading.Timer(var.SERVER_PING_INTERVAL, ping_server_timer, args=(cli,))
                t.daemon = True
                t.start()

            ping_server_timer(cli)
Exemple #15
0
def kicked_from_chan(cli, rawnick, chan, target, reason):
    """Handle a user being kicked from a channel.

    Ordering and meaning of arguments for a channel KICK:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick (nick!ident@host) of the user performing the kick
    2 - The channel the kick was performed on
    3 - The target of the kick
    4 - The reason given for the kick (always present)

    """

    ch = channels.add(chan, cli)
    actor = users._get(rawnick, allow_none=True)  # FIXME
    user = users._get(target)  # FIXME
    Event("chan_kick", {}).dispatch(var, ch, actor, user, reason)

    if user is users.Bot:
        ch._clear()
    else:
        ch.remove_user(user)
Exemple #16
0
def join_chan(cli, rawnick, chan, account=None, realname=None):
    """Handle a user joining a channel, which may be the bot itself.

    Ordering and meaning of arguments for a channel JOIN:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick (nick!ident@host) of the user joining the channel
    2 - The channel the user joined

    The following two arguments are optional and only present if the
    server supports the extended-join capability (we will have requested
    it when we connected if it was supported):

    3 - The account the user is identified to, or "*" if none
    4 - The realname (gecos) of the user, or "" if none

    """

    if account == "*":
        account = None

    if realname == "":
        realname = None

    ch = channels.add(chan, cli)
    ch.state = channels._States.Joined

    user = users._add(cli, nick=rawnick, realname=realname, account=account) # FIXME
    ch.users.add(user)
    user.channels[ch] = set()
    # mark the user as here, in case they used to be connected before but left
    user.disconnected = False

    if user is users.Bot:
        ch.mode()
        ch.mode(Features["CHANMODES"][0])
        ch.who()

    Event("chan_join", {}).dispatch(var, ch, user)
Exemple #17
0
def kicked_from_chan(cli, rawnick, chan, target, reason):
    """Handle a user being kicked from a channel.

    Ordering and meaning of arguments for a channel KICK:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick (nick!ident@host) of the user performing the kick
    2 - The channel the kick was performed on
    3 - The target of the kick
    4 - The reason given for the kick (always present)

    """

    ch = channels.add(chan, cli)
    actor = users._get(rawnick, allow_none=True) # FIXME
    user = users._get(target) # FIXME
    Event("chan_kick", {}).dispatch(var, ch, actor, user, reason)

    if user is users.Bot:
        ch._clear()
    else:
        ch.remove_user(user)
Exemple #18
0
def join_chan(cli, rawnick, chan, account=None, realname=None):
    """Handle a user joining a channel, which may be the bot itself.

    Ordering and meaning of arguments for a channel JOIN:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick (nick!ident@host) of the user joining the channel
    2 - The channel the user joined

    The following two arguments are optional and only present if the
    server supports the extended-join capability (we will have requested
    it when we connected if it was supported):

    3 - The account the user is identified to, or "*" if none
    4 - The realname (gecos) of the user, or "" if none

    """

    if account == "*":
        account = None

    if realname == "":
        realname = None

    ch = channels.add(chan, cli)
    ch.state = channels._States.Joined

    user = users._add(cli, nick=rawnick, realname=realname,
                      account=account)  # FIXME
    ch.users.add(user)
    user.channels[ch] = set()

    if user is users.Bot:
        ch.mode()
        ch.mode(Features["CHANMODES"][0])
        ch.who()

    Event("chan_join", {}).dispatch(var, ch, user)
Exemple #19
0
def part_chan(cli, rawnick, chan, reason=""):
    """Handle a user leaving a channel, which may be the bot itself.

    Ordering and meaning of arguments for a channel PART:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick (nick!ident@host) of the user leaving the channel
    2 - The channel being left

    The following argument may or may not be present:

    3 - The reason the user gave for parting (if any)

    """

    ch = channels.add(chan, cli)
    user = users._get(rawnick)  # FIXME
    Event("chan_part", {}).dispatch(var, ch, user, reason)

    if user is users.Bot:  # oh snap! we're no longer in the channel!
        ch._clear()
    else:
        ch.remove_user(user)
Exemple #20
0
def part_chan(cli, rawnick, chan, reason=""):
    """Handle a user leaving a channel, which may be the bot itself.

    Ordering and meaning of arguments for a channel PART:

    0 - The IRCClient instance (like everywhere else)
    1 - The raw nick (nick!ident@host) of the user leaving the channel
    2 - The channel being left

    The following argument may or may not be present:

    3 - The reason the user gave for parting (if any)

    """

    ch = channels.add(chan, cli)
    user = users._get(rawnick) # FIXME
    Event("chan_part", {}).dispatch(var, ch, user, reason)

    if user is users.Bot: # oh snap! we're no longer in the channel!
        ch._clear()
    else:
        ch.remove_user(user)
Exemple #21
0
def extended_who_reply(cli, bot_server, bot_nick, data, chan, ident,
                       ip_address, host, server, nick, status, hop, idle,
                       account, realname):
    """Handle WHOX responses for servers that support it.

    An extended WHO (WHOX) is caracterised by a second parameter to the request
    That parameter must be '%' followed by at least one of 'tcuihsnfdlar'
    If the 't' specifier is present, the specifiers must be followed by a comma and at most 3 bytes
    This is the ordering if all parameters are present, but not all of them are required
    If a parameter depends on a specifier, it will be stated at the front
    If a specifier is not given, the parameter will be omitted in the reply

    Ordering and meaning of arguments for an extended WHO (WHOX) response:

    0  -   - The IRCClient instance (like everywhere else)
    1  -   - The server the requester (i.e. the bot) is on
    2  -   - The nickname of the requester (i.e. the bot)
    3  - t - The data sent alongside the request
    4  - c - The channel the request was made on
    5  - u - The ident of the user in this reply
    6  - i - The IP address of the user in this reply
    7  - h - The hostname of the user in this reply
    8  - s - The server the user in this reply is on
    9  - n - The nickname of the user in this reply
    10 - f - Status (H = Not away, G = Away, * = IRC operator, @ = Opped in the channel in 5, + = Voiced in the channel in 5)
    11 - d - The hop count
    12 - l - The idle time (or 0 for users on other servers)
    13 - a - The services account name (or 0 if none/not logged in)
    14 - r - The realname (gecos)

    This fires off the "who_result" event, and dispatches it with three
    arguments, the game state namespace, a Channel, and a User. Less
    important attributes can be accessed via the event.params namespace.

    """

    if account == "0":
        account = None

    hop = int(hop)
    idle = int(idle)
    is_away = ("G" in status)

    data = int.from_bytes(data.encode(Features["CHARSET"]), "little")

    modes = {Features["PREFIX"].get(s) for s in status} - {None}

    user = users._add(cli,
                      nick=nick,
                      ident=ident,
                      host=host,
                      realname=realname,
                      account=account)  # FIXME

    ch = None
    if not channels.predicate(chan):
        ch = channels.add(chan, cli)
        if ch not in user.channels:
            user.channels[ch] = modes
            ch.users.add(user)
            for mode in modes:
                if mode not in ch.modes:
                    ch.modes[mode] = set()
                ch.modes[mode].add(user)

    event = Event("who_result", {},
                  away=is_away,
                  data=data,
                  ip_address=ip_address,
                  server=server,
                  hop_count=hop,
                  idle_time=idle,
                  extended_who=True)
    event.dispatch(var, ch, user)

    if ch is channels.Main and not users.exists(nick):  # FIXME
        users.add(nick,
                  ident=ident,
                  host=host,
                  account=account,
                  inchan=True,
                  modes=modes,
                  moded=set())
Exemple #22
0
def handle_endlistmode(cli, chan, mode):
    """Handle the end of a list mode listing."""

    ch = channels.add(chan, cli)
    ch.queue("end_listmode", {}, (var, ch, mode))
Exemple #23
0
def handle_endlistmode(cli, chan, mode):
    """Handle the end of a list mode listing."""

    ch = channels.add(chan, cli)
    ch.queue("end_listmode", {}, (var, ch, mode))
Exemple #24
0
def extended_who_reply(cli, bot_server, bot_nick, data, chan, ident, ip_address, host, server, nick, status, hop, idle, account, realname):
    """Handle WHOX responses for servers that support it.

    An extended WHO (WHOX) is caracterised by a second parameter to the request
    That parameter must be '%' followed by at least one of 'tcuihsnfdlar'
    If the 't' specifier is present, the specifiers must be followed by a comma and at most 3 bytes
    This is the ordering if all parameters are present, but not all of them are required
    If a parameter depends on a specifier, it will be stated at the front
    If a specifier is not given, the parameter will be omitted in the reply

    Ordering and meaning of arguments for an extended WHO (WHOX) response:

    0  -   - The IRCClient instance (like everywhere else)
    1  -   - The server the requester (i.e. the bot) is on
    2  -   - The nickname of the requester (i.e. the bot)
    3  - t - The data sent alongside the request
    4  - c - The channel the request was made on
    5  - u - The ident of the user in this reply
    6  - i - The IP address of the user in this reply
    7  - h - The hostname of the user in this reply
    8  - s - The server the user in this reply is on
    9  - n - The nickname of the user in this reply
    10 - f - Status (H = Not away, G = Away, * = IRC operator, @ = Opped in the channel in 5, + = Voiced in the channel in 5)
    11 - d - The hop count
    12 - l - The idle time (or 0 for users on other servers)
    13 - a - The services account name (or 0 if none/not logged in)
    14 - r - The realname (gecos)

    This fires off the "who_result" event, and dispatches it with three
    arguments, the game state namespace, a Channel, and a User. Less
    important attributes can be accessed via the event.params namespace.

    """

    if account == "0":
        account = None

    hop = int(hop)
    idle = int(idle)
    is_away = ("G" in status)

    data = int.from_bytes(data.encode(Features["CHARSET"]), "little")

    modes = {Features["PREFIX"].get(s) for s in status} - {None}

    user = users._add(cli, nick=nick, ident=ident, host=host, realname=realname, account=account) # FIXME

    ch = None
    if not channels.predicate(chan):
        ch = channels.add(chan, cli)
        if ch not in user.channels:
            user.channels[ch] = modes
            ch.users.add(user)
            for mode in modes:
                if mode not in ch.modes:
                    ch.modes[mode] = set()
                ch.modes[mode].add(user)

    event = Event("who_result", {}, away=is_away, data=data, ip_address=ip_address, server=server, hop_count=hop, idle_time=idle, extended_who=True)
    event.dispatch(var, ch, user)

    if ch is channels.Main and not users.exists(nick): # FIXME
        users.add(nick, ident=ident, host=host, account=account, inchan=True, modes=modes, moded=set())
Exemple #25
0
def who_reply(cli, bot_server, bot_nick, chan, ident, host, server, nick,
              status, hopcount_gecos):
    """Handle WHO replies for servers without WHOX support.

    Ordering and meaning of arguments for a bare WHO response:

    0 - The IRCClient instance (like everywhere else)
    1 - The server the requester (i.e. the bot) is on
    2 - The nickname of the requester (i.e. the bot)
    3 - The channel the request was made on
    4 - The ident of the user in this reply
    5 - The hostname of the user in this reply
    6 - The server the user in this reply is on
    7 - The nickname of the user in this reply
    8 - The status (H = Not away, G = Away, * = IRC operator, @ = Opped in the channel in 4, + = Voiced in the channel in 4)
    9 - The hop count and realname (gecos)

    This fires off the "who_result" event, and dispatches it with three
    arguments, the game state namespace, a Channel, and a User. Less
    important attributes can be accessed via the event.params namespace.

    """

    hop, realname = hopcount_gecos.split(" ", 1)
    hop = int(hop)
    # We throw away the information about the operness of the user, but we probably don't need to care about that
    # We also don't directly pass which modes they have, since that's already on the channel/user
    is_away = ("G" in status)

    modes = {Features["PREFIX"].get(s) for s in status} - {None}

    user = users._add(cli,
                      nick=nick,
                      ident=ident,
                      host=host,
                      realname=realname)  # FIXME
    ch = None
    if not channels.predicate(chan):  # returns True if it's not a channel
        ch = channels.add(chan, cli)

        if ch not in user.channels:
            user.channels[ch] = modes
            ch.users.add(user)
            for mode in modes:
                if mode not in ch.modes:
                    ch.modes[mode] = set()
                ch.modes[mode].add(user)

    event = Event("who_result", {},
                  away=is_away,
                  data=0,
                  ip_address=None,
                  server=server,
                  hop_count=hop,
                  idle_time=None,
                  extended_who=False)
    event.dispatch(var, ch, user)

    if ch is channels.Main and not users.exists(nick):  # FIXME
        users.add(nick,
                  ident=ident,
                  host=host,
                  account="*",
                  inchan=True,
                  modes=modes,
                  moded=set())