diff --git a/botconfig.py.example b/botconfig.py.example index 1904948..01d1002 100644 --- a/botconfig.py.example +++ b/botconfig.py.example @@ -7,7 +7,7 @@ NICK = "mywolfbot" CMD_CHAR = "!" CHANGING_HOST_QUIT_MESSAGE = "Changing host" -JOIN_AFTER_CLOAKED = True # Set to false if the bot does not have a cloak +SASL_AUTHENTICATION = False # put account name in USERNAME ^ if different from nick DISABLE_DEBUG_MODE = False # Entirely disable debug mode IGNORE_HIDDEN_COMMANDS = True # Ignore commands sent to @#channel or +#channel ALLOW_NOTICE_COMMANDS = False # allow /notice #channel !command to be interpreted as a command diff --git a/modules/common.py b/modules/common.py index 5feb359..bae8a40 100644 --- a/modules/common.py +++ b/modules/common.py @@ -6,6 +6,7 @@ import logging import tools.moduleloader as ld import traceback from settings import common as var +from base64 import b64encode def on_privmsg(cli, rawnick, chan, msg, notice = False): currmod = ld.MODULES[ld.CURRENT_MODULE] @@ -94,9 +95,6 @@ hook = decorators.generate(HOOKS, raw_nick=True, permissions=False) def connect_callback(cli): - identified = False - need_ghost = False - def prepare_stuff(*args): cli.join(botconfig.CHANNEL) cli.msg("ChanServ", "op "+botconfig.CHANNEL) @@ -106,67 +104,56 @@ def connect_callback(cli): ld.MODULES[ld.CURRENT_MODULE].connect_callback(cli) - cli.nick(botconfig.NICK) # just in case + cli.nick(botconfig.NICK) # very important (for regain/release) - if botconfig.JOIN_AFTER_CLOAKED: - prepare_stuff = hook("event_hosthidden", hookid=294)(prepare_stuff) - else: - prepare_stuff = hook("endofmotd", hookid=294)(prepare_stuff) - - @hook("mode") - def check_if_identified(cli, spam, egg, m, *etc): - if m == "+i": - identified = True + prepare_stuff = hook("endofmotd", hookid=294)(prepare_stuff) - @hook("nicknameinuse") - def mustghost(cli, *blah): - cli.ns_identify(cli.password) - cli.nick(botconfig.NICK+"_") - if identified: - cli.ns_ghost() - cli.nick(botconfig.NICK) - else: - @hook("mode") - def do_ghost(cli, spam, egg, m, *etc): - if m == "+i": - cli.ns_ghost() - - if not botconfig.JOIN_AFTER_CLOAKED: - prepare_stuff(cli) - - @hook("quit", hookid=232) - def after_ghost(cli, nick, reason): - if nick == botconfig.NICK and reason == "Disconnected by services": - cli.nick(botconfig.NICK) + def mustregain(cli, *blah): + cli.ns_regain() - decorators.unhook(HOOKS, 232) + def mustrelease(cli, *rest): + cli.ns_release() + cli.nick(botconfig.NICK) - @hook("unavailresource") - def mustrelease(cli, *blah): - cli.ns_identify(cli.password) + @hook("unavailresource", hookid=239) + @hook("nicknameinuse", hookid=239) + def must_use_temp_nick(cli, *etc): cli.nick(botconfig.NICK+"_") - if identified: - cli.ns_release() - cli.nick(botconfig.NICK) - else: - @hook("mode") - def do_release(cli, spam, egg, m, *etc): - if m == "+i": - cli.ns_release() - - if not botconfig.JOIN_AFTER_CLOAKED: - prepare_stuff(cli) - - @hook("notice", hookid=233) - def after_release(cli, *etc): #hopefully this works - cli.nick(botconfig.NICK) - - decorators.unhook(HOOKS, 233) + cli.user(botconfig.NICK, "") - if not botconfig.JOIN_AFTER_CLOAKED: # join immediately - pass - # prepare_stuff(cli) + decorators.unhook(HOOKS, 239) + hook("unavailresource")(mustrelease) + hook("nicknameinuse")(mustregain) + if botconfig.SASL_AUTHENTICATION: + + @hook("authenticate") + def auth_plus(cli, something, plus): + if plus == "+": + nick_b = bytes(botconfig.USERNAME if botconfig.USERNAME else botconfig.NICK, "utf-8") + pass_b = bytes(botconfig.PASS, "utf-8") + secrt_msg = b'\0'.join((nick_b, nick_b, pass_b)) + print(secrt_msg) + cli.send("AUTHENTICATE " + b64encode(secrt_msg).decode("utf-8")) + + @hook("cap") + def on_cap(cli, svr, mynick, ack, cap): + if ack.upper() == "ACK" and "sasl" in cap: + cli.send("AUTHENTICATE PLAIN") + + @hook("903") + def on_successful_auth(cli, blah, blahh, blahhh): + cli.cap("END") + + @hook("904") + @hook("905") + @hook("906") + @hook("907") + def on_failure_auth(cli, *etc): + cli.quit() + print("Authentication failed. Did you fill the account name "+ + "in botconfig.USERNAME if it's different from the bot nick?") + @hook("ping") diff --git a/modules/wolfgame.py b/modules/wolfgame.py index 4c9f1df..5b3f988 100644 --- a/modules/wolfgame.py +++ b/modules/wolfgame.py @@ -104,7 +104,7 @@ def connect_callback(cli): cmodes.append(("-q", quieted)) @hook("mode", hookid=294) - def on_give_me_ops(cli, blah, blahh, modeaction, target): + def on_give_me_ops(cli, blah, blahh, modeaction, target=""): if modeaction == "+o" and target == botconfig.NICK and var.PHASE == "none": decorators.unhook(HOOKS, 294) mass_mode(cli, cmodes) @@ -357,7 +357,7 @@ def join(cli, nick, chann_, rest): if var.PHASE == "none": - cli.mode(chan, "+v", nick, nick+"!*@*") + cli.mode(chan, "+v", nick) var.ROLES["person"].append(nick) var.PHASE = "join" var.WAITED = 0 @@ -374,7 +374,7 @@ def join(cli, nick, chann_, rest): cli.notice(nick, "Sorry but the game is already running. Try again next time.") else: - cli.mode(chan, "+v", nick, nick+"!*@*") + cli.mode(chan, "+v", nick) var.ROLES["person"].append(nick) cli.msg(chan, '\u0002{0}\u0002 has joined the game.'.format(nick)) diff --git a/oyoyo/client.py b/oyoyo/client.py index 545f78a..65f4d6a 100644 --- a/oyoyo/client.py +++ b/oyoyo/client.py @@ -107,6 +107,7 @@ class IRCClient(object): self.authname = "" self.connect_cb = None self.blocking = True + self.sasl_auth = False self.lock = threading.RLock() self.tokenbucket = TokenBucket(23, 1.73) @@ -147,7 +148,7 @@ class IRCClient(object): for arg in args]), i)) msg = bytes(" ", "utf_8").join(bargs) - logging.info('---> send "{0}"'.format(msg)) + logging.info('---> send {0}'.format(str(msg)[1:])) while not self.tokenbucket.consume(1): time.sleep(0.3) @@ -178,12 +179,19 @@ class IRCClient(object): if not self.blocking: self.socket.setblocking(0) - self.send("PASS {0}:{1}".format(self.authname if self.authname else self.nickname, - self.password if self.password else "NOPASS")) + if not self.sasl_auth: + self.send("PASS {0}:{1}".format(self.authname if self.authname else self.nickname, + self.password if self.password else "NOPASS")) + else: + self.cap("LS") self.nick(self.nickname) self.user(self.nickname, self.real_name) + if self.sasl_auth: + self.cap("REQ", "multi-prefix") + self.cap("REQ", "sasl") + if self.connect_cb: try: self.connect_cb(self) @@ -268,6 +276,8 @@ class IRCClient(object): self.msg("NickServ", "GHOST "+self.nickname) def ns_release(self): self.msg("NickServ", "RELEASE "+self.nickname) + def ns_regain(self): + self.msg("NickServ", "REGAIN "+self.nickname) def user(self, uname, rname): self.send("USER", uname, self.host, self.host, rname or uname) diff --git a/wolfbot.py b/wolfbot.py index 4e3d4a6..dfcbf0b 100755 --- a/wolfbot.py +++ b/wolfbot.py @@ -51,6 +51,7 @@ def main(): authname=botconfig.USERNAME, password=botconfig.PASS, nickname=botconfig.NICK, + sasl_auth=botconfig.SASL_AUTHENTICATION, connect_cb=modules.common.connect_callback ) cli.mainLoop()