commit 1a160af2be3363374b555e495d0552c77e0cf41b Author: Mysaa Date: Mon May 24 14:38:37 2021 +0200 Premier commit - Inclusion dans le projet git diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..572533e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.classpath +.settings +.project +bin/ diff --git a/src/com/bernard/julianatheme/EventReciever.java b/src/com/bernard/julianatheme/EventReciever.java new file mode 100644 index 0000000..c9afb2b --- /dev/null +++ b/src/com/bernard/julianatheme/EventReciever.java @@ -0,0 +1,10 @@ +package com.bernard.julianatheme; + +import static java.lang.annotation.ElementType.METHOD; + +import java.lang.annotation.Target; + +@Target(METHOD) +public @interface EventReciever { + +} diff --git a/src/com/bernard/julianatheme/JuLIAnatheme.java b/src/com/bernard/julianatheme/JuLIAnatheme.java new file mode 100644 index 0000000..241b53f --- /dev/null +++ b/src/com/bernard/julianatheme/JuLIAnatheme.java @@ -0,0 +1,36 @@ +package com.bernard.julianatheme; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.Member; + +public abstract class JuLIAnatheme { + + public Member cible, source; + + public abstract void write(DataOutputStream dos) throws IOException; + public abstract void read(DataInputStream dos) throws IOException; + + public JuLIAnatheme(Member cible, Member source) { + this.cible = cible; + this.source = source; + } + + public abstract void initialize(String extra,Guild g) throws InvalidAnathemDescriptionException; + + public static class InvalidAnathemDescriptionException extends Exception{ + + private static final long serialVersionUID = -6798769037564331527L; + + public InvalidAnathemDescriptionException(String anathemType,String malformed) { + super("Une malédiction '"+anathemType+"' ne peut pas recevoir une telle description ! (Voici l'erreur au cazou : "+malformed+")"); + } + + } + + public abstract String dump(); + +} diff --git a/src/com/bernard/julianatheme/JuliAnathèmeManager.java b/src/com/bernard/julianatheme/JuliAnathèmeManager.java new file mode 100644 index 0000000..d7c58d2 --- /dev/null +++ b/src/com/bernard/julianatheme/JuliAnathèmeManager.java @@ -0,0 +1,258 @@ +package com.bernard.julianatheme; + +import java.awt.Color; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Pattern; + +import org.reflections.Reflections; + +import com.bernard.discord.api.Command; +import com.bernard.discord.api.Discord; +import com.bernard.julianatheme.JuLIAnatheme.InvalidAnathemDescriptionException; + +import net.dv8tion.jda.core.EmbedBuilder; +import net.dv8tion.jda.core.MessageBuilder; +import net.dv8tion.jda.core.entities.*; +import net.dv8tion.jda.core.events.Event; + +public class JuliAnathèmeManager { + + + Map,Set> anathemes = new HashMap<>(); + + static Map> registeredAnathemes = new HashMap<>(); + static Map,Set> registeredEvents = new HashMap<>(); + + public static final String anathemeNamePattern = "^[a-zA-Z0-9_-]*$"; + + static { + //Load everybody + Reflections r = new Reflections(""); + for (Class clazz : r.getSubTypesOf(JuLIAnatheme.class)) { + try { + registerAnatheme(clazz.getField("NAME").get(null).toString(), clazz); + } catch (Exception e) { + registerAnatheme(clazz.getSimpleName(), clazz); + } + } + + } + + @Discord(description="Lance les évents de toutes les malédictions chagées") + public void anathemeEvent(Event e){ + System.out.println("Alors l'event "+e.toString()); + Set callList = registeredEvents.getOrDefault(e.getClass(), new HashSet<>()) ; + for(Method m : callList) { + Set callObjects = anathemes.getOrDefault(m.getDeclaringClass(), new HashSet<>()); + for(JuLIAnatheme o : callObjects) { + try { + m.invoke(o, e); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException err) { + System.err.println("Cette erreur n'est pas censée arrivée. Source : JuLI'Anathème event dispacher."); + err.printStackTrace(); + } + } + } + } + + @Command(admin=true,name="maudir",group="JuL'IAnathème",grp="janatheme",description="Maudit une personne. Usage 'maudir <@pseudo> ") + public void maudir(Message m,Guild g) { + + if(m.getMentionedUsers().size() < 1) { + notifyUser("Il faut notifier l'utilisateur qu vous voulez maudir", m.getAuthor(), m.getChannel()); + return; + } + String[] splitted = m.getContentRaw().split(" "); + if(splitted.length < 3) { + notifyUser("Veuillez utiliser la commande comme il faut (l'IA n'est pas encore prevue pour vous corriger). Regardez le !!help si probleme.", m.getAuthor(), m.getChannel()); + return; + } + System.out.println("Splitted : "+Arrays.toString(splitted)); + Member cible = g.getMember(m.getMentionedUsers().get(0)); + Member source = g.getMember(m.getAuthor()); + + String type = splitted[2]; + if(!registeredAnathemes.containsKey(type)) { + notifyUser("Je ne connais pas ce type de malédiction : "+type+", Et du coup j'ai maudit personne", m.getAuthor(), m.getChannel()); + return; + } + Class julianathemeType = registeredAnathemes.get(type); + + String extra = ""; + if(splitted.length > 3) + extra = splitted[3]; + JuLIAnatheme anatheme; + try { + anatheme = registeredAnathemes.get(type).getConstructor(Member.class,Member.class).newInstance(cible,source); + if(anatheme == null) + throw new NullPointerException("Le constructeur n'a pas renvoyé d'anathème (je veut pas savoir comment vous avez fait)"); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException | NullPointerException e) { + notifyUser("Je n'ai pas pu lancer la malédiction ... discutez du problème avec le dev de la malédiction (vous pouvez aussi lui montrer ça)", m.getAuthor(), m.getChannel()); + EmbedBuilder builder = new EmbedBuilder(); + builder.setTitle("Voila le log :"); + builder.addField(e.getClass().getCanonicalName(),e.getLocalizedMessage(),false); + builder.setColor(Color.red); + m.getChannel().sendMessage(builder.build()).complete(); + return; + } + try { + anatheme.initialize(extra,g); + } catch (InvalidAnathemDescriptionException e) { + MessageBuilder builder = new MessageBuilder(); + builder.append("Vous ne pouvez pas créer d'anathème avec cet extra :\n"); + builder.append("`"+extra+"` -> "); + builder.appendCodeBlock(e.getMessage(), null); + m.getChannel().sendMessage(builder.build()).complete(); + return; + } + System.out.println("Boucle"); + System.out.println(anathemes); + System.out.println(julianathemeType); + if(!anathemes.containsKey((julianathemeType))) + anathemes.put(julianathemeType, new HashSet<>()); + for (JuLIAnatheme testingAnatheme : anathemes.get(julianathemeType)) + if(testingAnatheme.cible.getUser().getIdLong() == cible.getUser().getIdLong()) { + notifyUser("Je n'ai pas pu lancer la malédiction ... cet utilisateur a déja été maudit, veuillez enlever puis refaire votre malédiction", m.getAuthor(), m.getChannel()); + return;//TODO Utiliser ci la fonction add (surenchère de julianatheme) + } + + anathemes.get(julianathemeType).add(anatheme); + System.out.println("Fin"); + System.out.println(anathemes); + System.out.println(julianathemeType); + + } + + @Command(admin=true,name="oracle",group="JuL'IAnathème",grp="janatheme",description="Demande à l'oracle, quelles sont les maledictions planant sur une personne. Usage: 'oracle <@pseudo>") + public void oracle(Message m,Guild g) { + + if(m.getMentionedUsers().size() < 1) { + notifyUser("Il faut notifier l'utilisateur qu vous voulez 'oracler'", m.getAuthor(), m.getChannel()); + return; + } + Member cible = g.getMember(m.getMentionedUsers().get(0)); + + Set anathemes = new HashSet<>(); + for(Entry,Set> anathemez : this.anathemes.entrySet()) + for (JuLIAnatheme testingAnatheme : anathemez.getValue()) + if(testingAnatheme.cible.getUser().getIdLong() == cible.getUser().getIdLong()) { + anathemes.add(testingAnatheme); + break; + } + + //Analyser les maledictions et les dump + if(anathemes.isEmpty()) { + MessageBuilder builder = new MessageBuilder(); + builder.append(cible); + builder.append(" : Cette personne est pure ... pour l'instant"); + m.getChannel().sendMessage(builder.build()).complete(); + return; + } + EmbedBuilder dumper = new EmbedBuilder(); + dumper.setTitle("Anathemes planant sur "+cible.getNickname()); + dumper.setColor(Color.ORANGE); + for (JuLIAnatheme juLIAnatheme : anathemes) { + dumper.addField(juLIAnatheme.getClass().getSimpleName(), juLIAnatheme.dump(), false); + } + m.getChannel().sendMessage(dumper.build()).complete(); + } + + @Command(admin=true,name="exorciser",group="JuL'IAnathème",grp="janatheme",description="Excorcise une personne (lui enlève sa malediction). Usage 'exoriser <@pseudo> ") + public void exorciser(Message m,Guild g) { + if(m.getMentionedUsers().size() < 1) { + notifyUser("Il faut notifier l'utilisateur qu vous voulez exorciser", m.getAuthor(), m.getChannel()); + return; + } + String[] splitted = m.getContentRaw().split(" "); + if(splitted.length < 3) { + notifyUser("Veuillez utiliser la commande comme il faut (l'IA n'est pas encore prevue pour vous corriger). Regardez le !!help si probleme.", m.getAuthor(), m.getChannel()); + return; + } + System.out.println("Splitted : "+Arrays.toString(splitted)); + Member cible = g.getMember(m.getMentionedUsers().get(0)); + + String type = splitted[2]; + if(!registeredAnathemes.containsKey(type)) { + notifyUser("Je ne connais pas ce type de malédiction : "+type+", Et du coup j'ai rien fait", m.getAuthor(), m.getChannel()); + return; + } + Class theClass = registeredAnathemes.get(type); + Set anathemes = this.anathemes.get(theClass); + JuLIAnatheme aSupprimer = null; + for (JuLIAnatheme anatheme : anathemes) + if(anatheme.cible.getUser().getIdLong() == cible.getUser().getIdLong()) + aSupprimer = anatheme; + + if(aSupprimer == null) { + MessageBuilder builder = new MessageBuilder(); + builder.append(cible); + builder.append(" : Cette personne est pure ... pour l'instant"); + m.getChannel().sendMessage(builder.build()).complete(); + return; + } + anathemes.remove(aSupprimer); + notifyUser("Ohhhh "+cible.getNickname()+" a été purifié !!! Son anathème "+type+" a disparu !",m.getAuthor(), m.getChannel()); + } + + public static void registerAnatheme(String name, Class clazz) { + System.out.println("Je vais registerer "+name); + if(clazz == null) { + System.err.println("Bon ben ... j'ajoute aucune classe ..."); + return; + } + if(name == null || name.isEmpty()) { + System.err.println("Il faut mettre un nom sur le carnet de naissance SVP"); + return; + } + if(!Pattern.matches(anathemeNamePattern, name)) { + System.err.println("Vous l'aimez pas votre enfant ? Donnez-lui un nom mieux que "+name+" (qui match \""+anathemeNamePattern+"\"!"); + return; + } + if(!JuLIAnatheme.class.isAssignableFrom(clazz)) { + System.err.println("Cette classe "+clazz.getCanonicalName()+" n'est pas fille de JuLIAnatheme (et bien ... il faut)"); + return; + } + try { + clazz.getConstructor(Member.class,Member.class); + } catch (NoSuchMethodException | SecurityException e) { + System.err.println("Cette classe "+clazz.getCanonicalName()+" n'a pas de constructeur avec deux paramètres 'Member' (cible et source) ou bien n'est pas accessible."); + return; + } + //Get events + Method[] mtds = clazz.getMethods(); + for(Method m : mtds) { + if(m.getAnnotationsByType(EventReciever.class).length > 0) { + Class[] pmts = m.getParameterTypes(); + if(pmts.length != 1 || Event.class.isAssignableFrom(pmts[0])){ + System.err.println("La methode "+m.getName()+" de la classe "+clazz.getName()+" possède l'annotation EventReciever mais ne possède pas un seul argument de type enfant de Event"); + return; + } + + } + } + registeredAnathemes.put(name, clazz); + } + + public void sheduleDataSaving() { + Thread t = new Thread(()-> { + //TODO implement data saving in BDD (file as default) + },"JuL'IAnathèmeDataSaving"); + t.start(); + } + + public static final void notifyUser(String problem,User user,MessageChannel channel) { + MessageBuilder builder = new MessageBuilder(); + builder.append(user); + builder.append(" : "); + builder.append(problem); + user.openPrivateChannel().queue((chan) -> + { + chan.sendMessage(builder.build()).queue(); + }); + } + +} diff --git a/src/com/bernard/julianatheme/anathemes/HelloAnatheme.java b/src/com/bernard/julianatheme/anathemes/HelloAnatheme.java new file mode 100644 index 0000000..f7c5cb9 --- /dev/null +++ b/src/com/bernard/julianatheme/anathemes/HelloAnatheme.java @@ -0,0 +1,52 @@ +package com.bernard.julianatheme.anathemes; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import com.bernard.discord.commands.JulSoundBox; +import com.bernard.julianatheme.EventReciever; +import com.bernard.julianatheme.JuLIAnatheme; + +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.Member; +import net.dv8tion.jda.core.events.guild.voice.GuildVoiceJoinEvent; + +public class HelloAnatheme extends JuLIAnatheme { + + public static final String NAME = "hello"; + + public HelloAnatheme(Member cible, Member source) { + super(cible, source); + } + + String soundName; + + @Override + public void write(DataOutputStream dos) throws IOException { + dos.writeUTF(soundName); + } + + @Override + public void read(DataInputStream dos) throws IOException { + soundName = dos.readUTF(); + } + + @Override + public void initialize(String extra, Guild g) throws InvalidAnathemDescriptionException { + soundName = extra; + if(JulSoundBox.checkUserSoundPermission(source.getUser(), extra)) + throw new InvalidAnathemDescriptionException("hello", "Le son "+extra+" n'est pas jouable (ou vous n'y avez pas accès) ... désolé"); + } + + @Override + public String dump() { + return "Je dois jouer "+soundName; + } + + @EventReciever + public void play(GuildVoiceJoinEvent event) { + JulSoundBox.sneakPlay(soundName, event.getChannelJoined()); + } + +} \ No newline at end of file diff --git a/src/com/bernard/julianatheme/anathemes/StopTalkingAnatheme.java b/src/com/bernard/julianatheme/anathemes/StopTalkingAnatheme.java new file mode 100644 index 0000000..ab18091 --- /dev/null +++ b/src/com/bernard/julianatheme/anathemes/StopTalkingAnatheme.java @@ -0,0 +1,92 @@ +package com.bernard.julianatheme.anathemes; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import com.bernard.julianatheme.EventReciever; +import com.bernard.julianatheme.JuLIAnatheme; + +import net.dv8tion.jda.core.MessageBuilder; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.Member; +import net.dv8tion.jda.core.entities.TextChannel; +import net.dv8tion.jda.core.events.message.MessageReceivedEvent; + +public class StopTalkingAnatheme extends JuLIAnatheme { + + public static final String NAME = "stopTalking"; + + long[] channelsIDs; + + + public StopTalkingAnatheme(Member cible, Member source) { + super(cible, source); + } + + @Override + public void write(DataOutputStream dos) throws IOException { + dos.writeInt(channelsIDs.length); + for (long cid : channelsIDs) + dos.writeLong(cid); + } + + @Override + public void read(DataInputStream dos) throws IOException { + channelsIDs = new long[dos.readInt()]; + for (int i = 0; i < channelsIDs.length; i++) + channelsIDs[i] = dos.readLong(); + + } + + @Override + public void initialize(String extra, Guild g) throws InvalidAnathemDescriptionException { + if (extra == "") { + List tCns = g.getTextChannels(); + channelsIDs = new long[tCns.size()]; + for (int i = 0; i < channelsIDs.length; i++) { + channelsIDs[i] = tCns.get(i).getIdLong(); + } + } else { + String[] splitted = extra.split(","); + channelsIDs = new long[splitted.length]; + for (int i = 0; i < splitted.length; i++) { + TextChannel restriction = g.getTextChannelById(splitted[i]); + if (restriction == null) + throw new InvalidAnathemDescriptionException("stopTalking", + "Il n'existe pas de TextChannel d'ID '" + splitted[i] + "' (du moins pas dans ce serveur)"); + channelsIDs[i] = restriction.getIdLong(); + } + } + } + + @Override + public String dump() { + return "Sur les caneaux " + Arrays.toString(channelsIDs); + } + + @EventReciever + public void replyEveryMessages(MessageReceivedEvent event) { + System.out.println("Retorquage en cours ..."); + if (event.getAuthor().getIdLong() == cible.getUser().getIdLong() + && Arrays.binarySearch(channelsIDs, event.getChannel().getIdLong()) >= 0) { + String counterLine = counterLines[(int) Math.floor((Math.random() * counterLines.length))]; + MessageBuilder builder = new MessageBuilder(); + builder.append(cible); + builder.append(" : "); + builder.append(counterLine); + event.getChannel().sendMessage(builder.build()).complete(); + } + } + + String[] counterLines = { "Mais qu'es-ce qu'il parle, lui ?", "Faites le taire !", "Peut-il fermer son clapet ?", + "Si c'est pour dire de la merd#, ca valait pas la peine", "Là on vois bien qu'il est idiot !", + "Tu sais que personne ne veut t'écouter", "Mais Arette de parler !!!", "Shut the fuck up !", + "https://youtu.be/Vh2je2c45lg", + "Mais qui a donné une langue à cette personne, un cerveau aurai été un bon début !", + "Tu as de la chance que mes devs m'on interdit de de mute ...", "Ah si tu pouvais fermer ... TA GEULE !", + "https://youtu.be/OoNSPEFDuxo", "Als Maul !!! (C'est plus frappant en allemand)" }; + +}