full threading for the reaper function
This commit is contained in:
parent
d64b4ee2f8
commit
0211053b1d
@ -35,7 +35,6 @@ def generate(fdict, **kwargs):
|
|||||||
if (fn.owner_only != owner_only or
|
if (fn.owner_only != owner_only or
|
||||||
fn.admin_only != admin_only):
|
fn.admin_only != admin_only):
|
||||||
raise Exception("Command: "+x+" has non-matching protection levels!")
|
raise Exception("Command: "+x+" has non-matching protection levels!")
|
||||||
|
|
||||||
fdict[x].append(innerf)
|
fdict[x].append(innerf)
|
||||||
innerf.owner_only = owner_only
|
innerf.owner_only = owner_only
|
||||||
innerf.raw_nick = raw_nick
|
innerf.raw_nick = raw_nick
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2008 Duncan Fordyce
|
# Copyright (c) 2011 Duncan Fordyce, Jimmy Cao
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
# in the Software without restriction, including without limitation the rights
|
# in the Software without restriction, including without limitation the rights
|
||||||
@ -18,11 +18,11 @@
|
|||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
|
import threading
|
||||||
|
import traceback
|
||||||
|
|
||||||
from oyoyo.parse import parse_raw_irc_command
|
from oyoyo.parse import parse_raw_irc_command
|
||||||
|
|
||||||
class IRCClientError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Adapted from http://code.activestate.com/recipes/511490-implementation-of-the-token-bucket-algorithm/
|
# Adapted from http://code.activestate.com/recipes/511490-implementation-of-the-token-bucket-algorithm/
|
||||||
@ -107,6 +107,7 @@ class IRCClient(object):
|
|||||||
self.port = None
|
self.port = None
|
||||||
self.connect_cb = None
|
self.connect_cb = None
|
||||||
self.blocking = True
|
self.blocking = True
|
||||||
|
self.lock = threading.RLock()
|
||||||
self.tokenbucket = TokenBucket(3, 1.63)
|
self.tokenbucket = TokenBucket(3, 1.63)
|
||||||
|
|
||||||
self.__dict__.update(kwargs)
|
self.__dict__.update(kwargs)
|
||||||
@ -128,25 +129,26 @@ class IRCClient(object):
|
|||||||
str they will be converted to bytes with the encoding specified by the
|
str they will be converted to bytes with the encoding specified by the
|
||||||
'encoding' keyword argument (default 'utf8').
|
'encoding' keyword argument (default 'utf8').
|
||||||
"""
|
"""
|
||||||
# Convert all args to bytes if not already
|
with self.lock:
|
||||||
encoding = kwargs.get('encoding') or 'utf_8'
|
# Convert all args to bytes if not already
|
||||||
bargs = []
|
encoding = kwargs.get('encoding') or 'utf_8'
|
||||||
for i,arg in enumerate(args):
|
bargs = []
|
||||||
if isinstance(arg, str):
|
for i,arg in enumerate(args):
|
||||||
bargs.append(bytes(arg, encoding))
|
if isinstance(arg, str):
|
||||||
elif isinstance(arg, bytes):
|
bargs.append(bytes(arg, encoding))
|
||||||
bargs.append(arg)
|
elif isinstance(arg, bytes):
|
||||||
elif arg is None:
|
bargs.append(arg)
|
||||||
continue
|
elif arg is None:
|
||||||
else:
|
continue
|
||||||
raise Exception(('Refusing to send arg at index {1} of the args from '+
|
else:
|
||||||
'provided: {0}').format(repr([(type(arg), arg)
|
raise Exception(('Refusing to send arg at index {1} of the args from '+
|
||||||
for arg in args]), i))
|
'provided: {0}').format(repr([(type(arg), arg)
|
||||||
|
for arg in args]), i))
|
||||||
|
|
||||||
msg = bytes(" ", "utf_8").join(bargs)
|
msg = bytes(" ", "utf_8").join(bargs)
|
||||||
logging.info('---> send "{0}"'.format(msg))
|
logging.info('---> send "{0}"'.format(msg))
|
||||||
|
|
||||||
self.socket.send(msg + bytes("\r\n", "utf_8"))
|
self.socket.send(msg + bytes("\r\n", "utf_8"))
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
""" initiates the connection to the server set in self.host:self.port
|
""" initiates the connection to the server set in self.host:self.port
|
||||||
@ -214,9 +216,8 @@ class IRCClient(object):
|
|||||||
self.command_handler[command](self, prefix,*largs)
|
self.command_handler[command](self, prefix,*largs)
|
||||||
elif "" in self.command_handler:
|
elif "" in self.command_handler:
|
||||||
self.command_handler[""](self, prefix, command, *largs)
|
self.command_handler[""](self, prefix, command, *largs)
|
||||||
finally:
|
except Exception as e:
|
||||||
# error will of already been logged by the handler
|
traceback.print_exc()
|
||||||
pass
|
|
||||||
|
|
||||||
yield True
|
yield True
|
||||||
finally:
|
finally:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2008 Duncan Fordyce
|
# Copyright (c) 2011 Duncan Fordyce, Jimmy Cao
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
# in the Software without restriction, including without limitation the rights
|
# in the Software without restriction, including without limitation the rights
|
||||||
@ -15,8 +15,6 @@
|
|||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
# THE SOFTWARE.
|
# THE SOFTWARE.
|
||||||
|
|
||||||
# taken from python irclib.. who took it from...
|
|
||||||
# Numeric table mostly stolen from the Perl IRC module (Net::IRC).
|
|
||||||
numeric_events = {
|
numeric_events = {
|
||||||
b"001": "welcome",
|
b"001": "welcome",
|
||||||
b"002": "yourhost",
|
b"002": "yourhost",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2008 Duncan Fordyce
|
# Copyright (c) 2011 Duncan Fordyce, Jimmy Cao
|
||||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
# of this software and associated documentation files (the "Software"), to deal
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
# in the Software without restriction, including without limitation the rights
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
4
var.py
4
var.py
@ -8,8 +8,8 @@ DRUNK_SHOTS_MULTIPLIER = 3
|
|||||||
NIGHT_TIME_LIMIT = 90
|
NIGHT_TIME_LIMIT = 90
|
||||||
DAY_TIME_LIMIT = 333
|
DAY_TIME_LIMIT = 333
|
||||||
START_WITH_DAY = False
|
START_WITH_DAY = False
|
||||||
KILL_IDLE_TIME = 0 #300
|
KILL_IDLE_TIME = 300
|
||||||
WARN_IDLE_TIME = 0 #180
|
WARN_IDLE_TIME = 180
|
||||||
GAME_COMMAND_ADMIN_ONLY = True
|
GAME_COMMAND_ADMIN_ONLY = True
|
||||||
|
|
||||||
# HIT MISS SUICIDE
|
# HIT MISS SUICIDE
|
||||||
|
168
wolfgame.py
168
wolfgame.py
@ -69,8 +69,7 @@ def connect_callback(cli):
|
|||||||
var.LAST_SAID_TIME = {}
|
var.LAST_SAID_TIME = {}
|
||||||
|
|
||||||
var.GAME_START_TIME = datetime.now() # for idle checker only
|
var.GAME_START_TIME = datetime.now() # for idle checker only
|
||||||
var.GRAVEYARD = []
|
var.GRAVEYARD_LOCK = threading.RLock()
|
||||||
var.GRAVEYARD_LOCK = threading.Lock()
|
|
||||||
|
|
||||||
prepare_stuff()
|
prepare_stuff()
|
||||||
|
|
||||||
@ -111,6 +110,7 @@ def reset(cli):
|
|||||||
if var.TIMERS[1]:
|
if var.TIMERS[1]:
|
||||||
var.TIMERS[1].cancel()
|
var.TIMERS[1].cancel()
|
||||||
var.TIMERS[1] = None
|
var.TIMERS[1] = None
|
||||||
|
var.GAME_ID = 0
|
||||||
|
|
||||||
cli.mode(chan, "-m")
|
cli.mode(chan, "-m")
|
||||||
cmodes = []
|
cmodes = []
|
||||||
@ -565,110 +565,107 @@ def del_player(cli, nick, forced_death = False):
|
|||||||
Returns: False if one side won.
|
Returns: False if one side won.
|
||||||
arg: forced_death = True when lynched.
|
arg: forced_death = True when lynched.
|
||||||
"""
|
"""
|
||||||
|
t = timetime() # time
|
||||||
cmode = []
|
with var.GRAVEYARD_LOCK:
|
||||||
cmode.append(("-v", nick))
|
if not var.GAME_ID or var.GAME_ID > t:
|
||||||
var.del_player(nick)
|
# either game ended, or a new game has started.
|
||||||
ret = True
|
return False
|
||||||
if var.PHASE == "join":
|
cmode = []
|
||||||
# Died during the joining process as a person
|
cmode.append(("-v", nick))
|
||||||
mass_mode(cli, cmode)
|
var.del_player(nick)
|
||||||
return not chk_win(cli)
|
ret = True
|
||||||
if var.PHASE != "join" and ret:
|
if var.PHASE == "join":
|
||||||
# Died during the game, so quiet!
|
# Died during the joining process as a person
|
||||||
if not is_fake_nick(nick):
|
mass_mode(cli, cmode)
|
||||||
cmode.append(("+q", nick))
|
return not chk_win(cli)
|
||||||
mass_mode(cli, cmode)
|
if var.PHASE != "join" and ret:
|
||||||
var.DEAD.append(nick)
|
# Died during the game, so quiet!
|
||||||
ret = not chk_win(cli)
|
if not is_fake_nick(nick):
|
||||||
if var.PHASE in ("night", "day") and ret:
|
cmode.append(("+q", nick))
|
||||||
# remove him from variables if he is in there
|
mass_mode(cli, cmode)
|
||||||
if var.VICTIM == nick:
|
var.DEAD.append(nick)
|
||||||
var.VICTIM = ""
|
ret = not chk_win(cli)
|
||||||
for x in (var.OBSERVED, var.HVISITED, var.GUARDED):
|
if var.PHASE in ("night", "day") and ret:
|
||||||
keys = list(x.keys())
|
# remove him from variables if he is in there
|
||||||
for k in keys:
|
if var.VICTIM == nick:
|
||||||
if k == nick:
|
var.VICTIM = ""
|
||||||
del x[k]
|
for x in (var.OBSERVED, var.HVISITED, var.GUARDED):
|
||||||
elif x[k] == nick:
|
keys = list(x.keys())
|
||||||
del x[k]
|
for k in keys:
|
||||||
if nick in var.GUNNERS.keys():
|
if k == nick:
|
||||||
del var.GUNNERS[nick]
|
del x[k]
|
||||||
if nick in var.CURSED:
|
elif x[k] == nick:
|
||||||
var.CURSED.remove(nick)
|
del x[k]
|
||||||
if var.PHASE == "day" and not forced_death and ret: # didn't die from lynching
|
if nick in var.GUNNERS.keys():
|
||||||
if nick in var.VOTES.keys():
|
del var.GUNNERS[nick]
|
||||||
del var.VOTES[nick] # Delete his votes
|
if nick in var.CURSED:
|
||||||
for k in var.VOTES.keys():
|
var.CURSED.remove(nick)
|
||||||
if nick in var.VOTES[k]:
|
if var.PHASE == "day" and not forced_death and ret: # didn't die from lynching
|
||||||
var.VOTES[k].remove(nick)
|
if nick in var.VOTES.keys():
|
||||||
chk_decision(cli)
|
del var.VOTES[nick] # Delete his votes
|
||||||
return ret
|
for k in var.VOTES.keys():
|
||||||
|
if nick in var.VOTES[k]:
|
||||||
|
var.VOTES[k].remove(nick)
|
||||||
|
chk_decision(cli)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@hook("ping")
|
@hook("ping")
|
||||||
def on_ping(cli, prefix, server):
|
def on_ping(cli, prefix, server):
|
||||||
cli.send('PONG', server)
|
cli.send('PONG', server)
|
||||||
check_graveyard(cli)
|
|
||||||
|
|
||||||
|
|
||||||
def reaper(cli):
|
def reaper(cli, gameid):
|
||||||
# check to see if idlers need to be killed.
|
# check to see if idlers need to be killed.
|
||||||
var.IDLE_KILLED = []
|
|
||||||
var.IDLE_WARNED = []
|
var.IDLE_WARNED = []
|
||||||
|
|
||||||
if not var.WARN_IDLE_TIME or not var.KILL_IDLE_TIME:
|
if not var.WARN_IDLE_TIME or not var.KILL_IDLE_TIME:
|
||||||
return
|
return
|
||||||
|
|
||||||
while var.PHASE != "none":
|
while gameid == var.GAME_ID:
|
||||||
to_warn = []
|
with var.GRAVEYARD_LOCK:
|
||||||
for nick in var.list_players():
|
to_warn = []
|
||||||
lst = var.LAST_SAID_TIME.get(nick, var.GAME_START_TIME)
|
to_kill = []
|
||||||
tdiff = datetime.now() - lst
|
for nick in var.list_players():
|
||||||
if (tdiff > timedelta(seconds=var.WARN_IDLE_TIME) and
|
lst = var.LAST_SAID_TIME.get(nick, var.GAME_START_TIME)
|
||||||
nick not in var.IDLE_WARNED):
|
tdiff = datetime.now() - lst
|
||||||
to_warn.append(nick)
|
if (tdiff > timedelta(seconds=var.WARN_IDLE_TIME) and
|
||||||
var.IDLE_WARNED.append(nick)
|
nick not in var.IDLE_WARNED):
|
||||||
var.LAST_SAID_TIME[nick] = (datetime.now() -
|
to_warn.append(nick)
|
||||||
timedelta(seconds=var.KILL_IDLE_TIME)) # Give him a chance
|
var.IDLE_WARNED.append(nick)
|
||||||
elif (tdiff > timedelta(seconds=var.KILL_IDLE_TIME) and
|
var.LAST_SAID_TIME[nick] = (datetime.now() -
|
||||||
nick not in var.IDLE_KILLED):
|
timedelta(seconds=var.WARN_IDLE_TIME)) # Give him a chance
|
||||||
with var.GRAVEYARD_LOCK:
|
elif (tdiff > timedelta(seconds=var.KILL_IDLE_TIME) and
|
||||||
var.GRAVEYARD.append(("kill",nick))
|
nick in var.IDLE_WARNED):
|
||||||
var.IDLE_KILLED.append(nick)
|
to_kill.append(nick)
|
||||||
if to_warn:
|
print("WILL KILL "+nick)
|
||||||
with var.GRAVEYARD_LOCK:
|
elif (tdiff < timedelta(seconds=var.WARN_IDLE_TIME) and
|
||||||
var.GRAVEYARD.append(("warn", to_warn))
|
nick in var.IDLE_WARNED):
|
||||||
sleep(10)
|
var.IDLE_WARNED.remove(nick) # he saved himself from death
|
||||||
|
chan = botconfig.CHANNEL
|
||||||
|
for nck in to_kill:
|
||||||
|
if nck not in var.list_players():
|
||||||
def check_graveyard(cli):
|
|
||||||
if not var.GRAVEYARD: return
|
|
||||||
chan = botconfig.CHANNEL
|
|
||||||
with var.GRAVEYARD_LOCK:
|
|
||||||
for action, x in var.GRAVEYARD:
|
|
||||||
if action=="kill":
|
|
||||||
if x not in var.list_players():
|
|
||||||
continue
|
continue
|
||||||
cli.msg(chan, ("\u0002{0}\u0002 didn't get out of bed "+
|
cli.msg(chan, ("\u0002{0}\u0002 didn't get out of bed "+
|
||||||
"for a very long time. S/He is declared dead. Appears "+
|
"for a very long time. S/He is declared dead. Appears "+
|
||||||
"(s)he was a \u0002{1}\u0002").format(x, var.get_role(x)))
|
"(s)he was a \u0002{1}\u0002").format(nck, var.get_role(nck)))
|
||||||
del_player(cli, x)
|
if not del_player(cli, nck):
|
||||||
elif action=="warn":
|
return
|
||||||
pl = var.list_players()
|
pl = var.list_players()
|
||||||
x = [a for a in x if a in pl]
|
x = [a for a in to_warn if a in pl]
|
||||||
|
if x:
|
||||||
cli.msg(chan, ("{0}: \u0002You have been idling for a while. "+
|
cli.msg(chan, ("{0}: \u0002You have been idling for a while. "+
|
||||||
"Please remember to say something soon or you "+
|
"Please remember to say something soon or you "+
|
||||||
"might be declared dead.\u0002").format(", ".join(x)))
|
"might be declared dead.\u0002").format(", ".join(x)))
|
||||||
var.GRAVEYARD = []
|
sleep(10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@cmd("") # update last said
|
@cmd("") # update last said
|
||||||
def update_last_said(cli, nick, *rest):
|
def update_last_said(cli, nick, *rest):
|
||||||
if var.PHASE not in ("join", "none"):
|
if var.PHASE not in ("join", "none"):
|
||||||
var.LAST_SAID_TIME[nick] = datetime.now()
|
var.LAST_SAID_TIME[nick] = datetime.now()
|
||||||
check_graveyard(cli)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1647,7 +1644,8 @@ def start(cli, nick, chan, rest):
|
|||||||
transition_day(cli)
|
transition_day(cli)
|
||||||
|
|
||||||
# DEATH TO IDLERS!
|
# DEATH TO IDLERS!
|
||||||
reapertimer = threading.Thread(None, reaper, args=(cli,))
|
var.GAME_ID = timetime()
|
||||||
|
reapertimer = threading.Thread(None, reaper, args=(cli,var.GAME_ID))
|
||||||
reapertimer.daemon = True
|
reapertimer.daemon = True
|
||||||
reapertimer.start()
|
reapertimer.start()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user