This commit is contained in:
Tyler Murphy 2022-10-05 13:44:55 -04:00
parent e1f2465204
commit 50af52f2e4
5 changed files with 320 additions and 7 deletions

13
pom.xml
View file

@ -33,7 +33,7 @@
</filter> </filter>
</filters> </filters>
<createDependencyReducedPom>false</createDependencyReducedPom> <createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>true</minimizeJar> <minimizeJar>false</minimizeJar>
<shadedArtifactAttached>true</shadedArtifactAttached> <shadedArtifactAttached>true</shadedArtifactAttached>
<transformers> <transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
@ -80,12 +80,12 @@
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<version>2.0.1</version> <version>2.0.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId> <artifactId>slf4j-simple</artifactId>
<version>2.0.1</version> <version>2.0.3</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sedmelluq</groupId> <groupId>com.sedmelluq</groupId>
@ -110,7 +110,12 @@
<dependency> <dependency>
<groupId>org.json</groupId> <groupId>org.json</groupId>
<artifactId>json</artifactId> <artifactId>json</artifactId>
<version>20220320</version> <version>20220924</version>
</dependency>
<dependency>
<groupId>com.github.markozajc</groupId>
<artifactId>akiwrapper</artifactId>
<version>1.5.2</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mariadb.jdbc</groupId> <groupId>org.mariadb.jdbc</groupId>

View file

@ -95,7 +95,8 @@ public class Responder extends ListenerAdapter {
new UnMute(), new UnMute(),
new SetJoining(), new SetJoining(),
new History(), new History(),
new Sticker() new Sticker(),
new Akinator()
}; };
Arrays.stream(objects).forEach(register::register); Arrays.stream(objects).forEach(register::register);
} }
@ -194,13 +195,14 @@ public class Responder extends ListenerAdapter {
try { try {
event.deferEdit().queue(); event.deferEdit().queue();
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters); Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
if(temp == null) return;
Response response = (Response) temp; Response response = (Response) temp;
edit(response, event.getHook()); edit(response, event.getHook());
} catch (Exception e) { } catch (Exception e) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED) .setColor(Color.RED)
.setTitle(":x: **Error**") .setTitle(":x: **Error**")
.setDescription(e.getCause().getMessage()); .setDescription(e.getCause() != null ? e.getCause().getMessage() : "An unknown error has occurred");
event.getHook().editOriginalEmbeds(builder.build()).queue(); event.getHook().editOriginalEmbeds(builder.build()).queue();
event.getHook().editOriginalComponents(new ArrayList<>()).queue(); event.getHook().editOriginalComponents(new ArrayList<>()).queue();
} }
@ -242,6 +244,10 @@ public class Responder extends ListenerAdapter {
// Invoke Method and Respond to User // Invoke Method and Respond to User
try { try {
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters); Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
if(temp == null) {
event.reply("You dont have permission to use this!").setEphemeral(true).queue();
return;
}
Response response = (Response) temp; Response response = (Response) temp;
event.deferReply(response.isError()).queue(); event.deferReply(response.isError()).queue();
reply(response, event.getHook()); reply(response, event.getHook());

View file

@ -22,6 +22,7 @@ public class Response {
private String fileName; private String fileName;
private boolean hidden = false; private boolean hidden = false;
private boolean removeComponents = false;
public static Response error(String message){ public static Response error(String message){
Response response = new Response(); Response response = new Response();
@ -94,6 +95,11 @@ public class Response {
return this; return this;
} }
public Response setRemoveComponents(boolean removeComponents) {
this.removeComponents = removeComponents;
return this;
}
public boolean isError(){ public boolean isError(){
return type.equals("error"); return type.equals("error");
} }
@ -110,6 +116,8 @@ public class Response {
public boolean hasSelectMenu() { return menu != null; } public boolean hasSelectMenu() { return menu != null; }
public boolean hasNoComponents() { return removeComponents; }
public Button[] getButtons() { public Button[] getButtons() {
Button[] arr = new Button[buttons.size()]; Button[] arr = new Button[buttons.size()];
arr = buttons.toArray(arr); arr = buttons.toArray(arr);

View file

@ -0,0 +1,293 @@
package net.tylermurphy.ken.command.game;
import com.github.markozajc.akiwrapper.Akiwrapper;
import com.github.markozajc.akiwrapper.AkiwrapperBuilder;
import com.github.markozajc.akiwrapper.core.entities.Guess;
import com.github.markozajc.akiwrapper.core.entities.Identifiable;
import com.github.markozajc.akiwrapper.core.entities.Question;
import com.github.markozajc.akiwrapper.core.exceptions.ServerNotFoundException;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.command.annotation.ButtonCallback;
import net.tylermurphy.ken.command.annotation.Command;
import net.tylermurphy.ken.util.Checks;
import java.awt.*;
import java.util.*;
import java.util.List;
public class Akinator {
protected Map<Long, Integer> gameMappings = new HashMap<>();
protected Map<Integer, AkinatorGame> games = new HashMap<>();
@Command(name="akinator", description="Plays akinator")
public Response execute(Member sender, GuildMessageChannel channel) {
if(gameMappings.containsKey(sender.getIdLong())) {
games.remove(gameMappings.get(sender.getIdLong()));
gameMappings.remove(sender.getIdLong());
}
new Thread(() -> {
try {
AkinatorGame game = new AkinatorGame(sender, this);
gameMappings.put(sender.getIdLong(), game.getGameId());
games.put(game.getGameId(), game);
Response response = game.respond(null);
channel.sendMessageEmbeds(response.getEmbeds()).setActionRow(response.getButtons()).queue();
} catch (ServerNotFoundException e) {
channel.sendMessage(":x: Failed to connect to Akinator").queue();
}
}).start();
return Response.success(":arrows_clockwise: Connecting to Akinator");
}
@ButtonCallback(name="akinator")
public Response onButton(String id, Message message, Member sender) {
try { Checks.hasPagedEmbed(message); }
catch (RuntimeException e) { return Response.error(e.getMessage()); }
int gameId = Integer.parseInt(message.getEmbeds().get(0).getFooter().getText().substring(9));
AkinatorGame game = games.get(gameId);
if(game == null) {
return Response.error("Game has ended");
}
if(game.getUserId() != sender.getIdLong()) {
return null;
}
return game.respond(id);
}
}
enum AkiStatus {
QUESTION,
GUESS,
CONTINUE
}
class AkinatorGame {
private static int lastGameId = 0;
private final Akinator container;
private final Akiwrapper wrapper;
private final List<Identifiable> sequence;
private final List<String> guesses;
private final String displayName;
private final long userId;
private final int gameId;
private AkiStatus status;
private int questionNumber;
private int sequenceIndex;
private int attemptedGuesses;
public AkinatorGame(Member member, Akinator container) throws ServerNotFoundException {
this.container = container;
this.wrapper = new AkiwrapperBuilder().build();
this.sequence = new LinkedList<>();
this.guesses = new LinkedList<>();
this.displayName = member.getEffectiveName();
this.userId = member.getUser().getIdLong();
this.gameId = lastGameId++;
this.status = AkiStatus.QUESTION;
this.questionNumber = 0;
this.sequenceIndex = -1;
this.attemptedGuesses = 0;
}
public long getUserId() {
return userId;
}
public int getGameId() {
return gameId;
}
public Response respond(String label) {
if(label == null) return next();
if(status == AkiStatus.GUESS) {
return respondGuess(label);
} else if (status == AkiStatus.QUESTION) {
return respondQuestion(label);
} else if (status == AkiStatus.CONTINUE) {
return respondContinue(label);
}
throw new RuntimeException("Failed to respond to user input");
}
private Response respondGuess(String label) {
switch (label) {
case "yes":
container.games.remove(gameId);
container.gameMappings.remove(userId);
return sendLoose();
case "no":
status = AkiStatus.CONTINUE;
return sendContinue();
case "back":
return back();
}
throw new RuntimeException("Failed to respond to user input");
}
private Response respondContinue(String label) {
switch (label) {
case "yes":
return next();
case "no":
container.games.remove(gameId);
container.gameMappings.remove(userId);
return sendWin();
case "back":
return back();
}
throw new RuntimeException("Failed to respond to user input");
}
private Response respondQuestion(String label) {
switch (label) {
case "yes":
wrapper.answer(Akiwrapper.Answer.YES);
break;
case "no":
wrapper.answer(Akiwrapper.Answer.NO);
break;
case "idk":
wrapper.answer(Akiwrapper.Answer.DONT_KNOW);
break;
case "back":
return back();
}
return next();
}
private Response next() {
sequenceIndex++;
Optional<Guess> guess = wrapper.getGuesses().stream().filter(g -> g.getProbability() > .85 && !guesses.contains(g.getId())).reduce((first, second) -> second);
if(guess.isPresent()) {
status = AkiStatus.GUESS;
sequence.add(guess.get());
attemptedGuesses++;
return sendGuess(guess.get());
} else {
status = AkiStatus.QUESTION;
Question question = wrapper.getQuestion();
sequence.add(question);
questionNumber++;
if(question == null) {
// remove game
return sendWin();
}
return sendQuestion(question);
}
}
private Response back() {
sequenceIndex--;
Identifiable current = sequence.get(sequenceIndex+1);
if(current instanceof Guess) {
attemptedGuesses--;
guesses.remove(guesses.size() - 1);
sequence.remove(current);
} else if(current instanceof Question) {
questionNumber--;
sequence.remove(current);
}
Identifiable previous = sequence.get(sequenceIndex);
if(previous instanceof Guess guess) {
status = AkiStatus.GUESS;
return sendGuess(guess);
} else if(previous instanceof Question question){
status = AkiStatus.QUESTION;
return sendQuestion(question);
}
throw new RuntimeException("Failed to go back in sequence");
}
private Response sendGuess(Guess guess) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
builder.setAuthor("Akinator: " + displayName);
builder.setTitle("Is this your character?");
builder.appendDescription("**" + guess.getName() + "**\n" + guess.getDescription());
builder.setImage(guess.getImage().toExternalForm());
builder.setFooter("Game id: " + gameId);
Response response = Response.success(builder.build())
.addPrimaryButton("akinator", "yes", "Yes")
.addPrimaryButton("akinator", "no", "No");
if(sequenceIndex > 0)
response.addSecondaryButton("akinator", "back", "Back");
return response;
}
private Response sendQuestion(Question question) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
builder.setAuthor("Akinator: " + displayName);
builder.setTitle("Question " + questionNumber);
builder.appendDescription(question.getQuestion());
builder.setFooter("Game id: " + gameId);
Response response = Response.success(builder.build())
.addPrimaryButton("akinator", "yes", "Yes")
.addPrimaryButton("akinator", "no", "No")
.addPrimaryButton("akinator", "idk", "IDK");
if(sequenceIndex > 0)
response.addSecondaryButton("akinator", "back", "Back");
return response;
}
private Response sendContinue() {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
builder.setAuthor("Akinator: " + displayName);
builder.setTitle("Continue?");
builder.appendDescription("Akinator guessed incorrectly, would you like to continue?");
builder.setFooter("Game id: " + gameId);
Response response = Response.success(builder.build())
.addPrimaryButton("akinator", "yes", "Yes")
.addPrimaryButton("akinator", "no", "No");
if(sequenceIndex > 0)
response.addSecondaryButton("akinator", "back", "Back");
return response;
}
private Response sendWin() {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
builder.setAuthor("Akinator: " + displayName);
builder.setTitle("You win!");
builder.appendDescription("Total guesses: " + attemptedGuesses + "\n");
builder.appendDescription("Total questions: " + questionNumber);
builder.setFooter("Game id: " + gameId);
builder.setColor(new Color(130,255,130));
return Response.success(builder.build()).setRemoveComponents(true);
}
private Response sendLoose() {
Guess guess = (Guess) sequence.get(sequenceIndex);
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed();
builder.setAuthor("Akinator: " + displayName);
builder.setTitle("You loose :(");
builder.appendDescription("Total guesses: " + attemptedGuesses + "\n");
builder.appendDescription("Total questions: " + questionNumber + "\n");
builder.appendDescription("Character Guessed: " + guess.getName());
builder.setImage(guess.getImage().toExternalForm());
builder.setFooter("Game id: " + gameId);
builder.setColor(new Color(255,130,130));
return Response.success(builder.build()).setRemoveComponents(true);
}
}

View file

@ -88,7 +88,8 @@ public class Help {
.appendDescription("**/claim** Claim moneys every 24h\n") .appendDescription("**/claim** Claim moneys every 24h\n")
.appendDescription("**/money** Check how much moneys you have\n") .appendDescription("**/money** Check how much moneys you have\n")
.appendDescription("**/roulette <bet>** Gamble on roulette\n") .appendDescription("**/roulette <bet>** Gamble on roulette\n")
.appendDescription("**/slots <bet>** Gamble on slots\n"), .appendDescription("**/slots <bet>** Gamble on slots\n")
.appendDescription("**/akinator** Play akinator\n"),
Ken.getInstance().getDefaultEmbed() Ken.getInstance().getDefaultEmbed()
.setAuthor("Command List") .setAuthor("Command List")
.setTitle(":desktop: **Social Commands**") .setTitle(":desktop: **Social Commands**")