diff --git a/modules/wolfgame.py b/modules/wolfgame.py index 1f6a1cb..b4657b9 100644 --- a/modules/wolfgame.py +++ b/modules/wolfgame.py @@ -333,7 +333,6 @@ def reset(): var.ROLES = {"person" : []} var.JOINED_THIS_GAME = [] # keeps track of who already joined this game at least once (cloaks) var.JOINED_THIS_GAME_ACCS = [] # same, except accounts - var.PING_JOIN_TIMER = 0 var.PINGED_ALREADY = [] var.PINGED_ALREADY_ACCS = [] var.NO_LYNCH = [] @@ -983,66 +982,67 @@ def toggle_altpinged_status(nick, value, old=None): var.PING_IF_NUMS[old].remove(cloak) def join_timer_handler(cli): - while var.PHASE == "join": - with var.GRAVEYARD_LOCK: - if var.PING_JOIN_TIMER and var.PING_JOIN_TIMER + timedelta(seconds=10) <= datetime.now(): - to_ping = [] - pl = var.list_players() + var.PINGING_IFS = True + to_ping = [] + pl = var.list_players() - var.PINGING_IFS = True - checker = [] - chk_acc = [] + checker = [] + chk_acc = [] - for num in var.PING_IF_NUMS_ACCS: - if num <= len(pl): - chk_acc.extend(var.PING_IF_NUMS_ACCS[num]) + for num in var.PING_IF_NUMS_ACCS: + if num <= len(pl): + chk_acc.extend(var.PING_IF_NUMS_ACCS[num]) - if not var.ACCOUNTS_ONLY: - for num in var.PING_IF_NUMS: - if num <= len(pl): - checker.extend(var.PING_IF_NUMS[num]) + if not var.ACCOUNTS_ONLY: + for num in var.PING_IF_NUMS: + if num <= len(pl): + checker.extend(var.PING_IF_NUMS[num]) - for acc in chk_acc[:]: - if acc in var.PINGED_ALREADY_ACCS: - chk_acc.remove(acc) + for acc in chk_acc[:]: + if acc in var.PINGED_ALREADY_ACCS: + chk_acc.remove(acc) - for cloak in checker[:]: - if cloak in var.PINGED_ALREADY: - checker.remove(cloak) + for cloak in checker[:]: + if cloak in var.PINGED_ALREADY: + checker.remove(cloak) - if not chk_acc and not checker: - var.PINGING_IFS = False - var.PING_JOIN_TIMER = 0 - return + if not chk_acc and not checker: + var.PINGING_IFS = False + return - @hook("whospcrpl", hookid=387) - def ping_altpingers(cli, server, nick, ident, cloak, _, user, status, acc): - if ('G' in status or is_user_stasised(user)[0] or not var.PINGING_IFS or - user == botconfig.NICK or user in pl): + @hook("whospcrpl", hookid=387) + def ping_altpingers(cli, server, nick, ident, cloak, _, user, status, acc): + if ('G' in status or is_user_stasised(user)[0] or not var.PINGING_IFS or + user == botconfig.NICK or user in pl): - return + return - if acc and acc != "*": - if acc in chk_acc and acc in var.PING_PREFS_ACCS and var.PING_PREFS_ACCS[acc] in ("once", "all"): - to_ping.append(user) - var.PINGED_ALREADY_ACCS.append(acc) + if acc and acc != "*": + if acc in chk_acc and acc in var.PING_PREFS_ACCS and var.PING_PREFS_ACCS[acc] in ("once", "all"): + to_ping.append(user) + var.PINGED_ALREADY_ACCS.append(acc) - elif not var.ACCOUNTS_ONLY and cloak in checker and cloak in var.PING_PREFS and var.PING_PREFS[cloak] in ("once", "all"): - to_ping.append(user) - var.PINGED_ALREADY.append(cloak) + elif not var.ACCOUNTS_ONLY and cloak in checker and cloak in var.PING_PREFS and var.PING_PREFS[cloak] in ("once", "all"): + to_ping.append(user) + var.PINGED_ALREADY.append(cloak) - @hook("endofwho", hookid=387) - def fetch_altpingers(*stuff): - var.PINGING_IFS = False - var.PING_JOIN_TIMER = 0 - decorators.unhook(HOOKS, 387) - if to_ping: - to_ping.sort(key=lambda x: x.lower()) - cli.msg(botconfig.CHANNEL, "PING! {0} players! {1}".format(len(pl), " ".join(to_ping))) + @hook("endofwho", hookid=387) + def fetch_altpingers(*stuff): + # fun fact: if someone joined 10 seconds after someone else, the bot would break. + # effectively, the join would delete join_pinger from var.TIMERS and this function + # here would be reached before it was created again, thus erroring and crashing. + # this is one of the multiple reasons we need unit testing + # I was lucky to catch this in testing, as it requires precise timing + # it only failed if a join happened while this outer func had started + if 'join_pinger' in var.TIMERS: + del var.TIMERS['join_pinger'] + var.PINGING_IFS = False + decorators.unhook(HOOKS, 387) + if to_ping: + to_ping.sort(key=lambda x: x.lower()) + cli.msg(botconfig.CHANNEL, "PING! {0} players! {1}".format(len(pl), " ".join(to_ping))) - cli.who(botconfig.CHANNEL, "%nushaf") - - time.sleep(5) + cli.who(botconfig.CHANNEL, "%nushaf") @cmd("join", "j", none=True, join=True) def join(cli, nick, chan, rest): @@ -1096,12 +1096,8 @@ def join_player(cli, player, chan, who = None, forced = False): var.PHASE = "join" var.WAITED = 0 var.GAME_ID = time.time() - var.PING_JOIN_TIMER = datetime.now() var.PINGED_ALREADY_ACCS = [] var.PINGED_ALREADY = [] - join_pinger = threading.Thread(None, join_timer_handler, args=(cli,)) - join_pinger.daemon = True - join_pinger.start() if cloak: var.JOINED_THIS_GAME.append(cloak) if acc: @@ -1156,8 +1152,14 @@ def join_player(cli, player, chan, who = None, forced = False): var.LAST_GSTATS = None var.LAST_PSTATS = None var.LAST_TIME = None - with var.GRAVEYARD_LOCK: - var.PING_JOIN_TIMER = datetime.now() + + if 'join_pinger' in var.TIMERS: + var.TIMERS['join_pinger'][0].cancel() + + t = threading.Timer(10, join_timer_handler, (cli,)) + var.TIMERS['join_pinger'] = (t, time.time(), 10) + t.daemon = True + t.start() def kill_join(cli, chan): pl = var.list_players() @@ -5572,6 +5574,10 @@ def start(cli, nick, chan, forced = False): if chan != botconfig.CHANNEL: return + if 'join_pinger' in var.TIMERS: + var.TIMERS['join_pinger'][0].cancel() + del var.TIMERS['join_pinger'] + villagers = var.list_players() pl = villagers[:]