54 Commits

Author SHA1 Message Date
Dico200
7a905643eb Enabled friends module, added friends check in imbusy, fixed small mistakes 2016-05-28 22:18:27 +02:00
Dico200
89e3982a29 Implement some of pizza's changes from imbusy branch 2016-05-26 04:37:47 +02:00
Dico200
28afa1ddcf Changed debug output, tweaked [busy] broadcast prefix 2016-05-25 18:54:32 +02:00
Dico200
8629b39ce1 Make /busy a toggle, move help page to /busy help. Changed a few messages 2016-05-25 18:41:42 +02:00
Dico200
00e38efd14 Added catcher for /mail send 2016-05-25 18:32:20 +02:00
Dico200
a532c6b42c Changed broadcast message, removed two debugs 2016-05-25 18:18:27 +02:00
Dico200
a2a43ed464 Replace camelCase with _ stuff 2016-05-25 16:13:36 +02:00
Dico
5592e16200 Solidify imbusy blocking pms, tpas, etc.
I used reflection to get the Map<String, Command> object from the SimpleCommandMap instance stored in the implementation of PluginManager.
I replaced all Command instances in there that handle /msg, /tpa, /tpahere and /reply, minus /minecraft:tell, with a wrapper that checks if the target is busy.
Tested adequately, but some more would be nice.
2016-05-25 15:49:11 +02:00
Dico200
9a1006e711 Imbusy command: status <player> tweaked, cleaned up return statements 2016-05-25 03:05:59 +02:00
Dico200
29e7ce174b Imbusy command: Replace plugin_header calls with a single one at the start 2016-05-25 03:02:01 +02:00
Dico200
8165d5977b Small change to imbusy messages 2016-05-25 03:00:35 +02:00
Dico200
fca3cf250c Imbusy: Fixed typos and some *flaws* which I will disregard here @curs3d 2016-05-25 02:52:24 +02:00
Dico200
7fdaee155a Fix yo shitty chatgroups code 2016-05-25 02:46:53 +02:00
Dico200
4e6bd44c38 Undoing these small changes from last commit... 2016-05-25 02:40:50 +02:00
Dico200
a555676076 Prevent complete multi-replacement in chatalias. Doesn't prevent 1 -> 2 and 23 -> 5 to make for 13 -> 5, but does prevent a -> 20 and 2 -> 3. Tested. 2016-05-25 02:39:05 +02:00
Dico
cb1a333a56 Merge pull request #41 from RedstonerServer/chatalias
Fixed player subcommand, removed debug outputs
2016-05-25 01:38:10 +02:00
Dico
07039b3d16 Fix command given for next help page in chatalias.py 2016-05-25 01:37:01 +02:00
Pepich
48251e1e52 Cleanup, adding debug outputs back, removing empty try/catch phrases 2016-04-12 14:52:16 +02:00
Pepich
fa1d5e900d Fixed player subcommand, removed debug outputs 2016-04-11 16:59:42 +02:00
jomo
622971c41c Merge pull request #40 from RedstonerServer/tweaks
Fixed indentation error ll 39-41 (damnspam)
2016-04-11 15:35:43 +02:00
Pepich
46f1564af0 Fixed indentation error ll 39-41 2016-04-11 15:18:59 +02:00
Pepich
d81d17b5f2 Merge pull request #39 from psrcek/dev
removed some unnecesary code
2016-03-26 22:08:34 +01:00
psrcek
c870561f7d removed some unnecesary code
The below if statement is always true and the value of timeout_on isn't used before a return statement.
                timeout_on = False
                if timeout_on == False:
2016-03-26 21:56:10 +01:00
Dico200
286f8751b5 Fix tab -.- lol why did it load locally? 2016-03-12 01:02:48 +01:00
Dico200
fad1ae0f90 Fixed a return message in blockplacemods.py 2016-03-12 01:00:07 +01:00
PixelSergey
621f4ca23b Added a debug decorator, use @debug to nicely print function errors 2016-03-08 20:32:56 +02:00
jomo
f2dfc6c473 Merge pull request #37 from RedstonerServer/tweaks
Minor tweaks
2016-02-15 17:48:22 +01:00
BuildTools
0aad531f9e Added more aliases 2016-02-15 17:38:19 +01:00
BuildTools
412ed59225 Added aliases and proper command description 2016-02-15 17:33:14 +01:00
BuildTools
9160c85d09 Added automatic disabling of cgt when leaving a chatgroup 2016-02-15 17:32:50 +01:00
jomo
a98a8a8657 Merge pull request #35 from RedstonerServer/tabnames
Fixed naming error in rank trainingmod
2016-02-15 16:51:55 +01:00
BuildTools
34ed3a1023 Fixed naming error in rank trainingmod 2016-02-15 16:50:21 +01:00
jomo
ddc4a9b457 Merge pull request #34 from RedstonerServer/tabnames
Adding tabnames, updating main
2016-02-15 01:34:56 +01:00
jomo
6a4d1447ec rename tabnames to nametags
I think it's a more descriptive name
2016-02-15 01:27:13 +01:00
jomo
5a0477fdbf clean up tabnames
doesn't throw exceptions when group can't be found, will print warning instead
2016-02-14 23:52:50 +01:00
BuildTools
91afa684cd removed unnessecary imports, code cleanup 2016-02-14 22:33:44 +01:00
BuildTools
70f2001e7b initial commit, adding the tabnames module 2016-02-14 22:25:02 +01:00
BuildTools
f03f34777b Added tabnames module, disabled iptracker due to instability 2016-02-14 22:24:11 +01:00
PixelSergey
799584df46 Unbusies on logout 2016-02-07 13:15:51 +02:00
BuildTools
3a2d1193ca iptracker v1.1.0 updating to helpers v2.0.0 functions; fixing bugs in data management and command execution 2016-01-09 16:43:19 +01:00
BuildTools
cbc77de826 Helpers v2.0.0, added versioning, added array_to_list and get_permission_content, renamed isIP to is_ip 2016-01-09 16:42:26 +01:00
BuildTools
883b02acd5 Initial commit of chatalias.py v2 2016-01-09 16:40:57 +01:00
PanFritz
4cf08dcd6d Merge pull request #30 from psrcek/dev
Fixed capitalization
2015-12-27 00:21:42 +01:00
psrcek
fa81ace66e Fixed capitalization 2015-12-26 23:57:34 +01:00
Dico200
528269afd6 Added comment with permission nodes to blockplacemods 2015-12-09 22:33:48 +01:00
Dico200
2c8bfff01f Add sudo_blacklist to blocked_cmds in serversigns 2015-11-30 02:31:28 +01:00
Dico200
2690da5666 This should keep players from interacting with comparators where they cannot build 2015-11-30 02:19:07 +01:00
Dico200
1969584312 Revert "Merge branch 'wrapper' of https://github.com/RedstonerServer/redstoner-utils into wrapper"
This reverts commit 4d5861fd36, reversing
changes made to 9d0e4c99ba.
2015-11-25 15:49:52 +01:00
Dico200
0172cf2feb Revert "wrapper_command WIP"
This reverts commit 522a7a99a1.
2015-11-25 15:24:34 +01:00
Dico200
522a7a99a1 wrapper_command WIP 2015-11-25 01:15:44 +01:00
Dico200
4d5861fd36 Merge branch 'wrapper' of https://github.com/RedstonerServer/redstoner-utils into wrapper 2015-11-23 23:29:06 +01:00
PanFritz
9d0e4c99ba Removed "ls" in for loop 2015-11-23 01:55:45 +01:00
PixelSergey
e57f721db3 Merge branch 'dev' of https://github.com/RedstonerServer/redstoner-utils into dev 2015-11-22 19:56:55 +02:00
PixelSergey
2808c5838b Fixed a bug in chatalias. Still safe :D 2015-11-22 19:56:11 +02:00
23 changed files with 962 additions and 552 deletions

View File

@@ -11,6 +11,17 @@ import org.bukkit.event.block.Action as Action
import org.bukkit.block.BlockFace as BlockFace import org.bukkit.block.BlockFace as BlockFace
import org.bukkit.scheduler.BukkitRunnable as Runnable import org.bukkit.scheduler.BukkitRunnable as Runnable
"""
# Permissions:
# - utils.toggle: for use of the command
# - utils.toggle.cauldron
# - utils.toggle.slab
# - utils.toggle.furnace
# - utils.toggle.piston
# - utils.toggle.dropper
# - utils.toggle.hopper
"""
settingInformation = dict( #[setting type, identifying description, detailed description, aliases, (optional) max slot id], setting types: 0 = toggle, default on. 1 = Set your setting to held itemstack, 2 = toggle, default off settingInformation = dict( #[setting type, identifying description, detailed description, aliases, (optional) max slot id], setting types: 0 = toggle, default on. 1 = Set your setting to held itemstack, 2 = toggle, default off
cauldron = [0, cauldron = [0,
"easy cauldron water level control", "easy cauldron water level control",
@@ -139,7 +150,8 @@ def toggle_command(sender, command, label, args):
if arg2 == "clear": if arg2 == "clear":
if enabled: if enabled:
del values[uuid] del values[uuid]
return " &aDisabled " + details[1] return " &aDisabled " + details[1]
return " &cAlready disabled: " + details[1]
if arg2 == "details": if arg2 == "details":
return " &aSetting %s:\n &9%s \n&6Accepted arguments: [<slot>|clear|details]" % (setting, details[2]) return " &aSetting %s:\n &9%s \n&6Accepted arguments: [<slot>|clear|details]" % (setting, details[2])

View File

@@ -1,138 +1,352 @@
# Chat Aliasing plugin by Curs3d # ############################################
################################## # Alias v2.0 by Pepich #
# Allows users to alias words, # Changes to previous version from curs3d: #
# so that when they send a # Dynamic alias limit from permissions #
# message in chat, it gets # AC/CG/MSG support #
# replaced by their specified # Color support #
# word. The JSON file for this # Bugfixes #
# plugin is generated if not # #
# present. Set values to -1 # TODO: #
# for "unlimited" setting. # Add command support... #
############################################
import os
import mysqlhack
import org.bukkit as bukkit
from org.bukkit import *
from helpers import * from helpers import *
import re
from traceback import format_exc as trace from traceback import format_exc as trace
from secrets import *
data = None # Version number and requirements
max_entries = 10 alias_version = "2.0.0"
max_alias_length = 35 helpers_versions = ["1.1.0", "2.0.0"]
# Minecraft message limit is 100 so I decided to give a little tolerance (and I added a bit more) enabled = False
max_overall_length = 100 + max_alias_length error = colorify("&cUnspecified error")
commands_per_page = 5
global_aliases = {"./":"/"}
data = {}
# DON'T SET THIS TO TRUE! MySQL requestst are NOT ASYNC yet! (And for some reason it doesn't want to store any data ._.)
use_mysql = False
alias_perm = "utils.alias.allowed" # Permissions:
exceed_length = "utils.alias.exceedlimit"
exceed_entries = "utils.alias.exceedlimit" # Grants full access immediately
exceed_overall_length = "utils.alias.exceedlimit" 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"
########
# CODE #
########
# OnEnable
enabled = helpers_version in helpers_versions
if not enabled:
error = colorify("&6Incompatible versions detected (&chelpers.py&6)")
def safe_open_json(): def safe_open_json(uuid):
global data if not os.path.exists("plugins/redstoner-utils.py.dir/files/aliases"):
if data is not None: os.makedirs("plugins/redstoner-utils.py.dir/files/aliases")
return data value = open_json_file("aliases/" + uuid)
data = open_json_file("aliases") if value is None:
if data is None: value = global_aliases
data = {} save_json_file("aliases/" + uuid, value)
save_json_file("aliases", data) return value
return data
def multiple_replace(aliases, text):
regex = re.compile("|".join(map(re.escape, aliases.keys())))
return regex.sub(lambda mo: aliases[mo.group(0)], text)
@hook.command("alias", @hook.command("alias",
usage="/<command> [to_alias] [alias...]", usage="/<command> <add, remove, list, help> [...]",
desc="Aliases words in chat") desc="Allows aliasing of words")
def on_alias_command(sender, cmd, label, args): def on_alias_command(sender, cmd, label, args):
try:
args = array_to_list(args)
if not enabled:
disabled_fallback(sender)
return True
if not hasPerm(sender, permission_BASE):
plugin_header(recipient=sender, name="Alias")
noperm(sender)
return True
return subcommands[args[0].lower()](sender, args[1:])
except:
return subcommands["help"](sender, "1")
if not is_player(sender):
msg(sender, "Sorry, non-players cannot alias words") def help(sender, args):
return True commands = [colorify("&e/alias help [page]")]
if not sender.hasPermission(alias_perm): if hasPerm(sender, permission_LIST):
plugin_header(recipient=sender, name="Chat Alias") commands += [colorify("&e/alias list &7- Lists all your aliases")]
noperm(sender) if hasPerm(sender, permission_MODIFY):
return True commands += [colorify("&e/alias add <word> <alias> &7- Add an alias")]
if len(args) == 0: commands += [colorify("&e/alias remove <word> &7- Remove an alias")]
plugin_header(recipient=sender, name="Chat Alias") if can_remote(sender):
msg(sender, "&7This is a plugin that allows you to get words" + while len(commands) < commands_per_page:
"replaced by other ones automatically!") commands += [""]
msg(sender, "&7\nCommands:") 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.")]
msg(sender, "&e/alias <word> &7removes <word> from your aliases. " + if hasPerm(sender, permission_LIST_OTHERS):
"Use &e/alias * &7to remove all aliases.") commands += [colorify("&e/alias player <name> list [silent]")]
msg(sender, "&e/alias <word> <replacement> &7will change &e<word> " + if hasPerm(sender, permission_MODIFY_OTHERS):
"&7to &e<replacement> &7in chat") commands += [colorify("&e/alias player <name> add <word> <alias> [silent]")]
msg(sender, "&7\nYour Aliases:") commands += [colorify("&e/alias player <name> remove <word> [silent]")]
data = safe_open_json() pages = (len(commands)-1)/commands_per_page + 1
try: page = 1
for alias, value in data[str(sender.getUniqueId())].items(): if len(args) != 0:
msg(sender, "&7%s &7==> %s" % (alias, value)) page = int(args[0])
except KeyError: if (page > pages):
pass page = pages
return True if page < 1:
elif len(args) == 1: page = 1
data = safe_open_json() msg(sender, colorify("&e---- &6Help &e-- &6Page &c" + str(page) + "&6/&c" + str(pages) + " &e----"))
if args[0] == "*": page -= 1
try: to_display = commands[5*page:5*page+5]
del data[str(sender.getUniqueId())] for message in to_display:
except KeyError: msg(sender, message)
plugin_header(recipient=sender, name="Chat Alias") if page+1 < pages:
msg(sender, "&7No alias data to remove!") msg(sender, colorify("&6To display the next page, type &c/alias help " + str(page+2)))
return True return True
save_json_file("aliases", data)
plugin_header(recipient=sender, name="Chat Alias")
msg(sender, "&cALL &7alias data successfuly removed!") @hook.event("player.PlayerJoinEvent", "high")
return True def on_join(event):
try: if enabled:
if data[str(sender.getUniqueId())].pop(args[0], None) is None: t = threading.Thread(target=load_data, args=(uid(event.getPlayer()), ))
plugin_header(recipient=sender, name="Chat Alias") t.daemon = True
msg(sender, "&7Could not remove: alias not present!") t.start()
return True
except KeyError:
plugin_header(recipient=sender, name="Chat Alias")
msg(sender, "&7Could not remove: you do not have any aliases!")
return True
save_json_file("aliases", data)
plugin_header(recipient=sender, name="Chat Alias")
msg(sender, "&7Alias for %s &7successfuly removed" % args[0])
return True
elif len(args) >= 2:
data = safe_open_json()
alias = " ".join(args[1:])
try:
if (len(alias) > max_alias_length) and (max_alias_length >= 0) and (not sender.hasPermission(exceed_length)):
plugin_header(recipient=sender, name="Chat Alias")
msg(sender, "&7Please do not alias long words/sentences.")
return True
if (len(data[str(sender.getUniqueId())]) >= max_entries) and (max_entries >= 0) and (not sender.hasPermission(exceed_entries)):
plugin_header(recipient=sender, name="Chat Alias")
msg(sender, "&7You have reached your alias limit!")
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, "&7Chat Alias %s &7==> %s &7successfully created!" % (args[0], alias))
return True
else: else:
return False if event.getPlayer().hasPermission(permission_FINFO):
disabled_fallback(event.getPlayer())
@hook.event("player.AsyncPlayerChatEvent", "high") @hook.event("player.AsyncPlayerChatEvent", "high")
def on_player_chat(event): def on_player_chat(event):
playerid = str(event.getPlayer().getUniqueId()) try:
data = safe_open_json() if enabled:
if event.isCancelled(): if event.isCancelled():
return return
if not data[playerid]: if not hasPerm(event.getPlayer(), permission_USE):
return return
event.setMessage(multiple_replace(data[playerid], event.getMessage())) for alias, value in data[str(uid(event.getPlayer()))].items():
if not event.getPlayer().hasPermission(permission_ALL) and len(event.getMessage()) > int(get_permission_content(event.getPlayer(), permission_LENGTH)):
event.setCanceled(True)
plugin_header(event.getPlayer, "Alias")
msg(event.getPlayer(), "The message you wanted to generate would exceed your limit. Please make it shorter!")
return
if event.getPlayer().hasPermission("essentials.chat.color"):
event.setMessage(event.getMessage().replace(colorify(alias), colorify(value)))
else:
event.setMessage(event.getMessage().replace(alias, value))
except:
print(trace())
if (event.getPlayer().hasPermission("essentials.chat.color")):
event.setMessage(colorify(event.getMessage()))
if (max_overall_length >= 0) and (len(event.getMessage()) > max_overall_length) and (not event.getPlayer().hasPermission(exceed_overall_length)):
event.setCancelled(True)
plugin_header(recipient=event.getPlayer(), name="Chat Alias")
msg(event.getPlayer(), "&7The message generated was too long and was not sent. :/")
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(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")
if not sender.hasPermission(permission_ALL) and len(data[uid(sender)]) >= int(get_permission_content(sender, permission_AMOUNT)):
msg(sender, "&cCould not create alias: Max_limit reached!")
return True
args = [args[0]] + [" ".join(args[1:])]
if not add_alias_data(uid(sender), str(args[0]), args[1]):
msg(sender, colorify("&c") + "Could not add an alias for this sequence because a priorly added alias contains it")
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 = get_player(args[0])
if args[3].lower() == "false":
plugin_header(target, "Alias")
msg(target, "&cPlayer " + sender_name + " &cis creating an alias for you!")
if not sender.hasPermission(permission_ALL) and len(data[uid(sender)]) >= int(get_permission_content(target, permission_AMOUNT)):
msg(sender, "&cCould not create alias: Max_limit reached!")
if args[3].lower() == "false":
msg(target, "&cCould not create alias: Max_limit reached!")
return True
if len(args) == 3:
args += ["true"]
if not add_alias_data(uid(target), str(args[1]), str(args[2])):
message = colorify("&c") + "Could not add an alias for this sequence because a priorly added alias contains it"
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 add_alias_data(puuid, aliased, new_alias):
prior = data[puuid]
if aliased not in prior:
for alias in prior.values():
if aliased in 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 (" + str(len(data[uid(target)])) + " in total):")
for word, alias in data[str(uid(target))].items():
msg(sender, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=target.hasPermission("essentials.chat.color"))
if args[1].lower() == "false":
msg(target, colorify("&7") + word + colorify("&7 -> ") + alias, usecolor=target.hasPermission("essentials.chat.color"))
return True
def remote(sender, args):
try:
return remotes[args[1].lower()](sender, [args[0]] + args[2:])
except:
return subcommands["help"](sender, ["2"])
def load_data(uuid):
try:
load_data_thread(uuid)
# t = threading.Thread(target=load_data_thread, args=(uuid))
# t.daemon = True
# t.start()
except:
print(trace())
def load_data_thread(uuid):
if use_mysql:
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("SELECT alias FROM alias WHERE uuid = ?", (uuid, ))
results = curs.fetchall()
if len(results) == 0:
results = global_aliases
curs.execute("INSERT INTO alias VALUES (?,?)", (uuid, results, ))
data[uuid] = results
else:
data[uuid] = safe_open_json(uuid)
def save_data(uuid):
try:
save_data_thread(uuid)
# t = threading.Thread(target=save_data_thread, args=(uuid))
# t.daemon = True
# t.start()
except:
print(trace())
def save_data_thread(uuid):
if use_mysql:
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs = conn.cursor()
curs.execute("UPDATE alias SET alias = ? WHERE uuid = ?", (data[uuid], uuid, ))
else:
save_json_file("aliases/" + uuid, data[uuid])
# Subcommands:
subcommands = {
"help": help,
"add": add,
"remove": remove,
"player": remote,
"list": list_alias
}
remotes = {
"add": radd,
"remove": rremove,
"list": rlist_alias,
}

View File

@@ -21,6 +21,8 @@ def on_chatgroup_command(sender, command, label, args):
if len(args) == 1 and args[0] == "leave": if len(args) == 1 and args[0] == "leave":
if sender_id in groups.keys(): if sender_id in groups.keys():
groupchat(sender, "left the group", True) groupchat(sender, "left the group", True)
if sender in cg_toggle_list:
cg_toggle_list.remove(p)
group = groups[sender_id] group = groups[sender_id]
del(groups[sender_id]) del(groups[sender_id])
save_groups() save_groups()
@@ -87,7 +89,7 @@ def groupchat(sender, message, ann = False):
def do_for_chatgroup(group, func, *args, **kwargs): def do_for_chatgroup(group, func, *args, **kwargs):
for receiver in server.getOnlinePlayers(): for receiver in server.getOnlinePlayers():
if groups.get(uid(receiver)) == group: if groups.get(uid(receiver)) == group:
func(receiver, args, kwargs) func(receiver, *args, **kwargs)
def send_tpa_request(receiver, sender): def send_tpa_request(receiver, sender):
if not receiver == sender: if not receiver == sender:

View File

@@ -36,9 +36,9 @@ def on_dammnspam_command(sender, command, label, args):
msg(sender, "&c/damnspam <seconds after off> <seconds after on> &e(Levers only)") msg(sender, "&c/damnspam <seconds after off> <seconds after on> &e(Levers only)")
return True return True
#Gittestlol #Gittestlol
if not is_creative(sender): if not is_creative(sender):
msg(sender, "&cYou can only do this in Creative mode.") msg(sender, "&cYou can only do this in Creative mode.")
return True return True
# /damnspam <secs> # /damnspam <secs>
if len(args) == 1: if len(args) == 1:
@@ -47,8 +47,6 @@ def on_dammnspam_command(sender, command, label, args):
timeout_on = round(float(timeout_on), 2) timeout_on = round(float(timeout_on), 2)
timeout_off = timeout_on timeout_off = timeout_on
if 60 >= timeout_on <= -2 or timeout_on == 0: if 60 >= timeout_on <= -2 or timeout_on == 0:
timeout_on = False
if timeout_on == False:
msg(sender, "&cThe timeout must be within 0-60 or -1.") msg(sender, "&cThe timeout must be within 0-60 or -1.")
return True return True
except ValueError: except ValueError:

View File

@@ -5,6 +5,10 @@ friends = open_json_file("friends", {}) # {Player_UUID:[List_of_friend
friend_join_sound = "random.orb" friend_join_sound = "random.orb"
def is_friend_of(player, other):
lst = friends.get(uid(player))
return lst is not None and uid(other) in lst
@hook.event("player.PlayerJoinEvent", "high") # creates sound and sends a bold message on friend join @hook.event("player.PlayerJoinEvent", "high") # creates sound and sends a bold message on friend join
def fjm(event): # friend join message def fjm(event): # friend join message

108
helpers.py Normal file → Executable file
View File

@@ -1,32 +1,28 @@
#pylint: disable = F0401 #pylint: disable = F0401
import org.bukkit as bukkit
import org.bukkit.block as bblock
import org.bukkit.Location as Location
import org.bukkit.event.entity as entity
import org.bukkit.entity.Player as Player
import org.bukkit.command.ConsoleCommandSender
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause as TeleportCause
from re import sub from re import sub
from thread_utils import *
from player import py_players
from org.bukkit.entity import *
from player import get_py_player
from traceback import format_exc as trace
from java.util.UUID import fromString as juuid from java.util.UUID import fromString as juuid
from json import dumps as json_dumps, loads as json_loads from json import dumps as json_dumps, loads as json_loads
import org.bukkit as bukkit
import org.bukkit.Location as Location
import org.bukkit.entity.Player as Player
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause as TeleportCause
import org.bukkit.event.block.BlockBreakEvent as BlockBreakEvent
import org.bukkit.block as bblock
import org.bukkit.event.entity as entity
import org.bukkit.command.ConsoleCommandSender
from org.bukkit.entity import *
from player import get_py_player
from player import py_players
#Imports for async query #Imports for async query
import threading
import mysqlhack
from secrets import * from secrets import *
import mysqlhack
from com.ziclix.python.sql import zxJDBC from com.ziclix.python.sql import zxJDBC
import threading
from traceback import format_exc as trace
helpers_version = "2.0.0"
shared = {} # this dict can be used to share stuff across modules shared = {} # this dict can be used to share stuff across modules
server = bukkit.Bukkit.getServer() server = bukkit.Bukkit.getServer()
@@ -91,7 +87,7 @@ def colorify(text):
""" """
replace &-codes with real color codes replace &-codes with real color codes
""" """
return sub("&" + u"\u00A7", "&", "%s" % sub("&(?=[?\\da-fk-or])", u"\u00A7", "%s" % text)) return sub("&(?=[?\\da-fk-or])", u"\u00A7", "%s" % text)
def stripcolors(text): def stripcolors(text):
@@ -185,16 +181,6 @@ def is_creative(player):
return str(player.getGameMode()) == "CREATIVE" return str(player.getGameMode()) == "CREATIVE"
def is_rank(player, rank):
"""
rank: a string equal to the PEX group name found in /pex groups
returns True if one of the following conditions are met:
- the player is of the given rank,
- their rank inherits the given rank.
"""
return player.hasPermission("groups." + rank)
def uid(player): def uid(player):
""" """
returns the player's UUID returns the player's UUID
@@ -218,6 +204,31 @@ def known_player(player):
""" """
return player.hasPlayedBefore() return player.hasPlayedBefore()
"""
Runs a async query, calls target function with fetchall as an argument, it will be an empty list if there is nothing to fetch.
(So make sure your function takes that argument.)
If you want your function to run sync in the case you are doing something spigot wouldn't like to be async use the bukkit scheduler.
Example can be found in loginsecurity.py
"""
def async_query(mysql_database,query,query_args,target,*target_args,**target_kwargs):
def async_query_t(mysql_database,query,query_args,target,target_args,target_kwargs):
db_conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
db_curs = db_conn.cursor()
db_curs.execute(query,query_args)
db_conn.commit()
fetchall = db_curs.fetchall()
db_curs.close()
db_conn.close()
target(fetchall,target_args,target_kwargs)
t = threading.Thread(target=async_query_t,args=(mysql_database,query,query_args,target,target_args,target_kwargs))
t.daemon = True
t.start()
def open_json_file(filename, default = None): def open_json_file(filename, default = None):
""" """
opens the given json file and returns an object or returns None on error opens the given json file and returns an object or returns None on error
@@ -260,7 +271,8 @@ def send_JSON_message(playername, message):
bukkit.Bukkit.getServer().dispatchCommand(bukkit.Bukkit.getServer().getConsoleSender(), "tellraw " + playername + " " + message) bukkit.Bukkit.getServer().dispatchCommand(bukkit.Bukkit.getServer().getConsoleSender(), "tellraw " + playername + " " + message)
def isIP(tocheck): # Allows to check if a String is a valid IPv4 or not. Accepts any string, returns true if the String is a valid IPv4
def is_ip(tocheck):
subsets = ["","","",""] subsets = ["","","",""]
i = 0 i = 0
for j in range(0,len(tocheck)): for j in range(0,len(tocheck)):
@@ -278,3 +290,37 @@ def isIP(tocheck):
if not ((int(subsets[j]) >= 0) & (int(subsets[j]) <= 255)): if not ((int(subsets[j]) >= 0) & (int(subsets[j]) <= 255)):
return False return False
return True return True
# Allows the use of e.g. numeric permission nodes like "permission.amount.5" and similar.
# To get the data fetch the player and the start of the permission node, looking like "permission.amount."
def get_permission_content(player, permnode):
perms = player.getEffectivePermissions()
for perm in perms:
if str(perm.getPermission()).startswith(permnode):
return str(perm.getPermission()).replace(permnode, "")
# Gets an online player from their name
def get_player(name):
for p in bukkit.Bukkit.getServer().getOnlinePlayers():
if p.getName().lower() == name.lower():
return p
return None
def array_to_list(array):
return_list = []
for a in array:
return_list += [a]
return return_list
#debug wrapper
def debug(func):
def wrap(*args, **kwargs):
try:
func(*args, **kwargs)
except:
print(trace())
return wrap

359
imbusy.py
View File

@@ -1,107 +1,308 @@
# I'M BUSY! Plugin by Curs3d # ##################################
############################## # I'M BUSY! Plugin by Curs3d #
# Concept by CookieManors :D # # Concept by CookieManors :D #
# http://bit.ly/1GnNPW8 # ##################################
############################## # This plugin permits users to #
# This plugin permits users to # send a command that renders #
# send a command that renders # them "busy", not letting them #
# them "busy", not letting them # to get tpa requests or direct #
# to get tpa requests or direct # messages, except from console. #
# messages, except from console. # On restart, all busy data will #
# On restart, all busy data will # be cleared. #
# be cleared. ##################################
from helpers import * from helpers import *
from basecommands import simplecommand from friends import is_friend_of
from traceback import format_exc as trace import org.bukkit.command.Command as Command
busy_players = []
imbusy_version = "v1.1.0"
base_permission = "utils.busy" # for /busy status
use_permission = "utils.busy.use" # for being busy
override_permission = "utils.busy.override" # for being able to bother busy people
def unclear(): busy_players = {} # name : false/true where false is normal busy and true is super busy
msg(sender, "Umm, what? Sorry, directions unlclear, got head stuck in washing machine")
@hook.command("busy", @hook.command("imbusy",
aliases = ["focus"], aliases = ["busy"],
usage = "/<command> <on|off|status>", usage = "/<command> [on, off, status/check]",
description = "Sets busy mode on, you cannot recieve tpas and MSGs" description = "Offers control over your busy status"
) )
def on_busy_command(sender, cmd, label, args): def on_busy_command(sender, cmd, label, args):
if not is_player(sender): if not is_player(sender):
msg(sender, "Sorry, Console cannot be busy") msg(sender, "&7Sorry, Console cannot be busy")
return True return True
if not sender.hasPermission("utils.busy.allowed"): plugin_header(recipient = sender, name = "I'M BUSY!")
plugin_header(recipient = sender, name = "I'M BUSY!")
#args = array_to_list(args)
if not sender.hasPermission(base_permission):
noperm(sender) noperm(sender)
return True return True
if len(args) == 0: if len(args) == 0:
plugin_header(recipient = sender, name = "I'M BUSY!") return toggle(sender)
msg(sender, "This plugin allows being busy, and when turned on you will not recieve any direct messages or tpa requests.")
msg(sender, "\nCommands:") arg0 = args[0].lower()
msg(sender, "/busy on: turns on busy mode") if arg0 == "on":
msg(sender, "/busy off: turns off busy mode") return on(sender)
msg(sender, "/busy status [player]: shows your or [player]'s current busy status.") if arg0 == "off":
return off(sender)
if arg0 in ("status", "check"):
return status(sender, args[1:])
if arg0 == "super":
return super_cmd(sender)
return help(sender)
def toggle(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True return True
sender_name = sender.getName()
if sender_name in busy_players:
del busy_players[sender_name]
broadcast(None, sender.getDisplayName() + " &7is no longer busy...")
else:
busy_players.append(sender_name)
broadcast(None, sender.getDisplayName() + " &7is now busy...")
return True
elif len(args) == 1:
if args[0] == "on":
if sender.getName() in busy_players:
plugin_header(recipient = sender, name = "I'M BUSY!")
msg(sender, "You cannot be even more focused than this without being a jedi!")
return True
busy_players.append(sender.getName())
plugin_header(recipient = sender, name = "I'M BUSY!")
broadcast(None, "%s is now SUPER busy! Don't even TRY bothering them, it will not work!" % sender.getName())
return True
elif args[0] == "off": def help(sender):
plugin_header(recipient = sender, name = "I'M BUSY!") msg(sender, "Let's you put yourself in busy status, preventing pms and tpa requests from other players")
try: msg(sender, "\n&eCommands:")
busy_players.remove(sender.getName()) msg(sender, "&e/busy &7- Toggles busy status")
msg(sender, "Master has sent /busy command, %s is freeee!" % sender.getName()) msg(sender, "&e/busy on &7- Turns on busy status")
return True msg(sender, "&e/busy off &7- Turns off busy status")
except ValueError: msg(sender, "&e/busy status [player] &7- shows your or [player]'s current busy status")
msg(sender, "You are not busy! You cannot be even less busy! Are you perhaps bored?") msg(sender, "&e/busy super &7- sets your status to SUPER busy such that even friends can not bother you")
return True return True
elif args[0] == "status":
plugin_header(recipient = sender, name = "I'M BUSY!") def on(sender):
if sender.getName() in busy_players: if not sender.hasPermission(use_permission):
msg(sender, "You are super-duper busy and concentrated right now. Think, think, think!") noperm(sender)
return True return True
sender_name = sender.getName()
if busy_players.get(sender_name) is False: # can be None, False or True
msg(sender, "&7You are already busy!")
else:
busy_players[sender_name] = False # busy but not super busy
broadcast(None, sender.getDisplayName() + " &7is now busy...")
return True
def off(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
sender_name = sender.getName()
if sender_name not in busy_players:
msg(sender, "&7You are not busy! You cannot be even less busy! Are you perhaps bored?")
return True
del busy_players[sender_name]
broadcast(None, sender.getDisplayName() + " &7is no longer busy...")
return True
def status(sender, args):
if not sender.hasPermission(base_permission):
noperm(sender)
return True
if len(args) == 0:
if sender.getName() in busy_players:
if busy_players[sender_name] is False:
msg(sender, "&7You are currently busy.")
else: else:
msg(sender, "You are completely unable to focus right now.") msg(sender, "&7You are currently SUPER busy.")
return True
else: else:
plugin_header(recipient = sender, name = "I'M BUSY!") msg(sender, "&7You are currently not busy.")
unclear() else:
target = server.getPlayer(args[0])
if target is None:
msg(sender, "&7That player is not online")
elif target.getName() in busy_players:
if busy_players[target.getName()] is False:
msg(sender, "&7Player %s &7is currently busy." % target.getDisplayName())
else:
msg(sender, "&7Player %s &7is currently SUPER busy." % target.getDisplayName())
else:
msg(sender, "&7Player %s &7is currently not busy." % target.getDisplayName())
return True
def super_cmd(sender):
if not sender.hasPermission(use_permission):
noperm(sender)
return True
sender_name = sender.getName()
if busy_players.get(sender_name) is True:
msg(sender, "&7You are already SUPER busy!")
else:
busy_players[sender_name] = True # SUPER busy
broadcast(None, sender.getDisplayName() + " &7is now SUPER busy...")
return True
@hook.event("player.PlayerQuitEvent", "lowest")
def on_player_leave(event):
player_name = event.getPlayer().getName()
if player_name in busy_players:
del busy_players[player_name]
#---- Dicode for catching any bothering of busy people ----
reply_targets = {}
def can_send(sender, target):
if not target.getName() in busy_players:
return True
if target is sender or sender.hasPermission(override_permission):
return True
return busy_players[target.getName()] is False and is_friend_of(target, sender)
def whisper(sender, target_name):
target = server.getPlayer(target_name)
if target is not None:
if not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False return False
elif len(args) == 2 and args[0] == "status": reply_targets[sender.getName()] = target.getName()
plugin_header(recipient = sender, name = "I'M BUSY!")
if args[1] in busy_players:
msg(sender, "Yes, %s is busy. Shhh..." % args[1])
return True
else:
msg(sender, "No, you're good. Feel free to chat with %s!" % args[1])
return True
else: # allow the target to reply regardless of sender being busy
plugin_header(recipient = sender, name = "I'M BUSY!") if target.getName() in reply_targets:
unclear() del reply_targets[target.getName()]
return True
def reply(sender):
if sender.getName() in reply_targets:
target = server.getPlayer(reply_targets[sender.getName()])
if target is not None:
if not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
# allow the target to reply regardless of sender being busy
if target.getName() in reply_targets:
del reply_targets[target.getName()]
return True
class CommandWrapper(Command):
def __init__(self, wrapped, checker):
Command.__init__(self, wrapped.getName())
self.setDescription(wrapped.getDescription())
self.setPermission(wrapped.getPermission())
self.setUsage(wrapped.getUsage())
self.setAliases(wrapped.getAliases())
self.wrapped = wrapped
self.checker = checker
def execute(self, sender, label, args):
try:
if not is_player(sender) or self.checker(sender, args):
return self.wrapped.execute(sender, label, args)
except:
error(trace())
return True
def tabComplete(self, sender, alias, args):
return self.wrapped.tabComplete(sender, alias, args)
def msg_command_checker(sender, args):
return len(args) <= 1 or whisper(sender, args[0])
def reply_command_checker(sender, args):
return len(args) == 0 or reply(sender)
def tpa_command_checker(sender, args):
if len(args) == 0:
return True
target = server.getPlayer(args[0])
if target is not None and not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False return False
return True
def tpahere_command_checker(sender, args):
return tpa_command_checker(sender, args)
def mail_command_checker(sender, args):
info("Mail command executed")
if len(args) < 3 or args[0].lower() != "send":
return True
target = server.getPlayer(args[1])
if target is not None and not can_send(sender, target):
msg(sender, "&c[&fBUSY&c] %s&r is busy!" % target.getDisplayName())
return False
return True
@hook.event("player.PlayerCommandPreprocessEvent", "monitor") @hook.event("player.PlayerCommandPreprocessEvent", "monitor")
def on_cmd_preprocess_event(event): def on_player_command_preprocess(event):
message = event.getMessage().split(" ") message = event.getMessage().split(" ")
if message[0] == "/msg" or message[0] == "/w" or message[0] == "/m" or \ if len(message) > 1 and message[0].lower() in ("/tell", "/minecraft:tell") and not whisper(event.getPlayer(), message[1]):
message[0] == "/tell" or message[0] == "/tpa" or message[0] == "/tpahere": event.setCancelled(True)
if message[1] in busy_players:
plugin_header(recipient = event.getPlayer(), name = "I'M BUSY!")
msg(event.getPlayer(), "We are sorry, but %s is currently busy. Please try again later." % message[1]) @hook.enable
event.setCancelled(True) def replace_ess_commands():
try:
map_field = server.getPluginManager().getClass().getDeclaredField("commandMap")
map_field.setAccessible(True)
command_map = map_field.get(server.getPluginManager())
commands_field = command_map.getClass().getDeclaredField("knownCommands")
commands_field.setAccessible(True)
map = commands_field.get(command_map)
ess_msg_cmd = map.get("essentials:msg")
ess_reply_cmd = map.get("essentials:reply")
ess_tpa_cmd = map.get("essentials:tpa")
ess_tpahere_cmd = map.get("essentials:tpahere")
ess_mail_cmd = map.get("essentials:mail")
msg_cmd_wrapper = CommandWrapper(ess_msg_cmd, msg_command_checker)
reply_cmd_wrapper = CommandWrapper(ess_reply_cmd, reply_command_checker)
tpa_cmd_wrapper = CommandWrapper(ess_tpa_cmd, tpa_command_checker)
tpahere_cmd_wrapper = CommandWrapper(ess_tpahere_cmd, tpahere_command_checker)
mail_cmd_wrapper = CommandWrapper(ess_mail_cmd, mail_command_checker)
iterator = map.entrySet().iterator()
wrapped_commands = []
while iterator.hasNext():
entry = iterator.next()
value = entry.getValue()
changed = True
if value is ess_msg_cmd:
entry.setValue(msg_cmd_wrapper)
elif value is ess_reply_cmd:
entry.setValue(reply_cmd_wrapper)
elif value is ess_tpa_cmd:
entry.setValue(tpa_cmd_wrapper)
elif value is ess_tpahere_cmd:
entry.setValue(tpahere_cmd_wrapper)
elif value is ess_mail_cmd:
entry.setValue(mail_cmd_wrapper)
else:
changed = False
if changed:
wrapped_commands.append(entry.getKey())
info("[imbusy] wrapped commands: /" + ", /".join(wrapped_commands))
except:
error("[Imbusy] Failed to wrap essentials commands")
error(trace())

215
iptracker.py Normal file → Executable file
View File

@@ -1,107 +1,108 @@
import mysqlhack import mysqlhack
import org.bukkit as bukkit import org.bukkit as bukkit
import json import json
from java.util import UUID as UUID from java.util import UUID as UUID
from helpers import * from helpers import *
from org.bukkit import * from org.bukkit import *
from traceback import format_exc as trace from traceback import format_exc as trace
from iptracker_secrets import * from iptracker_secrets import *
iptrack_permission = "utils.iptrack" iptrack_permission = "utils.iptrack"
iptrack_version = "1.1.0"
@hook.event("player.PlayerJoinEvent", "low")
def on_player_join(event): @hook.event("player.PlayerJoinEvent", "low")
t = threading.Thread(target=on_player_join_thread, args=(event, )) def on_player_join(event):
t.daemon = True t = threading.Thread(target=on_player_join_thread, args=(event, ))
t.start() t.daemon = True
t.start()
def on_player_join_thread(event):
player = event.getPlayer() def on_player_join_thread(event):
ip = player.getAddress().getHostString() player = event.getPlayer()
uuid = uid(player) ip = player.getAddress().getHostString()
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver") uuid = uid(player)
curs = conn.cursor() conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid, )) curs = conn.cursor()
results = curs.fetchall() curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid, ))
if len(results) == 0: results = curs.fetchall()
ips = [] if len(results) == 0:
else: ips = []
ips = json.loads(results[0][0]) else:
curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (ip, )) ips = json.loads(results[0][0])
results = curs.fetchall() curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (ip, ))
if len(results) == 0: results = curs.fetchall()
uuids = [] if len(results) == 0:
else: uuids = []
uuids = json.loads(results[0][0]) else:
new_ip_entry = (len(ips) == 0) uuids = json.loads(results[0][0])
new_uuid_entry = (len(uuids) == 0) new_ip_entry = (len(ips) == 0)
if ip not in ips: new_uuid_entry = (len(uuids) == 0)
ips.append(ip) if ip not in ips:
if new_ip_entry: ips.append(ip)
curs.execute("INSERT INTO uuid2ips VALUES (?,?)", (uuid, json.dumps(ips), )) if new_ip_entry:
else: curs.execute("INSERT INTO uuid2ips VALUES (?,?)", (uuid, json.dumps(ips), ))
curs.execute("UPDATE uuid2ips SET ips = ? WHERE uuid = ?", (uuid, json.dumps(ips), )) else:
if uuid not in uuids: curs.execute("UPDATE uuid2ips SET ips = ? WHERE uuid = ?", (json.dumps(ips), uuid, ))
uuids.append(uuid) if uuid not in uuids:
if new_uuid_entry: uuids.append(uuid)
curs.execute("INSERT INTO ip2uuids VALUES (?,?)", (ip, json.dumps(uuids), )) if new_uuid_entry:
else: curs.execute("INSERT INTO ip2uuids VALUES (?,?)", (ip, json.dumps(uuids), ))
curs.execute("UPDATE ip2uuids SET uuids = ? WHERE uuid = ?", (ip, json.dumps(uuids), )) else:
conn.commit() curs.execute("UPDATE ip2uuids SET uuids = ? WHERE ip = ?", (json.dumps(uuids), ip, ))
curs.close() conn.commit()
conn.close() curs.close()
conn.close()
@hook.command("getinfo")
def on_getinfo_command(sender, args): @hook.command("getinfo")
t = threading.Thread(target=on_player_join_thread, args=(sender, args)) def on_getinfo_command(sender, args):
t.daemon = True t = threading.Thread(target=on_getinfo_command_thread, args=(sender, args))
t.start() t.daemon = True
t.start()
def on_getinfo_command_thread(sender, args):
if(sender.hasPermission(iptrack_permission)): def on_getinfo_command_thread(sender, args):
if not checkargs(sender, args, 1, 1): if(sender.hasPermission(iptrack_permission)):
return False if not checkargs(sender, args, 1, 1):
else: return False
if isIP(args[0]): else:
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver") if is_ip(args[0]):
curs = conn.cursor() conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (args[0], )) curs = conn.cursor()
results = curs.fetchall() curs.execute("SELECT uuids FROM ip2uuids WHERE ip = ?", (args[0], ))
curs.close() results = curs.fetchall()
conn.close() curs.close()
if len(results) == 0: conn.close()
msg(sender, "IP " + args[0] + " is not registered in the database, maybe you got a number wrong?") if len(results) == 0:
else: msg(sender, "IP " + args[0] + " is not registered in the database, maybe you got a number wrong?")
uuids = json.loads(results[0][0]) else:
msg(sender, "IP " + args[0] + " was seen with " + str(len(uuids)) + " different Accounts:") uuids = json.loads(results[0][0])
for i in range(0, len(uuids)): msg(sender, "IP " + args[0] + " was seen with " + str(len(uuids)) + " different Accounts:")
p=Bukkit.getOfflinePlayer(UUID.fromString(uuids[i])) for i in range(0, len(uuids)):
if is_player(sender): p=Bukkit.getOfflinePlayer(UUID.fromString(uuids[i]))
send_JSON_message(sender.getName(), '["",{"text":"' + p.getName() + ' - (uuid: ' + uuids[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + p.getName() + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for ' + p.getName() + ' in the database, simply click the name!","color":"gold"}]}}}]') if is_player(sender):
else: send_JSON_message(sender.getName(), '["",{"text":"' + p.getName() + ' - (uuid: ' + uuids[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + p.getName() + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for ' + p.getName() + ' in the database, simply click the name!","color":"gold"}]}}}]')
msg(sender,p.getName() + " - (uuid: " + uuids[i] + ")") else:
else: msg(sender,p.getName() + " - (uuid: " + uuids[i] + ")")
target = Bukkit.getOfflinePlayer(args[0]) else:
uuid = target.getUniqueId() target = Bukkit.getOfflinePlayer(args[0])
conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver") uuid = target.getUniqueId()
curs = conn.cursor() conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid.toString(), )) curs = conn.cursor()
results = curs.fetchall() curs.execute("SELECT ips FROM uuid2ips WHERE uuid = ?", (uuid.toString(), ))
curs.close() results = curs.fetchall()
conn.close() curs.close()
if len(results) == 0: conn.close()
msg(sender, "Player " + args[0] + " is not registered in the database, maybe you misspelled the name?") if len(results) == 0:
else: msg(sender, "Player " + args[0] + " is not registered in the database, maybe you misspelled the name?")
ips = json.loads(results[0][0]) else:
msg(sender, "Player " + args[0] + " was seen with " + str(len(ips)) + " different IPs:") ips = json.loads(results[0][0])
for i in range(0, len(ips)): msg(sender, "Player " + args[0] + " was seen with " + str(len(ips)) + " different IPs:")
if is_player(sender): for i in range(0, len(ips)):
send_JSON_message(sender.getName(), '["",{"text":"' + ips[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + ips[i] + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for the IP ' + ips[i] + ' in the database, simply click the IP!","color":"gold"}]}}}]') if is_player(sender):
else: send_JSON_message(sender.getName(), '["",{"text":"' + ips[i] + '","color":"gold","clickEvent":{"action":"run_command","value":"/getinfo ' + ips[i] + '"},"hoverEvent":{"action":"show_text","value":{"text":"","extra":[{"text":"To search for the IP ' + ips[i] + ' in the database, simply click the IP!","color":"gold"}]}}}]')
msg(sender,ips[i]) else:
else: msg(sender,ips[i])
noperm(sender) else:
return True noperm(sender)
return True

View File

@@ -8,7 +8,7 @@ import mysqlhack
from com.ziclix.python.sql import zxJDBC from com.ziclix.python.sql import zxJDBC
from java.lang import Runnable from java.lang import Runnable
wait_time = 60 #seconds wait_time = 30 #seconds
admin_perm = "utils.loginsecurity.admin" admin_perm = "utils.loginsecurity.admin"
min_pass_length = 8 min_pass_length = 8
blocked_events = ["block.BlockBreakEvent", "block.BlockPlaceEvent", "player.PlayerMoveEvent","player.AsyncPlayerChatEvent"] blocked_events = ["block.BlockBreakEvent", "block.BlockPlaceEvent", "player.PlayerMoveEvent","player.AsyncPlayerChatEvent"]
@@ -272,4 +272,4 @@ def pre_command_proccess(event):
args = event.getMessage().split(" ") args = event.getMessage().split(" ")
if not args[0].lower() == "/login": if not args[0].lower() == "/login":
msg(player.player, "&4You need to login before you do that!") msg(player.player, "&4You need to login before you do that!")
event.setCancelled(True) event.setCancelled(True)

85
main.py
View File

@@ -11,9 +11,8 @@ sys.path += ['', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/l
try: try:
# Library that adds a bunch of re-usable methods which are used in nearly all other modules # Library that adds a bunch of re-usable methods which are used in nearly all other modules
from helpers import * from helpers import *
from wrapper import *
except: except:
print("[RedstonerUtils] ERROR: Failed to import Wrapper:") print("[RedstonerUtils] ERROR: Failed to import helpers:")
print(print_traceback()) print(print_traceback())
@@ -25,17 +24,89 @@ def on_enable():
@hook.disable @hook.disable
def on_disable(): def on_disable():
#shared["modules"]["reports"].stop_reporting() shared["modules"]["reports"].stop_reporting()
info("RedstonerUtils disabled!") info("RedstonerUtils disabled!")
info("Loading RedstonerUtils...") info("Loading RedstonerUtils...")
# Import all modules, in this order # Import all modules, in this order
shared["load_modules"] = ["test"] shared["load_modules"] = [
# Collection of tiny utilities
"misc",
# Adds chat for staff using /ac <text or ,<text>
"adminchat",
# Adds /badge, allows to give players achievements
"badges",
# Adds a few block placement corrections/mods
"blockplacemods",
# Adds /calc, toggles automatic solving of Math expressions in chat
"calc",
# Adds aliasing of chat words
"chatalias",
# For players to point friends
"friends",
# Plugin to locate laggy chunks. /lc <n> lists chunks with more than n entities
"lagchunks",
# Adds /report and /rp, Stores reports with time and location
"reports",
# Adds group-chat with /chatgroup and /cgt to toggle normal chat into group mode
"chatgroups",
# Adds /token, reads and writes from the database to generate pronouncable (and thus memorable) registration-tokens for the website
"webtoken",
# Adds /lol, broadcasts random funyy messages. A bit like the splash text in the menu
"saylol",
# Adds /signalstrength, lets you request a signal strength and an amount of items will be inserted into target container to meet that strength.
"signalstrength",
# Shows the owner of a skull when right-clicked
"skullclick",
# Adds /listen, highlights chat and plays a sound when your name was mentioned
"mentio",
# Adds /cycler, swaps the hotbar with inventory when player changes slot from right->left or left->right
"cycle",
# Adds /getmotd & /setmotd to update the motd on the fly (no reboot)
"motd",
# AnswerBot. Hides stupid questions from chat and tells the sender about /faq or the like
"abot",
# Adds '/forcefield', creates forcefield for players who want it.
"forcefield",
# Adds /damnspam, creates timeout for buttons/levers to mitigate button spam.
"damnspam",
# Adds /check, useful to lookup details about a player
"check",
# Adds /an, a command you can use to share thoughts/plans/news
"adminnotes",
# Adds busy status to players
"imbusy",
# Adds /imout, displays fake leave/join messages
"imout",
#adds snowbrawl minigame
"snowbrawl",
# Adds /tm [player] for a messages to be sent to this player via /msg
"pmtoggle",
# Replacement for LoginSecurity
"loginsecurity",
# Centralized Player class
"player",
# Servercontrol extension for telnet access to logs/AC
#"servercontrol",
# Script helper plugin
"scriptutils",
# Per-player notes
"tag",
# vanish toggle module - temporary fix
#"vanishfix",
# obisidian mining punishment plugin
"punishments",
# a simple replacement for the buggy essentials /vanish
"vanish",
# ip-tracking utility - disabled as of instability
#"iptracker",
#server signs for everyone
"serversigns",
# Makes player's names colored, sorts tab list by rank
"nametags"
]
shared["modules"] = {} shared["modules"] = {}
for module in shared["load_modules"]: for module in shared["load_modules"]:
try: try:

13
misc.py
View File

@@ -114,9 +114,20 @@ def rs_material_broken_by_flow(material):
length = len(parts) length = len(parts)
return length > 1 and (parts[0] == "DIODE" or parts[1] in ("TORCH", "WIRE", "BUTTON", "HOOK") or (length == 3 and parts[1] == "COMPARATOR")) return length > 1 and (parts[0] == "DIODE" or parts[1] in ("TORCH", "WIRE", "BUTTON", "HOOK") or (length == 3 and parts[1] == "COMPARATOR"))
@hook.event("player.PlayerInteractEvent")
def on_interact(event):
if (not event.isCancelled()
and str(event.getAction()) == "RIGHT_CLICK_BLOCK"
and str(event.getMaterial()) in ("REDSTONE_COMPARATOR_OFF", "REDSTONE_COMPARATOR_ON")
and not can_build(player, event.getClickedBlock())
):
event.setCancelled(True)
sudo_blacklist = ["pyeval", "script_backup_begin", "script_backup_end", "script_backup_error", "script_backup_database_begin", "script_backup_database_dumps", "script_backup_database_end", sudo_blacklist = ["pyeval", "script_backup_begin", "script_backup_end", "script_backup_error", "script_backup_database_begin", "script_backup_database_dumps", "script_backup_database_end",
"script_backup_database_error", "script_backup_database_abort", "script_trim", "script_trim_result", "script_spigot_update", "script_disk_filled", "script_restart", "script_restart_abort", "script_backup_database_error", "script_backup_database_abort", "script_trim", "script_trim_result", "script_spigot_update", "script_disk_filled", "script_restart", "script_restart_abort",
"script_stop", "script_stop_abort", "script_shutdown", "stop", "esudo", "essentials:sudo"] "script_stop", "script_stop_abort", "script_shutdown", "stop", "esudo", "essentials:sudo", "sudo"]
@simplecommand("sudo", @simplecommand("sudo",
usage = "<player> [cmd..]", usage = "<player> [cmd..]",

View File

@@ -1,33 +0,0 @@
import mysqlhack
from secrets import *
from thread_utils import *
from com.ziclix.python.sql import zxJDBC
from traceback import format_exc as trace
class mysql_connect:
def __init__(self):
self.conn = zxJDBC.connect(mysql_database, mysql_user, mysql_pass, "com.mysql.jdbc.Driver")
self.curs = self.conn.cursor()
def execute(self, query, args=None):
if args is None:
return self.curs.execute(query)
else:
return self.curs.execute(query, args)
def fetchall(self):
return self.curs.fetchall()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_inst, exc_tb):
if exc_type is None:
try:
self.conn.commit()
self.curs.close()
self.conn.close()
except:
print(trace())
else:
print(exc_tb)

View File

@@ -4,12 +4,12 @@ A library that makes use of the so called ClassPathHack for jython
to allow proper loading of mysql-connector.jar at runtime. to allow proper loading of mysql-connector.jar at runtime.
Import only, no methods. Import only, no methods.
""" """
import jarray
import java.net.URL
import java.io.File
from java.lang import Class
import java.net.URLClassLoader
import java.lang.reflect.Method import java.lang.reflect.Method
import java.io.File
import java.net.URL
import java.net.URLClassLoader
import jarray
from java.lang import Class
# hacky code to add mysql-connector to java's classpath ('classPathHack') # hacky code to add mysql-connector to java's classpath ('classPathHack')

37
nametags.py Executable file
View File

@@ -0,0 +1,37 @@
from helpers import *
##############################################################
# #
# This module automatically puts people in the corresponding #
# scoreboard team so that their name is colored properly and #
# tab will be nicely sorted. #
# #
##############################################################
ranks = ["visitor", "member", "builder", "trusted", "trainingmod", "mod", "admin"]
# prefixes are used for sorting in the tab list
prefixes = {"admin":"a", "mod":"b", "trainingmod":"c", "trusted":"d", "builder":"e", "member":"f","visitor":"g"}
@hook.event("player.PlayerJoinEvent", "low")
def on_player_join(event):
player = event.getPlayer()
team = get_team(player)
if team:
cmd = "scoreboard teams join %s %s" % (team, player.getName())
server.dispatchCommand(server.getConsoleSender(), cmd)
def get_rank(player):
player_rank = None
for rank in ranks:
if not player.hasPermission("group.%s" % rank):
break
player_rank = rank
if not player_rank:
warn("Couldn't find rank for player %s" % player.getName())
return player_rank
def get_team(player):
rank = get_rank(player)
if rank:
prefix = prefixes.get(rank)
return "_".join([prefix, rank])

View File

@@ -2,4 +2,3 @@ name: RedstonerUtils
main: main.py main: main.py
version: 3.1.0 version: 3.1.0
author: redstone_sheep author: redstone_sheep

View File

@@ -5,7 +5,11 @@ from java.util.UUID import fromString as juuid
toggle_dict = {} toggle_dict = {}
permission = "utils.pmtoggle" permission = "utils.pmtoggle"
@hook.command("tm") @hook.command("pmtoggle",
aliases = ["tm", "mt", "tmsg", "msgt", "pmt", "tpm"],
usage = "/<command> [player]",
description = "Toggle automatic sending of messages"
)
def on_toggle_message_command(sender, command, label, args): def on_toggle_message_command(sender, command, label, args):
if not sender.hasPermission(permission) or not is_player(sender): if not sender.hasPermission(permission) or not is_player(sender):
noperm(sender) noperm(sender)

View File

@@ -5,7 +5,7 @@ import java.util.UUID as UUID
import org.bukkit.Material as Material import org.bukkit.Material as Material
import org.bukkit.block.BlockFace as BlockFace import org.bukkit.block.BlockFace as BlockFace
blocked_cmds = ("pex", "kick", "ban", "tempban", "pyeval", "sudo", "stop", "reload", "op", "deop", "whitelist") blocked_cmds = tuple(shared["modules"]["misc"].sudo_blacklist) + ("pex", "kick", "ban", "tempban", "reload", "op", "deop", "whitelist")
def load_signs(): def load_signs():
signs_obj = open_json_file("serversigns", []) signs_obj = open_json_file("serversigns", [])

View File

@@ -25,7 +25,7 @@ mkdir -v "build"
cd "build" cd "build"
echo -e "\n> Downloading Spigot build tools" echo -e "\n> Downloading Spigot build tools"
curl --progress-bar -Lo "buildtools.jar" "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" curl --progress-bar -Lo "BuildTools.jar" "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar"
echo -e "\n> Building Spigot, this will take a while ..." echo -e "\n> Building Spigot, this will take a while ..."
java -jar BuildTools.jar > /dev/null java -jar BuildTools.jar > /dev/null
@@ -91,7 +91,7 @@ echo -e "\n> All plugins downloaded"
cd "redstoner-utils.py.dir" cd "redstoner-utils.py.dir"
echo -e "\n> Duplicating sample files" echo -e "\n> Duplicating sample files"
for file in ls ./*.example; do for file in ./*.example; do
cp -v "$file" "$(echo "$file" | rev | cut -d "." -f 2- | rev)" cp -v "$file" "$(echo "$file" | rev | cut -d "." -f 2- | rev)"
done done

View File

@@ -1,24 +0,0 @@
import threading
"""
Quick implementation of a @synchronized and @asynchronized decorators
"""
#To be replaced by bukkit scheduler.
"""
def sync(lock=None):
def decorator(wrapped):
def wrapper(*args, **kwargs):
with lock:
return wrapped(*args, **kwargs)
return wrapper
return decorator
"""
def async(daemon = True):
def decorator(function):
def wrapper(*args,**kwargs):
thread = threading.Thread(target=function,args=args,kwargs=kwargs)
thread.daemon = daemon
thread.start()
return wrapper
return decorator

View File

@@ -1,11 +0,0 @@
"""
Adapter classes for spigot api for more idiomatic python code.
Before you run away from this if the class you need to use isn't here, please create it.
"""
from helpers import *
from wrapper_event import *
from wrapper_player import *
from wrapper_command import *

View File

@@ -1,11 +0,0 @@
from wrapper_player import *
def command(command = "help"):
def decorator(wrapped):
@hook.command(command)
def wrapper(sender, command, label, args):
try:
return wrapped(sender = py_players[sender], command = command, label = label, args = args)
except:
print(print_traceback())
return decorator

View File

@@ -1,22 +0,0 @@
from wrapper import *
from wrapper_player import *
from traceback import format_exc as print_traceback
class py_event:
def __init__(self,event):
self.event = event
try:
self.player = py_players[event.getPlayer()]
except:
warn("Player doesn't exist")
def event_handler(event_name = None, priority = "normal"):
def decorator(wrapped):
@hook.event(event_name, priority)
def wrapper(event):
try:
wrapped(py_event(event))
except:
print(print_traceback())
return decorator

View File

@@ -1,89 +0,0 @@
import time
import mysqlhack
from mysql_utils import *
from thread_utils import *
from players_secret import *
from datetime import datetime
from com.ziclix.python.sql import zxJDBC
class py_player:
def __init__(self,player):
self.player = player
self.login_time = time.time()
self.logging_in = False
self.nickname = self.name
self.registered = False
self.password = "None"
self.banned = False
self.banned_reason = "You have been banned!"
self.played_time = time.time() - self.login_time
self.last_login = datetime.now()
self.first_seen = datetime.now()
def kick(self, kick_message = "You have been kicked from the server!"):
self.player.KickPlayer(kick_message)
@property
def name(self):
return self.player.getName()
@property
def uuid(self):
return str(self.player.getUniqueId())
class Py_players:
def __init__(self):
self.players = []
def __len__(self):
return len(self.players)
def __getitem__(self, player):
for py_player in self.players:
if py_player.name == player.getName():
return py_player
else:
return None
def remove(self, player):
self.players.remove(player)
def append(self, player):
self.players.append(player)
py_players = Py_players()
@async(daemon=True)
def fetch_player(player):
with mysql_connect() as sql:
sql.execute("SELECT * FROM utils_players WHERE uuid = ?", (player.uuid,))
result = sql.fetchall()
if len(result) is 0:
with mysql_connect() as sql:
sql.execute("INSERT INTO utils_players \
(uuid, name, nickname, registered, password, banned, \
banned_reason, played_time, last_login, first_seen) \
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
args=(player.uuid, player.name, player.nickname, player.registered,
player.password, player.banned,
player.banned_reason, player.played_time,
player.last_login, player.first_seen))
else:
pass
#test
@hook.event("player.PlayerJoinEvent","lowest")
def on_join(event):
player = py_player(event.getPlayer())
py_players.append(player)
fetch_player(player)
@hook.event("player.PlayerQuitEvent","highest")
def on_leave(event):
py_players.remove(py_players[event.getPlayer()])