From 885889495ad85f5ecef4d52de84d2a1ca07e756e Mon Sep 17 00:00:00 2001 From: "Vgr E. Barry" Date: Wed, 16 Nov 2016 16:18:27 -0500 Subject: [PATCH] Properly handle the bot's nick being already in use --- oyoyo/client.py | 20 ++++++++------------ src/handler.py | 37 ++++++++++++++++++++----------------- src/users.py | 24 +++++++++++++++++++++++- 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/oyoyo/client.py b/oyoyo/client.py index 32f50b7..53438e5 100644 --- a/oyoyo/client.py +++ b/oyoyo/client.py @@ -179,7 +179,7 @@ class IRCClient: if not self.blocking: self.socket.setblocking(0) - self.cap("LS 302") + self.send("CAP LS 302") if self.server_pass and (not self.sasl_auth or "{password}" not in self.server_pass): message = "PASS :{0}".format(self.server_pass).format( @@ -187,7 +187,7 @@ class IRCClient: password=self.password) self.send(message) - self.nick(self.nickname) + self.send("NICK", self.nickname) self.user(self.ident, self.real_name) if self.connect_cb: @@ -272,24 +272,20 @@ class IRCClient: self.send("MODE {0}".format(" ".join(args))) def kick(self, chan, nick, msg=""): self.send("KICK", chan, nick, ":"+msg) - def nick(self, nick): - self.send("NICK {0}".format(nick)) def who(self, *args): self.send("WHO {0}".format(" ".join(args))) - def cap(self, req): - self.send("CAP {0}".format(req)) def ns_identify(self, account, passwd, nickserv, command): if command: self.msg(nickserv, command.format(account=account, password=passwd)) - def ns_ghost(self, nickserv, command): + def ns_ghost(self, nick, password, nickserv, command): if command: - self.msg(nickserv, command.format(nick=self.nickname)) - def ns_release(self, nickserv="NickServ", command="RELEASE {nick}"): + self.msg(nickserv, command.format(nick=nick, password=password)) + def ns_release(self, nick, password, nickserv="NickServ", command="RELEASE {nick}"): if command: - self.msg(nickserv, command.format(nick=self.nickname)) - def ns_regain(self, nickserv="NickServ", command="REGAIN {nick}"): + self.msg(nickserv, command.format(nick=nick, password=password)) + def ns_regain(self, nick, password, nickserv="NickServ", command="REGAIN {nick}"): if command: - self.msg(nickserv, command.format(nick=self.nickname)) + self.msg(nickserv, command.format(nick=nick, password=password)) def user(self, ident, rname): self.send("USER", ident, self.host, self.host, ":{0}".format(rname or ident)) def mainLoop(self): diff --git a/src/handler.py b/src/handler.py index cd6ec15..188c1d6 100644 --- a/src/handler.py +++ b/src/handler.py @@ -56,9 +56,6 @@ def connect_callback(cli): # This callback only sets up event listeners wolfgame.connect_callback() - users.Bot = users.User(cli, botconfig.NICK, None, None, None, None) - users.Bot.modes = set() # only for the bot (user modes) - # just in case we haven't managed to successfully auth yet if not botconfig.SASL_AUTHENTICATION: cli.ns_identify(botconfig.USERNAME or botconfig.NICK, @@ -82,24 +79,29 @@ def connect_callback(cli): #if var.CHANSERV_OP_COMMAND: # TODO: Add somewhere else if needed # cli.msg(var.CHANSERV, var.CHANSERV_OP_COMMAND.format(channel=botconfig.CHANNEL)) - cli.nick(botconfig.NICK) # very important (for regain/release) + users.Bot.change_nick(botconfig.NICK) - def mustregain(cli, *blah): - if not botconfig.PASS: + def mustregain(cli, server, bot_nick, nick, msg): + if not botconfig.PASS or bot_nick == nick: return - cli.ns_regain(nickserv=var.NICKSERV, command=var.NICKSERV_REGAIN_COMMAND) + cli.ns_regain(nick=botconfig.NICK, password=botconfig.PASS, nickserv=var.NICKSERV, command=var.NICKSERV_REGAIN_COMMAND) + users.Bot.change_nick(botconfig.NICK) - def mustrelease(cli, *rest): - if not botconfig.PASS: + def mustrelease(cli, server, bot_nick, nick, msg): + if not botconfig.PASS or bot_nick == nick: return # prevents the bot from trying to release without a password - cli.ns_release(nickserv=var.NICKSERV, command=var.NICKSERV_RELEASE_COMMAND) - cli.nick(botconfig.NICK) + func = cli.ns_release + if getattr(botconfig, "USE_NICKSERV_GHOST", False): # FIXME + func = cli.ns_ghost + func(nick=botconfig.NICK, password=botconfig.PASS, nickserv=var.NICKSERV, command=var.NICKSERV_RELEASE_COMMAND) + users.Bot.change_nick(botconfig.NICK) @hook("unavailresource", hookid=239) @hook("nicknameinuse", hookid=239) def must_use_temp_nick(cli, *etc): - cli.nick(botconfig.NICK+"_") - cli.user(botconfig.NICK, "") + users.Bot.nick += "_" + users.Bot.change_nick() + cli.user(botconfig.NICK, "") # TODO: can we remove this? hook.unhook(239) hook("unavailresource")(mustrelease) @@ -112,7 +114,6 @@ def connect_callback(cli): supported_caps = set() - @hook("cap") def on_cap(cli, svr, mynick, cmd, caps, star=None): if cmd == "LS": @@ -129,12 +130,12 @@ def connect_callback(cli): common_caps = request_caps & supported_caps if common_caps: - cli.cap("REQ " ":{0}".format(" ".join(common_caps))) + cli.send("CAP REQ " ":{0}".format(" ".join(common_caps))) elif cmd == "ACK": if "sasl" in caps: cli.send("AUTHENTICATE PLAIN") else: - cli.cap("END") + cli.send("CAP END") elif cmd == "NAK": # This isn't supposed to happen. The server claimed to support a # capability but now claims otherwise. @@ -151,7 +152,7 @@ def connect_callback(cli): @hook("903") def on_successful_auth(cli, blah, blahh, blahhh): - cli.cap("END") + cli.send("CAP END") @hook("904") @hook("905") @@ -162,4 +163,6 @@ def connect_callback(cli): "in botconfig.USERNAME if it's different from the bot nick?") cli.quit() + users.Bot = users.BotUser(cli, botconfig.NICK) + # vim: set sw=4 expandtab: diff --git a/src/users.py b/src/users.py index 972cf39..e98e152 100644 --- a/src/users.py +++ b/src/users.py @@ -173,7 +173,7 @@ class User(IRCContext): def __new__(cls, cli, nick, ident, host, realname, account, **kwargs): self = super().__new__(cls) - super(cls, self).__init__(nick, cli, **kwargs) + super(User, self).__init__(nick, cli, **kwargs) self._ident = ident self._host = host @@ -523,3 +523,25 @@ class FakeUser(User): @rawnick.setter def rawnick(self, rawnick): self.nick = parse_rawnick_as_dict(rawnick)["nick"] + +class BotUser(User): # TODO: change all the 'if x is Bot' for 'if isinstance(x, BotUser)' + + def __new__(cls, cli, nick): + self = super().__new__(cls, cli, nick, None, None, None, None) + self.modes = set() + return self + + def change_nick(self, nick=None): + if nick is None: + nick = self.nick + self.client.send("NICK", nick) + + + + + + + + + +