Modify idlemove module to be able to chain thresholds for moving and add source channel filters

This commit is contained in:
Stefan Hacker
2010-12-27 02:42:23 +01:00
parent bf006394da
commit b25b446f84
6 changed files with 96 additions and 58 deletions

View File

@@ -93,7 +93,7 @@ def x2bool(s):
if isinstance(s, bool):
return s
elif isinstance(s, basestring):
return s.lower() in ['1', 'true']
return s.strip().lower() in ['1', 'true']
raise ValueError()
def commaSeperatedIntegers(s):
@@ -109,3 +109,10 @@ def commaSeperatedStrings(s):
containing comma seperated strings into a list of strings
"""
return map(str.strip, s.split(','))
def commaSeperatedBool(s):
"""
Helper function to convert a string from the config
containing comma seperated strings into a list of booleans
"""
return map(x2bool, s.split(','))

View File

@@ -30,7 +30,7 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import unittest
from config import Config, x2bool, commaSeperatedIntegers, commaSeperatedStrings
from config import Config, x2bool, commaSeperatedIntegers, commaSeperatedStrings, commaSeperatedBool
from tempfile import mkstemp
import os
import re
@@ -88,13 +88,13 @@ value = True
os.remove(path)
def testX2bool(self):
assert(x2bool("true") == True)
assert(x2bool(" true") == True)
assert(x2bool("false") == False)
assert(x2bool("TrUe") == True)
assert(x2bool("FaLsE") == False)
assert(x2bool("0") == False)
assert(x2bool(" TrUe") == True)
assert(x2bool("FaLsE ") == False)
assert(x2bool("0 ") == False)
assert(x2bool("1") == True)
assert(x2bool("10") == False)
assert(x2bool(" 10") == False)
assert(x2bool("notabool") == False)
def testCommaSeperatedIntegers(self):
@@ -104,6 +104,9 @@ value = True
def testCommaSeperatedStrings(self):
assert(commaSeperatedStrings("Bernd, the, bred !") == ["Bernd", "the", "bred !"])
def testCommaSeperatedBool(self):
assert(commaSeperatedBool("tRue ,false, 0, 0, 1,1, test") == [True, False, False, False, True, True, False])
def testConfig(self):
path = create_file(self.cfg_content)
try:

View File

@@ -13,6 +13,9 @@ interval = 10
servers =
[all]
; All parameters in here also take a comma seperated list of values.
; You can use this to chain idle thresholds.
; Time in seconds after which to consider a player idle
threshold = 3600
; Mute the player idle
@@ -21,6 +24,8 @@ mute = True
deafen = False
; Id of the channel to move the player to when idle
channel = 0
; Channel the player has to be in for this treshold rule to affect him (-1 == Any)
;source_channel = -1
; For every server you want to override the [all] section for create
; a [server_<serverid>] section. For example:

View File

@@ -33,12 +33,13 @@
# idlemove.py
#
# Module for moving/muting/deafening idle players after
# a certain amount of time and moving them back once
# they interact again.
# a certain amount of time and unmuting/undeafening them
# once they become active again
#
from mumo_module import (x2bool,
commaSeperatedIntegers,
commaSeperatedBool,
MumoModule,
Config)
@@ -53,18 +54,12 @@ class idlemove(MumoModule):
('interval', float, 0.1),
('servers', commaSeperatedIntegers, []),
),
'all':(
('threshold', int, 3600),
('mute', x2bool, True),
('deafen', x2bool, False),
('channel', int, 1)
),
lambda x: re.match('server_\d+', x):(
('threshold', int, 3600),
('mute', x2bool, True),
('deafen', x2bool, False),
('channel', int, 1),
('restore', x2bool, True)
lambda x: re.match('(all)|(server_\d+)', x):(
('threshold', commaSeperatedIntegers, [3600]),
('mute', commaSeperatedBool, [True]),
('deafen', commaSeperatedBool, [False]),
('channel', commaSeperatedIntegers, [1]),
('source_channel', commaSeperatedIntegers, [-1])
),
}
@@ -134,41 +129,66 @@ class idlemove(MumoModule):
self.affectedusers[sid] = set()
index = self.affectedusers[sid]
# Remember values so we can see changes later
threshold = None
mute = user.mute
deafen = user.deaf
channel = user.channel
update = False
if not user in index and user.idlesecs > scfg.threshold:
if scfg.deafen \
and not (user.suppress or user.selfMute or user.mute) \
and not (user.selfDeaf or user.deaf):
log.info('Mute and deafen user %s (%d / %d) on server %d', user.name, user.session, user.userid, sid)
user.deaf = True
update = True
elif scfg.mute and not (user.suppress or user.selfMute or user.mute):
log.info('Mute user %s (%d / %d) on server %d', user.name, user.session, user.userid, sid)
user.mute = True
update = True
over_threshold = False
if scfg.channel >= 0 and user.channel != scfg.channel:
log.info('Move user %s (%d / %d) on server %d', user.name, user.session, user.userid, sid)
user.channel = scfg.channel
update = True
# Search all our stages top down for a violated treshold and pick the first
for i in range(len(scfg.threshold) - 1, -1, -1):
try:
source_channel = scfg.source_channel[i]
except IndexError:
source_channel = -1
if update:
index.add(user.session)
try:
threshold = scfg.threshold[i]
mute = scfg.mute[i]
deafen = scfg.deafen[i]
channel = scfg.channel[i]
except IndexError:
log.warning("Incomplete configuration for stage %d of server %i, ignored", i, server.id())
continue
elif user.session in index and user.idlesecs < scfg.threshold:
if user.idlesecs > threshold and\
(source_channel == -1 or\
user.channel == source_channel or\
user.channel == channel):
over_threshold = True
# Update if state changes needed
if user.deaf != deafen:
update = True
if user.mute != mute:
update = True
if channel >= 0 and user.channel != channel:
update = True
if update:
index.add(user.session)
log.info('%ds > %ds: State transition for user %s (%d/%d) from mute %s -> %s / deaf %s -> %s | channel %d -> %d on server %d',
user.idlesecs, threshold, user.name, user.session, user.userid, user.mute, mute, user.deaf, deafen,
user.channel, channel, server.id())
break
if not over_threshold and user.session in self.affectedusers[sid]:
deafen = False
mute = False
channel = user.channel
index.remove(user.session)
if scfg.deafen:
log.info('Unmute and undeafen user %s (%d / %d) on server %d', user.name, user.session, user.userid, sid)
user.mute = False
user.deaf = False
update = True
elif scfg.mute:
log.info('Unmute user %s (%d / %d) on server %d', user.name, user.session, user.userid, sid)
user.mute = False
update = True
log.info("Restore user %s (%d/%d) on server %d", user.name, user.session, user.userid, server.id())
update = True
if update:
user.deaf = deafen
user.mute = mute
user.channel = channel
server.setState(user)
#
#--- Server callback functions
#

View File

@@ -374,11 +374,12 @@ def do_main_program():
manager.stopModules()
manager.stop()
info('Shutdown complete')
return state
class CustomLogger(Ice.Logger):
"""
Logger implementation to pipe Ice log messages into
out own log
our own log
"""
def __init__(self):
@@ -459,12 +460,13 @@ if __name__ == '__main__':
print >> sys.stderr, 'Fatal error, could not daemonize process due to missing "daemon" library, ' \
'please install the missing dependency and restart the authenticator'
sys.exit(1)
do_main_program()
ret = do_main_program()
else:
context = daemon.DaemonContext(working_directory=sys.path[0],
stderr=logfile)
context.__enter__()
try:
do_main_program()
ret = do_main_program()
finally:
context.__exit__(None, None, None)
sys.exit(ret)

View File

@@ -32,7 +32,8 @@
from config import (Config,
x2bool,
commaSeperatedIntegers,
commaSeperatedStrings)
commaSeperatedStrings,
commaSeperatedBool)
from worker import Worker