Compare commits

...

10 Commits

Author SHA1 Message Date
Mysaa
c456837148 Petite mise à jour des évenements 2021-05-23 02:47:29 +02:00
Mysaa
59f22e5edb Oups, il manquait un accent 2021-05-23 02:45:57 +02:00
Mysaa
ff94a614c3 Merge branch 'altBrch' 2021-05-23 02:44:20 +02:00
Mysaa
cad2de01d1 Deux fichiers oubliés dans le commit précédent 2021-05-23 02:40:44 +02:00
Mysaa
b3601efefa Modifications sur les problèmes de caractères (notamment) 2021-05-23 02:36:59 +02:00
Mysaa
0094701c2a Modification de l'api et de l'internaddon 2021-05-23 02:34:31 +02:00
Mysaa
9683cf84cd Quelques erreurs de connection à la base de données 2021-05-23 02:32:45 +02:00
Mysaa
3640b97dde Encore des modifications 2021-05-23 02:31:16 +02:00
Mysaa
42ad4335b2 Petites modifications des fichiers 2021-05-23 02:28:56 +02:00
Mysaa
045d5186aa Écriture du fichier de code d'ÉcouteurDEvents 2021-05-23 02:27:16 +02:00
18 changed files with 2799 additions and 187 deletions

View File

@ -0,0 +1,86 @@
/*
* This build file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java Library project to get you started.
* For more details take a look at the Java Libraries chapter in the Gradle
* user guide available at https://docs.gradle.org/4.3/userguide/java_library_plugin.html
*/
// Apply the java-library plugin to add support for Java Library
apply plugin: 'java-library'
apply plugin: 'eclipse'
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()
}
sourceSets {
main {
java {
srcDir '/src/main/java'
exclude 'com/bernard/juliabot/internalddon/**'
}
}
}
task apiJar(type: Jar) {
archiveName = "JuliabotAPI.jar"
group 'build'
description "Fait un jar avec juste l'api"
from(sourceSets.main.output) {
include "com/bernard/juliabot/api/**"
}
}
task internalddonJar(type: Jar) {
archiveName = "JuliabotInternaddon_beta.jar"
group 'build'
description "Fait un jar avec juste l'addon interne"
from(sourceSets.main.output) {
include "com/bernard/juliabot/internaddon/**"
}
}
task execute(type:JavaExec) {
group 'execution'
description "Compile et execute le fichier jar"
main = 'com.bernard.juliabot.Julia'
classpath = sourceSets.main.runtimeClasspath
}
task copyDependencies(type: Copy) {
group 'build'
from configurations.compile
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'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
compile 'org.slf4j:slf4j-nop:1.7.25'
compile 'net.dv8tion:JDA:4.2.0_189'
compile 'com.thedeanda:lorem:2.1'
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'
}

View File

@ -0,0 +1,10 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user guide at https://docs.gradle.org/4.8.1/userguide/multi_project_builds.html
*/
rootProject.name = 'Juliabot'

View File

@ -0,0 +1,59 @@
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();
}
}
}
}

View File

@ -0,0 +1,87 @@
package com.bernard.juliabot;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.bernard.juliabot.api.CCommande;
import com.bernard.juliabot.api.Command;
public class CommandeSurchargee {
String name;
Command command;
Map<Set<Class<?>>,Method> versions = new HashMap<>();
public CommandeSurchargee(Command c) {
this.name = c.name();
this.command = c;
}
public Method getExecutor(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));
}
public void surcharger(Set<Class<?>> discriminant, Method m) {
Set<Class<?>> critargs = checkFiliature(discriminant);
versions.put(critargs, m);
}
public static Set<Class<?>> checkFiliature(Set<Class<?>> unorderedDiscriminant){
return unorderedDiscriminant.stream()
.map(CommandeSurchargee::getAllMamans)
.flatMap(Set::stream)
.filter(CCommande.class::isAssignableFrom)
.filter(c->c.isInterface())
.collect(Collectors.toSet());
}
public static Set<Class<?>> getAllMamans(Class<?> clazz) {
Set<Class<?>> res = new HashSet<>();
res.add(clazz);
if(clazz == Object.class)return res;
// First, add all the interfaces implemented by this class
Class<?>[] interfaces = clazz.getInterfaces();
res.addAll(Arrays.asList(interfaces));
for (Class<?> interfaze : interfaces) {
res.addAll(getAllMamans(interfaze));
}
// Add the super class
Class<?> superClass = clazz.getSuperclass();
// Interfaces does not have java,lang.Object as superclass, they have null, so break the cycle and return
if (superClass == null) {
return res;
}
// Now inspect the superclass
res.addAll(getAllMamans(superClass));
return res;
}
@Override
public String toString() {
return "CommandeSurchargee [name=" + name + ", versions=" + versions + "]";
}
public String getDesc() {
return command.description();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,11 @@
package com.bernard.juliabot;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -11,111 +15,196 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Scanner;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import org.apache.commons.io.output.TeeOutputStream;
import com.bernard.juliabot.JuliaAddon.JarWithMultipleAddonsException;
import com.bernard.juliabot.JuliaAddon.JuliaClassLoader;
import com.bernard.juliabot.api.CCommande;
import com.bernard.juliabot.api.Command;
import com.bernard.juliabot.api.CommandCall;
import com.bernard.juliabot.api.Discord;
import com.thedeanda.lorem.LoremIpsum;
import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;
import net.dv8tion.jda.core.events.Event;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.events.Event;
import net.dv8tion.jda.api.events.GenericEvent;
public class Julia {
public static final String juliaddonsFolder = "/home/julia/juliaddons/";
private static final String token = "";
public static final String sysinPipe = "/home/julia/entree";
public static final String CONNECTION_DATA_FILEPATH = "/var/julia/julia.conn";
static Julia theJulia;
JDA jda;
Map<String,JuliaAddon> avalivableAddons;//pkg+version->addon
Map<String,JuliaAddon> avalivableAddons;// pkg+version->addon
Map<Long,Character> laboratoriesIdentifieurs;//Store channels IDs ...
Map<Character,Laboratory> laboratoires;
Map<String,Long> fileTrack;//<File name in juliaddonFolder, lastModified>
EcouteurDEvents lecouteur;
ReadLoop sysinator;
Connection eventDatabase;
Connection juliaDatabase;
JuliaErrPrintStream syserr;
public Julia() {
avalivableAddons = new HashMap<>();
laboratoriesIdentifieurs = new HashMap<>();
laboratoires = new HashMap<>();
fileTrack = new HashMap<>();
}
public synchronized void startup() {
BufferedReader bis;
try {
bis = new BufferedReader(new FileReader(CONNECTION_DATA_FILEPATH));
String token = bis.readLine();
//Set up mysql cnnections (events & data)
Properties connectionProps = new Properties();
connectionProps.put("user", "julia");
connectionProps.put("password", "juliabestbotever");
connectionProps.put("user", bis.readLine());
connectionProps.put("password", bis.readLine());
connectionProps.put("serverTimezone", "UTC");
connectionProps.put("verifyServerCertificate", "false");
connectionProps.put("useSSL", "true");
connectionProps.put("requireSSL", "true");
String urlAndPort = bis.readLine();
try {
eventDatabase = DriverManager.getConnection("jdbc:mysql://localhost:3306/juliaEvents", connectionProps);
juliaDatabase = DriverManager.getConnection("jdbc:mysql://localhost:3306/julia", connectionProps);
eventDatabase = DriverManager.getConnection("jdbc:mysql://"+urlAndPort+"/juliaEvents", connectionProps);
juliaDatabase = DriverManager.getConnection("jdbc:mysql://"+urlAndPort+"/julia", connectionProps);
} catch (SQLException e) {
System.err.println("Impossible de se connecter a la BDD, ca ne sers a rien de lancer JuL'IA du coup ... Bonne nuit");
e.printStackTrace();
syserr.flush();
bis.close();
return;
}
//XXX sSet up JDA and Bot
System.out.println("La BDD est chargée" + eventDatabase+","+juliaDatabase);
// Démarrage de JDA et du Bot
try {
jda = new JDABuilder(AccountType.BOT).setToken(token).buildBlocking();
lecouteur = new EcouteurDEvents(this);
jda = JDABuilder.createDefault(token).addEventListeners(getLecouteur()).build();
getJda().awaitReady();
} catch(Exception e) {
System.err.println("Impossible de démarrer JuL'IA");
e.printStackTrace();
syserr.flush();
bis.close();
return;
}
long guildHello = Long.parseLong(bis.readLine());
long textChannelHello = Long.parseLong(bis.readLine());
getJda().getGuildById(guildHello).getTextChannelById(textChannelHello).sendMessage(LoremIpsum.getInstance().getWords(10, 15)).complete();
long guildErr = Long.parseLong(bis.readLine());
long textChannelErr = Long.parseLong(bis.readLine());
syserr = new JuliaErrPrintStream(getJda().getGuildById(guildErr).getTextChannelById(textChannelErr));
TeeOutputStream tos = new TeeOutputStream(System.err, syserr.printStream());
System.setErr(new PrintStream(tos));
Timer syserrtimer = new Timer("Syserr-refresh", true);
syserrtimer.schedule(new TimerTask() {
@Override
public void run() {Julia.theJulia().syserr.flushMessage();}
} , 0, 1000);
bis.close();
} catch (FileNotFoundException e1) {
System.err.println("Euhhhhh je n'ai pas trouvé le fichier "+CONNECTION_DATA_FILEPATH+" et je ne peux donc pas lire ma carte d'identitée");
e1.printStackTrace();
} catch (IOException e1) {
System.err.println("Euhhhhh je n'ai pas réussi à lire le fichier "+CONNECTION_DATA_FILEPATH+" et je ne peux donc pas lire ma carte d'identitée");
e1.printStackTrace();
}
//Launch update to see every addon in juliaddon/
update();//Va remplir la map avalivableAddons
//Démarrage du sysin
sysinator = new ReadLoop();
Thread sysinThread = new Thread(sysinator, "sysin-reader");
sysinThread.start();
System.out.println("Sont disponibles :"+avalivableAddons);
//Loader l'internalddon (hard-coded)
//laboratoires.get('#').loadAddon("com.bernard.juliabot.internaddon", "beta", false);//Pas besoin d'update, il viens d'etre fait
//Load addons in # and in $ (récupere ce qu'il faut dans la BDD)
Set<String> toLoad = new HashSet<>();
try {
Statement statement = juliaDatabase.createStatement();
ResultSet result = statement.executeQuery("SELECT * FROM loadedJuliaddons");
do {
while(result.next()) {
char laboratory = result.getString("laboratory").charAt(0);
String pkg = result.getString("pkg");
String version = result.getString("version");
if(!laboratoires.containsKey(laboratory))
laboratoires.put(laboratory, new Laboratory(laboratory));
Laboratory labo = laboratoires.get(laboratory);
labo.loadAddon(pkg, version, false);//Pas besoin d'update, il viens d'etre fait
}while(result.next());
toLoad.add(laboratory+pkg+":"+version);
}
} catch (SQLException e) {
System.err.println("Impossible de charger les plugins, vous aurez tout a faire a la main !");
e.printStackTrace();
syserr.flush();
}
System.out.println("Les addons à charger : "+toLoad);
try {
juliaDatabase.createStatement().executeUpdate("DELETE FROM loadedJuliaddons");
} catch (SQLException e) {
System.err.println("Je n'ai pas pu vider la table ... atention aux doublons !");
e.printStackTrace();
syserr.flush();
}
for(String l : toLoad) {
if(!getLaboratoires().containsKey(l.charAt(0)))
getLaboratoires().put(l.charAt(0), new Laboratory(l.charAt(0)));
Laboratory labo = getLaboratoires().get(l.charAt(0));
labo.loadAddon(l.substring(1, l.lastIndexOf(":")), l.substring(l.lastIndexOf(":")+1), false);//Pas besoin d'update, il viens d'etre fait
}
}
public synchronized void update() {
Map<String,JuliaAddon> avalivableAddons = new HashMap<>();
File juliaddonFolder = new File(juliaddonsFolder);
for(File f : juliaddonFolder.listFiles((parent,name)->name.toLowerCase().endsWith(".jar"))){
if(fileTrack.get(f.getName()) == f.lastModified())
if(fileTrack.containsKey(f.getName()) && fileTrack.get(f.getName()) == f.lastModified())
continue;//Le fichier n'a pas bougé, pas besoin de le relire
fileTrack.put(f.getName(), f.lastModified());
try {
@ -124,7 +213,7 @@ public class Julia {
JuliaAddon addon = new JuliaAddon(jar);
String id = addon.pkg+":"+addon.version;
if(avalivableAddons.containsKey(id))
System.err.println("L'addon "+id+" a déjà été chargé dans les fichiers "+avalivableAddons.get(id).jarFile.getName()+" et "+jar.getName()+", je garde que le deuxième !");
System.err.println("L'addon "+id+" a déjà été chargée dans les fichiers "+avalivableAddons.get(id).jarFile.getName()+" et "+jar.getName()+", je garde que le deuxi<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>me !");
avalivableAddons.put(id, addon);
}catch(JarWithMultipleAddonsException e) {
Set<Set<JarEntry>> addonsEntries = e.getAddonsEntries();
@ -133,36 +222,82 @@ public class Julia {
JuliaAddon addon = new JuliaAddon(jar, entry);
String id = addon.pkg+":"+addon.version;
if(avalivableAddons.containsKey(id))
System.err.println("L'addon "+id+" a déjà été chargé dans les fichiers "+avalivableAddons.get(id).jarFile.getName()+" et "+jar.getName()+", je garde que le deuxième !");
System.err.println("L'addon "+id+" a déjà été chargée dans les fichiers "+avalivableAddons.get(id).jarFile.getName()+" et "+jar.getName()+", je garde que le deuxi<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>me !");
avalivableAddons.put(id, addon);
} catch (JarWithMultipleAddonsException e1) {
System.err.println("THIS SHOULD NOT HAPPEN");
System.err.println("TOUT EST CASSÉ ALERTE ROUGE !");
System.err.println("C'est problematique, j'eteint tout, c'est mieux");
System.err.println("C'est problematique, j'éteint tout, c'est mieux");
syserr.flush();
System.exit(31415926);
}
}
}catch(IllegalStateException e) {
System.err.println(e.getMessage());
syserr.flush();
}
} catch (IOException e) {
System.err.println("Impossible de lire le fichier jar "+f.getName());
e.printStackTrace();
syserr.flush();
}
syserr.flush();
}
this.avalivableAddons = avalivableAddons;
}
public Connection getJuliaDatabase() {
return juliaDatabase;
}
public class ReadLoop implements Runnable{
boolean running = false;
@Override
public void run() {
running = true;
try {
Scanner sc = new Scanner(new File(sysinPipe));
while(running) {
String request = sc.nextLine();
System.out.println("Je suis censée avoir lu la commande "+request);
//TODO réagir ...
}
sc.close();
} catch (FileNotFoundException e) {
System.err.println("Erreur de lecture du sysin, je deviens sourd");
e.printStackTrace();
syserr.flush();
running=false;
}
}
}
public class Laboratory{
char laboratory;
Map<String,JuliaAddon> loadedAddons;//<pkg,JuliaAddon>
Map<String,Method> loadedCommands;
Map<Class<?>,Object> callerObjects;
Map<String,String> aliases;
Map<Class<? extends Event>,Set<Method>> loadedEvents;
Map<String,JuliaAddon> loadedAddons;//<pkg,JuliaAddon> : les addons chargés dans ce laboratoire
Map<String,CommandeSurchargee> loadedCommands;//<commandName,Calling method> : les commandes chargées
Map<Class<?>,Object> callerObjects; // <Classe, objet de cette classe> : Les objets instanciés dans ce laboratoire
Map<String,String> aliases;// <alias, vrainom>
Map<Class<? extends Event>,Set<Method>> loadedEvents;// Les méthodes à appeler quand un event de cette classe est lancé
Map<String,JuliaClassLoader> clazzTrack;//<className,JuliaClassLoader which loaded ths class in this laboratory>
public Laboratory(char laboratory) {
this.laboratory = laboratory;
loadedAddons = new HashMap<>();
@ -170,6 +305,7 @@ public class Julia {
aliases = new HashMap<>();
loadedEvents = new HashMap<>();
clazzTrack = new HashMap<>();
callerObjects = new HashMap<>();
}
public JuliaClassLoader findClassLoader(String className) {
@ -180,6 +316,7 @@ public class Julia {
unloadAddon(pkg);
loadAddon(pkg, version);
}
public void loadAddon(String pkg,String version) {
this.loadAddon(pkg, version, true);
}
@ -187,9 +324,9 @@ public class Julia {
public synchronized void loadAddon(String pkg,String version,boolean update) {
if(update)Julia.this.update();
if(loadedAddons.containsKey(pkg))
throw new IllegalStateException("Impossible de charger le juliaddon "+pkg+" dans le laboratoire "+laboratory+", il est déjà chargé");
throw new IllegalStateException("Impossible de charger le juliaddon "+pkg+" dans le laboratoire "+laboratory+", il est d<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>j<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> charg<72><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
try {
PreparedStatement s = juliaDatabase.prepareStatement("INSERT INTO juliaddons (laboratory,pkg,version) VALUES (?,?,?)");
PreparedStatement s = juliaDatabase.prepareStatement("INSERT INTO loadedJuliaddons (ID,laboratory,pkg,version) VALUES (NULL,?,?,?)");
s.setString(1, Character.toString(laboratory));
s.setString(2, pkg);
s.setString(3, version);
@ -197,6 +334,7 @@ public class Julia {
} catch (SQLException e) {
System.err.println("Je ne peux pas notifier la BDD que je load le plugin, je le load pas du coup ...");
e.printStackTrace();
syserr.flush();
return;
}
@ -221,6 +359,7 @@ public class Julia {
} catch (SQLException e) {
System.err.println("Je ne peux pas notifier la BDD que je unload le plugin, je l'unload mais vous risquez d'avoir des problemes ...");
e.printStackTrace();
syserr.flush();
return;
}
JuliaAddon addon = loadedAddons.get(pkg);
@ -229,32 +368,44 @@ public class Julia {
}
public synchronized void registerCommand(Method m,Command c) {
if(loadedCommands.containsKey(c.name()))
throw new IllegalStateException("Une commade "+c.name()+" a déjà été enregistrée !");
if(!loadedCommands.containsKey(c.name()))
loadedCommands.put(c.name(), new CommandeSurchargee(c));
//Verify that commands asks for good argument
Class<?>[] parameters = m.getParameterTypes();
if(parameters.length > 1)
throw new IllegalArgumentException("La méthode d'une commande ne peux prendre au maximum qu'un argument (de type CommandCall), la méthode fautive étant "+m.toGenericString());
if(parameters.length == 1 && parameters[0] == CommandCall.class)
throw new IllegalArgumentException("La méthode d'une commande, si elle possede un argument, ce dernier doit tre de type CommandCall, la méthode fautive étant "+m.toGenericString());
if(!Arrays.stream(m.getParameterTypes()).map(CCommande.class::isAssignableFrom).reduce(Boolean::logicalAnd).get())
throw new IllegalArgumentException("Les paramètres d'une commande doivent tous implémenter CCommande");
try {
m.setAccessible(true);
}catch(SecurityException e) {
throw new IllegalArgumentException("Impossible de me donner le droit d'éxecuter "+m.toGenericString());
}
// Argument OK
//Register aliases
for(String alias:c.aliases()) {
if(aliases.containsKey(alias))
System.err.println("Faut remplacer l'alias "+alias+", plus de deux addons l'utilisent");
aliases.put(alias, c.name());
}
// print un message d'erreur si un alias a déjà été enregistré pour une autre commande
Arrays.stream(c.aliases())
.filter(aliases::containsKey).filter(alias -> !aliases.get(alias).equals(c.name()))
.forEach(alias -> System.err.println("Faut remplacer l'alias "+alias+", plus de deux addons l'utilisent"));
Arrays.stream(c.aliases())
.filter(a -> !aliases.containsKey(a)).forEach(alias -> aliases.put(alias, c.name()));
//Création de l'objet si ca n'a pas été fait
checkObject(m.getDeclaringClass());
loadedCommands.put(c.name(), m);
//Enregistre la nouvelle surcharge
loadedCommands.get(c.name()).surcharger(Arrays.stream(m.getParameterTypes()).collect(Collectors.toSet()), m);
}
@SuppressWarnings("unchecked")//It is, in reallity checked
public synchronized void registerEvent(Method m, Discord d) {
Class<?>[] parameters = m.getParameterTypes();
if(parameters.length != 1)
throw new IllegalArgumentException("Les catcheurs d'events ne doivent avoir qu'un seul paramètre, extends Event, la méthde fautive étant "+m.toGenericString());
if(Event.class.isAssignableFrom(parameters[0]))
throw new IllegalArgumentException("Les catcheurs d'events ne doivent avoir qu'un seul paramétre, extends Event, la méthode fautive étant "+m.toGenericString());
if(!Event.class.isAssignableFrom(parameters[0]))
throw new IllegalArgumentException("Les catcheur d'events ne doivent avoir qu'un paramètre, qui doit extends Event, la méthode fautive étant "+m.toGenericString());
//La méthode est vérifiée
if(!loadedEvents.containsKey(parameters[0]))
@ -294,6 +445,14 @@ public class Julia {
case "java.lang.Character":
params[i] = this.laboratory;
break;
case "java.sql.Connection":
params[i] = Julia.this.juliaDatabase;
break;
case "net.dv8tion.jda.core.JDA":
params[i] = Julia.this.getJda();
break;
//TODO completer les paramètres
default:
continue constLoop;
}
@ -303,21 +462,117 @@ public class Julia {
//Tant pis, constructeur suivant
continue constLoop;
}
if(o != null)break;//Sortir de la boucle, on a notre juli objet
if(o != null)break;//Sortir de la boucle, on a notre joli objet
}
if(o == null) {
System.err.println("Je ne peux pas créer l'objet, faudait mettre un costructeur valide (en mon sens :P)");
System.err.println("Je fais tout planter du coup, votrez addon sera pas chargé !");
throw new IllegalStateException("Pas de constructeur valable");
}
callerObjects.put(clazz, o);
}
}
public void trigger(Event event) {
// TODO Auto-generated method stub
public void trigger(GenericEvent event) {
Class<? extends GenericEvent> eventClass = event.getClass();
Set<Method> toCall = loadedEvents.get(eventClass);
for(Method m : toCall) {
Object callable = callerObjects.get(m.getDeclaringClass());
try {
m.invoke(callable, event);
} catch (IllegalAccessException e) {
System.err.println("C'est pas joli joli, je suis censé lancer une méthode à laquelle je n'ai pas accès : "+m.toGenericString());
throw new IllegalStateException(e);
} catch (IllegalArgumentException e) {
System.err.println("La méthode n'est pas censée recevoir de tels erreurs, je devrai avoir chécké la méthode, mais elle ne veut pas de mes arguments ... : "+m.toGenericString());
throw new IllegalStateException(e);
} catch (InvocationTargetException e) {
System.err.println("La méthode à lancé cette exception ... je la relance derrière du coup : "+m.toGenericString());
e.printStackTrace();
syserr.flush();
throw new IllegalStateException(e);
}
}
}
public CommandCalled executeCommand(String name, CCommande content) {
String cname = name;
if(aliases.containsKey(name))
cname = aliases.get(name);
if(!loadedCommands.containsKey(cname))
throw new IllegalArgumentException("Je ne connais ni la commande, ni l'alias "+cname);
CommandeSurchargee scommande = loadedCommands.get(cname);
Method m = scommande.getExecutor(content);
if(m==null)
throw new IllegalArgumentException("La commande "+cname+" alias "+name+" n'est pas prévue pour s'éxecuter avec un "+content.getClass().getCanonicalName());
final Object[] parameters = new Object[m.getParameterCount()];
Arrays.fill(parameters, content);
final Object caller = callerObjects.get(m.getDeclaringClass());
final CommandCalled called = new CommandCalled(m, content, name, cname, caller);
Thread t = new Thread(() -> {
try {
m.invoke(caller, parameters);
} catch (IllegalAccessException e) {
System.err.println("Problème d'accès à la méthode "+m.toGenericString()+" ... c'est embêtant");
e.printStackTrace();
syserr.flush();
called.setExitValue(e.getCause());
} catch (IllegalArgumentException e) {
System.err.println("Étrange, je pensais avoir check les arguments");
e.printStackTrace();
syserr.flush();
called.setExitValue(e.getCause());
} catch (InvocationTargetException e) {
//Lui a planté
called.setExitValue(e.getCause());
System.err.println("L'appel a la commande a planté ...");
e.getCause().printStackTrace();
}
syserr.flush();
called.ended();
}, "commande-"+cname+".aka."+name+"-"+System.nanoTime());
called.setThread(t);
t.start();
return called;
}
public Map<String, JuliaAddon> getLoadedAddons() {
return loadedAddons;
}
public Map<String, CommandeSurchargee> getLoadedCommands() {
return loadedCommands;
}
public Map<String, String> getAliases() {
return aliases;
}
public Map<Class<? extends Event>, Set<Method>> getLoadedEvents() {
return loadedEvents;
}
public char getL() {
return laboratory;
}
}
@ -327,10 +582,23 @@ public class Julia {
public static void main(String[] args) {
theJulia = new Julia();
theJulia.startup();
}
public static Julia theJulia() {
return theJulia;
}
public JDA getJda() {
return jda;
}
public Map<Character,Laboratory> getLaboratoires() {
return laboratoires;
}
public EcouteurDEvents getLecouteur() {
return lecouteur;
}
}

View File

@ -8,6 +8,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@ -15,15 +16,15 @@ 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.Julia.Laboratory;
import com.bernard.juliabot.api.JuLIAddon;
public class JuliaAddon {
private static final Pattern pkgFromClassName = Pattern.compile("^(\\w(\\.\\w){2,})\\.\\w(\\$\\w)*$");
private static final Pattern jarNameParser = Pattern.compile("^([^_])_([^_])(_(.*))?.jar$");
private static final Pattern pkgFromClassName = Pattern.compile("^(\\w+(\\.\\w+){2,})\\.\\w+(\\$\\w+)*$");
private static final Pattern jarNameParser = Pattern.compile("^([^_]+)_([^_]+)(_(.+))?.jar$");
String pkg;
@ -51,27 +52,30 @@ public class JuliaAddon {
//Parsing du nom du fichier
Matcher jarMatcher = jarNameParser.matcher(jar.getName());
jarMatcher.matches();
if(!jarMatcher.matches())
throw new IllegalStateException("Le fichier n'a pas un nom valide, je ne peux pas récupérer la version du juliaddon : "+jar.getName().split("/")[jar.getName().split("/").length-1]);
//String jarAddonName = jarMatcher.group(1);
String jarVersion = jarMatcher.group(2);
//String jarExtra = jarMatcher.group(3);
version = jarVersion;
//Sets addon,pkg,version(si redefini) et addonClass
unassignedClassLoader = new JuliaClassLoader(jar, entriesToRead);
unassignedClassLoader = new JuliaClassLoader(jar, entriesToRead,new DummyLaboratory());
}
public synchronized JuliaClassLoader newClassLoader(Laboratory laboratory) {
if(unassignedClassLoader==null)
try {
JuliaClassLoader cl = new JuliaClassLoader(jarFile, loaderEntries);
cl.laboratory = laboratory;
JuliaClassLoader cl = new JuliaClassLoader(jarFile, loaderEntries,laboratory);
classLoaders.put(laboratory.laboratory, cl);
return cl;
} catch (JarWithMultipleAddonsException e) {
System.err.println("Cette erreur n'est pas censée arriver, alerte rouge");
System.exit(685533990);
}
JuliaClassLoader cl = unassignedClassLoader;
unassignedClassLoader = null;
cl.laboratory = laboratory;
@ -79,21 +83,34 @@ public class JuliaAddon {
return cl;
}
public String getName() {
return addon.name();
}
public String getVersion() {
return version;
}
public class JuliaClassLoader extends ClassLoader {
Map<String,Class<?>> loadedClasses;
Set<JarEntry> entries;
JarFile jar;
Laboratory laboratory = null;
HashSet<Method> registeredCommands;
HashSet<Method> registeredEvents;
public JuliaClassLoader(JarFile jar,Set<JarEntry> entriesToRead) throws JarWithMultipleAddonsException {
public JuliaClassLoader(JarFile jar,Set<JarEntry> entriesToRead,Laboratory labo) throws JarWithMultipleAddonsException {
super();
entries = entriesToRead;
this.jar = jar;
loadedClasses = new HashMap<>();
this.laboratory = labo;
Set<Class<?>> readClasses = new HashSet<>();
Map<String,JarEntry> juliaddons = new HashMap<>();
for(JarEntry entry : entriesToRead) {
@ -104,11 +121,12 @@ public class JuliaAddon {
//Le fichier est un .class
try {
String className = entry.getName().replaceAll("/", ".").substring(0, entry.getName().length()-".class".length());
byte[] classData = new byte[(int) entry.getSize()];
InputStream reader = jar.getInputStream(entry);
reader.read(classData);
reader.close();
Class<?> clazz = defineClass(className,classData,0,(int) entry.getSize());
Class<?> clazz;
try {
clazz = loadClass(className);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("J'ai demandé a charger une classe sachant que je l'ai dans le jar, mais j'ai quand meme pas réussi à la charger ...", e);
}
readClasses.add(clazz);
//Instantiated class
@ -119,7 +137,7 @@ public class JuliaAddon {
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(juliaddons.containsKey(pkg))
throw new IllegalArgumentException("Il existe deja un juliaddon dans le package "+pkg+" , déplacez "+clazz.getName()+" ou "+juliaddons.get(pkg).getName());
throw new IllegalArgumentException("Il existe deja un juliaddon dans le package "+pkg+" , d<EFBFBD><EFBFBD>placez "+clazz.getName()+" ou "+juliaddons.get(pkg).getName());
juliaddons.put(pkg, entry);
//If overwritten, will JarWithMultipleAddonsException
JuliaAddon.this.addon = clazz.getAnnotation(JuLIAddon.class);
@ -136,12 +154,8 @@ public class JuliaAddon {
System.err.println("Vous essayez de mettre cette classe dans un package interdit ! Honte a vous");
e.printStackTrace();
continue;
} catch (IOException e) {
System.err.println("Impossible de lire les données du fichier "+entry.getName()+" dans le jar "+jar.getName());
e.printStackTrace();
continue;
} catch (IllegalArgumentException e) {
System.err.println("Le fichier "+entry.getName()+" ne décris pas un Juliaddon valide, il n'a donc pas été chargé, mais faites attention !");
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();
continue;
}
@ -167,7 +181,7 @@ public class JuliaAddon {
while((lastPoint = pkg.lastIndexOf(".")) != -1) {//Il y a encore des dossier a monter
pkg = pkg.substring(0, lastPoint+1);//Recule de un dossier
if(addonsEntriesVector.containsKey(pkg)) {
//Pas besoin de tester la validite du pkg car si invalide il ne serai pas rentré dans le Set juliaddons
//Pas besoin de tester la validite du pkg car si invalide il ne serai pas rentr<EFBFBD><EFBFBD> dans le Set juliaddons
addonsEntriesVector.get(pkg).add(entry);
continue eLoop;
}
@ -181,10 +195,7 @@ public class JuliaAddon {
}
//Initialisation du JuliaClassloader
//Les parametres addon, pkg,version et addonCLass ont déjà été initialisés lors de l'itération des fichiers du jar
loadedClasses = new HashMap<>();
for(Class<?> clazz : readClasses)
loadedClasses.put(clazz.getName(), clazz);
//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
}
@ -193,7 +204,24 @@ public class JuliaAddon {
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if(loadedClasses.containsKey(name))
return loadedClasses.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();
if(oentry.isPresent()) {
try {
JarEntry entry = oentry.get();
byte[] classData = new byte[(int) entry.getSize()];
InputStream reader = jar.getInputStream(entry);
reader.read(classData);
reader.close();
Class<?> clazz = defineClass(name,classData,0,(int) entry.getSize());
loadedClasses.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();
}
}
JuliaClassLoader cl = laboratory.findClassLoader(name);
if(cl != null)
try {
@ -271,4 +299,12 @@ public class JuliaAddon {
}
public static final class DummyLaboratory extends Julia.Laboratory{
public DummyLaboratory() {
Julia.theJulia().super(Character.MIN_VALUE);
}
}
}

View File

@ -0,0 +1,60 @@
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;
}
}

View File

@ -0,0 +1,9 @@
package com.bernard.juliabot.api;
import com.bernard.juliabot.Julia.Laboratory;
public interface CCommande {
public Laboratory getLabo();
}

View File

@ -9,6 +9,7 @@ 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
}

View File

@ -0,0 +1,45 @@
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();
}
}

View File

@ -0,0 +1,24 @@
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();
}

View File

@ -11,9 +11,20 @@ import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(TYPE)
public @interface JuLIAddon {
/**
* Le nom de l'addon
*/
String name();
/**
* La version de l'addon
*/
String version() default "";
/**
* Différentes classes, en plus de celle , dans laquelle chercher des méthodes définissant des événements ou des commandes
*/
Class<?>[] searchPath() default {};
/**
* La liste des personnes ayant dévellopé cet addon
*/
public String[] devs();
public boolean important() default false;
}

View File

@ -0,0 +1,40 @@
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 ?");
}
}
}

View File

@ -0,0 +1,9 @@
package com.bernard.juliabot.api;
public interface StringCCommande extends CCommande{
public String getStringCommand();
public CommandArguments getArguments();
}

View File

@ -0,0 +1,19 @@
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();
}
}

View File

@ -0,0 +1,335 @@
package com.bernard.juliabot.internaddon;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import com.bernard.juliabot.CommandCalled;
import com.bernard.juliabot.Julia;
import com.bernard.juliabot.Julia.Laboratory;
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.thedeanda.lorem.LoremIpsum;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
@JuLIAddon(name="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) {
if(e.getMessage().getContentRaw().startsWith(COMMANDEUR)) {
String name = 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
InternalddonCCommande ccommande = new InternalddonCCommande(e,labo);
try {
CommandCalled called = labo.executeCommand(name, ccommande);
System.out.println(called);
}catch(IllegalArgumentException ex) {
// La commande n'existe pas
e.getChannel().sendMessage("Moi pas connaitre `"+name+"`. Vous apprendre moi ?").queue();
}
}
}
@Command(name = "julia", aliases="juju", description = "Répond à l'appel", admin = true)
public void julia(DiscordCCommande 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) !",
"Présent(avion) !", "Présent(e)(bleu) !", "Présent(e)(avion) !", "Présent(bleu)(avion) !", "Présent(e)(bleu)(avion) !",
"Oui, c'est moi", user.getName(), "ailuJ", "42 ... oups", "C'est à moi que tu parle ?!", "Entrez c'est ouvert", "Derrière toi !!!",
"J'ai tujorous pas cropmis a qoui ca sret l'otrahhgrope ...", "Laissez moi préparer la domination du monde en paix s'il vous plaét !",
"Je SuIS Un RObot BZzzBzZZZbZZbZZ", "Juliaaaa dadedidadeda dedadedi dadeda", "Tutturu", "Tadaaaaaaa !"};
String out = julias[(int)Math.floor(Math.random() * julias.length)];
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("```");
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');
}
s.append("```");
commande.getChannel().sendMessage(s).queue();
}
@Command(name = "blabla", aliases= {}, description = "Pour vous prouver que je parle", admin = true)
public void blabla(DiscordCCommande 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) {
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();
StringBuilder s = new StringBuilder();
s.append("```"+commande.getStringCommand()+"```");
s.append("Liste des nommes : \n");
s.append(IntStream.range(0, ca.getNommeCount()).mapToObj(i -> "\t"+i+" : `"+ca.getNomme(i)+"`").collect(Collectors.joining("\n")));
s.append("\nListe des flags : \n");
s.append(ca.getFlags().stream().map(f->"\t`"+f+"`").collect(Collectors.joining("\n")));
s.append("\nListe des arguments : \n");
commande.getMessage().getChannel().sendMessage(s).queue();
}
@Command(name="guilds", description = "Liste les guildes disponibles",admin=true)
public void guilds(DiscordCCommande commande) {
MessageBuilder mb = new MessageBuilder();
mb.append("Liste des serveurs :\n");
Julia.theJulia().getJda().getGuilds()
.stream()
.map(g -> g.getName() + "(" + g.getMemberCount() + " membres, id:" + g.getId() + ")\n")
.forEach(mb::append);;
commande.getChannel().sendMessage(mb.build()).complete();
}
@Command(name="update",description = "Met a jour le dossier des addons",admin=true)
public void update(StringCCommande commande) {
Julia.theJulia().update();
}
@Command(name="load",description = "Charge l'addon dans ce laboratoire",admin=true)
public void load(DiscordCCommande commande) {
CommandArguments cc = commande.getArguments();
String addonName = cc.getNomme(1);
String version = cc.getNomme(2);
Laboratory l = commande.getLabo();
String out = "Terminé avec succés";
try {
l.loadAddon(addonName, version);
}catch (Exception e) {
out = "```"+e.getClass().toString()+"\n"+e.getMessage()+"```";
}
commande.getChannel().sendMessage(out);
}
@Command(name="unload",description = "Décharge l'addon de ce laboratoire",admin=true)
public void unload(DiscordCCommande commande) {
CommandArguments cc = commande.getArguments();
String addonName = cc.getNomme(1);
Laboratory l = commande.getLabo();
String out = "Terminé avec succés";
try {
l.unloadAddon(addonName);
}catch (Exception e) {
out = "```"+e.getClass().toString()+"\n"+e.getMessage()+"```";
}
commande.getChannel().sendMessage(out);
}
@Command(name="caca",description = "Déclanche une exception ... Faut bien tester, hein !",admin=true)
public void caca(DiscordCCommande commande) {
throw new IllegalStateException("Nan mais tout va bien ... je fait ce qu'on m'a demandé ^^");
}
public class InternalddonCCommande implements DiscordCCommande,StringCCommande{
Message m;
Laboratory labo;
public InternalddonCCommande(MessageReceivedEvent e,Laboratory labo) {
m = e.getMessage();
this.labo = labo;
}
@Override
public String getStringCommand() {
return m.getContentRaw();
}
@Override
public CommandArguments getArguments() {
return parseCommandArguments(getStringCommand());
}
@Override
public Message getMessage() {
return m;
}
@Override
public MessageChannel getChannel() {
return m.getChannel();
}
@Override
public User getUser() {
return m.getAuthor();
}
@Override
public JDA getJDA() {
return m.getJDA();
}
@Override
public String getContentStripped() {
return m.getContentStripped();
}
@Override
public OffsetDateTime getPostDate() {
return m.getTimeCreated();
}
@Override
public Laboratory getLabo() {
return labo;
}
}
public static CommandArguments parseCommandArguments(String raw) {
List<String> nommes = new ArrayList<String>();
Map<String,String> arguments = new HashMap<>();
Set<String> flags = new HashSet<>();
String state = "n";
String reading = "";
List<String> stringized = new ArrayList<>();
for(String morceau : raw.split(" ")) {
if(state.equals("n")) {
if(morceau.isEmpty())
continue;
if(morceau.startsWith("\"") || morceau.startsWith("`")) {
state = String.valueOf(morceau.charAt(0));
morceau = morceau.substring(1);
}else {
stringized.add(morceau);
continue;
}
}
if(state.equals("\"") || state.equals("`")) {
if(morceau.isEmpty()) {
reading += " ";
continue;
}
if(morceau.endsWith(state)) {
reading += morceau.substring(0, morceau.length()-1);
stringized.add(reading);
reading = "";
state = "n";
continue;
}
reading += morceau + " ";
continue;
}
}
for(String morceau : stringized) {
if(state.equals("n")) {
if(morceau.isEmpty())
continue;
if(morceau.startsWith("--")) {
state = "#"+morceau.substring(2);
continue;
}
if(morceau.startsWith("-")) {
flags.add(morceau.substring(1));
continue;
}
nommes.add(morceau);
continue;
}
if(state.startsWith("#")) {
arguments.put(state.substring(1), morceau);
continue;
}
}
return new CommandArguments(nommes, arguments, flags);
}
}

View File

@ -0,0 +1,36 @@
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
}
}
}