improved admin-only command setting,
removed extra junk, added !wait + start time wait.
This commit is contained in:
parent
7a3cbe132d
commit
267d7104bc
@ -1,14 +1,20 @@
|
|||||||
from oyoyo.parse import parse_nick
|
from oyoyo.parse import parse_nick
|
||||||
|
import botconfig;
|
||||||
|
|
||||||
def generate(fdict):
|
def generate(fdict):
|
||||||
def cmd(s, raw_nick=False):
|
def cmd(s, raw_nick=False, admin_only=False):
|
||||||
def dec(f):
|
def dec(f):
|
||||||
def innerf(*args):
|
def innerf(*args):
|
||||||
largs = list(args)
|
largs = list(args)
|
||||||
largs[1] = parse_nick(largs[1])[0]
|
if not raw_nick: largs[1] = parse_nick(largs[1])[0]
|
||||||
|
if admin_only:
|
||||||
|
if largs[1] in botconfig.ADMINS:
|
||||||
|
return f(*largs)
|
||||||
|
else:
|
||||||
|
largs[0].notice(largs[1], "You are not an admin.")
|
||||||
|
return
|
||||||
return f(*largs)
|
return f(*largs)
|
||||||
if raw_nick: fdict[s] = f
|
fdict[s] = innerf
|
||||||
else: fdict[s] = innerf
|
|
||||||
return f
|
return f
|
||||||
return dec
|
return dec
|
||||||
return cmd
|
return cmd
|
@ -17,18 +17,9 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
import string
|
|
||||||
import time
|
|
||||||
import threading
|
|
||||||
import os
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from oyoyo.parse import *
|
from oyoyo.parse import parse_raw_irc_command
|
||||||
from oyoyo.cmdhandler import CommandError
|
from oyoyo.cmdhandler import CommandError
|
||||||
import collections
|
|
||||||
|
|
||||||
|
|
||||||
class IRCClientError(Exception):
|
class IRCClientError(Exception):
|
||||||
pass
|
pass
|
||||||
@ -201,89 +192,6 @@ class IRCClient:
|
|||||||
self.send("USER", uname, self.host, self.host,
|
self.send("USER", uname, self.host, self.host,
|
||||||
rname or uname)
|
rname or uname)
|
||||||
|
|
||||||
class IRCApp:
|
|
||||||
""" This class manages several IRCClient instances without the use of threads.
|
|
||||||
(Non-threaded) Timer functionality is also included.
|
|
||||||
"""
|
|
||||||
|
|
||||||
class _ClientDesc:
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.con = None
|
|
||||||
self.autoreconnect = False
|
|
||||||
self.__dict__.update(kwargs)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._clients = {}
|
|
||||||
self._timers = []
|
|
||||||
self.running = False
|
|
||||||
self.sleep_time = 0.5
|
|
||||||
|
|
||||||
def addClient(self, client, autoreconnect=False):
|
|
||||||
""" add a client object to the application. setting autoreconnect
|
|
||||||
to true will mean the application will attempt to reconnect the client
|
|
||||||
after every disconnect. you can also set autoreconnect to a number
|
|
||||||
to specify how many reconnects should happen.
|
|
||||||
|
|
||||||
warning: if you add a client that has blocking set to true,
|
|
||||||
timers will no longer function properly """
|
|
||||||
logging.info('added client %s (ar=%s)' % (client, autoreconnect))
|
|
||||||
self._clients[client] = self._ClientDesc(autoreconnect=autoreconnect)
|
|
||||||
|
|
||||||
def addTimer(self, seconds, cb):
|
|
||||||
""" add a timed callback. accuracy is not specified, you can only
|
|
||||||
garuntee the callback will be called after seconds has passed.
|
|
||||||
( the only advantage to these timers is they dont use threads )
|
|
||||||
"""
|
|
||||||
assert isinstance(cb, collections.Callable)
|
|
||||||
logging.info('added timer to call %s in %ss' % (cb, seconds))
|
|
||||||
self._timers.append((time.time() + seconds, cb))
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
""" run the application. this will block until stop() is called """
|
|
||||||
# TODO: convert this to use generators too?
|
|
||||||
self.running = True
|
|
||||||
while self.running:
|
|
||||||
found_one_alive = False
|
|
||||||
|
|
||||||
for client, clientdesc in self._clients.items():
|
|
||||||
if clientdesc.con is None:
|
|
||||||
clientdesc.con = client.connect()
|
|
||||||
|
|
||||||
try:
|
|
||||||
next(clientdesc.con)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error('client error %s' % e)
|
|
||||||
logging.error(traceback.format_exc())
|
|
||||||
if clientdesc.autoreconnect:
|
|
||||||
clientdesc.con = None
|
|
||||||
if isinstance(clientdesc.autoreconnect, (int, float)):
|
|
||||||
clientdesc.autoreconnect -= 1
|
|
||||||
found_one_alive = True
|
|
||||||
else:
|
|
||||||
clientdesc.con = False
|
|
||||||
else:
|
|
||||||
found_one_alive = True
|
|
||||||
|
|
||||||
if not found_one_alive:
|
|
||||||
logging.info('nothing left alive... quiting')
|
|
||||||
self.stop()
|
|
||||||
|
|
||||||
now = time.time()
|
|
||||||
timers = self._timers[:]
|
|
||||||
self._timers = []
|
|
||||||
for target_time, cb in timers:
|
|
||||||
if now > target_time:
|
|
||||||
logging.info('calling timer cb %s' % cb)
|
|
||||||
cb()
|
|
||||||
else:
|
|
||||||
self._timers.append((target_time, cb))
|
|
||||||
|
|
||||||
time.sleep(self.sleep_time)
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
""" stop the application """
|
|
||||||
self.running = False
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,15 +16,9 @@
|
|||||||
# THE SOFTWARE.
|
# THE SOFTWARE.
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import sys
|
|
||||||
|
|
||||||
from oyoyo.ircevents import *
|
from oyoyo.ircevents import generated_events, protocol_events,\
|
||||||
|
all_events, numeric_events
|
||||||
# Python < 3 compatibility
|
|
||||||
if sys.version_info < (3,):
|
|
||||||
class bytes(object):
|
|
||||||
def __new__(self, b='', encoding='utf8'):
|
|
||||||
return str(b)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_raw_irc_command(element):
|
def parse_raw_irc_command(element):
|
||||||
|
13
vars.py
13
vars.py
@ -1,12 +1,19 @@
|
|||||||
|
PING_WAIT = 300 # Seconds
|
||||||
|
MINIMUM_WAIT = 60
|
||||||
|
EXTRA_WAIT = 20
|
||||||
|
MAXIMUM_WAITED = 2 # limit for amount of !wait's
|
||||||
|
MAX_SHOTS = 2
|
||||||
|
|
||||||
|
# These change ingame
|
||||||
ROLES = {"person" : []}
|
ROLES = {"person" : []}
|
||||||
ORIGINAL_ROLES = None
|
ORIGINAL_ROLES = None
|
||||||
PHASE = "none" # "join", "day", or "night"
|
PHASE = "none" # "join", "day", or "night"
|
||||||
LAST_PING = 0
|
LAST_PING = 0
|
||||||
PING_WAIT = 300 # Seconds
|
CURSED = "" # nickname of cursed villager
|
||||||
WAIT = 60
|
GAME_START_TIME = 0
|
||||||
|
CAN_START_TIME = 0
|
||||||
WAITED = 0
|
WAITED = 0
|
||||||
GUNNERS = {}
|
GUNNERS = {}
|
||||||
MAX_SHOTS = 2
|
|
||||||
|
|
||||||
is_role = lambda plyr, rol: rol in ROLES and plyr in ROLES[rol]
|
is_role = lambda plyr, rol: rol in ROLES and plyr in ROLES[rol]
|
||||||
|
|
||||||
|
167
wolfgame.py
167
wolfgame.py
@ -2,6 +2,8 @@ from oyoyo.parse import parse_nick
|
|||||||
import vars
|
import vars
|
||||||
import botconfig
|
import botconfig
|
||||||
import decorators
|
import decorators
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
|
||||||
COMMANDS = {}
|
COMMANDS = {}
|
||||||
PM_COMMANDS = {}
|
PM_COMMANDS = {}
|
||||||
@ -17,7 +19,6 @@ def connect_callback(cli):
|
|||||||
cli.identify(botconfig.PASS)
|
cli.identify(botconfig.PASS)
|
||||||
cli.join(botconfig.CHANNEL)
|
cli.join(botconfig.CHANNEL)
|
||||||
cli.msg("ChanServ", "op "+botconfig.CHANNEL)
|
cli.msg("ChanServ", "op "+botconfig.CHANNEL)
|
||||||
cli.msg(botconfig.CHANNEL, "\u0002Wolfbot2 is here.\u0002")
|
|
||||||
|
|
||||||
def reset_game():
|
def reset_game():
|
||||||
vars.ROLES = {"person" : []}
|
vars.ROLES = {"person" : []}
|
||||||
@ -29,12 +30,12 @@ def say(cli, nick, rest): # To be removed later
|
|||||||
cli.msg(botconfig.CHANNEL, "{0} says: {1}".format(nick, rest))
|
cli.msg(botconfig.CHANNEL, "{0} says: {1}".format(nick, rest))
|
||||||
|
|
||||||
|
|
||||||
@pmcmd("!bye")
|
@pmcmd("!bye", admin_only=True)
|
||||||
@cmd("!bye")
|
@cmd("!bye", admin_only=True)
|
||||||
def forced_exit(cli, nick, *rest): # Admin Only
|
def forced_exit(cli, nick, *rest): # Admin Only
|
||||||
if nick in botconfig.ADMINS:
|
reset_game(cli, nick, rest[0], None)
|
||||||
cli.quit("Forced quit from admin")
|
cli.quit("Forced quit from admin")
|
||||||
raise SystemExit
|
raise SystemExit
|
||||||
|
|
||||||
@cmd("!exec")
|
@cmd("!exec")
|
||||||
def py(cli, nick, chan, rest):
|
def py(cli, nick, chan, rest):
|
||||||
@ -71,55 +72,165 @@ def pinger(cli, nick, chan, rest):
|
|||||||
@cmd("!join")
|
@cmd("!join")
|
||||||
def join(cli, nick, chan, rest):
|
def join(cli, nick, chan, rest):
|
||||||
if vars.PHASE == "none":
|
if vars.PHASE == "none":
|
||||||
|
cli.mode(chan, "+v", nick, nick+"!*@*")
|
||||||
vars.ROLES["person"].append(nick)
|
vars.ROLES["person"].append(nick)
|
||||||
vars.PHASE = "join"
|
vars.PHASE = "join"
|
||||||
|
vars.CAN_START_TIME = time.time() + vars.MINIMUM_WAIT
|
||||||
cli.msg(chan, '\u0002{0}\u0002 has started a game of Werewolf. \
|
cli.msg(chan, '\u0002{0}\u0002 has started a game of Werewolf. \
|
||||||
Type "!join" to join. Type "!start" to start the game. \
|
Type "!join" to join. Type "!start" to start the game. \
|
||||||
Type "!wait" to increase join wait time.'.format(nick))
|
Type "!wait" to increase join wait time.'.format(nick))
|
||||||
elif nick in list_players():
|
elif nick in vars.list_players():
|
||||||
cli.notice(nick, "You're already playing!")
|
cli.notice(nick, "You're already playing!")
|
||||||
elif vars.PHASE != "join":
|
elif vars.PHASE != "join":
|
||||||
cli.notice(nick, "Sorry but the game is already running. Try again next time.")
|
cli.notice(nick, "Sorry but the game is already running. Try again next time.")
|
||||||
else:
|
else:
|
||||||
|
cli.mode(chan, "+v", nick, nick+"!*@*")
|
||||||
vars.ROLES["person"].append(nick)
|
vars.ROLES["person"].append(nick)
|
||||||
cli.msg(chan, '\u0002{0}\u0002 has joined the game.'.format(nick))
|
cli.msg(chan, '\u0002{0}\u0002 has joined the game.'.format(nick))
|
||||||
|
|
||||||
@cmd("!stats")
|
@cmd("!stats")
|
||||||
def stats(cli, nick, chan, rest):
|
def stats(cli, nick, chan, rest):
|
||||||
if vars.PHASE == "none":
|
if vars.PHASE == "none":
|
||||||
|
cli.notice(nick, "No game is currently running.")
|
||||||
return
|
return
|
||||||
pl = list_players()
|
|
||||||
|
pl = vars.list_players()
|
||||||
if len(pl) > 1:
|
if len(pl) > 1:
|
||||||
cli.msg(chan, '{0}: {1} players: {2}'.format(nick,
|
cli.msg(chan, '{0}: \u0002{1}\u0002 players: {2}'.format(nick,
|
||||||
len(pl), ", ".join(pl)))
|
len(pl), ", ".join(pl)))
|
||||||
else:
|
else:
|
||||||
cli.msg(chan, '{0}: 1 player: {1}'.format(nick, pl[0]))
|
cli.msg(chan, '{0}: \u00021\u0002 player: {1}'.format(nick, pl[0]))
|
||||||
|
|
||||||
if vars.PHASE == "join":
|
if vars.PHASE == "join":
|
||||||
return
|
return
|
||||||
|
|
||||||
msg = []
|
message = []
|
||||||
for role in vars.ROLES.keys():
|
for role in ("wolf", "seer", "harlot"):
|
||||||
num = len(vars.ROLES[role])
|
count = len(vars.ROLES.get(role,[]))
|
||||||
if num > 1:
|
if count > 1:
|
||||||
msg.append("{0} {1}".format(num, plural(role)))
|
message.append("\u0002(0}\u0002 {1}".format(count, vars.plural(role)))
|
||||||
else:
|
else:
|
||||||
msg.append("{0} {1}".format(num, role))
|
message.append("\u0002{0}\u0002 {1}".format(count, role))
|
||||||
if len(msg) > 2: # More than 2 roles to say
|
cli.msg(chan,
|
||||||
msg[-1] = "and "+msg[-1]+"."
|
"{0}: There are {1}, and {2}.".format(nick,
|
||||||
msg[0] = "{0}: There are ".format(nick) + msg[0]
|
", ".join(message[0:-1]),
|
||||||
cli.msg(chan, ", ".join(msg))
|
message[-1]))
|
||||||
elif len(msg) == 2: # 2 roles to say
|
|
||||||
cli.msg(chan, "{0}: There are ".format(nick) + msg[0],
|
|
||||||
"and", msg[1] + ".")
|
|
||||||
elif len(msg) == 1:
|
|
||||||
cli.msg(chan, "{0}: There is ".format(nick) + msg[0] + ".")
|
|
||||||
|
|
||||||
|
def transition_night(cli, chan):
|
||||||
|
vars.PHASE = "night"
|
||||||
|
|
||||||
@cmd("!start")
|
@cmd("!start")
|
||||||
def start(cli, nick, chan, rest):
|
def start(cli, nick, chan, rest):
|
||||||
pl = list_players()
|
pl = vars.list_players()
|
||||||
|
if vars.PHASE == "none":
|
||||||
if(len(pl)) < 4:
|
cli.notice(nick, "No game is currently running.")
|
||||||
|
return
|
||||||
|
if vars.PHASE != "join":
|
||||||
|
cli.notice(nick, "Werewolf is already in play.")
|
||||||
|
return
|
||||||
|
if nick not in pl:
|
||||||
|
cli.notice(nick, "You're currently not playing.")
|
||||||
|
return
|
||||||
|
now = time.time()
|
||||||
|
if vars.CAN_START_TIME > now:
|
||||||
|
cli.msg(chan, "Please wait at least {0} more seconds.".format(
|
||||||
|
int(vars.CAN_START_TIME - now)))
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(pl) < 4:
|
||||||
cli.msg(chan, "{0}: Four or more players are required to play.".format(nick))
|
cli.msg(chan, "{0}: Four or more players are required to play.".format(nick))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
vars.ROLES = {}
|
||||||
|
nharlots = 0
|
||||||
|
nseers = 0
|
||||||
|
nwolves = 0
|
||||||
|
ndrunk = 0
|
||||||
|
ncursed = 0
|
||||||
|
|
||||||
|
if len(pl) >= 8:
|
||||||
|
nharlots = 1
|
||||||
|
nseers = 1
|
||||||
|
nwolves = 2
|
||||||
|
ndrunk = 1
|
||||||
|
ncursed = 1
|
||||||
|
elif(len(pl)) >= 6:
|
||||||
|
nseers = 1
|
||||||
|
nwolves = 1
|
||||||
|
ndrunk = 1
|
||||||
|
ncursed = 1
|
||||||
|
else:
|
||||||
|
nseers = 1
|
||||||
|
nwolves = 1
|
||||||
|
|
||||||
|
seer = random.choice(pl)
|
||||||
|
vars.ROLES["seer"] = [seer]
|
||||||
|
pl.remove(seer)
|
||||||
|
if nharlots:
|
||||||
|
harlots = random.sample(pl, nharlots)
|
||||||
|
vars.ROLES["harlot"] = harlots
|
||||||
|
for h in harlots:
|
||||||
|
pl.remove(h)
|
||||||
|
if nwolves:
|
||||||
|
wolves = random.sample(pl, nwolves)
|
||||||
|
vars.ROLES["wolf"] = wolves
|
||||||
|
for w in wolves:
|
||||||
|
pl.remove(w)
|
||||||
|
if ndrunk:
|
||||||
|
drunk = random.choice(pl)
|
||||||
|
vars.ROLES["village drunk"] = [drunk]
|
||||||
|
pl.remove(drunk)
|
||||||
|
vars.ROLES["villager"] = pl
|
||||||
|
|
||||||
|
if ncursed:
|
||||||
|
CURSED = random.choice(var.ROLES["villager"] + \
|
||||||
|
var.ROLES.get("harlot", []) +\
|
||||||
|
var.ROLES.get("village drunk", []))
|
||||||
|
|
||||||
|
cli.msg(chan, "{0}: Welcome to Werewolf, the popular detective/social \
|
||||||
|
party game (a theme of Mafia).".format(", ".join(vars.list_players())))
|
||||||
|
cli.mode(chan, "+m")
|
||||||
|
|
||||||
|
vars.ORIGINAL_ROLES = dict(vars.ROLES) # Make a copy
|
||||||
|
transition_night(cli, chan)
|
||||||
|
|
||||||
|
@cmd("!wait")
|
||||||
|
def wait(cli, nick, chan, rest):
|
||||||
|
pl = vars.list_players()
|
||||||
|
if vars.PHASE == "none":
|
||||||
|
cli.notice(nick, "No game is currently running.")
|
||||||
|
return
|
||||||
|
if vars.PHASE != "join":
|
||||||
|
cli.notice(nick, "Werewolf is already in play.")
|
||||||
|
return
|
||||||
|
if nick not in pl:
|
||||||
|
cli.notice(nick, "You're currently not playing.")
|
||||||
|
return
|
||||||
|
if vars.WAITED >= vars.MAXIMUM_WAITED:
|
||||||
|
cli.msg(chan, "Limit has already been reached for extending the wait time.")
|
||||||
|
return
|
||||||
|
|
||||||
|
now = time.time()
|
||||||
|
if now > vars.CAN_START_TIME:
|
||||||
|
vars.CAN_START_TIME = now + vars.EXTRA_WAIT
|
||||||
|
else:
|
||||||
|
vars.CAN_START_TIME += vars.EXTRA_WAIT
|
||||||
|
vars.WAITED += 1
|
||||||
|
cli.msg(chan, "{0} increased the wait \
|
||||||
|
time by {1} seconds.".format(nick, vars.EXTRA_WAIT))
|
||||||
|
|
||||||
|
@cmd("!reset", admin_only = True)
|
||||||
|
def reset_game(cli, nick, chan, rest):
|
||||||
|
vars.PHASE = "none"
|
||||||
|
cli.mode(chan, "-m")
|
||||||
|
for pl in vars.list_players():
|
||||||
|
cli.mode(chan, "-v", pl)
|
||||||
|
|
||||||
|
vars.ROLES = {"person" : []}
|
||||||
|
vars.ORIGINAL_ROLES = None
|
||||||
|
vars.CURSED = ""
|
||||||
|
vars.GAME_START_TIME = 0
|
||||||
|
vars.CAN_START_TIME = 0
|
||||||
|
vars.GUNNERS = {}
|
||||||
|
vars.WAITED = 0
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user