Ejemplo n.º 1
0
    async def line_read(self, line: Line):
        print(f"{self.name} < {line.format()}")
        if   line.command == "001":
            await self.send(build("JOIN", [",".join(CHANS)]))
        elif (line.command == "JOIN" and
                not self.is_me(line.hostmask.nickname)):
            user = self.users[self.casefold(line.hostmask.nickname)]
            fingerprint = f"{line.hostmask.hostname}#{user.realname}"
            for pattern, mask in PATTERNS:
                match = re.search(pattern, fingerprint)
                if match:
                    ip     = match.group("ip")
                    mask_f = mask.format(IP=ip)

                    reason = await _match(ip)
                    if reason is not None:
                        await self._act(ACT_SOFT, line, mask_f, ip, reason)
                        if not ACC or not user.account:
                            await self._act(ACT_HARD, line, mask_f, ip, reason)
        elif (line.command == "INVITE" and
                self.is_me(line.params[0])):
            userhost = f"{line.hostmask.username}@{line.hostmask.hostname}"
            for admin_mask in ADMINS:
                if admin_mask.match(userhost):
                    await self.send(build("JOIN", [line.params[1]]))
                    break
Ejemplo n.º 2
0
    async def _oper_up(self,
            oper_name: str,
            oper_file: str,
            oper_pass: str):

        try:
            challenge = Challenge(keyfile=oper_file, password=oper_pass)
        except Exception:
            traceback.print_exc()
        else:
            await self.send(build("CHALLENGE", [oper_name]))
            challenge_text = Response(RPL_RSACHALLENGE2,      [SELF, ANY])
            challenge_stop = Response(RPL_ENDOFRSACHALLENGE2, [SELF])
            #:niven.freenode.net 740 sandcat :foobarbazmeow
            #:niven.freenode.net 741 sandcat :End of CHALLENGE

            while True:
                challenge_line = await self.wait_for({
                    challenge_text, challenge_stop
                })
                if challenge_line.command == RPL_RSACHALLENGE2:
                    challenge.push(challenge_line.params[1])
                else:
                    retort = challenge.finalise()
                    await self.send(build("CHALLENGE", [f"+{retort}"]))
                    break
Ejemplo n.º 3
0
async def on_mode(self, line):
    if self.nickname in line.source:
        return
    if line.params in [["#chaos", "+q", self.nickname],
                       ["#chaos", "+qo", self.nickname, self.nickname]]:
        await self.send(build("MODE", self.tomode))
        return
    unmo = []
    for i in self.channels['#chaos'].users:  #set(line.params[2:]):
        nick = i.lower()
        if line.params[0] in self.channels and nick in self.channels[
                line.params[0]].users:
            us = await checkUser(self, nick)
            if us:
                unmo.append(us)
    if len(unmo) > 0:
        if 'a' in line.params[
                1]:  # meh, only take away protected if protected was set
            self.tomode = [
                "#chaos", "+q-c**t" + "q" * len(unmo) + "o" * len(unmo) +
                "a" * len(unmo), "xfnw"
            ] + unmo + unmo + unmo
        else:
            self.tomode = [
                "#chaos", "+q-c**t" + "q" * len(unmo) + "o" * len(unmo), "xfnw"
            ] + unmo + unmo
        await self.send(build("MODE", self.tomode))
Ejemplo n.º 4
0
    async def line_read(self, line: Line):
        if line.command == RPL_WELCOME:
            oper_name, oper_file, oper_pass = self._config.oper
            await self._oper_up(oper_name, oper_file, oper_pass)

        elif (line.command == "PRIVMSG" and
                self.is_me(line.params[0])):

            nickname = line.hostmask.nickname

            command, *args = line.params[1].lower().split()

            if command == "grantme":
                opername = await self._oper_name(nickname)
                if opername is not None:
                    if not args:
                        await self.send(build("NOTICE", [nickname, "give me an argument then"]))
                    elif not args[0] in self._config.privsets:
                        await self.send(build("NOTICE", [nickname, f"dunno what '{args[0]}' means"]))
                    else:
                        privset = args[0]
                        await self.send(build("GRANT",  [nickname, privset]))
                        await self.send(build("NOTICE", [nickname, f"good luck with {privset} mate"]))
                else:
                    await self.send(build("NOTICE", [nickname, "who are you though"]))
Ejemplo n.º 5
0
    async def line_read(self, line: Line):
        global CONFIG
        print(f"{self.name} < {line.format()}")
        if line.command == "001":
            chans = list(CONFIG.channels.keys())
            await self.send(build("JOIN", [",".join(chans)]))

        elif (line.command == "JOIN"
              and not self.is_me(line.hostmask.nickname)):
            nick = self.casefold(line.hostmask.nickname)
            chan = self.casefold(line.params[0])

            if not nick in self._whox:
                self._whox[nick] = []
            self._whox[nick].append(chan)

            await self.send(build("WHO", [nick, "%int,111"]))

        elif (line.command == RPL_WHOSPCRPL and line.params[1] == "111"):
            nick = self.casefold(line.params[3])
            print("whox", nick)

            if nick in self.users:
                user = self.users[nick]
                chan = self.channels[self._whox[nick][0]]
                host = line.params[2]
                if host == "255.255.255.255":
                    host = user.hostname

                await self._scan(user, chan, host)

        elif line.command == RPL_ENDOFWHO:
            nick = self.casefold(line.params[1])
            if nick in self._whox:
                print("popping", nick, self._whox[nick].pop(0))
                if not self._whox[nick]:
                    print("removing", nick)
                    del self._whox[nick]

        elif (line.command == "JOIN" and self.is_me(line.hostmask.nickname)):
            await self.send(build("MODE", [line.params[0], "+bq"]))

        elif (line.command == "INVITE" and self.is_me(line.params[0])):
            userhost = f"{line.hostmask.username}@{line.hostmask.hostname}"
            for admin_mask in CONFIG.admins:
                if admin_mask.match(userhost):
                    await self.send(build("JOIN", [line.params[1]]))
                    break

        elif (line.command == "PRIVMSG" and self.is_me(line.params[0])
              and line.params[1] == "rehash"):
            userhost = f"{line.hostmask.username}@{line.hostmask.hostname}"
            for admin_mask in CONFIG.admins:
                if admin_mask.match(userhost):
                    CONFIG = load_config(CONFIG_PATH)
                    print("rehashed")
                    break
Ejemplo n.º 6
0
 async def handshake(self):
     try:
         await self.on_ls(self.server.available_caps)
     except HandshakeCancel:
         return
     else:
         await self.server.send(build("CAP", ["END"]))
Ejemplo n.º 7
0
    async def _read_lines(self):
        while True:
            async with self._read_lguard:
                pass

            if not self._process_queue:
                async with self._read_lwork:
                    read_aw = self._read_line(PING_TIMEOUT)
                    dones, notdones = await asyncio.wait(
                        [read_aw, self._wait_for.wait()],
                        return_when=asyncio.FIRST_COMPLETED)
                    self._wait_for.clear()

                    for done in dones:
                        if isinstance(done.result(), Line):
                            self._ping_sent = False
                            line = done.result()
                            emit = self.parse_tokens(line)
                            self._process_queue.append((line, emit))
                        elif done.result() is None:
                            if not self._ping_sent:
                                await self.send(build("PING", ["hello"]))
                                self._ping_sent = True
                            else:
                                await self.disconnect()
                                raise ServerDisconnectedException()
                    for notdone in notdones:
                        notdone.cancel()

            else:
                line, emit = self._process_queue.popleft()
                await self._on_read(line, emit)
Ejemplo n.º 8
0
 async def _next_who(self):
     if self._pending_who:
         chan = self._pending_who[0]
         if self.isupport.whox:
             await self.send(self.prepare_whox(chan))
         else:
             await self.send(build("WHO", [chan]))
Ejemplo n.º 9
0
    async def _batch_joins(self, channels: List[str], batch_n: int = 10):
        #TODO: do as many JOINs in one line as we can fit
        #TODO: channel keys

        for i in range(0, len(channels), batch_n):
            batch = channels[i:i + batch_n]
            await self.send(build("JOIN", [",".join(batch)]))
Ejemplo n.º 10
0
    async def handshake(self):
        nickname = self.params.nickname
        username = self.params.username or nickname
        realname = self.params.realname or nickname

        alt_nicks = self.params.alt_nicknames
        if not alt_nicks:
            alt_nicks = [nickname + "_" * i for i in range(1, 4)]
        self._alt_nicks = alt_nicks

        # these must remain non-awaited; reading hasn't started yet
        if not self.params.password is None:
            self.send(build("PASS", [self.params.password]))
        self.send(build("CAP", ["LS", "302"]))
        self.send(build("NICK", [nickname]))
        self.send(build("USER", [username, "0", "*", realname]))
Ejemplo n.º 11
0
    async def _ban_list(
            self,
            chan: str,
            depth=0) -> Optional[List[Tuple[(List[str], str, int)]]]:

        await self.send(build("MODE", [chan, "+b"]))

        masks: List[Tuple[List[str], str, int]] = []
        while True:
            line = await self.wait_for(
                Responses([RPL_BANLIST, RPL_ENDOFBANLIST, ERR_NOSUCHCHANNEL],
                          [SELF, Folded(chan)]))

            if line.command == ERR_NOSUCHCHANNEL:
                return None
            elif line.command == RPL_ENDOFBANLIST:
                break
            else:
                mask = line.params[2]
                set_by = line.params[3]
                set_at = int(line.params[4])
                masks.append(([mask], set_by, set_at))

        if depth == 0:
            for (mask, ), _, _ in list(masks):
                if mask.startswith("$j:"):
                    nextchan = mask.split(":", 1)[1].split("$", 1)[0]
                    nextchan_masks = await self._ban_list(nextchan, depth + 1)
                    if nextchan_masks is not None:
                        for nextmask, set_by, set_at in nextchan_masks:
                            masks.append((nextmask + [mask], set_by, set_at))

        return masks
Ejemplo n.º 12
0
    async def on_ls(self, tokens: Dict[str, str]):
        await self._sts(tokens)

        caps = list(self.server.desired_caps)+CAPS

        if (not self.server.params.sasl is None and
                not CAP_SASL in caps):
            caps.append(CAP_SASL)

        matched   = (c.available(tokens) for c in caps)
        cap_names = [name for name in matched if not name is None]

        if cap_names:
            await self.server.send(build("CAP", ["REQ", " ".join(cap_names)]))

            while cap_names:
                line = await self.server.wait_for({
                    Response("CAP", [ANY, "ACK"]),
                    Response("CAP", [ANY, "NAK"])
                })

                current_caps = line.params[2].split(" ")
                for cap in current_caps:
                    if cap in cap_names:
                        cap_names.remove(cap)
                if CAP_RESUME.available(current_caps):
                    await self.resume_token()

        if (self.server.cap_agreed(CAP_SASL) and
                not self.server.params.sasl is None):
            await self.server.sasl_auth(self.server.params.sasl)
Ejemplo n.º 13
0
    def send_whois(self,
                   target: str,
                   remote: bool = False) -> Awaitable[Optional[Whois]]:
        args = [target]
        if remote:
            args.append(target)

        fut = self.send(build("WHOIS", args))

        async def _assure() -> Optional[Whois]:
            folded = self.casefold(target)
            params = [ANY, Folded(folded)]

            obj = Whois()
            while True:
                line = await self.wait_for(
                    Responses([
                        ERR_NOSUCHNICK, ERR_NOSUCHSERVER, RPL_WHOISUSER,
                        RPL_WHOISSERVER, RPL_WHOISOPERATOR, RPL_WHOISIDLE,
                        RPL_WHOISCHANNELS, RPL_WHOISHOST, RPL_WHOISACCOUNT,
                        RPL_WHOISSECURE, RPL_ENDOFWHOIS
                    ], params), fut)
                if line.command in [ERR_NOSUCHNICK, ERR_NOSUCHSERVER]:
                    return None
                elif line.command == RPL_WHOISUSER:
                    nick, user, host, _, real = line.params[1:]
                    obj.nickname = nick
                    obj.username = user
                    obj.hostname = host
                    obj.realname = real
                elif line.command == RPL_WHOISIDLE:
                    idle, signon, _ = line.params[2:]
                    obj.idle = int(idle)
                    obj.signon = int(signon)
                elif line.command == RPL_WHOISACCOUNT:
                    obj.account = line.params[2]
                elif line.command == RPL_WHOISCHANNELS:
                    channels = list(filter(bool, line.params[2].split(" ")))
                    if obj.channels is None:
                        obj.channels = []

                    for i, channel in enumerate(channels):
                        symbols = ""
                        while channel[0] in self.isupport.prefix.prefixes:
                            symbols += channel[0]
                            channel = channel[1:]

                        channel_user = ChannelUser(
                            Name(obj.nickname, folded),
                            Name(channel, self.casefold(channel)))
                        for symbol in symbols:
                            mode = self.isupport.prefix.from_prefix(symbol)
                            if mode is not None:
                                channel_user.modes.append(mode)

                        obj.channels.append(channel_user)
                elif line.command == RPL_ENDOFWHOIS:
                    return obj

        return MaybeAwait(_assure)
Ejemplo n.º 14
0
    def send_joins(self,
                   names: List[str],
                   keys: List[str] = []) -> Awaitable[List[Channel]]:

        folded_names = [self.casefold(name) for name in names]

        if not keys:
            fut = self.send(build("JOIN", [",".join(names)]))
        else:
            fut = self.send(build("JOIN", [",".join(names)] + keys))

        async def _assure():
            channels: List[Channel] = []

            while folded_names:
                line = await self.wait_for(
                    {
                        Response(RPL_CHANNELMODEIS, [ANY, ANY]),
                        Responses(JOIN_ERR_FIRST, [ANY, ANY]),
                        Response(ERR_USERONCHANNEL, [ANY, SELF, ANY]),
                        Response(ERR_LINKCHANNEL, [ANY, ANY, ANY])
                    }, fut)

                chan: Optional[str] = None
                if line.command == RPL_CHANNELMODEIS:
                    chan = line.params[1]
                elif line.command in JOIN_ERR_FIRST:
                    chan = line.params[1]
                elif line.command == ERR_USERONCHANNEL:
                    chan = line.params[2]
                elif line.command == ERR_LINKCHANNEL:
                    #XXX i dont like this
                    chan = line.params[2]
                    await self.wait_for(
                        Response(RPL_CHANNELMODEIS, [ANY, Folded(chan)]))
                    channels.append(self.channels[self.casefold(chan)])
                    continue

                if chan is not None:
                    folded = self.casefold(chan)
                    if folded in folded_names:
                        folded_names.remove(folded)
                        channels.append(self.channels[folded])

            return channels

        return MaybeAwait(_assure)
Ejemplo n.º 15
0
def ircverify(username, verif_code):
    # define the variables
    d = irctokens.StatefulDecoder()
    e = irctokens.StatefulEncoder()
    s = socket.socket()

    #connecting to the server
    s.connect(("127.0.0.1", 6667))

    #defining the send function with proper formatting
    def _send(line):
        print(f"> {line.format()}")
        e.push(line)
        while e.pending():
            e.pop(s.send(e.pending()))

    # registering the connection to the server

    _send(irctokens.build("USER", [username, "0", "*", username]))
    _send(irctokens.build("NICK", [username]))

    # go through the cases

    while True:
        lines = d.push(s.recv(1024))

        if lines == None:  #if nothing is received from server
            return "server error"
            break

        for line in lines:
            print(f"< {line.format()}")

            if line.command == "433":  # if nickname already in use
                return "433"

            elif line.command == "005":  # when 005 is received pass the nickserv register command command
                _send(
                    irctokens.build(
                        "PRIVMSG",
                        ["NickServ", f"VERIFY {username} {verif_code}"]))

            if line.command == "NOTICE" and line.params == [
                    username, "Account created"
            ]:  # if Services respond with appropriate notice NOTICE
                _send(irctokens.build("QUIT"))
                return "success"
Ejemplo n.º 16
0
    async def _send_auth_text(self, text: str):
        n = AUTH_BYTE_MAX
        chunks = [text[i:i+n] for i in range(0, len(text), n)]
        if len(chunks[-1]) == 400:
            chunks.append("+")

        for chunk in chunks:
            await self.server.send(build("AUTHENTICATE", [chunk]))
Ejemplo n.º 17
0
    async def line_read(self, line: Line):
        print(f"{self.name} < {line.format()}")
        if line.command == "001":
            await self.send(build("JOIN", [",".join(CHANS)]))
        elif (line.command == "JOIN"
              and not self.is_me(line.hostmask.nickname)):
            nick = line.hostmask.nickname
            await self.send(build("WHO", [nick, "%int,111"]))
            who_line = await self.wait_for(
                Response(RPL_WHOSPCRPL,
                         [ANY, "111", ANY, Folded(nick)]))
            host = who_line.params[2]
            if (host == "255.255.255.255"
                    and line.hostmask.hostname is not None):
                host = line.hostmask.hostname

            user = self.users[self.casefold(line.hostmask.nickname)]
            fingerprint = f"{host}#{user.realname}"
            for pattern, mask_templ in PATTERNS:
                match = re.search(pattern, fingerprint)
                if match:
                    chan = self.channels[self.casefold(line.params[0])]
                    ip = match.group("ip")
                    mask = mask_templ.format(IP=ip)

                    list_modes = (chan.list_modes.get("b", []) +
                                  chan.list_modes.get("q", []))
                    if not mask in list_modes:
                        reason = await _match(ip)
                        if reason is not None:
                            await self._act(False, line, mask, ip, reason)
                            if not ACC or not user.account:
                                await self._act(True, line, mask, ip, reason)
                    else:
                        print("already caught")

        elif (line.command == "JOIN" and self.is_me(line.hostmask.nickname)):
            await self.send(build("MODE", [line.params[0], "+bq"]))

        elif (line.command == "INVITE" and self.is_me(line.params[0])):
            userhost = f"{line.hostmask.username}@{line.hostmask.hostname}"
            for admin_mask in ADMINS:
                if admin_mask.match(userhost):
                    await self.send(build("JOIN", [line.params[1]]))
                    break
Ejemplo n.º 18
0
    def send_part(self, name: str):
        fut = self.send(build("PART", [name]))

        async def _assure():
            line = await self.wait_for(
                Response("PART", [Folded(name)], source=MASK_SELF), fut)
            return

        return MaybeAwait(_assure)
Ejemplo n.º 19
0
Archivo: bot.py Proyecto: xfnw/Sifakis
    async def line_read(self, line: Line):
        print(f"{self.name} < {line.format()}")
        if line.command == "001":
            self.lc = "#" * (self.name == "freenode") + logchan
            print(f"connected to {self.name}")
            await self.send(build("JOIN", [self.lc]))
        if line.command == "PRIVMSG":
            if line.tags and 'batch' in line.tags and line.tags['batch'] == '1':
                return
            if line.params[1] == '!reload':
                importlib.reload(filts)
                await self.linelog('reloaded')  #sifakis
            if line.params[1][
                    0:
                    9] == "Sifakis: " and line.tags and 'account' in line.tags and line.tags[
                        'account'] == 'lickthecheese':
                await self.linelog(str(await aexec(self, line.params[1][9:])))
        if line.command == "INVITE":
            await self.send(build("JOIN", [line.params[1]]))

        asyncio.create_task(filts.line_read(self, line))
Ejemplo n.º 20
0
    async def external(self) -> SASLResult:
        await self.server.send(build("AUTHENTICATE", ["EXTERNAL"]))
        line = await self.server.wait_for({
            AUTHENTICATE_ANY,
            NUMERICS_INITIAL
        })

        if line.command == "907":
            # we've done SASL already. cleanly abort
            return SASLResult.ALREADY
        elif line.command == "908":
            available = line.params[1].split(",")
            raise SASLUnknownMechanismError(
                "Server does not support SASL EXTERNAL "
                f"(it supports {available}")
        elif line.command == "AUTHENTICATE" and line.params[0] == "+":
            await self.server.send(build("AUTHENTICATE", ["+"]))

            line = await self.server.wait_for(NUMERICS_LAST)
            if line.command == "903":
                return SASLResult.SUCCESS
        return SASLResult.FAILURE
Ejemplo n.º 21
0
    async def line_read(self, line: Line):
        if line.command == "001":
            chan_bans = await self._ban_list(CHAN)
            if chan_bans is None:
                sys.stderr.write(f"{CHAN} not found\n")
                sys.exit(1)

            accounts: Dict[str, List[str]] = {}
            for mask_tree, set_by, set_at in chan_bans:
                mask = mask_tree[0]
                if mask.startswith("$a:"):
                    if not mask in accounts:
                        accounts[mask] = []

                    accounts[mask].append((mask_tree[1:] or [CHAN])[0])

            states: List[Tuple[str, bool]] = []
            for mask in accounts.keys():
                account = mask.split(":", 1)[1].split("$", 1)[0]
                account = self.casefold(account)

                await self.send(build("NS", ["INFO", account]))
                line = await self.wait_for({RESP_REG, RESP_UNREG})

                if line.params[1].startswith("Information on "):
                    if not NONEXISTENT_ONLY:
                        states.append((mask, True))
                    await self.wait_for(RESP_END)
                else:
                    states.append((mask, False))

            states_where: Dict[str, Any] = {}
            for mask, registered in states:
                state: Dict[Any, Any] = {}

                sources = accounts[mask]
                if len(sources) == 1:
                    state["source"] = sources[0]
                else:
                    state["source"] = sources

                if not NONEXISTENT_ONLY:
                    state["registered"] = registered

                states_where[mask] = state

            with open(FILE, "w") as outfile:
                outfile.write(yaml.dump(states_where, sort_keys=False))
                outfile.write("\n")
            print(f"! written to {FILE}")
            sys.exit()
Ejemplo n.º 22
0
    def send_message(self, target: str,
                     message: str) -> Awaitable[Optional[str]]:
        fut = self.send(build("PRIVMSG", [target, message]))

        async def _assure():
            line = await self.wait_for(
                Response("PRIVMSG", [Folded(target), ANY], source=MASK_SELF),
                fut)
            if line.command == "PRIVMSG":
                return line.params[1]
            else:
                return None

        return MaybeAwait(_assure)
Ejemplo n.º 23
0
async def line_read(self, line):
    # line tags command params source
    if line.command == "PING" or line.command == "001":
        self.jointh = []
        self.tomode = ["#chaos", "-c**t"]
        self.attack = ['anton', 'julian']
    if line.command == "482":
        await self.send(build("cs", ["owner", "#chaos"]))
    if line.command == "JOIN":
        await on_join(self, line)
    if line.command == "MODE":
        await on_mode(self, line)
    if line.command == "KICK":
        await on_kick(self, line)
Ejemplo n.º 24
0
    async def _cs_op(self, channel: Channel) -> bool:
        await self.send(build("PRIVMSG", ["ChanServ", f"OP {channel.name}"]))

        try:
            await self.wait_for(Response(
                "MODE",
                [Folded(channel.name), "+o", SELF],
                source=CHANSERV,
            ),
                                timeout=2)
        except asyncio.TimeoutError:
            return False
        else:
            return True
Ejemplo n.º 25
0
    async def _cmodes(self, chan: str) -> Optional[str]:
        chan_fold = self.casefold(chan)
        if chan_fold in self.channels:
            channel = self.channels[chan_fold]
            return "".join(channel.modes.keys())

        await self.send(build("MODE", [chan]))
        line = await self.wait_for(Responses(
            [RPL_CHANNELMODEIS, ERR_NOSUCHCHANNEL],
            [SELF, Folded(chan)]
        ))

        if line.command == RPL_CHANNELMODEIS:
            return line.params[2].replace("+", "")

        return None
Ejemplo n.º 26
0
    async def _ban_list(self,
            chan:  str,
            modes: str,
            depth=0
            ) -> Optional[List[Tuple[Type, List[str], str, int]]]:

        await self.send(build("MODE", [chan, f"+{modes}"]))

        ends = len(modes)
        masks: List[Tuple[Type, List[str], str, int]] = []
        while True:
            line = await self.wait_for(Responses([
                RPL_BANLIST, RPL_QUIETLIST,
                RPL_ENDOFBANLIST, RPL_ENDOFQUIETLIST, ERR_NOSUCHCHANNEL
            ], [SELF, Folded(chan)]))

            if line.command == ERR_NOSUCHCHANNEL:
                return None
            elif line.command in [RPL_ENDOFBANLIST, RPL_ENDOFQUIETLIST]:
                ends -= 1
                if ends == 0:
                    break
            else:
                offset = 0
                type = Type.BAN
                if line.command == RPL_QUIETLIST:
                    offset += 1
                    type = Type.QUIET
                mask   = line.params[offset+2]
                set_by = line.params[offset+3]
                set_at = int(line.params[offset+4])
                masks.append((type, [mask], set_by, set_at))

        if depth == 0:
            for type, (mask,), _, _ in list(masks):
                if mask.startswith("$j:"):
                    nextchan = mask.split(":", 1)[1].split("$", 1)[0]
                    nextchan_masks = await self._ban_list(
                        nextchan, "b", depth + 1
                    )
                    if nextchan_masks is not None:
                        for _, nextmask, set_by, set_at in nextchan_masks:
                            masks.append(
                                (type, nextmask+[mask], set_by, set_at)
                            )

        return masks
Ejemplo n.º 27
0
    async def _act(self, user: User, chan: Channel, mask: str, ip: str,
                   reason: str):

        act_sets = CONFIG.act_defaults
        act_sets_c = CONFIG.channels.get(chan.name_lower, None)
        if act_sets_c is not None:
            act_sets = act_sets_c

        act_cmds = [CONFIG.act_sets[a] for a in act_sets]
        acts = list(itertools.chain(*act_cmds))
        # put False (non-op) acts first
        acts.sort(key=lambda x: x[0])

        data = {
            "CHAN": chan.name,
            "NICK": user.nickname,
            "USER": user.username,
            "HOST": user.hostname,
            "MASK": mask,
            "IP": ip,
            "REASON": reason
        }

        remove_op = False
        last = len(acts) - 1
        for i, (need_op, action_s) in enumerate(acts):
            if need_op:
                if not "o" in chan.users[self.nickname_lower].modes:
                    got_op = await self._cs_op(chan)
                    if not got_op:
                        break
                    else:
                        remove_op = True

            action = tokenise(action_s.format(**data))
            if i == last and remove_op:
                target = self.casefold(action.params[0])
                if (action.command == "MODE" and chan.name_lower == target
                        and len(action.params[2:]) < self.isupport.modes):
                    action.params[1] += "-o"
                    action.params.append(self.nickname)
                else:
                    await self.send(action)
                    action = build("MODE", [chan.name, "-o", self.nickname])
            await self.send(action)
Ejemplo n.º 28
0
    def send_nick(self, new_nick: str) -> Awaitable[bool]:
        fut = self.send(build("NICK", [new_nick]))

        async def _assure() -> bool:
            line = await self.wait_for(
                {
                    Response("NICK", [Folded(new_nick)], source=MASK_SELF),
                    Responses([
                        ERR_BANNICKCHANGE, ERR_NICKTOOFAST, ERR_CANTCHANGENICK
                    ], [ANY]),
                    Responses([
                        ERR_NICKNAMEINUSE, ERR_ERRONEUSNICKNAME,
                        ERR_UNAVAILRESOURCE
                    ], [ANY, Folded(new_nick)])
                }, fut)
            return line.command == "NICK"

        return MaybeAwait(_assure)
Ejemplo n.º 29
0
    async def resume_token(self):
        line = await self.server.wait_for(Response("RESUME", ["TOKEN", ANY]))
        token = line.params[1]
        address, port = self.server.server_address()
        resume_policy = ResumePolicy(address, token)

        previous_policy = self.server.params.resume
        self.server.params.resume = resume_policy
        await self.server.resume_policy(resume_policy)

        if previous_policy is not None and not self.server.registered:
            await self.server.send(build("RESUME", [previous_policy.token]))
            line = await self.server.wait_for({
                Response("RESUME", ["SUCCESS"]),
                Response("FAIL",   ["RESUME"])
            })
            if line.command == "RESUME":
                raise HandshakeCancel()
Ejemplo n.º 30
0
    async def _assure_op(self, channel: Channel) -> bool:
        channel_self = channel.users[self.nickname_lower]
        if not "o" in channel_self.modes:
            await self.send(
                build("PRIVMSG", ["ChanServ", f"OP {channel.name}"]))

            try:
                await self.wait_for(Response(
                    "MODE",
                    [Folded(channel.name), "+o", SELF],
                    source=CHANSERV,
                ),
                                    timeout=5)
            except asyncio.TimeoutError:
                return False
            else:
                return True
        else:
            return False