diff --git a/config.py b/config.py index 2208e70..50510e7 100644 --- a/config.py +++ b/config.py @@ -23,9 +23,9 @@ __initialized = False __config_store = ConfigObj('local_config{}.ini'.format(CONFIG_SUFFIX), configspec='local_config.ini.spec') runtime_config_store = ConfigObj('persistent_config.ini'.format(CONFIG_SUFFIX), configspec='persistent_config.ini.spec') -validator = Validator() -result = __config_store.validate(validator) -runtime_config_store.validate(validator) +result = __config_store.validate(Validator()) +# copy is essential to store values with a default.. see configobj.py:2053 +assert runtime_config_store.validate(Validator(), copy=True) if not result: print('Config file validation failed!') diff --git a/idlebot.py b/idlebot.py index 802ac19..87542c1 100755 --- a/idlebot.py +++ b/idlebot.py @@ -52,8 +52,8 @@ class IdleBot(ClientXMPP): )) self.hangup() return False - elif msg_obj['mucnick'] in config.runtimeconf_get("other_bots"): - # not talking to the other bot. + elif msg_obj['mucnick'] in config.runtimeconf_get("other_bots", ()): + self.logger.debug("not talking to the other bot named {}".format( msg_obj['mucnick'])) return False else: return True diff --git a/plugins.py b/plugins.py index 5a2ea28..7bdf3e4 100644 --- a/plugins.py +++ b/plugins.py @@ -392,7 +392,7 @@ def command_uptime(argv, **args): if 1 == u: plural_uptime = '' - if 1 == config.runtimeconf_get('request_counter'): + if 1 == int(config.runtimeconf_get('request_counter')): plural_request = '' log.info('sent statistics') @@ -995,6 +995,22 @@ def remove_from_botlist(argv, **args): return False +@pluginfunction("add-to-botlist", "add a user to the botlist", ptypes_COMMAND) +def add_to_botlist(argv, **args): + if len(argv) != 2: + return {'msg': "wrong number of arguments!"} + + if args['reply_user'] != config.conf_get('bot_owner'): + return {'msg': "only %s may do this!" % config.conf_get('bot_owner')} + + if argv[1] not in config.runtime_config_store['other_bots']: + config.runtime_config_store['other_bots'].append(argv[1]) + config.runtimeconf_persist() + return {'msg': '%s was added to the botlist.' % argv[1]} + else: + return {'msg': '%s is already in the botlist.' % argv[1]} + + @pluginfunction("set-status", "set bot status", ptypes_COMMAND) def set_status(argv, **args): if 'set-status' != argv[0] or len(argv) != 2: @@ -1018,13 +1034,22 @@ def set_status(argv, **args): @pluginfunction('reset-jobs', "reset joblist", ptypes_COMMAND, ratelimit_class=RATE_NO_LIMIT) def reset_jobs(argv, **args): - if 'reset-jobs' != argv[0] or args['reply_user'] != config.conf_get('bot_owner'): + if args['reply_user'] != config.conf_get('bot_owner'): return else: joblist.clear() return {'msg': 'done.'} +@pluginfunction('save-config', "save config", ptypes_COMMAND, ratelimit_class=RATE_NO_LIMIT) +def save_config(argv, **args): + if args['reply_user'] != config.conf_get('bot_owner'): + return + else: + config.runtime_config_store.write() + return {'msg': 'done.'} + + @pluginfunction('flausch', "make people flauschig", ptypes_COMMAND, ratelimit_class=RATE_FUN) def flausch(argv, **args): if len(argv) != 2: @@ -1101,6 +1126,24 @@ def resolve_url_title(**args): } +@pluginfunction('show-runtimeconfig', "show the current runtimeconfig", ptypes_COMMAND, ratelimit_class=RATE_NO_LIMIT) +def show_runtimeconfig(argv, **args): + if args['reply_user'] != config.conf_get('bot_owner'): + return + else: + msg = json.dumps(config.runtime_config_store, indent=4) + return {'msg': msg} + + +@pluginfunction('reload-runtimeconfig', "reload the runtimeconfig", ptypes_COMMAND, ratelimit_class=RATE_NO_LIMIT) +def reload_runtimeconfig(argv, **args): + if args['reply_user'] != config.conf_get('bot_owner'): + return + else: + config.runtime_config_store.reload() + return {'msg': 'done'} + + def else_command(args): log.info('sent short info') return { diff --git a/test_urlbot.py b/test_urlbot.py index ecb3428..2ffc70c 100644 --- a/test_urlbot.py +++ b/test_urlbot.py @@ -3,8 +3,12 @@ To be executed with nose TODO: test all plugins, maybe declare their sample input somewhere near the code """ -import unittest +import tempfile import time +import unittest + +import mock as mock + from common import buckets, rate_limit, RATE_GLOBAL @@ -237,3 +241,67 @@ class TestPlugins(unittest.TestCase): self.assertIn('time', result['event']) self.assertIn('msg', result['event']) self.assertIn('msg', result) + + def test_botlist(self): + import config + + def test_in_actual_file(filename): + with open(filename) as f: + filecontent = str(f.read()) + self.assertIn('DERPDERP', filecontent) + + def test_in_file(): + with tempfile.NamedTemporaryFile() as f: + filename = config.runtime_config_store.filename + config.runtime_config_store.write(outfile=f) + config.runtime_config_store.filename = filename + f.seek(0) + filecontent = str(f.read()) + self.assertIn('DERPDERP', filecontent) + + def test_in_memory(): + self.assertEqual(config.runtime_config_store['other_bots'], ['DERPDERP']) + + def test_in_write(): + filename = config.runtime_config_store.filename + filecontent = config.runtime_config_store.write() + config.runtime_config_store.filename = filename + self.assertIn('DERPDERP', '\n'.join(filecontent)) + + orig_filename = config.runtime_config_store.filename + config.runtime_config_store.filename = None + + # empty the botlist + config.runtime_config_store['other_bots'] = [] + with open(orig_filename, 'wb') as f: + f.write(b'') + + # only append to the dict, asserting it's in memory + self.assertEqual(config.runtime_config_store['other_bots'], []) + config.runtime_config_store['other_bots'].append('DERPDERP') + test_in_memory() + test_in_write() + + # using the setter (with write usage), assert it's in the file + # config.runtimeconf_set('other_bots', ['DERPDERP']) + test_in_memory() + test_in_write() + test_in_file() + + # reloading the config, assuming in memory AND file + test_in_memory() + test_in_write() + test_in_file() + + config.runtime_config_store.filename = orig_filename + config.runtime_config_store.write() + + test_in_actual_file(orig_filename) + + def tearDown(self): + import config + if 'DERPDERP' in config.runtime_config_store['other_bots']: + config.runtime_config_store['other_bots'].remove('DERPDERP') + config.runtime_config_store.write() + + diff --git a/urlbot.py b/urlbot.py index 7ef43c5..e47775a 100755 --- a/urlbot.py +++ b/urlbot.py @@ -115,7 +115,8 @@ class UrlBot(IdleBot): self.logger.warning("I'm muted! (status: %s)", self.show) return - config.runtimeconf_set('request_counter', config.runtimeconf_get('request_counter') + 1) + request_counter = int(config.runtimeconf_get('request_counter')) + config.runtimeconf_set('request_counter', request_counter + 1) if str is not type(message): message = '\n'.join(message)