if len(sys.argv) > 1:
token_file = sys.argv[1]
-admins = []
-admin_role = 'Cat'
-fd = open('ADMINS', 'r')
-for line in fd.readlines():
- admin = line.strip()
- admins.append(admin)
-fd.close()
-
fd = open(token_file, 'r')
token = fd.readline().strip()
fd.close()
discordlog = logging.getLogger('discord')
log = logging.getLogger('catbot')
bot.log = log
+bot.db = db
log.setLevel(logging.DEBUG if bot.get('debug') else logging.INFO)
plugins.log_level(log.level)
yield from bot.maybe_say(message.channel, 'hiss!')
@asyncio.coroutine
-def is_admin(server, member):
- if server is None:
- return member.id in admins
- for role in server.roles:
- if role.name != admin_role:
- continue
- if role in member.roles:
- return True
- return False
-
-@asyncio.coroutine
def identify(destination, target):
do = Identify.member.value | Identify.role.value | Identify.channel.value
channel_id = None
@asyncio.coroutine
def do_commands(message, command, raw, non_admin):
if not non_admin:
- result = yield from is_admin(message.server, message.author)
- if not result:
+ if not bot.is_admin(message.author, message.server):
yield from not_admin(message)
return
yield from cat.yelp(message.channel)
return
- elif command == 'debug':
- # debug
- m = re.match(r'\bdebug\s+(o(?:ff|n))\b', raw, re.IGNORECASE)
- if m is None:
- yield from bot.say(message.channel, 'Sorry!')
- return
-
- arg = m.group(1)
- if arg == 'on':
- discordlog.setLevel(logging.DEBUG)
- log.setLevel(logging.DEBUG)
- db.log_level(logging.DEBUG)
- plugins.log_level(logging.DEBUG)
- elif arg == 'off':
- discordlog.setLevel(logging.WARN)
- log.setLevel(logging.INFO)
- db.log_level(logging.WARN)
- plugins.log_level(logging.INFO)
-
elif command == 'delete':
# delete
if message.channel.is_private:
yield from client.purge_from(message.channel, *args, limit = limit)
return
- elif command == 'dryrun':
- # dryrun
- m = re.match(r'\bdryrun\s+(o(?:ff|n))\b', raw, re.IGNORECASE)
- if m is None:
- yield from bot.say(message.channel, 'Sorry!')
- return
-
- arg = m.group(1)
- if arg == 'on':
- log.info('DRYRUN mode')
- bot.set('dryrun', True)
- elif arg == 'off':
- log.info('Live mode')
- bot.set('dryrun', False)
-
elif command == 'id':
# id
m = re.match(r'\bid\s+(.*)', raw, re.IGNORECASE)
'admin': {
'fn': do_commands,
'args': [False],
- 'commands': ['avatar', 'debug', 'delete', 'dryrun', 'idle', 'rss']
+ 'commands': ['avatar', 'delete', 'idle', 'rss']
},
'any': {
'fn': do_commands,
bot.client = client
bot.db = db
plugins.set_client(client)
+if 'admin' in plugins.plugins():
+ plugins.get_plugin('admin').db = db
+ plugins.get_plugin('admin').plugins = plugins
@asyncio.coroutine
def builtin_commands(message, command, raw):
if state['last_spoke']:
bot.set('last_spoke', state['last_spoke'])
log.info('Logged in as {}#{}'.format(client.user.name, client.user.id))
- log.info('Admins are: {}'.format(admins))
if not threads_ready.value:
plugins.on_ready()
asyncio.async(maybe_sleep())
'playing': multiprocessing.Value('b', False)
}
+def is_admin(user, server = None):
+ ret = False
+ params = ['global']
+ if server is not None:
+ params.append(server.id)
+ sql = 'select id from admins where server_id in ({}) and bot_id in (?, ?) and user_id=?'.format(', '.join(['?'] * len(params)))
+ params.append('global')
+ params.append(client.user.id)
+ params.append(user.id)
+ cursor = db.query(sql, params)
+ for row in cursor.fetchall():
+ ret = True
+ break
+ db.close_db()
+ log.info('User {} {} an administrator{}'.format(user.name, 'is' if ret else 'is not', ' on server {}'.format(server.name) if server is not None else ''))
+ return ret
+
def get(key):
if key in variables:
return variables[key].value
cursor = self.query('create table if not exists state (id char(36) not null, bot_id varchar(32) not null, avatar varchar(128), idle boolean not null default false, last_spoke datetime)')
cursor = self.query('create unique index if not exists state_id on state (id)')
cursor = self.query('create unique index if not exists state_bot_id on state (bot_id)')
+ cursor = self.query('create table if not exists admins (id char(36) not null, bot_id varchar(32) not null, server_id varchar(32) not null, user_id varchar(32))')
+ cursor = self.query('create unique index if not exists admins_id on admins (id)')
+ cursor = self.query('create index if not exists admins_bot_id on admins (bot_id)')
self.dbh.commit()
self.close_db()
--- /dev/null
+import asyncio
+import logging
+import shlex
+import sys
+
+from plugins import PluginCommand
+import bot
+import cat
+
+class Admin(object):
+ def __init__(self):
+ self.discordlog = logging.getLogger('discord')
+ self.botlog = logging.getLogger('catbot')
+ self.db = None
+ self.plugins = None
+ return None
+
+ def description(self):
+ return 'Lets privileged users manage the bot.'
+
+ def create_tables(self):
+ self.open_db()
+ self.dbh.commit()
+ self.close_db()
+
+ def valid_commands(self):
+ return ['debug', 'dryrun', 'shutdown']
+
+ @asyncio.coroutine
+ def handle_command(self, message, command, raw):
+ if command not in self.valid_commands():
+ return PluginCommand.ignored
+ yield from self.run_command(message, shlex.split(raw))
+ return PluginCommand.exclusive
+
+ @asyncio.coroutine
+ def handle_help(self, message, command, *args):
+ yield from self.help_command(message, *args)
+
+ @asyncio.coroutine
+ def run_command(self, message, args):
+ if not bot.is_admin(message.author):
+ yield from cat.hiss(message.channel)
+ return
+
+ command = args[0]
+ if command == 'debug':
+ yield from self.handle_debug(message, args[1:])
+ elif command == 'dryrun':
+ yield from self.handle_dryrun(message, args[1:])
+ elif command == 'shutdown':
+ yield from self.handle_shutdown(message)
+
+ @asyncio.coroutine
+ def help_command(self, message, command):
+ if command == 'debug':
+ lines = [
+ 'Turn debugging on or off.',
+ '```',
+ 'debug on',
+ 'debug off',
+ '```',
+ '',
+ 'You will need access to my logs to see the debugging output!'
+ ]
+ elif command == 'dryrun':
+ lines = [
+ 'Enable or disable plugins (if supported).',
+ '```',
+ 'dryrun on',
+ 'dryrun off',
+ '```'
+ ]
+ elif command == 'shutdown':
+ lines = [
+ 'Shut the bot down!',
+ '```shutdown```'
+ ]
+ else:
+ lines = ['*shrugs*']
+ yield from bot.say_many(message.channel, lines)
+
+ @asyncio.coroutine
+ def handle_debug(self, message, args):
+ if len(args):
+ arg = args[0].lower()
+ if arg == 'on':
+ self.discordlog.setLevel(logging.DEBUG)
+ self.botlog.setLevel(logging.DEBUG)
+ if self.db is not None:
+ self.db.log_level(logging.DEBUG)
+ if self.plugins is not None:
+ self.plugins.log_level(logging.DEBUG)
+ elif arg == 'off':
+ self.discordlog.setLevel(logging.WARN)
+ self.botlog.setLevel(logging.INFO)
+ if self.db is not None:
+ self.dblog.log_level(logging.WARN)
+ if self.plugins is not None:
+ self.plugins.log_level(logging.INFO)
+ else:
+ yield from cat.yelp(message.channel)
+ return
+ yield from bot.maybe_say(message.channel, 'purr', wake = False)
+ else:
+ yield from cat.yelp(message.channel)
+
+ @asyncio.coroutine
+ def handle_dryrun(self, message, args):
+ if len(args):
+ arg = args[0].lower()
+ if arg == 'on':
+ log.info('DRYRUN mode.')
+ bot.set('dryrun', True)
+ elif arg == 'off':
+ log.info('Live mode.')
+ bot.set('dryrun', False)
+ else:
+ yield from cat.yelp(message.channel)
+ return
+ yield from bot.maybe_say(message.channel, 'purr', wake = False)
+ else:
+ yield from cat.yelp(message.channel)
+
+ @asyncio.coroutine
+ def handle_shutdown(self, message):
+ log.warning('Shutdown initiated!')
+ result = yield from bot.say(message.channel, 'Goodbye!')
+ result = yield from client.logout()
+ try:
+ sys.exit(0)
+ except:
+ pass