Gestion dans une classe à part des multi commands
This commit is contained in:
parent
2e94f6c703
commit
a9e1e0fc6b
@ -23,7 +23,7 @@ ___________________
|
|||||||
## badwords.txt
|
## badwords.txt
|
||||||
Ce fichier est au format texte. Chaque ligne est une expression régulière correspondant à un élément censuré.
|
Ce fichier est au format texte. Chaque ligne est une expression régulière correspondant à un élément censuré.
|
||||||
|
|
||||||
Les lignes vides seront ignorés (ou ne contenant que des caractères non imprimable). Lescaractères non imprimables en début et fin de ligne sont conservés
|
Les lignes vides seront ignorés (ou ne contenant que des caractères non imprimable). Les caractères non imprimables en début et fin de ligne sont conservés.
|
||||||
|
|
||||||
___________________
|
___________________
|
||||||
|
|
||||||
@ -48,3 +48,23 @@ La structure d'un fichier se présente comme ce qui suit.
|
|||||||
En première ligne, on a la commande d'origine (celle tapée par le joueur) avec le `/` devant.
|
En première ligne, on a la commande d'origine (celle tapée par le joueur) avec le `/` devant.
|
||||||
La deuxième ligne est la commande de remplacement, toujours avec le `/` devant.
|
La deuxième ligne est la commande de remplacement, toujours avec le `/` devant.
|
||||||
La troisième ligne correspond aux permissions associés à cet alias, séparé par des `;`. Le joueur doit avoir au moins une de ces permissions pour que l'alias s'applique. Si l'alias s'applique à tous les joueurs, on peut utiliser `*`.
|
La troisième ligne correspond aux permissions associés à cet alias, séparé par des `;`. Le joueur doit avoir au moins une de ces permissions pour que l'alias s'applique. Si l'alias s'applique à tous les joueurs, on peut utiliser `*`.
|
||||||
|
|
||||||
|
___________________
|
||||||
|
|
||||||
|
## multicommands
|
||||||
|
Chaque multicommand se trouve dans un fichier se trouvant dans le sous-dossier.
|
||||||
|
le nom du fichier correspond au nom de la commande `muco`, suivi de l'extension `.txt`. Par exemple, pour `/muco site`, le fichier correspondant sera `site.txt`.
|
||||||
|
|
||||||
|
Dans le fichier, chaque ligne correspond à une commande exécutée par la sous-commande `muco`.
|
||||||
|
Une ligne aura cette forme :
|
||||||
|
|
||||||
|
T C A /CMD ...
|
||||||
|
|
||||||
|
- `T` : temps en tick, depuis l'exécution de la commande /muco
|
||||||
|
- `C` : "C" si doit être exécuté en tant que la console, autre chose sinon
|
||||||
|
- `A` : "A" si la commande peut être exécuté en mode asynchrone, autre chose, sinon
|
||||||
|
- `/CMD ...` correspond à la commande, avec le / devant. Peut contenir $1, $2, ... comme des paramètres
|
||||||
|
|
||||||
|
(T, C et A ne peuvent pas contenir d'espace)
|
||||||
|
|
||||||
|
Les lignes vides et les lignes dont le premier caractère est un `#` seront ignorés. Les caractères non imprimables en début et fin de ligne sont conservés
|
||||||
|
@ -2,10 +2,11 @@ package net.mc_pandacraft.java.plugin.pandacraftutils.commands;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.config.ConfigManager;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.config.ConfigManager;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.config.elements.MultiCommandConfigEntry;
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.config.elements.MultiCommandConfigEntry.MucoSubCommand;
|
||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayer;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayer;
|
||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayerManager;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.players.OnlinePlayerManager;
|
||||||
|
|
||||||
@ -30,12 +31,13 @@ public class CommandMuco extends AbstractCommandExecutor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, List<String>> lists = ConfigManager.getInstance().MultiCommand_config;
|
|
||||||
|
|
||||||
|
|
||||||
String list_name = args[0].toLowerCase();
|
String list_name = args[0].toLowerCase();
|
||||||
|
|
||||||
if (!lists.containsKey(list_name)) {
|
MultiCommandConfigEntry list = ConfigManager.getInstance().multiCommandConfig.getEntry(list_name);
|
||||||
|
|
||||||
|
if (list == null) {
|
||||||
sender.sendMessage(ChatColor.RED+"La sous commande '"+list_name+"' n'existe pas");
|
sender.sendMessage(ChatColor.RED+"La sous commande '"+list_name+"' n'existe pas");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -46,18 +48,17 @@ public class CommandMuco extends AbstractCommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// gestion des paramètres $1 $2 ...
|
||||||
List<String> params = new ArrayList<String>();
|
List<String> params = new ArrayList<String>();
|
||||||
|
|
||||||
|
|
||||||
for (int i=1; i<args.length; i++) {
|
for (int i=1; i<args.length; i++) {
|
||||||
params.add(args[i]);
|
params.add(args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
List<String> list = lists.get(list_name);
|
|
||||||
|
|
||||||
for (String line : list) {
|
|
||||||
|
for (MucoSubCommand line : list.getSubCommands()) {
|
||||||
executeListedCommand(sender, line, params);
|
executeListedCommand(sender, line, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ public class CommandMuco extends AbstractCommandExecutor {
|
|||||||
|
|
||||||
|
|
||||||
private List<String> getMucoLists(OnlinePlayer permittedPlayer) {
|
private List<String> getMucoLists(OnlinePlayer permittedPlayer) {
|
||||||
Set<String> list_names = ConfigManager.getInstance().MultiCommand_config.keySet();
|
Set<String> list_names = ConfigManager.getInstance().multiCommandConfig.getList();
|
||||||
|
|
||||||
List<String> retList = new ArrayList<String>();
|
List<String> retList = new ArrayList<String>();
|
||||||
|
|
||||||
@ -119,38 +120,17 @@ public class CommandMuco extends AbstractCommandExecutor {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void executeListedCommand(CommandSender sender, String line, List<String> params) {
|
private void executeListedCommand(CommandSender sender, MucoSubCommand subCommand, List<String> params) {
|
||||||
String[] args = line.split(" ", 4);
|
|
||||||
|
|
||||||
if (args.length != 4) {
|
|
||||||
plugin.getLogger().warning("/muco : bad format for "+ChatColor.ITALIC+line);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long time;
|
String cmd = subCommand.command;
|
||||||
|
|
||||||
try {
|
|
||||||
time = Integer.parseInt(args[0]);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
plugin.getLogger().warning("/muco : bad format for "+ChatColor.ITALIC+line);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean console = args[1].equalsIgnoreCase("c");
|
|
||||||
boolean async = args[2].equalsIgnoreCase("a");
|
|
||||||
|
|
||||||
if (!args[3].startsWith("/")) {
|
|
||||||
plugin.getLogger().warning("/muco : bad format for "+ChatColor.ITALIC+line);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String cmd = args[3].substring(1);
|
|
||||||
|
|
||||||
for (int i=0; i<params.size(); i++) {
|
for (int i=0; i<params.size(); i++) {
|
||||||
cmd = cmd.replaceAll("\\$"+(i+1), params.get(i));
|
cmd = cmd.replaceAll("\\$"+(i+1), params.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
sender = console ? plugin.getServer().getConsoleSender() : sender;
|
sender = subCommand.console ? plugin.getServer().getConsoleSender() : sender;
|
||||||
|
|
||||||
BukkitScheduler scheduler = plugin.getServer().getScheduler();
|
BukkitScheduler scheduler = plugin.getServer().getScheduler();
|
||||||
|
|
||||||
@ -168,10 +148,10 @@ public class CommandMuco extends AbstractCommandExecutor {
|
|||||||
}.init(sender, cmd);
|
}.init(sender, cmd);
|
||||||
|
|
||||||
|
|
||||||
if (async)
|
if (subCommand.async)
|
||||||
scheduler.runTaskLaterAsynchronously(plugin, executor, time);
|
scheduler.runTaskLaterAsynchronously(plugin, executor, subCommand.tick);
|
||||||
else
|
else
|
||||||
scheduler.runTaskLater(plugin, executor, time);
|
scheduler.runTaskLater(plugin, executor, subCommand.tick);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
package net.mc_pandacraft.java.plugin.pandacraftutils.config;
|
package net.mc_pandacraft.java.plugin.pandacraftutils.config;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils;
|
import net.mc_pandacraft.java.plugin.pandacraftutils.PandacraftUtils;
|
||||||
|
|
||||||
@ -83,6 +80,7 @@ public class ConfigManager {
|
|||||||
public final ChatBadWordsConfig chatBadWordsConfig;
|
public final ChatBadWordsConfig chatBadWordsConfig;
|
||||||
public final AutoMessagesConfig autoMessagesConfig;
|
public final AutoMessagesConfig autoMessagesConfig;
|
||||||
public final CommandAliasConfig commandAliasConfig;
|
public final CommandAliasConfig commandAliasConfig;
|
||||||
|
public final MultiCommandConfig multiCommandConfig;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -100,136 +98,13 @@ public class ConfigManager {
|
|||||||
chatBadWordsConfig = new ChatBadWordsConfig();
|
chatBadWordsConfig = new ChatBadWordsConfig();
|
||||||
autoMessagesConfig = new AutoMessagesConfig();
|
autoMessagesConfig = new AutoMessagesConfig();
|
||||||
commandAliasConfig = new CommandAliasConfig();
|
commandAliasConfig = new CommandAliasConfig();
|
||||||
|
multiCommandConfig = new MultiCommandConfig();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// dossier qui doit contenir les séries de commandes
|
|
||||||
File multiCommandsDir = new File(configDir, "multicommands");
|
|
||||||
multiCommandsDir.mkdir();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
initMultiCommand();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Multicommand
|
|
||||||
*/
|
|
||||||
|
|
||||||
public Map<String, List<String>> MultiCommand_config;
|
|
||||||
|
|
||||||
|
|
||||||
private void initMultiCommand() {
|
|
||||||
/*
|
|
||||||
* Format d'un String dans l'ArrayList :
|
|
||||||
* T C A /CMD ...
|
|
||||||
* - T : temps en tick, depuis l'exécution de la commande /muco
|
|
||||||
* - C : "C" si doit être exécuté en tant que la console, autre chose sinon
|
|
||||||
* - A : "A" si la commande peut être exécuté en mode asynchrone, autre chose, sinon
|
|
||||||
* (T, C et A ne peuvent pas contenir d'espace)
|
|
||||||
* /CMD ... correspond à la commande, avec le / devant. Peut contenir $1, $2, ... comme des paramètres
|
|
||||||
*/
|
|
||||||
|
|
||||||
MultiCommand_config = new HashMap<String, List<String>>();
|
|
||||||
|
|
||||||
List<String> list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /pex user $1 remove $2");
|
|
||||||
list.add("1 - - /pex user $1 add $3");
|
|
||||||
list.add("1 - - /m $1 La mise à jour de votre grade est terminé :) !");
|
|
||||||
MultiCommand_config.put("gradejoueur", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /region select arenespleef_niv1");
|
|
||||||
list.add("1 - - //replace 0 87");
|
|
||||||
list.add("2 - - /region select arenespleef_niv2");
|
|
||||||
list.add("3 - - //replace 0 87");
|
|
||||||
list.add("4 - - /region select arenespleef_niv3");
|
|
||||||
list.add("5 - - //replace 0 87");
|
|
||||||
list.add("6 - - /region select arenespleef_niv4");
|
|
||||||
list.add("7 - - //replace 0 87");
|
|
||||||
list.add("8 - - /region select arenespleef_niv5");
|
|
||||||
list.add("9 - - //replace 0 87");
|
|
||||||
list.add("10 - - /region select arenespleef_niv6");
|
|
||||||
list.add("11 - - //replace 0 87");
|
|
||||||
list.add("12 - - /region select arenespleef_niv7");
|
|
||||||
list.add("13 - - //replace 0 87");
|
|
||||||
list.add("14 - - /region select arenespleef_niv8");
|
|
||||||
list.add("15 - - //replace 0 87");
|
|
||||||
MultiCommand_config.put("arenespleef_reparer", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /pex user $1 group add premium");
|
|
||||||
list.add("0 - - /m $1 Vous venez de passer Premium :)");
|
|
||||||
MultiCommand_config.put("addpremium", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /pex user $1 group remove premium");
|
|
||||||
MultiCommand_config.put("delpremium", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /pex user $1 group add ultimate");
|
|
||||||
list.add("0 - - /m $1 Vous venez de recevoir le grade Ultimate, félicitation :)");
|
|
||||||
MultiCommand_config.put("addultimate", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /pex user $1 group remove ultimate");
|
|
||||||
list.add("0 - - /mail send $1 Vous venez de perdre votre grade Ultimate et tous ses avantages car la durée est écoulée.");
|
|
||||||
list.add("1 - - /mail send $1 Si vous voulez encore en profiter, rendez vous sur http://mc-pandacraft.net/?p=ultimate");
|
|
||||||
MultiCommand_config.put("delultimate", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /region select arenepvp_solarene");
|
|
||||||
list.add("1 - - //replace 11 20");
|
|
||||||
MultiCommand_config.put("arenepvp_proteger_lave", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /region select arenepvp_solarene");
|
|
||||||
list.add("1 - - //replace 20 11");
|
|
||||||
MultiCommand_config.put("arenepvp_remettre_lave", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /region select arenepvp_toit");
|
|
||||||
list.add("1 - - //replace 20 98");
|
|
||||||
MultiCommand_config.put("arenepvp_fermer_fenetre", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /region select arenepvp_toit");
|
|
||||||
list.add("1 - - //replace 98 20");
|
|
||||||
MultiCommand_config.put("arenepvp_ouvrir_fenetre", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 C - /broadcast &7Site Web :&a https://www.mc-pandacraft.net/");
|
|
||||||
MultiCommand_config.put("site", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 C - /broadcast &7Devenir &f[&bMembre&f]&7 :&a http://mc-pandacraft.net/?id=12");
|
|
||||||
MultiCommand_config.put("sitemembre", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 C - /broadcast Grade &f[&eUltimate&f]&7 :&a http://mc-pandacraft.net/?p=ultimate");
|
|
||||||
MultiCommand_config.put("siteultimate", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /mv regen Survival_the_end");
|
|
||||||
list.add("1 - - /mvconfirm");
|
|
||||||
MultiCommand_config.put("new_ender", list);
|
|
||||||
|
|
||||||
list = new ArrayList<String>();
|
|
||||||
list.add("0 - - /mv regen Survival_nether");
|
|
||||||
list.add("1 - - /mvconfirm");
|
|
||||||
list.add("600 - - /mv regen Faction_nether");
|
|
||||||
list.add("601 - - /mvconfirm");
|
|
||||||
MultiCommand_config.put("new_nether", list);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.config;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.mc_pandacraft.java.plugin.pandacraftutils.config.elements.MultiCommandConfigEntry;
|
||||||
|
|
||||||
|
public class MultiCommandConfig extends AbstractConfig {
|
||||||
|
|
||||||
|
private final Map<String, MultiCommandConfigEntry> config;
|
||||||
|
|
||||||
|
public MultiCommandConfig() throws Exception {
|
||||||
|
super("multicommands", FileType.DIR);
|
||||||
|
|
||||||
|
List<File> files = getFileList();
|
||||||
|
|
||||||
|
config = new HashMap<String, MultiCommandConfigEntry>();
|
||||||
|
|
||||||
|
for (File f : files) {
|
||||||
|
|
||||||
|
String name = f.getName().split("\\.")[0];
|
||||||
|
|
||||||
|
if (name == null || name.trim().equals(""))
|
||||||
|
{
|
||||||
|
warning("nom de fichier '"+f.getName()+"' invalide");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> lines = getFileLines(true, true, false, f);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
config.put(name, new MultiCommandConfigEntry(name, lines));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getList() {
|
||||||
|
return Collections.unmodifiableSet(config.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiCommandConfigEntry getEntry(String name) {
|
||||||
|
return config.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package net.mc_pandacraft.java.plugin.pandacraftutils.config.elements;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
|
||||||
|
public class MultiCommandConfigEntry {
|
||||||
|
private final String name;
|
||||||
|
private final List<MucoSubCommand> subCommands;
|
||||||
|
|
||||||
|
|
||||||
|
public MultiCommandConfigEntry(String n, List<String> subCommandsString) throws Exception {
|
||||||
|
|
||||||
|
if (n == null || n.trim().equals("") || subCommandsString == null || subCommandsString.size() == 0)
|
||||||
|
throw new IllegalArgumentException("Un des paramètres du constructeur est invalide");
|
||||||
|
|
||||||
|
name = n;
|
||||||
|
|
||||||
|
subCommands = new ArrayList<MucoSubCommand>();
|
||||||
|
|
||||||
|
for (String subCmd : subCommandsString) {
|
||||||
|
|
||||||
|
String[] args = subCmd.split(" ", 4);
|
||||||
|
|
||||||
|
|
||||||
|
if (args.length != 4)
|
||||||
|
throw new Exception("/muco : bad format for "+ChatColor.ITALIC+subCmd);
|
||||||
|
|
||||||
|
long time;
|
||||||
|
|
||||||
|
try {
|
||||||
|
time = Integer.parseInt(args[0]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new Exception("/muco : bad format for "+ChatColor.ITALIC+subCmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean console = args[1].equalsIgnoreCase("c");
|
||||||
|
boolean async = args[2].equalsIgnoreCase("a");
|
||||||
|
|
||||||
|
if (!args[3].startsWith("/"))
|
||||||
|
throw new Exception("/muco : bad format for "+ChatColor.ITALIC+subCmd);
|
||||||
|
|
||||||
|
String cmd = args[3].substring(1);
|
||||||
|
|
||||||
|
subCommands.add(new MucoSubCommand(time, console, async, cmd));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getName() { return name; }
|
||||||
|
|
||||||
|
public List<MucoSubCommand> getSubCommands() {
|
||||||
|
return Collections.unmodifiableList(subCommands);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class MucoSubCommand {
|
||||||
|
|
||||||
|
public final long tick;
|
||||||
|
public final boolean console;
|
||||||
|
public final boolean async;
|
||||||
|
public final String command;
|
||||||
|
|
||||||
|
|
||||||
|
private MucoSubCommand(long t, boolean c, boolean a, String cmd) {
|
||||||
|
if (t < 0 || cmd == null)
|
||||||
|
throw new IllegalArgumentException("Un des paramètres du constructeur est invalide");
|
||||||
|
|
||||||
|
tick = t;
|
||||||
|
console = c;
|
||||||
|
async = a;
|
||||||
|
command = cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user