diff options
Diffstat (limited to 'chatalias.py')
-rw-r--r-- | chatalias.py | 469 |
1 files changed, 364 insertions, 105 deletions
diff --git a/chatalias.py b/chatalias.py index dc7db72..bc21e13 100644 --- a/chatalias.py +++ b/chatalias.py @@ -1,127 +1,386 @@ -# Chat Aliasing plugin by Curs3d # -################################## -# Allows users to alias words, -# so that when they send a -# message in chat, it gets -# replaced by their specified -# word. Configuration of this -# plugin is in the "gnl" -# (general) tag of the JSON -# file named "aliases". The -# file is generated if not -# present. Set values to -1 -# for "unlimited" setting. +# TODO: Add cg/ac/msg support +import os +import mysqlhack +import org.bukkit as bukkit +from org.bukkit import * from helpers import * -from traceback import format_exc as trace -data = None +# Version number and requirements -def safe_open_json(): - global data - if data is not None: - return data - data = open_json_file("aliases") - if data is None: - data = {"gnl":{"max_len":"35","max_entries":"10"}} - save_json_file("aliases", data) - return data +alias_version = "2.1.0" +helpers_versions = ["1.1.0", "2.0.0"] +enabled = False +error_msg = colorify("&cUnspecified error") +commands_per_page = 5 +global_aliases = {"./":"/"} +data = {} +use_mysql = True +# Permissions: -@hook.command("alias", usage = "/<command> [to_alias] [alias...]", desc = "Aliases words in chat") -def on_alias_command(sender, cmd, label, args): +# Grants full access immediately +permission_ALL = "utils.alias.*" +# Access to the command to display the help screen +permission_BASE = "utils.alias" +# Make replacements only when the user has this permission +permission_USE = "utils.alias.use" +# Modify aliases +permission_MODIFY = "utils.alias.modify" +permission_MODIFY_OTHERS = "utils.alias.modify.others" +# List aliases +permission_LIST = "utils.alias.list" +permission_LIST_OTHERS = "utils.alias.list.others" +# Set alias amounts/length limits, e.g. utils.alias.amount.420 +permission_AMOUNT = "utils.alias.amount." +permission_LENGTH = "utils.alias.length." +# See when the plugin was disabled due to version errors +permission_INFO = "utils.alias.info" +permission_FINFO = "utils.alias.finfo" - if not is_player(sender): - msg(sender, "Sorry, Console cannot alias words") - return True +######## +# CODE # +######## - if not sender.hasPermission("utils.alias.allowed"): - plugin_header(recipient = sender, name = "Chat Alias") - noperm(sender) - return True +def safe_open_json(uuid): + if not os.path.exists("plugins/redstoner-utils.py.dir/files/aliases"): + os.makedirs("plugins/redstoner-utils.py.dir/files/aliases") + value = open_json_file("aliases/" + uuid) + if value is None: + value = dict(global_aliases) + save_json_file("aliases/" + uuid, value) + return value - if len(args) == 0: - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "This is a plugin that allows you to type in chat and have words replaced by other ones automatically!") - msg(sender, "\nCommands:") - msg(sender, "/alias <word>: removes <word> from aliased words. Use * to remove all aliased words.") - msg(sender, "/alias <word> <others...>: Will change <word> to <others...> in chat") - msg(sender, "\nYour Aliases:") - data = safe_open_json() - try: - for alias, value in data[str(sender.getUniqueId())].items(): - msg(sender, "%s ==> %s" % (alias, value)) - except KeyError: - pass - return True - elif len(args) == 1: - data = safe_open_json() - if args[0] == "*": - try: - del data[str(sender.getUniqueId())] - except KeyError: - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "No alias data to remove!") - return True - save_json_file("aliases", data) - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "ALL alias data successfuly removed!") +@hook.command("alias", + usage="/<command> <add, remove, list, help> [...]", + desc="Allows aliasing of words") +def on_alias_command(sender, cmd, label, args): + if not is_player(sender): + msg(sender, "&cThe console cannot use aliases!") + return True + try: + args = array_to_list(args) + if not enabled: + disabled_fallback(sender) return True - - try: - if data[str(sender.getUniqueId())].pop(args[0], None) is None: - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "Could not remove: alias not present!") - return True - except KeyError: - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "Could not remove: you do not have any aliases!") + if not hasPerm(sender, permission_BASE): + plugin_header(recipient=sender, name="Alias") + noperm(sender) return True - - save_json_file("aliases", data) - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "Alias for %s successfuly removed" % args[0]) + return subcommands[args[0].lower()](sender, args[1:]) + except: + return subcommands["help"](sender, "1") + + +def help(sender, args): + commands = [colorify("&e/alias help [page]")] + if hasPerm(sender, permission_LIST): + commands += [colorify("&e/alias list &7- Lists all your aliases")] + if hasPerm(sender, permission_MODIFY): + commands += [colorify("&e/alias add <word> <alias> &7- Add an alias")] + commands += [colorify("&e/alias remove <word> &7- Remove an alias")] + if can_remote(sender): + while len(commands) < commands_per_page: + commands += [""] + commands += [colorify("&7Following commands will be executed on <player> yet all output will be redirected to you, except when you set silent to false, then <player> will see it too.")] + if hasPerm(sender, permission_LIST_OTHERS): + commands += [colorify("&e/alias player <name> list [silent]")] + if hasPerm(sender, permission_MODIFY_OTHERS): + commands += [colorify("&e/alias player <name> add <word> <alias> [silent]")] + commands += [colorify("&e/alias player <name> remove <word> [silent]")] + pages = (len(commands)-1)/commands_per_page + 1 + page = 1 + if len(args) != 0: + page = int(args[0]) + if (page > pages): + page = pages + if page < 1: + page = 1 + msg(sender, colorify("&e---- &6Help &e-- &6Page &c" + str(page) + "&6/&c" + str(pages) + " &e----")) + page -= 1 + to_display = commands[5*page:5*page+5] + for message in to_display: + msg(sender, message) + if page+1 < pages: + msg(sender, colorify("&6To display the next page, type &c/alias help " + str(page+2))) + return True + + +@hook.event("player.PlayerJoinEvent", "high") +def on_join(event): + if enabled: + t = threading.Thread(target=load_data, args=(uid(event.getPlayer()), )) + t.daemon = True + t.start() + else: + if event.getPlayer().hasPermission(permission_FINFO): + disabled_fallback(event.getPlayer()) + + +@hook.event("player.AsyncPlayerChatEvent", "high") +def on_player_chat(event): + if enabled: + if event.isCancelled(): + return + player = event.getPlayer() + if not hasPerm(player, permission_USE): + return + msg_limit = int(get_permission_content(player, permission_LENGTH)) + for alias, value in data[str(uid(player))].items(): + if player.hasPermission("essentials.chat.color"): + event.setMessage(event.getMessage().replace(colorify(alias), colorify(value))) + else: + event.setMessage(event.getMessage().replace(alias, value)) + if not player.hasPermission(permission_ALL) and len(event.getMessage()) > msg_limit: + event.setCancelled(True) + plugin_header(player, "Alias") + msg(player, "The message you wanted to generate would exceed the length limit limit of %d. Please make it shorter!" % msg_limit) + return + + +def hasPerm(player, permission): + return (player.hasPermission(permission)) or (player.hasPermission(permission_ALL)) + + +def disabled_fallback(receiver): + if not hasPerm(receiver, permission_INFO): + msg(receiver, colorify("&cUnknown command. Use &e/help&c, &e/plugins &cor ask a mod.")) + else: + msg(receiver, colorify("&cPlugin alias v" + alias_version + " has experienced an &eEMERGENCY SHUTDOWN:")) + msg(receiver, error_msg) + msg(receiver, colorify("&cPlease contact a dev/admin (especially pep :P) about this to take a look at it.")) + + +def can_remote(player): + return hasPerm(player, permission_LIST_OTHERS) or hasPerm(player, permission_MODIFY_OTHERS) + + +def add(sender, args): + plugin_header(sender, "Alias") + uuid = uid(sender) + args = [args[0]] + [" ".join(args[1:])] + if (args[0] not in data[uuid]) and is_alias_limit_reached(sender, sender): return True - - elif len(args) >= 2: - data = safe_open_json() - alias = " ".join(args[1:]) - try: - if len(alias) > int(data["gnl"]["max_len"]) and int(data["gnl"]["max_len"]) >= 0: - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "Please do not alias long words/sentences.") - return True - - if len(data[str(sender.getUniqueId())]) >= int(data["gnl"]["max_entries"]) and int(data["gnl"]["max_entries"]) >= 0: - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "You have reached the maximum amount of alias entries! Sorry!") - return True - except KeyError: - data[str(sender.getUniqueId())] = {} - - data[str(sender.getUniqueId())][args[0]] = alias - save_json_file("aliases", data) - plugin_header(recipient = sender, name = "Chat Alias") - msg(sender, "Chat Alias %s ==> %s successfully created!" % (args[0], alias)) + if not add_alias_data(uuid, str(args[0]), args[1]): + msg(sender, colorify("&c") + "Could not add this alias because it would cause some sequences to be replaced multiple times", usecolor = False) return True - + msg(sender, colorify("&7Alias: ") + args[0] + colorify("&7 -> " + args[1] + colorify("&7 was succesfully created!")), usecolor=sender.hasPermission("essentials.chat.color")) + return True + + +def radd(sender, args): + plugin_header(sender, "Alias") + args = args[0:2] + [" ".join(args[2:len(args)-1])] + [args[len(args)-1]] + if is_player(sender): + sender_name = colorify(sender.getDisplayName()) else: + sender_name = colorify("&6Console") + target = server.getPlayer(args[0]) + if target == None: + msg(sender, "&cThat player is not online") + return True + uuid = uid(target) + if args[3].lower() == "false": + plugin_header(target, "Alias") + msg(target, "&cPlayer " + sender_name + " &cis creating an alias for you!") + elif args[3].lower() != "true": + args[2] += " " + args[3] + if (args[1] not in data[uuid]) and is_alias_limit_reached(target, sender, args[3].lower() == "false"): + return True + if len(args) == 3: + args += ["true"] + if not add_alias_data(uuid, str(args[1]), str(args[2])): + message = colorify("&c") + "Could not add this alias because it would cause some sequences to be replaced multiple times" + msg(sender, message) + if args[3].lower() == "false": + msg(target, message) + return True + msg(sender, colorify("&7Alias: ") + args[1] + colorify("&7 -> " + args[2] + colorify("&7 was succesfully created!")), usecolor=target.hasPermission("essentials.chat.color")) + if args[3].lower() == "false": + msg(target, colorify("&7Alias: ") + args[1] + colorify("&7 -> " + args[2] + colorify("&7 was succesfully created!")), usecolor=target.hasPermission("essentials.chat.color")) + return True + + +def is_alias_limit_reached(player, recipient, not_silent = False): + if player.hasPermission(permission_ALL): return False + alias_limit = int(get_permission_content(player, permission_AMOUNT)) + if len(data[uid(player)]) >= alias_limit: + message = ("&cYour limit of %d has been reached" if player is recipient else "&cThe limit of %d has been reached for that player") % alias_limit + msg(recipient, message) + if not_silent: + msg(player, message) + return True + return False -@hook.event("player.AsyncPlayerChatEvent", "high") -def on_player_chat(event): - playerid = str(event.getPlayer().getUniqueId()) - data = safe_open_json() +def add_alias_data(puuid, aliased, new_alias): + prior = data[puuid] + + # prevent 2 -> 3 if there is 1 -> 2 + if aliased not in prior: + for alias in prior.values(): + if aliased in alias: + return False + + # prevent 1 -> 2 if there is 2 -> 3 + for sequence in prior: + if sequence in new_alias: + return False + + prior[aliased] = new_alias + save_data(puuid) + return True + + +def remove(sender, args): + plugin_header(sender, "Alias") + try: + msg(sender, colorify("&7Successfully removed alias ") + args[0] + colorify(" &7-> ") + data[uid(sender)].pop(args[0]) + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color")) + save_data(uid(sender)) + except: + msg(sender, colorify("&cCould not remove alias ") + args[0] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color")) + return True + + +def rremove(sender, args): + plugin_header(sender, "Alias") + target = get_player(args[0]) + if is_player(sender): + sender_name = colorify(sender.getDisplayName()) + else: + sender_name = colorify("&6Console") + if args[2].lower() == "false": + plugin_header(target, "Alias") + msg(target, "&cPlayer " + sender_name + " &cis removing an alias for you!") + try: + alias = data[uid(target)].pop(args[1]) + msg(sender, colorify("&7Successfully removed alias ") + args[1] + colorify(" &7-> ") + alias + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color")) + if args[2].lower() == "false": + msg(target, colorify("&7Successfully removed alias ") + args[1] + colorify(" &7-> ") + alias + colorify("&7!"), usecolor=sender.hasPermission("essentials.chat.color")) + save_data(uid(target)) + except: + msg(sender, colorify("&cCould not remove alias ") + args[1] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color")) + if args[2].lower() == "false": + msg(target, colorify("&cCould not remove alias ") + args[1] + colorify(", it does not exist."), usecolor=sender.hasPermission("essentials.chat.color")) + return True + + +def list_alias(sender, args): + plugin_header(sender, "Alias") + msg(sender, "&7You have a total of " + str(len(data[uid(sender)])) + " aliases:") + for word, alias in data[str(uid(sender))].items(): + msg(sender, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=sender.hasPermission("essentials.chat.color")) + return True + + +def rlist_alias(sender, args): + plugin_header(sender, "Alias") + target = get_player(args[0]) + if is_player(sender): + sender_name = colorify(sender.getDisplayName()) + else: + sender_name = colorify("&6Console") + if len(args) == 1: + args += ["true"] + msg(sender, "Player " + args[0] + " has following aliases (" + str(len(data[uid(target)])) + " in total):") + if args[1].lower() == "false": + plugin_header(target, "Alias") + msg(target, "&cPlayer " + sender_name + " &cis listing your aliases") + for word, alias in data[str(uid(target))].items(): + msg(sender, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=target.hasPermission("essentials.chat.color")) + return True - if event.isCancelled(): - return +def remote(sender, args): try: - crashtest = data[playerid].items() - except KeyError: - return + return remotes[args[1].lower()](sender, [args[0]] + args[2:]) + except: + return subcommands["help"](sender, ["2"]) - for alias, value in data[playerid].items(): - event.setMessage(event.getMessage().replace(alias, value)) + +def load_data(uuid): + if use_mysql: + try: + t = threading.Thread(target=load_data_thread, args=(uuid,)) + t.daemon = True + t.start() + except: + error(trace()) + else: + data[uuid] = safe_open_json(uuid) + +def load_data_thread(uuid): + conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver") + curs = conn.cursor() + curs.execute("SELECT `alias` FROM `chatalias` WHERE `uuid` = ?;", (uuid, )) + results = curs.fetchall() + if len(results) == 0: + value = dict(global_aliases) + curs.execute("INSERT INTO `chatalias` VALUES (?,?);", (uuid, json_dumps(results), )) + conn.commit() + else: + value = json_loads(results[0][0]) + curs.close() + conn.close() + data[uuid] = value + + +def save_data(uuid): + if use_mysql: + try: + t = threading.Thread(target=save_data_thread, args=(uuid,)) + t.daemon = True + t.start() + except: + error(trace()) + else: + save_json_file("aliases/" + uuid, data[uuid]) + +def save_data_thread(uuid): + conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver") + curs = conn.cursor() + try: + curs.execute("UPDATE `chatalias` SET `alias` = ? WHERE `uuid` = ?;", (json_dumps(data[uuid]), uuid, )) + except: + error(trace()) + conn.commit() + curs.close() + conn.close() + + +# Subcommands: +subcommands = { + "help": help, + "?": help, + "add": add, + "remove": remove, + "del": remove, + "delete": remove, + "player": remote, + "remote": remote, + "list": list_alias +} + +remotes = { + "add": radd, + "remove": rremove, + "del": rremove, + "delete": rremove, + "list": rlist_alias, +} + +# OnModuleLoad + +enabled = helpers_version in helpers_versions +if not enabled: + error_msg = colorify("&6Incompatible versions detected (&chelpers.py&6)") +for player in server.getOnlinePlayers(): + if enabled: + t = threading.Thread(target=load_data, args=(uid(player), )) + t.daemon = True + t.start() + else: + if player.hasPermission(permission_FINFO): + disabled_fallback(player) |