Premier commit - Inclusion dans le projet git

This commit is contained in:
Mysaa 2021-05-24 14:38:37 +02:00
commit 1a160af2be
6 changed files with 452 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.classpath
.settings
.project
bin/

View File

@ -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 {
}

View File

@ -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();
}

View File

@ -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<Class<? extends JuLIAnatheme>,Set<JuLIAnatheme>> anathemes = new HashMap<>();
static Map<String,Class<? extends JuLIAnatheme>> registeredAnathemes = new HashMap<>();
static Map<Class<? extends Event>,Set<Method>> registeredEvents = new HashMap<>();
public static final String anathemeNamePattern = "^[a-zA-Z0-9_-]*$";
static {
//Load everybody
Reflections r = new Reflections("");
for (Class<? extends JuLIAnatheme> 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<Method> callList = registeredEvents.getOrDefault(e.getClass(), new HashSet<>()) ;
for(Method m : callList) {
Set<JuLIAnatheme> 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> <type> <extra>")
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<? extends JuLIAnatheme> 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<JuLIAnatheme> anathemes = new HashSet<>();
for(Entry<Class<? extends JuLIAnatheme>,Set<JuLIAnatheme>> 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> <type>")
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<? extends JuLIAnatheme> theClass = registeredAnathemes.get(type);
Set<JuLIAnatheme> 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<? extends JuLIAnatheme> 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();
});
}
}

View File

@ -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());
}
}

View File

@ -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<TextChannel> 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)" };
}