Mise à jour du bot à une version de JDA plus récente, et ajout de commentaires
This commit is contained in:
parent
c456837148
commit
6721dd4f6d
37
build.gradle
37
build.gradle
@ -13,11 +13,13 @@ apply plugin: 'java'
|
||||
|
||||
compileJava.options.encoding = 'UTF-8'
|
||||
|
||||
// In this section you declare where to find the dependencies of your project
|
||||
repositories {
|
||||
// Use jcenter for resolving your dependencies.
|
||||
// You can declare any Maven/Ivy/file repository here.
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
|
||||
maven {
|
||||
name 'm2-dv8tion'
|
||||
url 'https://m2.dv8tion.net/releases'
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@ -31,7 +33,7 @@ sourceSets {
|
||||
}
|
||||
|
||||
task apiJar(type: Jar) {
|
||||
archiveName = "JuliabotAPI.jar"
|
||||
archiveFileName = "JuliabotAPI.jar"
|
||||
group 'build'
|
||||
description "Fait un jar avec juste l'api"
|
||||
from(sourceSets.main.output) {
|
||||
@ -40,7 +42,7 @@ task apiJar(type: Jar) {
|
||||
}
|
||||
|
||||
task internalddonJar(type: Jar) {
|
||||
archiveName = "JuliabotInternaddon_beta.jar"
|
||||
archiveFileName = "JuliabotInternaddon_beta.jar"
|
||||
group 'build'
|
||||
description "Fait un jar avec juste l'addon interne"
|
||||
from(sourceSets.main.output) {
|
||||
@ -51,36 +53,29 @@ task internalddonJar(type: Jar) {
|
||||
task execute(type:JavaExec) {
|
||||
group 'execution'
|
||||
description "Compile et execute le fichier jar"
|
||||
main = 'com.bernard.juliabot.Julia'
|
||||
mainClass = 'com.bernard.juliabot.Julia'
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
}
|
||||
|
||||
task copyDependencies(type: Copy) {
|
||||
group 'build'
|
||||
from configurations.compile
|
||||
from configurations.default
|
||||
into 'dependencies'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// This dependency is exported to consumers, that is to say found on their compile classpath.
|
||||
api 'org.apache.commons:commons-math3:3.6.1'
|
||||
|
||||
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
|
||||
implementation 'com.google.guava:guava:23.0'
|
||||
implementation 'org.slf4j:slf4j-nop:1.7.25'
|
||||
|
||||
// Use JUnit test framework
|
||||
testImplementation 'junit:junit:4.12'
|
||||
implementation 'net.dv8tion:JDA:4.4.0_352'
|
||||
|
||||
compile 'org.slf4j:slf4j-nop:1.7.25'
|
||||
implementation 'com.thedeanda:lorem:2.1'
|
||||
|
||||
compile 'net.dv8tion:JDA:4.2.0_189'
|
||||
implementation 'commons-io:commons-io:2.6'
|
||||
|
||||
compile 'com.thedeanda:lorem:2.1'
|
||||
implementation group: 'org.postgresql', name: 'postgresql', version: '42.2.22'
|
||||
|
||||
compile 'commons-io:commons-io:2.6'
|
||||
|
||||
// https://mvnrepository.com/artifact/mysql/mysql-connector-java
|
||||
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.21'
|
||||
implementation 'com.github.mpkorstanje:simmetrics-core:4.1.1'
|
||||
|
||||
}
|
||||
|
||||
|
||||
89
src/main/java/com/bernard/juliabot/AppelACommande.java
Normal file
89
src/main/java/com/bernard/juliabot/AppelACommande.java
Normal file
@ -0,0 +1,89 @@
|
||||
package com.bernard.juliabot;
|
||||
|
||||
import static com.bernard.juliabot.api.Julia.erreur;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.bernard.juliabot.api.CCommande;
|
||||
|
||||
/**
|
||||
* Objet utilitaire représentant l'appel à une commande, qui suivera l'execution de la
|
||||
* commande et permet de les gérer dans des threads séparés.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public class AppelACommande {
|
||||
|
||||
Method called;
|
||||
CCommande argument;
|
||||
String name;
|
||||
String cname;
|
||||
Object caller;
|
||||
Thread commandThread;
|
||||
Throwable exitValue = null;
|
||||
volatile boolean running;
|
||||
volatile boolean started;
|
||||
|
||||
/**
|
||||
* Crée l'objet en spécifiant simplement ses paramètres.
|
||||
* @param called La méthode qu'il faut appeler pour executer la commande.
|
||||
* @param argument L'argument à cette méthode, «comment» la commande doit être lancée.
|
||||
* @param name Le nom de la commande tel qu'il a été demandé.
|
||||
* @param cname Le nom de la commande l'identifiant, sans alias.
|
||||
* @param caller L'objet sur lequel doit être invoquée la commande.
|
||||
*/
|
||||
public AppelACommande(Method called, CCommande argument, String name, String cname, Object caller) {
|
||||
this.called = called;
|
||||
this.argument = argument;
|
||||
this.name = name;
|
||||
this.cname = cname;
|
||||
this.caller = caller;
|
||||
this.running = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Définit le therad d'appel de la fonction.
|
||||
*/
|
||||
public void setThread(Thread commandThread) {
|
||||
this.commandThread = commandThread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit la valeur de retour du programme (un Throwable en java)
|
||||
* @param t
|
||||
*/
|
||||
public void setExitValue(Throwable t) {
|
||||
this.exitValue = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* impose la terminaison de l'execution de la commande.
|
||||
*/
|
||||
public void termine() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teste si la commande est en cours de résolution
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met le thread courant en pause jusqu'à ce que la commande soit résolue.
|
||||
*/
|
||||
public void waitFin() {
|
||||
while(running) {
|
||||
try {
|
||||
Thread.sleep(42);
|
||||
} catch (InterruptedException e) {
|
||||
erreur("On s'est fait intérrompre !",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
package com.bernard.juliabot;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.bernard.juliabot.api.CCommande;
|
||||
|
||||
public class CommandCalled {
|
||||
|
||||
Method called;
|
||||
CCommande argument;
|
||||
String name;
|
||||
String cname;
|
||||
Object caller;
|
||||
Thread commandThread;
|
||||
Throwable exitValue = null;
|
||||
volatile boolean running;
|
||||
volatile boolean started;
|
||||
|
||||
public CommandCalled(Method called, CCommande argument, String name, String cname, Object caller) {
|
||||
this.called = called;
|
||||
this.argument = argument;
|
||||
this.name = name;
|
||||
this.cname = cname;
|
||||
this.caller = caller;
|
||||
this.running = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setThread(Thread commandThread) {
|
||||
this.commandThread = commandThread;
|
||||
}
|
||||
|
||||
public void setExitValue(Throwable t) {
|
||||
this.exitValue = t;
|
||||
}
|
||||
|
||||
public void ended() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public void waitForExecution() {
|
||||
while(running) {
|
||||
try {
|
||||
Thread.sleep(42);
|
||||
} catch (InterruptedException e) {
|
||||
System.err.println("Icapacité de pauser le thread : ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -6,25 +6,25 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.bernard.juliabot.api.CCommande;
|
||||
import com.bernard.juliabot.api.Command;
|
||||
import com.bernard.juliabot.api.Commande;
|
||||
|
||||
//TODO la javadoc
|
||||
public class CommandeSurchargee {
|
||||
|
||||
String name;
|
||||
Command command;
|
||||
String nom;
|
||||
Commande commande;
|
||||
|
||||
Map<Set<Class<?>>,Method> versions = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
public CommandeSurchargee(Command c) {
|
||||
this.name = c.name();
|
||||
this.command = c;
|
||||
public CommandeSurchargee(Commande c) {
|
||||
this.nom = c.name();
|
||||
this.commande = c;
|
||||
}
|
||||
|
||||
public Method getExecutor(CCommande commande) {
|
||||
public Method getExecuteur(CCommande commande) {
|
||||
Set<Class<?>> critargs = checkFiliature(Stream.of(commande.getClass()).collect(Collectors.toSet()));
|
||||
System.out.println("////////"+critargs);
|
||||
return versions.get(versions.keySet().stream().filter(cr -> critargs.containsAll(cr)).findAny().orElse(null));
|
||||
}
|
||||
|
||||
@ -77,11 +77,15 @@ public class CommandeSurchargee {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CommandeSurchargee [name=" + name + ", versions=" + versions + "]";
|
||||
return "CommandeSurchargee [name=" + nom + ", versions=" + versions + "]";
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return command.description();
|
||||
return commande.description();
|
||||
}
|
||||
|
||||
public Commande getCommande() {
|
||||
return commande;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
||||
package com.bernard.juliabot;
|
||||
|
||||
import static com.bernard.juliabot.api.Julia.erreur;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -16,38 +18,88 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.bernard.juliabot.Julia.Laboratory;
|
||||
import com.bernard.juliabot.api.Command;
|
||||
import com.bernard.juliabot.api.Discord;
|
||||
import com.bernard.juliabot.api.JuLIAddon;
|
||||
import com.bernard.juliabot.Julia.Laboratoire;
|
||||
import com.bernard.juliabot.api.Commande;
|
||||
import com.bernard.juliabot.api.EventDiscord;
|
||||
import com.bernard.juliabot.api.Juliaddon;
|
||||
|
||||
/**
|
||||
* Un objet de cette classe représente un juliaddon, hors contexte de chargement.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public class JuliaAddon {
|
||||
|
||||
/**
|
||||
* Un pattern qui permettre d'extraire le paquet dans lequel est un fichier .class
|
||||
*/
|
||||
private static final Pattern pkgFromClassName = Pattern.compile("^(\\w+(\\.\\w+){2,})\\.\\w+(\\$\\w+)*$");
|
||||
/*
|
||||
* Un pattern permettant d'extraire la version d'un juliaddon d'un fichier.
|
||||
*/
|
||||
private static final Pattern jarNameParser = Pattern.compile("^([^_]+)_([^_]+)(_(.+))?.jar$");
|
||||
|
||||
|
||||
/**
|
||||
* Le pkg de l'addon.
|
||||
*/
|
||||
String pkg;
|
||||
/**
|
||||
* La version de l'addon.
|
||||
*/
|
||||
String version;
|
||||
|
||||
JarFile jarFile;
|
||||
long lastModified;
|
||||
Set<JarEntry> loaderEntries;
|
||||
/**
|
||||
* Le fichier jar duquel a été chargé cet addon
|
||||
*/
|
||||
JarFile fichierJar;
|
||||
/**
|
||||
* Le timestamp de dernière modification du fichier jar au chargement de l'addon, afin de pouvoir tester
|
||||
* plus rapidement si il est à jour avec le fichier jar associé.
|
||||
*/
|
||||
long derniereModif;
|
||||
/**
|
||||
* Liste des entrées du fichier jar à contenant l'addon, trèèèèès utile dans le cas d'un jar avec plusieurs addons.
|
||||
*/
|
||||
Set<JarEntry> entreesDuLoader;
|
||||
|
||||
Map<Character,JuliaClassLoader> classLoaders;
|
||||
JuliaClassLoader unassignedClassLoader = null;
|
||||
/**
|
||||
* Liste les classloaders associés à chaque laboratoire dans lequel est chargé cet addon.
|
||||
*/
|
||||
Map<Laboratoire,JuliaClassLoader> classLoaders;
|
||||
/**
|
||||
* Un classloader non assigné, qui est créé afin de récupérer des informations sur l'addon à sa création, et qui
|
||||
* peut être réutilisé pour un laboratoire.
|
||||
*/
|
||||
JuliaClassLoader classLoaderNonAssigne = null;
|
||||
|
||||
JuLIAddon addon;
|
||||
/**
|
||||
* L'annotation à l'origine de l'addon.
|
||||
*/
|
||||
Juliaddon addon;
|
||||
/**
|
||||
* La classe de cet annotation.
|
||||
*/
|
||||
Class<?> addonClass;
|
||||
|
||||
public JuliaAddon(JarFile jar) throws JarWithMultipleAddonsException {
|
||||
/**
|
||||
* Crée un addon à partir de toutes les entrées d'un fichier jar.
|
||||
* @param jar Le fichier jar à lire.
|
||||
* @throws JarAuxMultiplesAddonsException Si plusieurs addons sont présents dans le fichier jar.
|
||||
*/
|
||||
public JuliaAddon(JarFile jar) throws JarAuxMultiplesAddonsException {
|
||||
this(jar,jar.stream().collect(Collectors.toSet()));
|
||||
}
|
||||
|
||||
public JuliaAddon(JarFile jar,Set<JarEntry> entriesToRead) throws JarWithMultipleAddonsException {
|
||||
jarFile = jar;
|
||||
loaderEntries = entriesToRead;
|
||||
lastModified = new File(jar.getName()).lastModified();
|
||||
/**
|
||||
* Crée un addon à partir des entrées jar spécifiées.
|
||||
* @param jar Le fichier à lire.
|
||||
* @param entreesALire Les entrées à lire.
|
||||
* @throws JarAuxMultiplesAddonsException Si plusieurs addons sont dans ces entrées.
|
||||
*/
|
||||
public JuliaAddon(JarFile jar,Set<JarEntry> entreesALire) throws JarAuxMultiplesAddonsException {
|
||||
fichierJar = jar;
|
||||
entreesDuLoader = entreesALire;
|
||||
derniereModif = new File(jar.getName()).lastModified();
|
||||
classLoaders = new HashMap<>();
|
||||
|
||||
//Parsing du nom du fichier
|
||||
@ -61,59 +113,117 @@ public class JuliaAddon {
|
||||
|
||||
|
||||
//Sets addon,pkg,version(si redefini) et addonClass
|
||||
unassignedClassLoader = new JuliaClassLoader(jar, entriesToRead,new DummyLaboratory());
|
||||
classLoaderNonAssigne = new JuliaClassLoader(jar, entreesALire,new LaboFactice());
|
||||
|
||||
}
|
||||
|
||||
public synchronized JuliaClassLoader newClassLoader(Laboratory laboratory) {
|
||||
if(unassignedClassLoader==null)
|
||||
/**
|
||||
* Crée un classloader pour le laboratoire donné.
|
||||
* @param laboratoire le laboratoire qui sera associé au classloader.
|
||||
* @return Un classloader qui peut charger ce Juliaddon.
|
||||
*/
|
||||
public synchronized JuliaClassLoader nouveauClassLoader(Laboratoire laboratoire) {
|
||||
if(classLoaderNonAssigne==null)
|
||||
try {
|
||||
JuliaClassLoader cl = new JuliaClassLoader(jarFile, loaderEntries,laboratory);
|
||||
classLoaders.put(laboratory.laboratory, cl);
|
||||
JuliaClassLoader cl = new JuliaClassLoader(fichierJar, entreesDuLoader,laboratoire);
|
||||
classLoaders.put(laboratoire, cl);
|
||||
return cl;
|
||||
} catch (JarWithMultipleAddonsException e) {
|
||||
System.err.println("Cette erreur n'est pas censée arriver, alerte rouge");
|
||||
} catch (JarAuxMultiplesAddonsException e) {
|
||||
erreur("Cette erreur n'est pas censée arriver, alerte rouge");
|
||||
System.exit(685533990);
|
||||
}
|
||||
|
||||
JuliaClassLoader cl = unassignedClassLoader;
|
||||
unassignedClassLoader = null;
|
||||
cl.laboratory = laboratory;
|
||||
classLoaders.put(laboratory.laboratory, cl);
|
||||
JuliaClassLoader cl = classLoaderNonAssigne;
|
||||
classLoaderNonAssigne = null;
|
||||
cl.laboratoire = laboratoire;
|
||||
classLoaders.put(laboratoire, cl);
|
||||
return cl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getName() {
|
||||
return addon.name();
|
||||
/**
|
||||
* Récupère le nom de cet addon, tel que spécifié par le développeur.
|
||||
*/
|
||||
public String getNom() {
|
||||
return addon.nom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la version de cet addon.
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie le pkg de cet addon (qu'on peut voir comme son ID)
|
||||
*/
|
||||
public String getPkg() {
|
||||
return pkg;
|
||||
}
|
||||
|
||||
public JarFile getFichierJar() {
|
||||
return fichierJar;
|
||||
}
|
||||
|
||||
public long getDerniereModif() {
|
||||
return derniereModif;
|
||||
}
|
||||
|
||||
public JuliaClassLoader getLoader(Laboratoire labo) {
|
||||
return classLoaders.get(labo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Un classloader prévu pour lire des Juliaddons depuis des entrées de fichier jar.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public class JuliaClassLoader extends ClassLoader {
|
||||
|
||||
Map<String,Class<?>> loadedClasses;
|
||||
Set<JarEntry> entries;
|
||||
/**
|
||||
* Enregistres les classes déjà chargées pour un chargement plus rapide.
|
||||
*/
|
||||
Map<String,Class<?>> classesChargees;
|
||||
/**
|
||||
* L'ensemble des entrées que ce classloader à «le droit» de lire.
|
||||
*/
|
||||
Set<JarEntry> entrees;
|
||||
/**
|
||||
* Le fichier jar associé à ce classloader.
|
||||
*/
|
||||
JarFile jar;
|
||||
Laboratory laboratory = null;
|
||||
/**
|
||||
* Le laboratoire associé à ce classloader.
|
||||
*/
|
||||
Laboratoire laboratoire = null;
|
||||
|
||||
HashSet<Method> registeredCommands;
|
||||
HashSet<Method> registeredEvents;
|
||||
/**
|
||||
* Liste les commandes enregistrées par ce classloader.
|
||||
*/
|
||||
Set<Method> commandesEnregistrees;
|
||||
/**
|
||||
* Liste les events enregistrées par ce classloader.
|
||||
*/
|
||||
Set<Method> eventsEnregistrees;
|
||||
|
||||
public JuliaClassLoader(JarFile jar,Set<JarEntry> entriesToRead,Laboratory labo) throws JarWithMultipleAddonsException {
|
||||
/**
|
||||
* Crée un classloader pour un certain jeu d'entrées jar dans un laboratoire.
|
||||
* @param jar le fichier jar duquel lire les entrées.
|
||||
* @param entreesALire Les entrées à lire pour ce classloader
|
||||
* @param labo Le laboratoire dans lequel est plongé ce classloader.
|
||||
* @throws JarAuxMultiplesAddonsException Si plusieurs addons sont trouvés dans le jar. Un classloader, un addon.
|
||||
*/
|
||||
public JuliaClassLoader(JarFile jar,Set<JarEntry> entreesALire,Laboratoire labo) throws JarAuxMultiplesAddonsException {
|
||||
super();
|
||||
entries = entriesToRead;
|
||||
entrees = entreesALire;
|
||||
this.jar = jar;
|
||||
loadedClasses = new HashMap<>();
|
||||
this.laboratory = labo;
|
||||
classesChargees = new HashMap<>();
|
||||
this.laboratoire = labo;
|
||||
Set<Class<?>> readClasses = new HashSet<>();
|
||||
Map<String,JarEntry> juliaddons = new HashMap<>();
|
||||
for(JarEntry entry : entriesToRead) {
|
||||
for(JarEntry entry : entreesALire) {
|
||||
if(entry.isDirectory())
|
||||
continue;
|
||||
if(!entry.getName().endsWith(".class"))
|
||||
@ -130,37 +240,37 @@ public class JuliaAddon {
|
||||
readClasses.add(clazz);
|
||||
//Instantiated class
|
||||
|
||||
if(clazz.isAnnotationPresent(JuLIAddon.class)) {
|
||||
if(clazz.isAnnotationPresent(Juliaddon.class)) {
|
||||
//Declare package and new addon
|
||||
Matcher m = pkgFromClassName.matcher(clazz.getName());
|
||||
if(!m.matches())
|
||||
throw new IllegalArgumentException("Le nom de la classe est invalide pour un Juliaddon (il faut au moins trois de profondeur dans le package) : "+clazz.getName());
|
||||
String pkg = m.group(1);
|
||||
if(pkg==null)
|
||||
throw new IllegalArgumentException("Imposible de récupérer le pkg.");
|
||||
if(juliaddons.containsKey(pkg))
|
||||
throw new IllegalArgumentException("Il existe deja un juliaddon dans le package "+pkg+" , d<><64>placez "+clazz.getName()+" ou "+juliaddons.get(pkg).getName());
|
||||
throw new IllegalArgumentException("Il existe deja un juliaddon dans le package "+pkg+" , déplacez "+clazz.getName()+" ou "+juliaddons.get(pkg).getName());
|
||||
juliaddons.put(pkg, entry);
|
||||
//If overwritten, will JarWithMultipleAddonsException
|
||||
JuliaAddon.this.addon = clazz.getAnnotation(JuLIAddon.class);
|
||||
JuliaAddon.this.addon = clazz.getAnnotation(Juliaddon.class);
|
||||
JuliaAddon.this.pkg = pkg;
|
||||
JuliaAddon.this.version = addon.version().isEmpty()?version:addon.version();
|
||||
JuliaAddon.this.addonClass = clazz;
|
||||
}
|
||||
|
||||
}catch (ClassFormatError e) {
|
||||
System.err.println("Impossible de lire cette classe, son format est incorrect ... veuillez recompiler le jar");
|
||||
e.printStackTrace();
|
||||
erreur("Impossible de lire cette classe, son format est incorrect ... veuillez recompiler le jar",e);
|
||||
continue;
|
||||
}catch(SecurityException e) {
|
||||
System.err.println("Vous essayez de mettre cette classe dans un package interdit ! Honte a vous");
|
||||
e.printStackTrace();
|
||||
erreur("Vous essayez de mettre cette classe dans un package interdit ! Honte a vous",e);
|
||||
continue;
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("Le fichier "+entry.getName()+" ne d<><64>cris pas un Juliaddon valide, il n'a donc pas <20><>t<EFBFBD><74> charg<72><67>, mais faites attention !");
|
||||
e.printStackTrace();
|
||||
erreur("Le fichier "+entry.getName()+" ne décris pas un Juliaddon valide, il n'a donc pas été chargé, mais faites attention !",e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(juliaddons.size()<1)
|
||||
throw new IllegalStateException("Aucun addon présent dans le fichier !");
|
||||
//Toutes les classes du Jar ont été lues : Si plusieurs addons, on rentre
|
||||
//dans le if pour lever l'exception, sinon, on initialise le JuliaClassLoader
|
||||
if(juliaddons.size() > 1) {
|
||||
@ -170,7 +280,7 @@ public class JuliaAddon {
|
||||
for (String pkg : juliaddons.keySet())
|
||||
addonsEntriesVector.put(pkg, new HashSet<>());
|
||||
|
||||
eLoop : for(JarEntry entry : entriesToRead) {
|
||||
eLoop : for(JarEntry entry : entreesALire) {
|
||||
if(entry.isDirectory())
|
||||
continue;
|
||||
if(!entry.getName().endsWith(".class"))
|
||||
@ -187,26 +297,28 @@ public class JuliaAddon {
|
||||
}
|
||||
}
|
||||
//Si le code atteint ici, le JarEntry n'appartient a aucun pkg valide
|
||||
System.err.println("Ce jar contiens plusieurs juliaddons. Nichtsdestotroz le fichier "+entry.getName()+" n'a pas de Juliaddon dans son package ou au dessus ... je ne charge donc pas la classe (attention, ca peux ammener a des ClassNotFoundException !!!)");
|
||||
erreur("Ce jar contiens plusieurs juliaddons. "
|
||||
+ "Nichtsdestotroz le fichier "+entry.getName()+" n'a pas de Juliaddon dans son package ou au dessus."
|
||||
+ "je ne charge donc pas la classe (attention, ça peux ammener a des ClassNotFoundException !)");
|
||||
continue;
|
||||
}
|
||||
addonsEntries = new HashSet<>(addonsEntriesVector.values());
|
||||
throw new JarWithMultipleAddonsException(addonsEntries);
|
||||
throw new JarAuxMultiplesAddonsException(addonsEntries);
|
||||
}
|
||||
|
||||
// Initialisation du JuliaClassloader
|
||||
//Les parametres addon, pkg,version et addonCLass ont d<EFBFBD><EFBFBD>j<EFBFBD><EFBFBD> <EFBFBD><EFBFBD>t<EFBFBD><EFBFBD> initialis<EFBFBD><EFBFBD>s lors de l'it<EFBFBD><EFBFBD>ration des fichiers du jar
|
||||
// Les paramètres addon, pkg,version et addonCLass ont déjà été initialisés lors de l'itération des fichiers du jar
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
if(loadedClasses.containsKey(name))
|
||||
return loadedClasses.get(name);
|
||||
if(classesChargees.containsKey(name))
|
||||
return classesChargees.get(name);
|
||||
///Recherche d'une entry qui collerai
|
||||
String fileName = name.replaceAll("\\.", "/")+".class";
|
||||
Optional<JarEntry> oentry = entries.stream().filter(je -> je.getName().equals(fileName)).findAny();
|
||||
Optional<JarEntry> oentry = entrees.stream().filter(je -> je.getName().equals(fileName)).findAny();
|
||||
if(oentry.isPresent()) {
|
||||
try {
|
||||
JarEntry entry = oentry.get();
|
||||
@ -215,19 +327,18 @@ public class JuliaAddon {
|
||||
reader.read(classData);
|
||||
reader.close();
|
||||
Class<?> clazz = defineClass(name,classData,0,(int) entry.getSize());
|
||||
loadedClasses.put(name, clazz);
|
||||
classesChargees.put(name, clazz);
|
||||
return clazz;
|
||||
} catch (IOException e) {
|
||||
System.err.println("Impossible de lire les donn<6E><6E>es du fichier "+oentry.get().getName()+" dans le jar "+jar.getName()+" je peux vous dire adieu je pense");
|
||||
e.printStackTrace();
|
||||
erreur("Impossible de lire les données du fichier "+oentry.get().getName()+" dans le jar "+jar.getName()+" je peux vous dire adieu je pense",e);
|
||||
}
|
||||
}
|
||||
JuliaClassLoader cl = laboratory.findClassLoader(name);
|
||||
JuliaClassLoader cl = laboratoire.trouveLeClassLoader(name);
|
||||
if(cl != null)
|
||||
try {
|
||||
return cl.loadClass(name, resolve);
|
||||
}catch(ClassNotFoundException e) {
|
||||
throw new ClassNotFoundException("J'ai délégué le chargement de la classe mais j'aurais pas du ... cette classe ne doit pas exister dans l'addon "+cl.getAddon().getName(),e);
|
||||
throw new ClassNotFoundException("J'ai délégué le chargement de la classe mais j'aurais pas du ... cette classe ne doit pas exister dans l'addon "+cl.getAddon().getNom(),e);
|
||||
}
|
||||
else
|
||||
try {
|
||||
@ -238,73 +349,113 @@ public class JuliaAddon {
|
||||
|
||||
}
|
||||
|
||||
public void registerCommandsAndEvents() {
|
||||
registeredCommands = new HashSet<>();
|
||||
registeredEvents = new HashSet<>();
|
||||
/**
|
||||
* Enregistre dans le laboratoire toutes les commandes et
|
||||
* les events présents dans les classes de ce classloader
|
||||
*/
|
||||
public void enregistrerCommadesEtEvents() {
|
||||
commandesEnregistrees = new HashSet<>();
|
||||
eventsEnregistrees = new HashSet<>();
|
||||
Set<Method> toWatch = new HashSet<>();
|
||||
Collections.addAll(toWatch, JuliaAddon.this.addonClass.getMethods());
|
||||
for (Class<?> clazz : JuliaAddon.this.addon.searchPath())
|
||||
for (Class<?> clazz : JuliaAddon.this.addon.filles())
|
||||
try {
|
||||
Collections.addAll(toWatch, loadClass(clazz.getName()).getMethods());//loadClass(clazz.getName()) poir eviter les references cassees par les classloaders
|
||||
} catch (SecurityException | ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("L'addon "+JuliaAddon.this.addonClass.getName()+" spécifie la classe "+clazz.getName());
|
||||
erreur("L'addon "+JuliaAddon.this.addonClass.getName()+" spécifie la classe "+clazz.getName(),e);
|
||||
}
|
||||
for(Method m : toWatch) {
|
||||
Command c = m.getAnnotation(Command.class);
|
||||
Discord d = m.getAnnotation(Discord.class);
|
||||
Commande c = m.getAnnotation(Commande.class);
|
||||
EventDiscord d = m.getAnnotation(EventDiscord.class);
|
||||
if(c != null) {
|
||||
registeredCommands.add(m);
|
||||
laboratory.registerCommand(m, c);
|
||||
commandesEnregistrees.add(m);
|
||||
laboratoire.enregistrerCommande(m, c);
|
||||
}else if(d != null) {
|
||||
registeredEvents.add(m);
|
||||
laboratory.registerEvent(m, d);
|
||||
eventsEnregistrees.add(m);
|
||||
laboratoire.enregistrerEvent(m, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterCommandsAndEvents() {
|
||||
for(Method m : registeredCommands) {
|
||||
Command c = m.getAnnotation(Command.class);
|
||||
registeredCommands.add(m);
|
||||
laboratory.unregisterCommand(m, c);
|
||||
/**
|
||||
* Désenregistre du laboratoire associé toutes les commandes et les
|
||||
* events présents dans les classes de ce classloader.
|
||||
*/
|
||||
public void desenregistrerCommandesEtEvents() {
|
||||
for(Method m : commandesEnregistrees) {
|
||||
Commande c = m.getAnnotation(Commande.class);
|
||||
commandesEnregistrees.add(m);
|
||||
laboratoire.desenregistrerCommande(c);
|
||||
}
|
||||
for(Method m : registeredEvents) {
|
||||
Discord d = m.getAnnotation(Discord.class);
|
||||
registeredEvents.add(m);
|
||||
laboratory.unregisterEvent(m, d);
|
||||
for(Method m : eventsEnregistrees) {
|
||||
eventsEnregistrees.add(m);
|
||||
laboratoire.desenregistrerEvent(m);
|
||||
}
|
||||
registeredCommands.clear();
|
||||
registeredEvents.clear();
|
||||
commandesEnregistrees.clear();
|
||||
eventsEnregistrees.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère l'addon pour lequel est créé ce classloader.
|
||||
*/
|
||||
public JuliaAddon getAddon() {
|
||||
return JuliaAddon.this;
|
||||
}
|
||||
|
||||
public Set<Method> getCommandesEnregistrees() {
|
||||
return commandesEnregistrees;
|
||||
}
|
||||
|
||||
public static final class JarWithMultipleAddonsException extends Exception{
|
||||
public Set<Method> getEventsEnregistrees() {
|
||||
return eventsEnregistrees;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Une exception trahissant plusieurs addons dans un jeu d'entrées jar.
|
||||
*
|
||||
* L'exception contient des données qui devraient suffire à sélectionner de manière
|
||||
* plus judicieuse les entrées afin d'eviter le problème.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public static final class JarAuxMultiplesAddonsException extends Exception{
|
||||
|
||||
private static final long serialVersionUID = -7557959851687207287L;
|
||||
|
||||
/**
|
||||
* Partition des entrées qui devrait séparer correctement les addons
|
||||
*/
|
||||
Set<Set<JarEntry>> addonsEntries;
|
||||
|
||||
public JarWithMultipleAddonsException(Set<Set<JarEntry>> addonsEntries) {
|
||||
public JarAuxMultiplesAddonsException(Set<Set<JarEntry>> addonsEntries) {
|
||||
this.addonsEntries = addonsEntries;
|
||||
}
|
||||
|
||||
public Set<Set<JarEntry>> getAddonsEntries() {
|
||||
public Set<Set<JarEntry>> entreesDeLAddon() {
|
||||
return addonsEntries;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final class DummyLaboratory extends Julia.Laboratory{
|
||||
/**
|
||||
* Un laboratoire factice prévu pour observer les fichier jar sans les enregistrer nul part.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public static final class LaboFactice extends Julia.Laboratoire{
|
||||
|
||||
public DummyLaboratory() {
|
||||
Julia.theJulia().super(Character.MIN_VALUE);
|
||||
public LaboFactice() {
|
||||
Julia.theJulia().super("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return pkg + ":" + version;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,60 +0,0 @@
|
||||
package com.bernard.juliabot;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import net.dv8tion.jda.api.MessageBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
|
||||
public class JuliaErrPrintStream extends OutputStream {
|
||||
|
||||
StringBuilder tas = new StringBuilder(2000);// Les 2000 caractères de Discord
|
||||
|
||||
Lock cadenas;
|
||||
|
||||
MessageChannel logChannel;
|
||||
|
||||
public static final int maxlength = 1900;
|
||||
|
||||
public JuliaErrPrintStream(MessageChannel logChan) {
|
||||
this.cadenas = new ReentrantLock();
|
||||
this.logChannel = logChan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int i) throws IOException {
|
||||
tas.append((char)(i));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void flushMessage() {
|
||||
if(tas.length()==0)return;
|
||||
this.cadenas.lock();
|
||||
String str = tas.toString();
|
||||
for(int i = 0; i*maxlength < tas.length();i++) {
|
||||
MessageBuilder builder = new MessageBuilder();
|
||||
builder.appendCodeBlock(str.substring(i*maxlength, Math.min((i+1)*maxlength,tas.length())), "");
|
||||
logChannel.sendMessage(builder.build()).queue();
|
||||
}
|
||||
tas = new StringBuilder();
|
||||
this.cadenas.unlock();
|
||||
|
||||
}
|
||||
|
||||
PrintStream ps = null;
|
||||
public PrintStream printStream() {
|
||||
if(ps == null)
|
||||
ps = new PrintStream(this);
|
||||
return ps;
|
||||
}
|
||||
|
||||
}
|
||||
184
src/main/java/com/bernard/juliabot/PrintStreamDiscord.java
Normal file
184
src/main/java/com/bernard/juliabot/PrintStreamDiscord.java
Normal file
@ -0,0 +1,184 @@
|
||||
package com.bernard.juliabot;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import net.dv8tion.jda.api.MessageBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
|
||||
/**
|
||||
* Stream de caractères dirigé vers un canal discord.
|
||||
*
|
||||
* Les utilisateurs doivent appller flushMessage() afin que soit envoyé le message.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public class PrintStreamDiscord extends OutputStream {
|
||||
|
||||
/**
|
||||
* Un buffer stoquant les prochains caractères à afficher.
|
||||
*/
|
||||
StringBuilder tas = new StringBuilder(2000);// Les 2000 caractères de Discord
|
||||
|
||||
/**
|
||||
* Cadenas bloquant le write pendant la création du message discord.
|
||||
*/
|
||||
Lock cadenas;
|
||||
|
||||
/**
|
||||
* Le channel dans lequel envoyer tous les caractères.
|
||||
*/
|
||||
MessageChannel logChannel;
|
||||
|
||||
/**
|
||||
* La longueur maximale d'un message sur discord.
|
||||
*/
|
||||
public static final int maxlength = 1900;
|
||||
|
||||
/**
|
||||
* Crée un canal dirigé vers le canal spécifié.
|
||||
* @param logChan Un channel discord pour lequel julia à un accès en écriture.
|
||||
*/
|
||||
public PrintStreamDiscord(MessageChannel logChan) {
|
||||
this.cadenas = new ReentrantLock();
|
||||
this.logChannel = logChan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int i) throws IOException {
|
||||
cadenas.lock();
|
||||
try {
|
||||
tas.append((char)(i));
|
||||
} finally {cadenas.unlock();}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Envoie le buffer dans le salon discord.
|
||||
*/
|
||||
public synchronized void flushMessage() {
|
||||
if(tas.length()==0)return;
|
||||
this.cadenas.lock();
|
||||
String str = tas.toString();
|
||||
for(int i = 0; i*maxlength < tas.length();i++) {
|
||||
MessageBuilder builder = new MessageBuilder();
|
||||
builder.appendCodeBlock(str.substring(i*maxlength, Math.min((i+1)*maxlength,tas.length())), "");
|
||||
logChannel.sendMessage(builder.build()).queue();
|
||||
}
|
||||
tas = new StringBuilder();
|
||||
this.cadenas.unlock();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Une instance de printstream sauvegardée.
|
||||
*/
|
||||
PrintStream ps = null;
|
||||
/**
|
||||
* Crée si besoin une seule fois un PrintStream écrivant dans cet OutputStream.
|
||||
*/
|
||||
public PrintStream printStream() {
|
||||
if(ps == null)
|
||||
ps = new PrintStream(this);
|
||||
return ps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un message découpé en blocs dans le canal spécifié.
|
||||
* Le message sera découpé en élements d'à peu près la taille max de message.
|
||||
* @param message Le message à écrire, potentiellement long.
|
||||
* @param logChannel Le canal de sortie.
|
||||
*/
|
||||
public static void logErrMessage(String message, MessageChannel logChannel) {
|
||||
for(int i = 0; i*maxlength < message.length();i++) {
|
||||
MessageBuilder builder = new MessageBuilder();
|
||||
builder.appendCodeLine(message.substring(i*maxlength, Math.min((i+1)*maxlength,message.length())));
|
||||
logChannel.sendMessage(builder.build()).queue();
|
||||
builder = new MessageBuilder();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Envoie le message découpé en blocs dans le canal d'erreur de ce PrintStream.
|
||||
* @param message Le message, potentiellement long, à afficher.
|
||||
*/
|
||||
public void errMessage(String message) {
|
||||
logErrMessage(message, logChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log l'erreur d'entrée dans le canal spécifié. Le message est affiché en premier en texte
|
||||
* brut, puis le Throwable est ensuite affiché dans un ou plusieurs blocs suivant sa taille.
|
||||
* @param message Le message décrivant le contexte de l'erreur
|
||||
* @param error L'erreur en elle-même
|
||||
* @param logChannel Le canal dans lequel afficher l'erreur.
|
||||
*/
|
||||
public static void logErrMessageAndThrowable(String message, Throwable error, MessageChannel logChannel) {
|
||||
StringWriter sw = new StringWriter();
|
||||
error.printStackTrace(new PrintWriter(sw));
|
||||
String errMessage = sw.toString();
|
||||
|
||||
if(errMessage.length()+message.length()+1<maxlength) {
|
||||
MessageBuilder builder = new MessageBuilder();
|
||||
|
||||
builder.appendCodeLine(message);
|
||||
builder.append('\n');
|
||||
builder.appendCodeBlock(errMessage, "");
|
||||
logChannel.sendMessage(builder.build()).queue();
|
||||
|
||||
}else {
|
||||
Julia.theJulia().realErr().println("Leeeeeee Bricoleur");
|
||||
// On doit faire du découpage.
|
||||
String[] nommes = errMessage.split("\n");
|
||||
MessageBuilder builder = new MessageBuilder();
|
||||
builder.appendCodeLine(message);
|
||||
builder.append('\n');
|
||||
int depassement = message.length()+1;
|
||||
StringBuilder reste = new StringBuilder();
|
||||
for(String nm : nommes) {
|
||||
if(depassement+nm.length()>=maxlength) {
|
||||
// On envoie maintenant
|
||||
builder.appendCodeBlock(reste.toString(), "");
|
||||
logChannel.sendMessage(builder.build()).queue();
|
||||
builder = new MessageBuilder();
|
||||
reste = new StringBuilder();
|
||||
depassement = 0;
|
||||
}
|
||||
if(nm.length() >= maxlength) { // Reste est nécessairement vide
|
||||
// Pas le choix que d'envoyer avec découpage dégueulasse.
|
||||
for(int i = 0; i*maxlength < nm.length();i++) {
|
||||
builder.appendCodeBlock(nm.substring(i*maxlength, Math.min((i+1)*maxlength,nm.length())), "");
|
||||
logChannel.sendMessage(builder.build()).queue();
|
||||
builder = new MessageBuilder();
|
||||
}
|
||||
}else {
|
||||
reste.append(nm+"\n");
|
||||
depassement += nm.length();
|
||||
}
|
||||
}
|
||||
builder.appendCodeBlock(reste.toString(), "");
|
||||
logChannel.sendMessage(builder.build()).queue();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log l'erreur d'entrée dans le canal de ce PrintStream. Le message est affiché en premier en texte
|
||||
* brut, puis le Throwable est ensuite affiché dans un ou plusieurs blocs suivant sa taille.
|
||||
* @param message Le message décrivant le contexte de l'erreur.
|
||||
* @param error L'erreur en elle-même.
|
||||
*/
|
||||
public void errMessageAndThrowable(String message, Throwable error) {
|
||||
logErrMessageAndThrowable(message, error, logChannel);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Décrit des arguments bash d'une commande type bash.
|
||||
*
|
||||
* La commande est séparée en nommes, arguments et flags, ces deux derniers étant
|
||||
* indépendant de leur position.
|
||||
*
|
||||
* Exemple: commande nomme1 nomme2 --flag1 --flag2 --arg1=val1 nomme3 --arg2=val2 --flag3
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public class ArgumentsComplexes {
|
||||
|
||||
List<String> nommes;
|
||||
Map<String,String> arguments;
|
||||
Set<String> flags;
|
||||
|
||||
/**
|
||||
* Initialise cet argument avec les paramètres indiqués.
|
||||
* @param nommes Les nommes, ordonnés de la commande
|
||||
* @param arguments Map qui à chaque argument associe sa valeur.
|
||||
* @param flags Ensemble non ordonné des flags.
|
||||
*/
|
||||
public ArgumentsComplexes(List<String> nommes, Map<String, String> arguments, Set<String> flags) {
|
||||
this.nommes = nommes;
|
||||
this.arguments = arguments;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la liste ordonnée des nommes.
|
||||
* @return Liste des nommes.
|
||||
*/
|
||||
public List<String> getNommes() {
|
||||
return Collections.unmodifiableList(nommes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie une map qui à chaque argument spécifié associe sa valeur.
|
||||
* @return La map des arguments.
|
||||
*/
|
||||
public Map<String, String> getArguments() {
|
||||
return Collections.unmodifiableMap(arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie l'ensemble des flags spécifiés.
|
||||
* @return L'ensemble des flags.
|
||||
*/
|
||||
public Set<String> getFlags() {
|
||||
return Collections.unmodifiableSet(flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie true si et seulement si le flag donné en paramètre a été spécifié.
|
||||
* @param flag le flag a tester
|
||||
* @return true ssi flag est spécifié.
|
||||
*/
|
||||
public boolean hasFlag(String flag) {
|
||||
return flags.contains(flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie la valeur associée à l'argument «name», et null si l'argument n'a pas été spécifié.
|
||||
* @param name le nom de l'argument.
|
||||
* @return La valeur de l'argument ou null.
|
||||
*/
|
||||
public String getArgument(String name) {
|
||||
return arguments.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie le n-ième nomme de la commande, le 0ème nomme correspondant typiquement au nom
|
||||
* de la commande elle-même.
|
||||
* @param pos L'indice du nomme.
|
||||
* @return La valeur du nomme.
|
||||
*/
|
||||
public String getNomme(int pos) {
|
||||
return nommes.get(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renvoie le nombre de nommes de la commande, utile pour tester si tous ont été spécifiés.
|
||||
* @return Le nombre de nommes.
|
||||
*/
|
||||
public int getNommeCount() {
|
||||
return nommes.size();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,9 +1,16 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import com.bernard.juliabot.Julia.Laboratory;
|
||||
|
||||
/**
|
||||
* Une super-interface décrivant les capacités d'une requête recue.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public interface CCommande {
|
||||
|
||||
public Laboratory getLabo();
|
||||
/**
|
||||
* L'ID du laboratoire dans lequel a été lancé la commande
|
||||
* @return La chaine de caractère de l'ID
|
||||
*/
|
||||
public String getLaboId();
|
||||
|
||||
}
|
||||
|
||||
60
src/main/java/com/bernard/juliabot/api/CCommandeDiscord.java
Normal file
60
src/main/java/com/bernard/juliabot/api/CCommandeDiscord.java
Normal file
@ -0,0 +1,60 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
|
||||
/**
|
||||
* Une CCommande décrivant une requète/commande envoyée depuis un message Discord.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public interface CCommandeDiscord extends CCommandeString {
|
||||
|
||||
/**
|
||||
* Renvoie le message qui a créé cette requête, tel que récupéré par la JDA.
|
||||
*
|
||||
* La consistance du message n'est pas assurée.
|
||||
* @return Le message à l'origine de la requête.
|
||||
*/
|
||||
public Message getMessage();
|
||||
|
||||
/**
|
||||
* Renvoie le canal dans lequel la requête a été formulée, tel que récupéré du JDA.
|
||||
*
|
||||
* La consistance du channel n'est pas assurée.
|
||||
* @return Le canal de formulation de la requête.
|
||||
*/
|
||||
public MessageChannel getChannel();
|
||||
|
||||
/**
|
||||
* Renvoie l'utilisateur ayant formulé cette requête, tel que récupéré par la JDA.
|
||||
*
|
||||
* La consistance de l'user n'est pas assurée.
|
||||
* @return L'utilisateur à l'origine de la requête.
|
||||
*/
|
||||
public User getUser();
|
||||
|
||||
/**
|
||||
* Renvoie la JDA qui a détécté l'évenement.
|
||||
*
|
||||
* @return La JDA initiante.
|
||||
*/
|
||||
public JDA getJDA();
|
||||
|
||||
/**
|
||||
* Renvoie le contenu original du message ayant créé la requête.
|
||||
* @return Le texte retiré de ses effets de style (markdown).
|
||||
*/
|
||||
public String getContentStripped();
|
||||
|
||||
/**
|
||||
* Renvoie la date de récéption du message.
|
||||
* @return La date de récéption du message.
|
||||
*/
|
||||
public OffsetDateTime getPostDate();
|
||||
|
||||
}
|
||||
23
src/main/java/com/bernard/juliabot/api/CCommandeString.java
Normal file
23
src/main/java/com/bernard/juliabot/api/CCommandeString.java
Normal file
@ -0,0 +1,23 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
/**
|
||||
* Une CCommande décrite par une chaine de caractères.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public interface CCommandeString extends CCommande{
|
||||
|
||||
/**
|
||||
* La chaine de caractères décrivant la commande.
|
||||
* @return La chaine sus-nommée.
|
||||
*/
|
||||
public String getStringCommand();
|
||||
|
||||
/**
|
||||
* Renvoie les arguments complèxes associés à cette chaine de caractères.
|
||||
* L'objet renvoyé peut être toujours le même ou généré à chaque fois.
|
||||
* @return Les arguments complexes récupérés de la chaine de la commande.
|
||||
*/
|
||||
public ArgumentsComplexes getArguments();
|
||||
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(value = ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Command {
|
||||
|
||||
public String name();
|
||||
public String[] aliases() default {};
|
||||
public String description();
|
||||
public String synopsis() default "";
|
||||
public boolean admin();//TODO a remplacer par les permissions
|
||||
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class CommandArguments {
|
||||
|
||||
List<String> nommes;
|
||||
Map<String,String> arguments;
|
||||
Set<String> flags;
|
||||
|
||||
public CommandArguments(List<String> nommes, Map<String, String> arguments, Set<String> flags) {
|
||||
this.nommes = nommes;
|
||||
this.arguments = arguments;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public List<String> getNommes() {
|
||||
return nommes;
|
||||
}
|
||||
|
||||
public Map<String, String> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public Set<String> getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public boolean hasTag(String tag) {
|
||||
return flags.contains(tag);
|
||||
}
|
||||
|
||||
public String getArgument(String name) {
|
||||
return arguments.get(name);
|
||||
}
|
||||
|
||||
public String getNomme(int pos) {
|
||||
return nommes.get(pos);
|
||||
}
|
||||
|
||||
public int getNommeCount() {
|
||||
return nommes.size();
|
||||
}
|
||||
|
||||
}
|
||||
41
src/main/java/com/bernard/juliabot/api/Commande.java
Normal file
41
src/main/java/com/bernard/juliabot/api/Commande.java
Normal file
@ -0,0 +1,41 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Annotation à appliquer à une méthode afin qu'elle réagisse aux commandes
|
||||
* envoyées sur discord ou via le sysin.
|
||||
*
|
||||
* Tous les arguments de la méthodes doivent étendre
|
||||
* {@link com.bernard.juliabot.api.CCommande}.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
@Target(value = ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Commande {
|
||||
|
||||
/**
|
||||
* Le nom de la commande. Doit être à peu prêt unique, les nom plus
|
||||
* «communs» doivent être mis dans les alias.
|
||||
*/
|
||||
public String name();
|
||||
/**
|
||||
* Tableau des alias possible de la commande, c'est moins grâve si
|
||||
* il y a des doublons.
|
||||
*/
|
||||
public String[] alias() default {};
|
||||
/**
|
||||
* Une description d'une ligne environ de la commande, explique son effet.
|
||||
*/
|
||||
public String description();
|
||||
/**
|
||||
* Le synopsis de la commande dans un style proche des pages man.
|
||||
*/
|
||||
public String synopsis() default "";
|
||||
/**
|
||||
* true si la commande ne peut être éxecutée que par des admins.
|
||||
*/
|
||||
public boolean admin() default false;//TODO a remplacer par les permissions
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(value = ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Discord {
|
||||
|
||||
public String description();
|
||||
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
|
||||
public interface DiscordCCommande extends StringCCommande {
|
||||
|
||||
public Message getMessage();
|
||||
|
||||
public MessageChannel getChannel();
|
||||
|
||||
public User getUser();
|
||||
|
||||
public JDA getJDA();
|
||||
|
||||
public String getContentStripped();
|
||||
|
||||
public OffsetDateTime getPostDate();
|
||||
|
||||
}
|
||||
20
src/main/java/com/bernard/juliabot/api/EventDiscord.java
Normal file
20
src/main/java/com/bernard/juliabot/api/EventDiscord.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Annotation à appliquer à une méthode pour indiquer qu'elle doit
|
||||
* être appelée lorsque la JDA recoit des évenements (et que ces évenements sont
|
||||
* bien destinés au bon laboratoire).
|
||||
*
|
||||
* Les méthodes doivent avoir un unique argument qui étende
|
||||
* {@link net.dv8tion.jda.api.events.GenericEvent}.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
@Target(value = ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EventDiscord {
|
||||
public String description();
|
||||
|
||||
}
|
||||
69
src/main/java/com/bernard/juliabot/api/Julia.java
Normal file
69
src/main/java/com/bernard/juliabot/api/Julia.java
Normal file
@ -0,0 +1,69 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import com.bernard.juliabot.PrintStreamDiscord;
|
||||
import static com.bernard.juliabot.Julia.theJulia;
|
||||
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
|
||||
/**
|
||||
* Anciennement appelée Trukilie, permet d'interragir avec Julia avec uniquement
|
||||
* des appels statics, et donc depuis n'importe où dans le programme.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public class Julia {
|
||||
|
||||
/**
|
||||
* Accès au JDA initialisé par Julia.
|
||||
* @return La JDA.
|
||||
*/
|
||||
public static JDA jda() {
|
||||
return theJulia().getJda();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère la connection SQL à la base de données.
|
||||
*
|
||||
* Prévu pour que les juliaddons accèdent à leurs données.
|
||||
* @return Une connection normalement ouverte.
|
||||
*/
|
||||
public static Connection juliaBDD() {
|
||||
return theJulia().getJuliaBDD();
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un message dans sysout et dans le canal «status» du Discord
|
||||
* @param message Le message à envoyer, optimalement d'une seule ligne et assez court.
|
||||
*/
|
||||
public static void status(String message) {
|
||||
System.out.println(message);
|
||||
|
||||
PrintStreamDiscord.logErrMessage(message, theJulia().statusTextChannel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un message dans le syserr et dans le canal d'erreur du Discord
|
||||
* @param message Le message décrivant l'erreur, optimalement d'une seule ligne et assez court.
|
||||
*/
|
||||
public static void erreur(String message) {
|
||||
theJulia().realErr().println(message);
|
||||
|
||||
if(theJulia().getSyserr() != null)
|
||||
theJulia().getSyserr().errMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Envoie un message d'erreur avec un stacktrace dans le syserr et dans le canal d'erreur du Discord.
|
||||
* @param message Le message décrivant l'erreur, optimalement d'une seule ligne et assez court.
|
||||
* @param error L'erreur qui sera écrite à la suite du message, avec son stacktrace.
|
||||
*/
|
||||
public static void erreur(String message, Throwable error) {
|
||||
theJulia().realErr().println(message);
|
||||
error.printStackTrace(theJulia().realErr());
|
||||
|
||||
theJulia().getSyserr().errMessageAndThrowable(message, error);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.bernard.juliabot.Julia;
|
||||
|
||||
public class JuliaConfig {
|
||||
|
||||
public static final String get(String name) {
|
||||
try {
|
||||
PreparedStatement st = Julia.theJulia().getJuliaDatabase().prepareStatement("SELECT * FROM juliaConfig WHERE strID=?");
|
||||
st.setString(1, name);
|
||||
ResultSet r = st.executeQuery();
|
||||
if(r.getFetchSize() == 0)
|
||||
throw new IllegalArgumentException("La configuration "+name+" n'existe pas ... veuillez la rentrer avant de la demander");
|
||||
String value = r.getString("value");
|
||||
return value;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalStateException("Impossible de faire des requetes à la bdd de julia. Est-elle initialisée au moins ?");
|
||||
}
|
||||
}
|
||||
|
||||
public static final void set(String name, String value) {
|
||||
try {
|
||||
PreparedStatement st = Julia.theJulia().getJuliaDatabase().prepareStatement("UPDATE juliaConfig SET value=? WHERE strID=?");
|
||||
st.setString(1, value);
|
||||
st.setString(2, value);
|
||||
int r = st.executeUpdate();
|
||||
if(r == 0)
|
||||
throw new IllegalArgumentException("La configuration "+name+" n'a pas pu être modifiée ... existe-elle ?");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
throw new IllegalStateException("Impossible de faire des requetes à la bdd de julia. Est-elle initialisée au moins ?");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,22 +7,31 @@ import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation à appliquer à une classe principale d'un Juliaddon.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Target(TYPE)
|
||||
public @interface JuLIAddon {
|
||||
public @interface Juliaddon {
|
||||
/**
|
||||
* Le nom de l'addon
|
||||
*/
|
||||
String name();
|
||||
String nom();
|
||||
/**
|
||||
* La version de l'addon
|
||||
*
|
||||
* Par défaut: La version spécifiée dans le nom du fichier de l'addon sera utilisé.
|
||||
*/
|
||||
String version() default "";
|
||||
/**
|
||||
* Différentes classes, en plus de celle là, dans laquelle chercher des méthodes définissant des événements ou des commandes
|
||||
*
|
||||
* Par défaut: Aucune fille, donc uniquement cette classe.
|
||||
*/
|
||||
Class<?>[] searchPath() default {};
|
||||
Class<?>[] filles() default {};
|
||||
/**
|
||||
* La liste des personnes ayant dévellopé cet addon
|
||||
*/
|
||||
@ -1,9 +0,0 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
public interface StringCCommande extends CCommande{
|
||||
|
||||
public String getStringCommand();
|
||||
|
||||
public CommandArguments getArguments();
|
||||
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package com.bernard.juliabot.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import com.bernard.juliabot.Julia;
|
||||
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
|
||||
public class Trukilie {
|
||||
|
||||
public static JDA jda() {
|
||||
return Julia.theJulia().getJda();
|
||||
}
|
||||
|
||||
public static Connection juliaDB() {
|
||||
return Julia.theJulia().getJuliaDatabase();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,60 +1,92 @@
|
||||
package com.bernard.juliabot.internaddon;
|
||||
|
||||
import static com.bernard.juliabot.api.Julia.erreur;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.DateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import com.bernard.juliabot.CommandCalled;
|
||||
import org.simmetrics.StringDistance;
|
||||
import org.simmetrics.metrics.StringDistances;
|
||||
|
||||
import com.bernard.juliabot.AppelACommande;
|
||||
import com.bernard.juliabot.CommandeSurchargee;
|
||||
import com.bernard.juliabot.Julia;
|
||||
import com.bernard.juliabot.Julia.Laboratory;
|
||||
import com.bernard.juliabot.Julia.Laboratoire;
|
||||
import com.bernard.juliabot.JuliaAddon;
|
||||
import com.bernard.juliabot.api.Command;
|
||||
import com.bernard.juliabot.api.CommandArguments;
|
||||
import com.bernard.juliabot.api.Discord;
|
||||
import com.bernard.juliabot.api.DiscordCCommande;
|
||||
import com.bernard.juliabot.api.JuLIAddon;
|
||||
import com.bernard.juliabot.api.StringCCommande;
|
||||
import com.bernard.juliabot.JuliaAddon.JuliaClassLoader;
|
||||
import com.bernard.juliabot.api.ArgumentsComplexes;
|
||||
import com.bernard.juliabot.api.CCommandeDiscord;
|
||||
import com.bernard.juliabot.api.CCommandeString;
|
||||
import com.bernard.juliabot.api.Commande;
|
||||
import com.bernard.juliabot.api.EventDiscord;
|
||||
import com.bernard.juliabot.api.Juliaddon;
|
||||
import com.thedeanda.lorem.LoremIpsum;
|
||||
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.MessageBuilder;
|
||||
import net.dv8tion.jda.api.entities.GuildChannel;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||
import net.dv8tion.jda.internal.utils.tuple.Pair;
|
||||
|
||||
@JuLIAddon(name="internaddon", devs = "Bernard", version="beta")
|
||||
/**
|
||||
* Cet addon est chargé de force dans chaque laboratoire. Il est celui qui permet de charger/décharger
|
||||
* les autres addons et surtout de comprendre les commandes depuis les events reçus.
|
||||
*
|
||||
* Cet addon est fait pour être le seul qui accède directement aux méthodes de {@link com.bernard.juliabot.Julia}, sans
|
||||
* passer par {@link com.bernard.juilabot.api.Julia}.
|
||||
* @author mysaa
|
||||
*/
|
||||
@Juliaddon(nom="internaddon", devs = "Bernard", version="beta")
|
||||
public class Internaddon {
|
||||
|
||||
public static final String COMMANDEUR = "!!";
|
||||
|
||||
@Discord(description = "LE catcheur des commandes discords. Les messages recus sont lus puis executes ici si ce sont des commandes")
|
||||
public void getCommand(MessageReceivedEvent e) {
|
||||
/**
|
||||
* Le catcheur d'evnts qui reconnais les commandes et demande à JuL'IA de les éxecuter.
|
||||
*/
|
||||
@EventDiscord(description = "LE catcheur des commandes discords. Les messages recus sont lus puis executes ici si ce sont des commandes")
|
||||
public void getCommande(MessageReceivedEvent e) {
|
||||
if(e.getMessage().getContentRaw().startsWith(COMMANDEUR)) {
|
||||
String name = e.getMessage().getContentRaw().split(" ")[0].substring(COMMANDEUR.length());
|
||||
String nom = e.getMessage().getContentRaw().split(" ")[0].substring(COMMANDEUR.length());
|
||||
|
||||
Laboratory labo = Julia.theJulia().getLaboratoires().get(Julia.theJulia().getLecouteur().getLabo(e));//Récupére le labo de l'évent
|
||||
Laboratoire labo = Julia.theJulia().getLecouteur().getLabo(e);//Récupére le labo de l'évent
|
||||
InternalddonCCommande ccommande = new InternalddonCCommande(e,labo);
|
||||
try {
|
||||
CommandCalled called = labo.executeCommand(name, ccommande);
|
||||
System.out.println(called);
|
||||
AppelACommande appelee = labo.executer(nom, ccommande);
|
||||
System.out.println(appelee);
|
||||
}catch(IllegalArgumentException ex) {
|
||||
// La commande n'existe pas
|
||||
e.getChannel().sendMessage("Moi pas connaitre `"+name+"`. Vous apprendre moi ?").queue();
|
||||
e.getChannel().sendMessage("Moi pas connaitre `"+nom+"`. Vous apprendre moi ?").queue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Command(name = "julia", aliases="juju", description = "Répond à l'appel", admin = true)
|
||||
public void julia(DiscordCCommande commande) {
|
||||
/**
|
||||
* Une commande pour tester le ping de julia.
|
||||
*/
|
||||
@Commande(name = "julia", alias="juju", synopsis = "!!julia", description = "Répond à l'appel", admin = true)
|
||||
public void julia(CCommandeDiscord commande) {
|
||||
User user = commande.getUser();
|
||||
MessageChannel channel = commande.getChannel();
|
||||
String[] julias = new String[]{"Présent !", "Présente !", "Présentbleu !", "Présentavion !", "Présent(e) !", "Présent(bleu) !",
|
||||
@ -66,62 +98,186 @@ public class Internaddon {
|
||||
channel.sendMessage(out).queue();
|
||||
}
|
||||
|
||||
@Command(name = "help", aliases= {"ausecours","?","allahuakbar"}, description = "Laissez-vous aider par le meilleur bot du monde", admin = true)
|
||||
public void help(DiscordCCommande commande) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append("```");
|
||||
public static final DateFormat addonFileTimeDf = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.FRANCE);
|
||||
|
||||
Laboratory l = commande.getLabo();
|
||||
s.append("Vous étes actuellement dans le laboratoire '"+l.getL()+"'\n");
|
||||
s.append("Liste des addons chargés :\n");
|
||||
for(JuliaAddon e : l.getLoadedAddons().values())
|
||||
s.append("\t- "+e.getName()+" en version "+e.getVersion()+"\n");
|
||||
s.append("\nListe des commandes chargées :\n");
|
||||
for(String c : l.getLoadedCommands().keySet()) {
|
||||
s.append("\t- "+c);
|
||||
String collected = l.getAliases().entrySet().stream()
|
||||
.filter(e->e.getValue().equals(c))
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.joining(", "));
|
||||
if(!collected.isEmpty())
|
||||
s.append(" a.k.a "+collected);
|
||||
if(l.getLoadedCommands().get(c).getDesc() != null)
|
||||
s.append(" :\n\t\t"+l.getLoadedCommands().get(c).getDesc());
|
||||
s.append('\n');
|
||||
/**
|
||||
* Liste les addons chargés ainsi que les commandes enregistrées.
|
||||
*/
|
||||
@Commande(name = "aide", alias= {"help","ausecours","?","allahuakbar"}, synopsis = "!!help [commandName | pkg] --labo=str", description = "Laissez-vous aider par le meilleur bot du monde", admin = true)
|
||||
public void aide(CCommandeDiscord commande) {
|
||||
ArgumentsComplexes args = commande.getArguments();
|
||||
|
||||
String lab = args.getArguments().getOrDefault("labo", commande.getLaboId());
|
||||
|
||||
Laboratoire l = Julia.theJulia().getLaboratoires().get(lab);
|
||||
EmbedBuilder msg = new EmbedBuilder();
|
||||
if(args.getNommeCount() == 1) {
|
||||
// On veut décrire un laboratoire.
|
||||
|
||||
msg.setTitle(String.format("Description du laboratoire «%s»", l.getL()));
|
||||
|
||||
for(JuliaAddon e : l.getAddonsCharges()) {
|
||||
String commandes = e.getLoader(l)
|
||||
.getCommandesEnregistrees()
|
||||
.stream()
|
||||
.map(m -> m.getAnnotation(Commande.class))
|
||||
.map(c -> c.name())
|
||||
.collect(Collectors.joining("; "));
|
||||
msg.addField(
|
||||
String.format("%s en version %s (%s)",e.getNom(),e.getVersion(),e.getPkg()),
|
||||
String.format("Liste des commandes disponibles: %s", commandes),
|
||||
false);
|
||||
}
|
||||
s.append("```");
|
||||
} else if (args.getNommeCount() == 2) {
|
||||
// Compréhension du premier argument das cet ordre:
|
||||
// pkg > lastPkgName > commandName > alias > addon
|
||||
|
||||
commande.getChannel().sendMessage(s).queue();
|
||||
String nom = args.getNomme(1);
|
||||
String pkg = null;
|
||||
CommandeSurchargee cs = null;
|
||||
|
||||
Set<String> pkgs = Julia.theJulia().pkgSet();
|
||||
|
||||
if(pkgs.contains(nom))
|
||||
pkg=nom; // C'est déjà un pkg donc bon
|
||||
else {
|
||||
Optional<String> ops = pkgs.stream()
|
||||
.filter(p -> p.toLowerCase(Locale.FRENCH).endsWith("."+nom.toLowerCase(Locale.FRENCH)))
|
||||
.findAny();
|
||||
if(ops.isPresent())
|
||||
pkg = ops.get();
|
||||
else {
|
||||
// On teste une commande OU un alias.
|
||||
cs = l.commandeAssociee(nom);
|
||||
|
||||
if(cs == null)
|
||||
pkg = comprendreAddon(nom);
|
||||
}
|
||||
}
|
||||
// On a «parse» le premier argument.
|
||||
|
||||
if(pkg != null) {
|
||||
// On veut décrire un package.
|
||||
String pkgf = pkg;
|
||||
Optional<JuliaAddon> addonO = l.getAddonsCharges()
|
||||
.stream()
|
||||
.filter(a -> a.getPkg().equals(pkgf))
|
||||
.findAny();
|
||||
if(addonO.isEmpty()) {
|
||||
// L'addon n'est pas chargé dans le laboratoire.
|
||||
repondre(commande, "Vous voulez de l'aide sur l'internaddon "+pkg+" mais "
|
||||
+ "il n'est pas chargé dans ce laboratoire ...").complete();
|
||||
return;
|
||||
}
|
||||
JuliaAddon addon = addonO.get();
|
||||
|
||||
msg.setTitle(String.format("Description du juliaddon %s (%s)",addon.getNom(),addon.getPkg()));
|
||||
msg.setDescription(String.format(
|
||||
"Cet addon est chargé dans le laboratoire %s en version %s. "
|
||||
+ "Il est extrait du fichier %s chargé pour la dernière fois %s",
|
||||
l.getL(),addon.getVersion(),addon.getFichierJar().getName(), addonFileTimeDf.format(Date.from(Instant.ofEpochMilli(addon.getDerniereModif())))));
|
||||
|
||||
JuliaClassLoader loader = addon.getLoader(l);
|
||||
|
||||
for(Method m : loader.getEventsEnregistrees()) {
|
||||
EventDiscord ed = m.getAnnotation(EventDiscord.class);
|
||||
if(ed==null) {
|
||||
erreur("Inconsistance dans le classLoader de l'addon "+addon+" : "
|
||||
+ "la méthode "+m.getName()+" est enregistrée comme event.");
|
||||
repondre(commande, "Une erreur de classes est survenue. Contactez un développeur du Julia.");
|
||||
return;
|
||||
}
|
||||
|
||||
@Command(name = "blabla", aliases= {}, description = "Pour vous prouver que je parle", admin = true)
|
||||
public void blabla(DiscordCCommande commande) {
|
||||
msg.addField(
|
||||
m.getName() ,
|
||||
ed.description(),
|
||||
false);
|
||||
}
|
||||
|
||||
msg.addBlankField(false);
|
||||
|
||||
for(Method m : loader.getCommandesEnregistrees()) {
|
||||
Commande ed = m.getAnnotation(Commande.class);
|
||||
if(ed==null) {
|
||||
erreur("Inconsistance dans le classLoader de l'addon "+addon+" : "
|
||||
+ "la méthode "+m.getName()+" est enregistrée comme commande");
|
||||
repondre(commande, "Une erreur de classes est survenue. Contactez un développeur du Julia.");
|
||||
return;
|
||||
}
|
||||
|
||||
msg.addField(
|
||||
(ed.alias().length==0)
|
||||
? String.format("Commande %s", ed.name())
|
||||
: String.format("Commande %s (alias %s)", ed.name(),String.join(" ou ",ed.alias())) ,
|
||||
ed.description(),
|
||||
false);
|
||||
}
|
||||
|
||||
|
||||
} else if (cs != null){
|
||||
// On veut décrire une commande.
|
||||
|
||||
Method executeur = cs.getExecuteur(commande);
|
||||
if(! (executeur.getDeclaringClass().getClassLoader() instanceof JuliaClassLoader)) {
|
||||
repondre(commande, "Impossible de récupérer l'addon correspondant à cette commande !");
|
||||
return;
|
||||
}
|
||||
JuliaAddon addon = ((JuliaClassLoader)executeur.getDeclaringClass().getClassLoader()).getAddon();
|
||||
|
||||
msg.setTitle("Commande "+cs.getCommande().name());
|
||||
|
||||
msg.setDescription(cs.getDesc());
|
||||
|
||||
msg.addField("Synopsis",cs.getCommande().synopsis()
|
||||
+ (cs.getCommande().admin()?"\nCette commande requiert les droits d'administrateur.":""),false);
|
||||
|
||||
msg.addField("Addon",
|
||||
String.format("Cette commande est décrite par l'addon %s en version %s décrit "
|
||||
+ "dans le fichier %s à la date %s. La méthode à executer est la méthode %s "
|
||||
+ "de la classe %s.", addon.getNom(),addon.getVersion(),addon.getFichierJar().getName(),
|
||||
addonFileTimeDf.format(Date.from(Instant.ofEpochMilli(addon.getDerniereModif()))),executeur.getName(),executeur.getDeclaringClass().getName()),false);
|
||||
|
||||
if(cs.getCommande().alias().length != 0)
|
||||
msg.addField("Aliases", String.join(", ", cs.getCommande().alias()), false);
|
||||
|
||||
} else {
|
||||
// On a pas compris ce qui devait être décrit.
|
||||
repondre(commande, "Je n'ai pas compris ce sur quoi je devais vous aider ...").complete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//msg.setFooter("Réponse à "+authorName(commande));// -> C'est moche
|
||||
|
||||
repondre(commande, msg.build()).complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fait que julia publie un gros bloc de texte de type Lorem ipsum.
|
||||
*/
|
||||
@Commande(name = "blabla", alias= {}, description = "Pour vous prouver que je parle", admin = true)//TODO ajouter des options peut-être.
|
||||
public void blabla(CCommandeDiscord commande) {
|
||||
Message m = commande.getMessage();
|
||||
m.getChannel().sendMessage("```"+LoremIpsum.getInstance().getWords(150, 200)+"```").queue();
|
||||
m.delete();
|
||||
}
|
||||
|
||||
@Command(name = "tuerBebePhoque", aliases= {}, description = "Pour votre plaisir", admin = true)
|
||||
public void tuerBebePhoque(DiscordCCommande commande) {
|
||||
/**
|
||||
* Renvoie la photo d'un bébé phoque mort pour soulager les développeurs stréssés.
|
||||
*/
|
||||
@Commande(name = "tuerBebePhoque", alias= {}, description = "Pour votre plaisir", admin = true)//TODO remplir un peu cette méthode.
|
||||
public void tuerBebePhoque(CCommandeDiscord commande) {
|
||||
Message m = commande.getMessage();
|
||||
m.getChannel().sendMessage("http://toni.mi.free.fr/vanhebdo/actions/phoques/im_phoque_coupGourdinAssomme_Sang.jpg").queue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Discord(description = "Arthur, par-ce que vous n'étes pas qu'une caricature")
|
||||
public void shutUp(MessageReceivedEvent e) {
|
||||
if(e.getAuthor().getIdLong() == 187677269626585089L) {//Yukimyo = L'Orchidoclaste
|
||||
|
||||
e.getChannel().sendMessage(e.getAuthor().getAsMention() +" dis du caca").queue();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Command(name = "args", description = "Décompose les messages à la Discord'", admin = true)
|
||||
public void args(DiscordCCommande commande) {
|
||||
CommandArguments ca = commande.getArguments();
|
||||
/**
|
||||
* Commande de test de la décomposition des commandes. //XXX: À supprimer
|
||||
* @see ArgumentsComplexes
|
||||
*/
|
||||
@Commande(name = "args", description = "Décompose les messages à la Discord'", admin = true)
|
||||
public void args(CCommandeDiscord commande) {
|
||||
ArgumentsComplexes ca = commande.getArguments();// Réparer la commande.
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append("```"+commande.getStringCommand()+"```");
|
||||
@ -135,8 +291,11 @@ public class Internaddon {
|
||||
|
||||
}
|
||||
|
||||
@Command(name="guilds", description = "Liste les guildes disponibles",admin=true)
|
||||
public void guilds(DiscordCCommande commande) {
|
||||
/**
|
||||
* Liste les guildes auquel Julia à accès.
|
||||
*/
|
||||
@Commande(name="guildes", alias= {"guilds"}, description = "Liste les guildes disponibles",admin=true)
|
||||
public void guildes(CCommandeDiscord commande) {
|
||||
MessageBuilder mb = new MessageBuilder();
|
||||
mb.append("Liste des serveurs :\n");
|
||||
Julia.theJulia().getJda().getGuilds()
|
||||
@ -146,64 +305,234 @@ public class Internaddon {
|
||||
commande.getChannel().sendMessage(mb.build()).complete();
|
||||
}
|
||||
|
||||
@Command(name="update",description = "Met a jour le dossier des addons",admin=true)
|
||||
public void update(StringCCommande commande) {
|
||||
/**
|
||||
* Met à jour la liste des addons disponibles, en lisant le dossier juliaddons.
|
||||
*/
|
||||
@Commande(name="maj", alias= {"update","miseAJour"},description = "Met a jour le dossier des addons",admin=true)
|
||||
public void maj(CCommandeString commande) {
|
||||
|
||||
Julia.theJulia().update();
|
||||
Julia.theJulia().addonsMaj();
|
||||
|
||||
if(CCommandeDiscord.class.isInstance(commande.getClass()))
|
||||
repondre((CCommandeDiscord)commande, "La liste des addons disponibles a été mise à jour.");
|
||||
}
|
||||
|
||||
@Command(name="load",description = "Charge l'addon dans ce laboratoire",admin=true)
|
||||
public void load(DiscordCCommande commande) {
|
||||
/**
|
||||
* Charge l'addon spécifié en ligne de commande dans le laboratoire d'appel.
|
||||
*/
|
||||
@Commande(name="charger", alias= {"load"}, description = "Charge l'addon dans ce laboratoire",admin=true)
|
||||
public void charger(CCommandeDiscord commande) {
|
||||
|
||||
CommandArguments cc = commande.getArguments();
|
||||
ArgumentsComplexes cc = commande.getArguments();
|
||||
|
||||
String addonName = cc.getNomme(1);
|
||||
String version = cc.getNomme(2);
|
||||
String lab = cc.getArguments().getOrDefault("labo", commande.getLaboId());
|
||||
|
||||
Laboratory l = commande.getLabo();
|
||||
if(cc.getNommeCount()<2) {
|
||||
repondre(commande, "Il vous faut préciser l'addon que vous voulez charger !").complete();
|
||||
return;
|
||||
}
|
||||
|
||||
String addonPkg = comprendreAddon(cc.getNomme(1));
|
||||
|
||||
if(addonPkg == null) {
|
||||
repondre(commande, String.format("Je ne trouve pas d'addon correspondant à «%s» ...", cc.getNomme(1))).complete();
|
||||
return;
|
||||
}
|
||||
|
||||
String version = null;
|
||||
if(cc.getNommeCount()<3)
|
||||
version = Julia.theJulia().latest(addonPkg);
|
||||
else
|
||||
version = cc.getNomme(2);
|
||||
|
||||
if(! Julia.theJulia().checkVersion(addonPkg,version)) {
|
||||
repondre(commande, "Je ne trouve pas la version "+version+" pour l'addon "+addonPkg).complete();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Laboratoire l = Julia.theJulia().getLaboratoires().get(lab);
|
||||
|
||||
String out = "Terminé avec succés";
|
||||
try {
|
||||
l.loadAddon(addonName, version);
|
||||
l.loadAddon(addonPkg, version);
|
||||
}catch (Exception e) {
|
||||
out = "```"+e.getClass().toString()+"\n"+e.getMessage()+"```";
|
||||
}
|
||||
commande.getChannel().sendMessage(out);
|
||||
repondre(commande, "Impossible de charger l'addon spécifié ! Contactez un admin julia.").complete();
|
||||
erreur("Tentative de chargement depuis l'internaddon", e);
|
||||
return;
|
||||
}
|
||||
|
||||
@Command(name="unload",description = "Décharge l'addon de ce laboratoire",admin=true)
|
||||
public void unload(DiscordCCommande commande) {
|
||||
repondre(commande, String.format("L'addon %s a été chargé dans sa version %s dans le laboratoire %s", addonPkg, version, lab)).complete();
|
||||
|
||||
CommandArguments cc = commande.getArguments();
|
||||
}
|
||||
|
||||
String addonName = cc.getNomme(1);
|
||||
/**
|
||||
* Décharge l'addon spécifié du laboratoire d'appel.
|
||||
*/
|
||||
@Commande(name="decharger", alias= {"unload"}, description = "Décharge l'addon de ce laboratoire",admin=true)
|
||||
public void decharger(CCommandeDiscord commande) {
|
||||
|
||||
ArgumentsComplexes cc = commande.getArguments();
|
||||
|
||||
String lab = cc.getArguments().getOrDefault("labo", commande.getLaboId());
|
||||
|
||||
if(cc.getNommeCount()<2) {
|
||||
repondre(commande, "Il vous faut préciser l'addon que vous voulez charger !").complete();
|
||||
return;
|
||||
}
|
||||
|
||||
String addonPkg = comprendreAddon(cc.getNomme(1));
|
||||
|
||||
|
||||
Laboratoire l = Julia.theJulia().getLaboratoires().get(lab);
|
||||
|
||||
Laboratory l = commande.getLabo();
|
||||
|
||||
String out = "Terminé avec succés";
|
||||
try {
|
||||
l.unloadAddon(addonName);
|
||||
l.dechargerAddon(addonPkg);
|
||||
}catch (Exception e) {
|
||||
out = "```"+e.getClass().toString()+"\n"+e.getMessage()+"```";
|
||||
repondre(commande, "Impossible de décharger l'addon spécifié ! Contactez un admin julia.").complete();
|
||||
erreur("Tentative de déchargement depuis l'internaddon", e);
|
||||
return;
|
||||
}
|
||||
commande.getChannel().sendMessage(out);
|
||||
|
||||
repondre(commande, String.format("L'addon %s a été déchargé du laboratoire %s", addonPkg, lab)).complete();
|
||||
|
||||
}
|
||||
|
||||
@Command(name="caca",description = "Déclanche une exception ... Faut bien tester, hein !",admin=true)
|
||||
public void caca(DiscordCCommande commande) {
|
||||
/**
|
||||
* Décharge puis recharge l'addon du laboratoire spécifié.
|
||||
*/
|
||||
@Commande(name="recharger", alias= {"reload"}, description = "Recharge l'addon de ce laboratoire",admin=true)
|
||||
public void recharger(CCommandeDiscord commande) {
|
||||
|
||||
ArgumentsComplexes cc = commande.getArguments();
|
||||
|
||||
String lab = cc.getArguments().getOrDefault("labo", commande.getLaboId());
|
||||
|
||||
if(cc.getNommeCount()<2) {
|
||||
repondre(commande, "Il vous faut préciser l'addon que vous voulez charger !").complete();
|
||||
return;
|
||||
}
|
||||
|
||||
String addonPkg = comprendreAddon(cc.getNomme(1));
|
||||
|
||||
|
||||
Laboratoire l = Julia.theJulia().getLaboratoires().get(lab);
|
||||
|
||||
try {
|
||||
l.rechargeAddon(addonPkg, null);
|
||||
}catch (Exception e) {
|
||||
repondre(commande, "Impossible de recharger l'addon spécifié ! Contactez un admin julia.").complete();
|
||||
erreur("Tentative de rechargement depuis l'internaddon", e);
|
||||
return;
|
||||
}
|
||||
|
||||
repondre(commande, String.format("L'addon %s a été rechargé dans le laboratoire %s", addonPkg, lab)).complete();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Une commande qui lance une IllegalStateException à des fins de tests.
|
||||
*/
|
||||
//XXX: À supprimer ou cacher
|
||||
@Commande(name="caca",description = "Déclanche une exception ... Faut bien tester, hein !",admin=true)
|
||||
public void caca(CCommandeDiscord commande) {
|
||||
throw new IllegalStateException("Nan mais tout va bien ... je fait ce qu'on m'a demandé ^^");
|
||||
}
|
||||
|
||||
StringDistance addonMetric = StringDistances.levenshtein();
|
||||
final float maxAcceptableDistance = 8.0f;
|
||||
|
||||
/**
|
||||
* Renvoie le pkg d'un addon disponible qui correspond le mieux au nom spécifié.
|
||||
* @param nom Le nom, typiquement donné par l'utilisateur.
|
||||
* @return Un pkg d'un internaddon, normalement chargeable.
|
||||
*/
|
||||
public String comprendreAddon(String nom) {
|
||||
Set<String> pkgs = Julia.theJulia().pkgSet();
|
||||
|
||||
if(pkgs.contains(nom))
|
||||
return nom; // C'est déjà un pkg donc bon
|
||||
|
||||
Optional<String> ops = pkgs.stream().filter(p -> p.endsWith("."+nom)).findAny();
|
||||
if(ops.isPresent())
|
||||
return ops.get();
|
||||
|
||||
|
||||
public class InternalddonCCommande implements DiscordCCommande,StringCCommande{
|
||||
|
||||
List<Pair<String, Float>> listProches = pkgs.stream()
|
||||
.map(s -> Pair.of(s, addonMetric.distance(s.substring(s.lastIndexOf(".")+1), nom)))
|
||||
.filter(e -> e.getRight() < maxAcceptableDistance)
|
||||
.sorted((a,b) -> Float.compare(a.getRight(), b.getRight()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if(listProches.size()>1)
|
||||
if(listProches.get(0).getRight() < listProches.get(1).getRight())
|
||||
return listProches.get(0).getLeft();
|
||||
else
|
||||
return null;
|
||||
else if(listProches.size()==1)
|
||||
return listProches.get(0).getLeft();
|
||||
else
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fait répondre à Julia sa réponse du message source
|
||||
* @param commande La ccommande de requête
|
||||
* @param message Le message à renvoyer
|
||||
* @return L'action d'envoi de la réponse.
|
||||
*/
|
||||
public MessageAction repondre(CCommandeDiscord commande, MessageEmbed message) {
|
||||
return commande.getMessage().replyEmbeds(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fait répondre à Julia sa réponse du message source
|
||||
* @param commande La ccommande de requête
|
||||
* @param message Le message à renvoyer
|
||||
* @return L'action d'envoi de la réponse.
|
||||
*/
|
||||
public MessageAction repondre(CCommandeDiscord commande, Message message) {
|
||||
return commande.getMessage().reply(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fait répondre à Julia sa réponse du message source
|
||||
* @param commande La ccommande de requête
|
||||
* @param message Le contenu du message à renvoyer
|
||||
* @return L'action d'envoi de la réponse.
|
||||
*/
|
||||
public MessageAction repondre(CCommandeDiscord commande, String message) {
|
||||
return commande.getMessage().reply(message).mentionRepliedUser(true);
|
||||
}
|
||||
|
||||
|
||||
public String authorName(CCommandeDiscord commande) {
|
||||
if(commande.getMessage().isFromGuild())
|
||||
return ((GuildChannel)commande.getChannel()).getGuild().retrieveMember(commande.getUser()).complete().getEffectiveName();
|
||||
else
|
||||
return commande.getUser().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Une simple implémentation de {@link CCommandeDiscord} et de {@link CCommandeString} afin d'appeler
|
||||
* les commandes depuis les events jda.
|
||||
* @author mysaa
|
||||
*
|
||||
*/
|
||||
public class InternalddonCCommande implements CCommandeDiscord,CCommandeString{
|
||||
|
||||
Message m;
|
||||
Laboratory labo;
|
||||
Laboratoire labo;
|
||||
|
||||
public InternalddonCCommande(MessageReceivedEvent e,Laboratory labo) {
|
||||
/**
|
||||
* Crée une simple commande.
|
||||
* @param e L'évenement trahissant la récéption de la commande.
|
||||
* @param labo Le laboratoire associé à la commande.
|
||||
*/
|
||||
public InternalddonCCommande(MessageReceivedEvent e,Laboratoire labo) {
|
||||
m = e.getMessage();
|
||||
this.labo = labo;
|
||||
}
|
||||
@ -214,7 +543,7 @@ public class Internaddon {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandArguments getArguments() {
|
||||
public ArgumentsComplexes getArguments() {
|
||||
return parseCommandArguments(getStringCommand());
|
||||
}
|
||||
|
||||
@ -249,14 +578,20 @@ public class Internaddon {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Laboratory getLabo() {
|
||||
return labo;
|
||||
public String getLaboId() {
|
||||
return labo.getL();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static CommandArguments parseCommandArguments(String raw) {
|
||||
/**
|
||||
* Comprend une ligne de commande, en séparant les nommes, flags et arguments en
|
||||
* un seul objet.
|
||||
* @param raw La ligne de commande à parser
|
||||
* @return L'objet arguments complexes contenant toutes les données séparées.
|
||||
*/
|
||||
public static ArgumentsComplexes parseCommandArguments(String raw) {
|
||||
|
||||
List<String> nommes = new ArrayList<String>();
|
||||
Map<String,String> arguments = new HashMap<>();
|
||||
@ -328,7 +663,7 @@ public class Internaddon {
|
||||
|
||||
}
|
||||
|
||||
return new CommandArguments(nommes, arguments, flags);
|
||||
return new ArgumentsComplexes(nommes, arguments, flags);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
package com.bernard.juliabot.internaddon;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
|
||||
public class UnstableMessage extends OutputStream{
|
||||
|
||||
MConsumer thisConsumer = new MConsumer();
|
||||
|
||||
public UnstableMessage(Message m) {
|
||||
// TODO Auto-generated constructor stub
|
||||
m.editMessage(""/* a préciser */).queue(thisConsumer, (e) -> {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void write(int arg0) throws IOException {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
public class MConsumer implements Consumer<Message>{
|
||||
@Override
|
||||
public void accept(Message arg0) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user