diff options
Diffstat (limited to 'plugins/guildbot')
-rw-r--r-- | plugins/guildbot/__init__.py | 18 | ||||
-rw-r--r-- | plugins/guildbot/__init__.pyc | bin | 0 -> 763 bytes | |||
-rw-r--r-- | plugins/guildbot/create_db.sql | 23 | ||||
-rw-r--r-- | plugins/guildbot/guilddb.py | 153 | ||||
-rw-r--r-- | plugins/guildbot/guilddb.pyc | bin | 0 -> 6575 bytes | |||
-rw-r--r-- | plugins/guildbot/handlers.py | 326 | ||||
-rw-r--r-- | plugins/guildbot/handlers.pyc | bin | 0 -> 10189 bytes |
7 files changed, 520 insertions, 0 deletions
diff --git a/plugins/guildbot/__init__.py b/plugins/guildbot/__init__.py new file mode 100644 index 0000000..0e4ffd5 --- /dev/null +++ b/plugins/guildbot/__init__.py @@ -0,0 +1,18 @@ +import handlers +from guilddb import GuildDB +from net.onlineusers import OnlineUsers + +PLUGIN = { + 'name': 'guildbot', + 'requires': (), + 'blocks': (), +} + +__all__ = ['PLUGIN', 'init'] + + +def init(config): + handlers.online_users = OnlineUsers(config.get('Other', 'online_txt_url'), + refresh_hook=handlers.online_list_update) + handlers.online_users.start() + handlers.db = GuildDB(config.get('GuildBot', 'dbfile')) diff --git a/plugins/guildbot/__init__.pyc b/plugins/guildbot/__init__.pyc Binary files differnew file mode 100644 index 0000000..f10c5b9 --- /dev/null +++ b/plugins/guildbot/__init__.pyc diff --git a/plugins/guildbot/create_db.sql b/plugins/guildbot/create_db.sql new file mode 100644 index 0000000..bdf1d76 --- /dev/null +++ b/plugins/guildbot/create_db.sql @@ -0,0 +1,23 @@ +pragma foreign_keys=on; + +create table if not exists GUILDS( + ID integer primary key not null, + NAME text[25] not null unique, + CREATED datetime default current_timestamp, + MOTD text[100]); + +create table if not exists PLAYERS( + ID integer primary key not null, + NAME text[25] not null unique, + LASTSEEN datetime, + GUILD_ID integer, + ACCESS integer default 0, + foreign key(GUILD_ID) references GUILDS(ID)); + +insert into GUILDS(NAME) values('Crew of Red Corsair'); +insert into GUILDS(NAME) values('Phoenix Council'); + +insert into PLAYERS(NAME, GUILD_ID, ACCESS) values('Travolta', 1, 10); +insert into PLAYERS(NAME, GUILD_ID, ACCESS) values('Rill', 1, 10); +insert into PLAYERS(NAME, GUILD_ID, ACCESS) values('veryape', 2, 10); + diff --git a/plugins/guildbot/guilddb.py b/plugins/guildbot/guilddb.py new file mode 100644 index 0000000..a720b49 --- /dev/null +++ b/plugins/guildbot/guilddb.py @@ -0,0 +1,153 @@ +import logging +import sys +import sqlite3 + + +class GuildDB: + + def __init__(self, dbfile): + self._dbfile = dbfile + self.logger = logging.getLogger('ManaChat.Guild') + self.db, self.cur = self._open_sqlite_db(dbfile) + + # self.cur.execute('PRAGMA foreign_keys = ON') + self.cur.execute('create table if not exists GUILDS(\ + ID integer primary key,\ + NAME text[25] not null unique,\ + CREATED datetime default current_timestamp,\ + MOTD text[100])') + self.cur.execute('create table if not exists PLAYERS(\ + ID integer primary key,\ + NAME text[25] not null unique,\ + LASTSEEN date,\ + GUILD_ID integer,\ + ACCESS integer not null default -10,\ + SHOWINFO boolean not null default 0,\ + foreign key(GUILD_ID) references GUILDS(ID))') + self.db.commit() + + def __del__(self): + try: + self.db.close() + except Exception: + pass + + def _open_sqlite_db(self, dbfile): + """ + Open sqlite db, and return tuple (connection, cursor) + """ + try: + db = sqlite3.connect(dbfile) + cur = db.cursor() + except sqlite3.Error, e: + self.logger.error("sqlite3 error: %s", e.message) + sys.exit(1) + return db, cur + + def guild_create(self, name): + self.cur.execute('insert into GUILDS(NAME) values(?)', (name,)) + self.db.commit() + if self.cur.rowcount: + self.logger.info('Created guild "%s"', name) + return True + else: + self.logger.info('Error creating guild "%s"', name) + return False + + def guild_delete(self, name): + self.cur.execute('select ID from GUILDS where name = ?', (name,)) + row = self.cur.fetchone() + if row: + guild_id = row[0] + self.cur.execute('delete from GUILDS where name=?', (name,)) + self.cur.execute('update PLAYERS set GUILD_ID = NULL, \ + ACCESS = -10, where GUILD_ID = ?', (guild_id,)) + self.db.commit() + self.logger.info('Deleted guild "%s"', name) + return True + else: + self.logger.error('Guild "%s" not found', name) + return False + + def guild_set_motd(self, name, motd): + self.cur.execute('update GUILD set MOTD = ? where NAME = ?', + (motd, name)) + self.db.commit() + if self.cur.rowcount: + self.logger.info('Guild "%s" MOTD: %s', name, motd) + return True + else: + self.logger.error('Error setting MOTD for guild: %s', name) + return False + + def player_info(self, name): + query = '''select GUILDS.ID,GUILDS.NAME,ACCESS + from PLAYERS join GUILDS + on PLAYERS.GUILD_ID = GUILDS.ID + where PLAYERS.NAME = ?''' + self.cur.execute(query, (name,)) + return self.cur.fetchone() + + def player_get_access(self, name, guild_name=''): + query = 'select ACCESS from PLAYERS where NAME = ?' + self.cur.execute(query, (name, guild_name)) + row = self.cur.fetchone() + if row: + return row[0] + else: + # self.logger.warning('player %s not found', name) + return -10 + + def player_set_access(self, name, access_level): + query = '''update table PLAYERS set ACCESS = ? + where name = ?''' + self.cur.execute(query, (name, access_level)) + self.db.commit() + + def player_join_guild(self, player, guild, access=0): + self.cur.execute('select ID from GUILDS where NAME = ?', (guild,)) + guild_info = self.cur.fetchone() + if guild_info: + guild_id = guild_info[0] + else: + self.logger.error('Guild "%s" not found', guild) + return False + + query = '''update or ignore PLAYERS + set GUILD_ID = ?, ACCESS = ? + where NAME = ?''' + self.cur.execute(query, (guild_id, access)) + + query = '''insert or ignore into + PLAYERS(NAME, GUILD_ID, ACCESS) + values(?, ?, ?)''' + self.cur.execute(query, (player, guild_id, access)) + + self.db.commit() + + self.logger.info('Added player "%s" to guild "%s"', + player, guild) + return True + + def player_set_showinfo(self, player, si=True): + query = '''update table PLAYERS set SHOWINFO = ? + where name = ?''' + self.cur.execute(query, (player, si)) + self.db.commit() + + def guild_remove_player(self, player_name): + query = '''update PLAYERS set GUILD_ID = NULL, ACCESS = -10 + where NAME = ?''' + self.cur.execute(query, (player_name,)) + self.db.commit() + + def all_players_same_guild(self, player_name): + query = '''select NAME from PLAYERS + where GUILD_ID = (select GUILD_ID from PLAYERS + where NAME = ?)''' + return self.cur.fetchall(query, (player_name,)) + + def all_players_any_guild(self): + query = '''select NAME from PLAYERS + where ACCESS >= 0''' + return self.cur.fetchall(query) diff --git a/plugins/guildbot/guilddb.pyc b/plugins/guildbot/guilddb.pyc Binary files differnew file mode 100644 index 0000000..9de8f66 --- /dev/null +++ b/plugins/guildbot/guilddb.pyc diff --git a/plugins/guildbot/handlers.py b/plugins/guildbot/handlers.py new file mode 100644 index 0000000..6d032b5 --- /dev/null +++ b/plugins/guildbot/handlers.py @@ -0,0 +1,326 @@ +from chat import send_whisper +from utils import extends +from commands import parse_player_name + + +online_users = None +db = None +max_msg_len = 200 +pending_invitations = {} + + +def ignore(): + pass + + +def listonline(nick, _): + curr_msg = '' + online = online_users.online_users + + for prow in db.all_players_same_guild(nick): + p = prow[0] + if p in online: + if len(curr_msg + ', ' + p) > max_msg_len: + send_whisper(nick, curr_msg) + curr_msg = p + else: + curr_msg = curr_msg + ', ' + p + + send_whisper(nick, curr_msg) + + +def leave(nick, _): + info = db.player_info(nick) + broadcast(nick, '"{}" left the guild'.format(nick), True) + db.guild_remove_player(nick) + send_whisper(nick, 'You left guild {}'.format(info[1])) + + +def showinfo(nick, _): + db.player_set_showinfo(nick, True) + send_whisper(nick, "Information messages are visible") + + +def hideinfo(nick, _): + db.player_set_showinfo(nick, False) + send_whisper(nick, "Information messages are hidden") + + +def status(nick, _): + _, guild, access = db.player_info(nick) + send_whisper(nick, 'Player:{}, Guild:{}, Access:{}'.format( + nick, guild, access)) + + +# FIXME: not finished +def invite(nick, player): + if not player: + send_whisper(nick, "Usage: !invite Player") + return + + pinfo = db.player_info(player) + if pinfo and pinfo[0]: + send_whisper(nick, '"{}" is already a member of guild "{}"'.format( + player, pinfo[1])) + return + + online = online_users.online_users + if player not in online: + send_whisper(nick, '"{}" is not online'.format(player)) + return + + _, guild, _ = db.player_info(nick) + invite_msg = ('You have been invited to the "{}" guild chat. ' + 'If you would like to accept this invitation ' + 'please reply "yes" and if not then "no"').format(guild) + send_whisper(player, invite_msg) + # FIXME: what if player is offline? online_list can be outdated + pending_invitations[player] = guild + + +def remove(nick, player): + if not player: + send_whisper(nick, "Usage: !remove Player") + return + + pinfo = db.player_info(player) + if not pinfo: + send_whisper(nick, '{} is not in any guild'.format(player)) + return + + gid, _, _ = db.player_info(nick) + if gid != pinfo[0]: + send_whisper(nick, '{} is not in your guild'.format(player)) + return + + broadcast(player, '{} was removed from your guild'.format(player), True) + db.guild_remove_player(player) + send_whisper(nick, 'You were removed from "{}" guild'.format(pinfo[1])) + + +def setmotd(nick, motd): + guild = db.player_info(nick)[1] + db.setmotd(guild, motd) + broadcast(nick, 'MOTD: ' + motd) + + +def removemotd(nick, _): + guild = db.player_info(nick)[1] + db.setmotd(guild, '') + broadcast(nick, 'MOTD removed') + + +def setaccess(nick, params): + try: + si = params.index(" ") + lvl = int(params[:si]) + player = params[si + 1:] + if len(player) < 4: + raise ValueError + except ValueError: + send_whisper(nick, "Usage: !setaccess Level Player") + return + + gid, guild_name, access = db.player_info(nick) + gidp, _, accessp = db.player_info(player) + + if gid != gidp: + send_whisper(nick, '{} is not in your guild "{}"'.format( + player, guild_name)) + return + + if access <= accessp: + send_whisper(nick, "You cannot set access level for {}".format( + player)) + return + + db.player_set_access(player, lvl) + send_whisper(nick, "Player: {}, access level: {}".format( + player, lvl)) + + +def disband(nick, _): + _, guild, _ = db.player_info(nick) + if db.guild_delete(guild): + send_whisper(nick, 'Deleted guild "{}"'.format(guild)) + else: + send_whisper(nick, 'Error deleting guild "{}"'.format(guild)) + + +def addguild(nick, params): + usage = 'Usage: !addguild Leader Guild (note: Leader can be quoted)' + if not params: + send_whisper(nick, usage) + return + + leader, guild = parse_player_name(params) + + if len(leader) < 4 or len(guild) < 4: + send_whisper(nick, usage) + return + + if db.guild_create(guild): + send_whisper(nick, 'Created guild "{}", leader is "{}"'.format( + guild, leader)) + else: + send_whisper(nick, "Error creating guild") + + +def removeguild(nick, guild_name): + if not guild_name: + send_whisper(nick, "Usage: !removeguild Guild") + return + + if db.guild_delete(guild_name): + send_whisper(nick, 'Deleted guild "{}"'.format(guild_name)) + else: + send_whisper(nick, 'Guild not found: "{}"'.format(guild_name)) + + +def globalmsg(nick, msg): + if not msg: + send_whisper(nick, "Usage: !global Message") + return + + online = online_users.online_users + for prow in db.all_players_any_guild(): + pname = prow[0] + if pname in online: + send_whisper(pname, msg) + + +def joinguild(nick, guild): + if not guild: + send_whisper(nick, "Usage: !joinguild Guild") + return + + if db.player_join_guild(nick, guild, 20): + send_whisper(nick, 'You joined guild "{}"'.format(guild)) + else: + send_whisper(nick, 'Guild "{}" does not exist'.format(guild)) + + +def showhelp(nick, _): + access = db.player_get_access(nick) + curr_line = '' + + for cmd, (lvl, _, hlp) in commands.iteritems(): + if access < lvl: + continue + + if hlp[0] == '+': + help_s = '!' + cmd + ' ' + hlp[1:] + else: + help_s = '!' + cmd + ' -- ' + hlp + + if len(curr_line + '; ' + help_s) > max_msg_len: + send_whisper(nick, curr_line) + curr_line = help_s + else: + curr_line = curr_line + '; ' + help_s + + if curr_line: + send_whisper(nick, curr_line) + + +commands = { + "help": (-10, showhelp, "show help"), + "info": (0, status, "display guild information"), + "listonline": (0, listonline, "list online players"), + "leave": (0, leave, "leave your guild"), + "showinfo": (0, showinfo, "verbose notifications"), + "hideinfo": (0, hideinfo, "quiet notifications"), + "invite": (5, invite, "+Player -- invite player to guild"), + "remove": (5, remove, "+Player -- remove player from guild"), + "setmotd": (5, setmotd, "+MOTD -- set MOTD"), + "removemotd": (5, removemotd, "remove MOTD"), + "setaccess": (10, setaccess, "+Level Player -- set access level"), + "disband": (10, disband, "disband your guild"), + "addguild": (20, addguild, "+Leader GuildName -- add guild"), + "removeguild": (20, removeguild, "+GuildName -- remove guild"), + "global": (20, globalmsg, "+Message -- global message"), + "joinguild": (20, joinguild, "+GuildName -- join a guild"), +} + + +def exec_command(nick, cmdline): + end = cmdline.find(" ") + if end < 0: + cmd = cmdline[1:] + arg = "" + else: + cmd = cmdline[1:end] + arg = cmdline[end + 1:] + + if cmd in commands: + lvl, func, _ = commands[cmd] + access = db.player_get_access(nick) + + if access < lvl: + send_whisper(nick, 'That command is fobidden for you!') + else: + func(nick, arg) + + else: + send_whisper(nick, 'Command !{} not found. Try !help'.format(cmd)) + + +def player_joining(player, guild): + db.player_join_guild(player, guild) + broadcast(player, '{} joined your guild'.format(player), True) + + +def broadcast(nick, msg, exclude_nick=False): + """ + Broadcast message for all players that belong the same guild as nick. + """ + n = 0 + for prec in db.all_players_same_guild(nick): + if exclude_nick and prec[0] == nick: + continue + n += 1 + send_whisper(prec[0], '{} : {}'.format(nick, msg)) + + if n == 0: + send_whisper(nick, "You don't belong to any guild") + + +def online_list_update(curr, prev): + for p in curr - prev: + ginfo = db.player_info(p) + if ginfo is not None: + if ginfo[0] is not None: + allp = set(db.all_players_same_guild(p)) + n = len(allp.intersection(curr)) + send_whisper(p, + 'Welcome to {}! ({} Members are online)'.format( + ginfo[1], n)) + broadcast(p, '{} is now Online'.format(p), True) + + for p in prev - curr: + broadcast(p, '{} is now Offline'.format(p), True) + + +@extends('smsg_whisper') +def got_whisper(data): + nick, message = data.nick, data.message + + if len(message) < 1: + return + + if message[0] == '!': + exec_command(nick, message) + else: + if nick in pending_invitations: + # TODO: inform message + if message.lower() == 'yes': + player_joining(nick, pending_invitations[nick]) + del pending_invitations[nick] + + else: + broadcast(nick, message) + + +@extends('smsg_whisper_response') +def send_whisper_result(data): + pass diff --git a/plugins/guildbot/handlers.pyc b/plugins/guildbot/handlers.pyc Binary files differnew file mode 100644 index 0000000..a109f0c --- /dev/null +++ b/plugins/guildbot/handlers.pyc |