From 3e56a66c37ef84d4ea7b93bf74e35b09eb444629 Mon Sep 17 00:00:00 2001 From: jcao219 Date: Sun, 7 Aug 2011 00:48:26 -0500 Subject: [PATCH] fixed non-privmsg-nickserv authentication, added rate limiting for !stats, !votes, !admins, detectives now have a more complete PM message --- botconfig.py.example | 1 + oyoyo/client.py | 5 ++++- var.py | 3 +++ wolfbot.py | 1 + wolfgame.py | 50 +++++++++++++++++++++++++++++++++++--------- 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/botconfig.py.example b/botconfig.py.example index 75378c3..3517e79 100644 --- a/botconfig.py.example +++ b/botconfig.py.example @@ -2,6 +2,7 @@ PASS = "my_nickserv_pass" CHANNEL = "#mywolfgame" HOST = "irc.freenode.net" PORT = 6667 # SSL not supported yet +USERNAME = "" # for authentication, can be left blank if same as NICK NICK = "mywolfbot" OWNERS = ("unaffiliated/wolfbot_admin1",) # the comma is required at the end if there is one owner ADMINS = ("unaffiliated/wolfbot_admin2", "unaffiliated/wolfbot_admin3") diff --git a/oyoyo/client.py b/oyoyo/client.py index 23f366f..2949b3b 100644 --- a/oyoyo/client.py +++ b/oyoyo/client.py @@ -100,6 +100,7 @@ class IRCClient(object): self.host = None self.port = None self.password = "" + self.authname = "" self.connect_cb = None self.blocking = True self.lock = threading.RLock() @@ -175,9 +176,11 @@ 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")) + self.nick(self.nickname) self.user(self.nickname, self.real_name) - self.send("PASS :{0}\r\n".format(self.password if self.password else "NOPASS")) if self.connect_cb: self.connect_cb(self) diff --git a/var.py b/var.py index fd75c29..1cc77ea 100644 --- a/var.py +++ b/var.py @@ -2,6 +2,9 @@ PING_WAIT = 300 # Seconds MINIMUM_WAIT = 60 EXTRA_WAIT = 20 MAXIMUM_WAITED = 2 # limit for amount of !wait's +STATS_RATE_LIMIT = 60 +VOTES_RATE_LIMIT = 60 +ADMINS_RATE_LIMIT = 300 SHOTS_MULTIPLIER = .12 # ceil(shots_multiplier * len_players) = bullets given MAX_PLAYERS = 30 DRUNK_SHOTS_MULTIPLIER = 3 diff --git a/wolfbot.py b/wolfbot.py index bbe4d18..0affa26 100644 --- a/wolfbot.py +++ b/wolfbot.py @@ -87,6 +87,7 @@ def main(): "":__unhandled__}, host=botconfig.HOST, port=botconfig.PORT, + authname=botconfig.USERNAME, password=botconfig.PASS, nickname=botconfig.NICK, connect_cb=wolfgame.connect_callback diff --git a/wolfgame.py b/wolfgame.py index 4353b75..22b0141 100644 --- a/wolfgame.py +++ b/wolfgame.py @@ -36,15 +36,11 @@ hook = decorators.generate(HOOKS, raw_nick=True) # Game Logic Begins: def connect_callback(cli): - cli.ns_identify(botconfig.PASS) def prepare_stuff(*args): cli.join(botconfig.CHANNEL) cli.msg("ChanServ", "op "+botconfig.CHANNEL) - var.USERS = [] - var.CLOAKS = [] - @hook("whoreply", id=294) def on_whoreply(cli, server, dunno, chan, dunno1, cloak, dunno3, user, status, dunno4): @@ -65,7 +61,6 @@ def connect_callback(cli): @hook("nicknameinuse") def mustghost(cli, *blah): cli.nick(botconfig.NICK+"_") - cli.ns_identify(botconfig.PASS) cli.ns_ghost() cli.nick(botconfig.NICK) prepare_stuff() @@ -73,12 +68,18 @@ def connect_callback(cli): @hook("unavailresource") def mustrelease(cli, *blah): cli.nick(botconfig.NICK+"_") - cli.ns_identify(botconfig.PASS) cli.ns_release() cli.nick(botconfig.NICK) prepare_stuff() - var.LAST_PING = 0 # time of last ping + var.LAST_PING = None # time of last ping + var.LAST_STATS = None + var.LAST_VOTES = None + var.LAST_ADMINS = None + + var.USERS = [] + var.CLOAKS = [] + var.PINGING = False var.ADMIN_PINGING = False var.ROLES = {"person" : []} @@ -214,7 +215,7 @@ def restart_program(cli, nick, *rest): def pinger(cli, nick, chan, rest): """Pings the channel to get people's attention. Rate-Limited.""" if (var.LAST_PING and - var.LAST_PING + timedelta(seconds=300) > datetime.now()): + var.LAST_PING + timedelta(seconds=var.PING_WAIT) > datetime.now()): cli.notice(nick, ("This command is ratelimited. " + "Please wait a while before using it again.")) return @@ -395,6 +396,14 @@ def stats(cli, nick, chan, rest): cli.notice(nick, "No game is currently running.") return + if (var.LAST_STATS and + var.LAST_STATS + timedelta(seconds=var.STATS_RATE_LIMIT) > datetime.now()): + cli.msg(chan, (nick+": This command is ratelimited. " + + "Please wait a while before using it again.")) + return + + var.LAST_STATS = datetime.now() + pl = var.list_players() pl.sort(key=lambda x: x.lower()) if len(pl) > 1: @@ -531,13 +540,23 @@ def chk_decision(cli): @cmd("votes") def show_votes(cli, nick, chan, rest): """Displays the voting statistics.""" + if var.PHASE in ("none", "join"): cli.notice(nick, "No game is currently running.") return if var.PHASE != "day": cli.notice(nick, "Voting is only during the day.") return - elif not var.VOTES.values(): + + if (var.LAST_VOTES and + var.LAST_VOTES + timedelta(seconds=var.VOTES_RATE_LIMIT) > datetime.now()): + cli.msg(chan, (nick+": This command is ratelimited. " + + "Please wait a while before using it again.")) + return + + var.LAST_VOTES = datetime.now() + + if not var.VOTES.values(): cli.msg(chan, nick+": No votes yet.") else: votelist = ["{0}: {1} ({2})".format(votee, @@ -1727,7 +1746,10 @@ def transition_night(cli): cli.msg(dttv, ("You are a \u0002detective\u0002.\n"+ "It is your job to determine all the wolves and traitors. "+ "Your job is during the day, and you can see the true "+ - "identity of all users, even traitors.")) + "identity of all users, even traitors.\n"+ + "But, each time you use your ability, you risk a 2/5 "+ + "chance of having your identity revealed to the wolves. So be "+ + "careful. Use \"!id\" to identify any player during the day.")) for d in var.ROLES["village drunk"]: cli.msg(d, 'You have been drinking too much! You are the \u0002village drunk\u0002.') @@ -2096,6 +2118,14 @@ def show_admins(cli, nick, chan, rest): """Pings the admins that are available.""" admins = [] + if (var.LAST_ADMINS and + var.LAST_ADMINS + timedelta(seconds=var.ADMINS_RATE_LIMIT) > datetime.now()): + cli.msg(chan, (nick+": This command is ratelimited. " + + "Please wait a while before using it again.")) + return + + var.LAST_ADMINS = datetime.now() + if var.ADMIN_PINGING: return var.ADMIN_PINGING = True