diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 00000000..9b3107fc Binary files /dev/null and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 00000000..2fa0addb --- /dev/null +++ b/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Sun Jun 02 11:19:53 PDT 2024 +gradle.version=8.7 diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 00000000..df139d5b Binary files /dev/null and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe new file mode 100644 index 00000000..b9f159b2 Binary files /dev/null and b/.gradle/file-system.probe differ diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties new file mode 100644 index 00000000..e69de29b diff --git a/src/main/java/org/jointheleague/api_wrapper/ReceivedMessage.java b/src/main/java/org/jointheleague/api_wrapper/ReceivedMessage.java index 03c76db1..8821ba7f 100644 --- a/src/main/java/org/jointheleague/api_wrapper/ReceivedMessage.java +++ b/src/main/java/org/jointheleague/api_wrapper/ReceivedMessage.java @@ -2,6 +2,7 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; public class ReceivedMessage { @@ -24,4 +25,7 @@ public Message sendResponse(MessageEmbed embed) { return this.event.getChannel().sendMessageEmbeds(embed).submit().join(); } + public User getAuthor() { + return this.event.getAuthor(); + } } \ No newline at end of file diff --git a/src/main/java/org/jointheleague/discord_bot/DiscordBot.java b/src/main/java/org/jointheleague/discord_bot/DiscordBot.java index cefb5f79..15e5d9b5 100644 --- a/src/main/java/org/jointheleague/discord_bot/DiscordBot.java +++ b/src/main/java/org/jointheleague/discord_bot/DiscordBot.java @@ -11,9 +11,10 @@ import org.jointheleague.features.examples.third_features.CatFactsApi; import org.jointheleague.features.examples.third_features.NewsApi; import org.jointheleague.features.examples.first_features.CurrentTime; -import org.jointheleague.features.examples.first_features.RandomNumber; import org.jointheleague.features.help_embed.HelpListener; -import org.jointheleague.features.student.first_feature.FeatureOne; +import org.jointheleague.features.student.first_feature.RiddleApi; +import org.jointheleague.features.student.first_feature.capitalsGame; +import org.jointheleague.features.student.first_feature.wuQuote; public class DiscordBot { @@ -56,7 +57,9 @@ public void connect(boolean printInvite) throws InterruptedException { api.addEventListener(helpListener); //add features - addFeature(new FeatureOne(channelName)); + addFeature(new wuQuote(channelName)); + addFeature(new capitalsGame(channelName)); + addFeature(new RiddleApi(channelName)); addFeature(new CurrentTime(channelName)); addFeature(new HighLowGame(channelName)); addFeature(new NewsApi(channelName)); diff --git a/src/main/java/org/jointheleague/features/student/first_feature/RiddleApi.java b/src/main/java/org/jointheleague/features/student/first_feature/RiddleApi.java new file mode 100644 index 00000000..c171b26c --- /dev/null +++ b/src/main/java/org/jointheleague/features/student/first_feature/RiddleApi.java @@ -0,0 +1,53 @@ +package org.jointheleague.features.student.first_feature; + +import org.jointheleague.api_wrapper.ReceivedMessage; +import org.jointheleague.features.student.first_feature.RiddleWrapper; +import org.jointheleague.features.help_embed.plain_old_java_objects.help_embed.HelpEmbed; +import org.jointheleague.features.templates.FeatureTemplate; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +public class RiddleApi extends FeatureTemplate { + + public final String COMMAND = "!riddleApi"; + + private WebClient webClient; + private static final String baseUrl = "https://riddles-api.vercel.app/random"; + + public RiddleApi(String channelName) { + super(channelName); + helpEmbed = new HelpEmbed(COMMAND, "Example of using an API to get information from another service. This returns a riddle."); + + //build the WebClient + this.webClient = WebClient + .builder() + .baseUrl(baseUrl) + .build(); + } + +@Override + public void handle(ReceivedMessage event) { + String messageContent = event.getMessageContent(); + if (messageContent.startsWith(COMMAND)) { + String riddle = getRiddle(); + event.sendResponse(riddle); + } + } + + public String getRiddle() { + + Mono mono = webClient.get() + .retrieve() + .bodyToMono(RiddleWrapper.class); + + + RiddleWrapper r = mono.block(); + return r.toString(); + } + + public void setWebClient(WebClient webClient) { + this.webClient = webClient; + } + +} + diff --git a/src/main/java/org/jointheleague/features/student/first_feature/RiddleWrapper.java b/src/main/java/org/jointheleague/features/student/first_feature/RiddleWrapper.java new file mode 100644 index 00000000..ff5d9167 --- /dev/null +++ b/src/main/java/org/jointheleague/features/student/first_feature/RiddleWrapper.java @@ -0,0 +1,36 @@ +package org.jointheleague.features.student.first_feature; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class RiddleWrapper { + + @SerializedName("riddle") + @Expose + private String riddle; + @SerializedName("answer") + @Expose + private String answer; + + public String getRiddle() { + return riddle; + } + + public void setRiddle(String riddle) { + this.riddle = riddle; + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } + + public String toString() + { + return "RIDDLE: " + this.riddle + "\n\nANSWER: "+ this.answer; + } + +} \ No newline at end of file diff --git a/src/main/java/org/jointheleague/features/student/first_feature/capitalsGame.java b/src/main/java/org/jointheleague/features/student/first_feature/capitalsGame.java new file mode 100644 index 00000000..fea919a1 --- /dev/null +++ b/src/main/java/org/jointheleague/features/student/first_feature/capitalsGame.java @@ -0,0 +1,133 @@ +package org.jointheleague.features.student.first_feature; + +import net.dv8tion.jda.api.entities.User; +import org.jointheleague.api_wrapper.ReceivedMessage; +import org.jointheleague.features.help_embed.plain_old_java_objects.help_embed.HelpEmbed; +import org.jointheleague.features.templates.FeatureTemplate; + +import java.util.*; + +public class capitalsGame extends FeatureTemplate { + + public final String COMMAND = "!capitalsGame"; + private final Random random = new Random(); + String country; + String capital; + int num; + String [] answers; + boolean play = false; + + + public capitalsGame(String channelName) { + super(channelName); + helpEmbed = new HelpEmbed(COMMAND, "Guess the correct capital of the country!"); + } + + @Override + public void handle(ReceivedMessage event) { + User messageAuthor = event.getAuthor(); + String messageContent = event.getMessageContent(); + + + + + //start the game with the command + if (messageContent.equals(COMMAND)) { + play = true; + LinkedList countries = new LinkedList(); + Collections.addAll(countries, new String []{"China", "UK", "Belgium", "Norway", "Japan", "Argentina", "Peru", "Mexico", "Greece", "Australia", "Ecuador", + "Afghanistan", "Qatar", "Egypt", "South Korea", "Angola", "Kenya", "Indonesia", "Ireland", "Italy", "Germany", + "Zimbabwe", "Uruguay", "Syria", "Paraguay", "Hungary", "Austria", "Azerbaijan", "Jamaica"}); + LinkedList capitals = new LinkedList(); + Collections.addAll(capitals, new String[]{"Beijing", "London", "Brussels", "Oslo", "Tokyo", "Buenos Aires", "Lima", "Mexico City", "Athens", "Canberra", + "Quito", "Kabul", "Doha", "Cairo", "Seoul", "Luanda", "Nairobi", "Jakarta", "Dublin", "Rome", "Berlin", + "Harare", "Montevideo", "Damascus", "Asuncion", "Budapest", "Vienna", "Baku", "Kingston"}); + + num = random.nextInt(capitals.size()); + + country = countries.remove(num); + capital = capitals.remove(num); + + + + answers = new String [5]; + + int answerIndex = random.nextInt(4); + answers[answerIndex] = capital; + for(int i = 0; i < answers.length-1; i++) + { + if(answers[i] == null) + { + int newRan = random.nextInt(capitals.size()); + answers[i] = capitals.remove(newRan); + } + } + + event.sendResponse("What is the capital of "+country+"? (Answer with the command followed by 'A', 'B', 'C', or 'D')"+ + "\nA: "+answers[0]+ + "\nB: "+answers[1]+ + "\nC: "+answers[2]+ + "\nD: "+answers[3]); + } + //check a guess + else if (messageContent.contains(COMMAND) + && !messageContent.contains("e.g.") + && !messageContent.contains("this:") && play) { + + + //check if the game has been started + if(capital.isEmpty()){ + //tell them to start the game first + event.sendResponse("Please start the game first using just the command"); + return; + } + + + //parse the guess from the message + String guess = messageContent.replaceAll(" ", "").replace(COMMAND, ""); + + if(guess.equals("A")) { + if(answers[0].equals(capital)) + { + event.sendResponse("Yes! The capital of "+country+ " is "+capital+ "! Well done!"); + play = false; + }else{ + event.sendResponse("Nope! The capital of "+country+ " is something else! Try again!"); + } + } + else if(guess.equals("B")){ + if(answers[1].equals(capital)) + { + event.sendResponse("Yes! The capital of "+country+ " is "+capital+ "! Well done!"); + play = false; + }else{ + event.sendResponse("Nope! The capital of "+country+ " is something else! Try again!"); + } + } + else if(guess.equals("C")){ + if(answers[2].equals(capital)) + { + event.sendResponse("Yes! The capital of "+country+ " is "+capital+ "! Well done!"); + play = false; + }else{ + event.sendResponse("Nope! The capital of "+country+ " is something else! Try again!"); + } + } + else if(guess.equals("D")){ + if(answers[3].equals(capital)) + { + event.sendResponse("Yes! The capital of "+country+ " is "+capital+ "! Well done!"); + play = false; + }else{ + event.sendResponse("Nope! The capital of "+country+ " is something else! Try again!"); + } + } + else + { + event.sendResponse("Please enter a valid command. "); + } + event.sendResponse(guess + " "); + + } + } +} diff --git a/src/main/java/org/jointheleague/features/student/first_feature/wuQuote.java b/src/main/java/org/jointheleague/features/student/first_feature/wuQuote.java new file mode 100644 index 00000000..9c5c05cf --- /dev/null +++ b/src/main/java/org/jointheleague/features/student/first_feature/wuQuote.java @@ -0,0 +1,49 @@ +package org.jointheleague.features.student.first_feature; + +import org.jointheleague.api_wrapper.ReceivedMessage; +import org.jointheleague.features.help_embed.plain_old_java_objects.help_embed.HelpEmbed; +import org.jointheleague.features.templates.FeatureTemplate; + +import java.util.Random; + +public class wuQuote extends FeatureTemplate { + public final String COMMAND = "!wuQuote"; + + public wuQuote(String channelName) { + super(channelName); + + //Create a help embed to describe feature when !help command is sent + helpEmbed = new HelpEmbed( + COMMAND, + "This command prints a wise quote from Master Wu." + ); + } +//IGNORE + @Override + public void handle(ReceivedMessage event) { + String messageContent = event.getMessageContent(); + if (messageContent.startsWith(COMMAND)) { + //respond to message here + String[] list = {"'Never put off until tomorrow, what can be done today.'", + "'What is weird? Someone who is different, or someone who is different from you?", + "'Ninja never quit.'", + "'If you want something bad enough, you find a way to make it happen.'", + "'Lost? Hm. An interesting word. Sometimes one has to be lost in order to be found.'", + "'The best way to defeat your enemy is to make them your friend.'", + "'Focus on your adversary, no matter how insignificant. Make its strength your strength.'", + "'You are all my prized pupils, but none of us can do this alone.'" + }; + Random r = new Random(); + event.sendResponse(list[r.nextInt(list.length-1)]); + + } + + } + } + + + + + + + diff --git a/src/test/java/org/jointheleague/features/student/first_feature/FeatureOneTest.java b/src/test/java/org/jointheleague/features/student/first_feature/FeatureOneTest.java index 8c95c657..7005c59d 100644 --- a/src/test/java/org/jointheleague/features/student/first_feature/FeatureOneTest.java +++ b/src/test/java/org/jointheleague/features/student/first_feature/FeatureOneTest.java @@ -21,7 +21,7 @@ public class FeatureOneTest { private final String testChannelName = "test"; - private final FeatureOne featureOne = new FeatureOne(testChannelName); + private final wuQuote featureOne = new wuQuote(testChannelName); private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); private final PrintStream originalOut = System.out; diff --git a/src/test/java/org/jointheleague/features/student/first_feature/RiddleApiTest.java b/src/test/java/org/jointheleague/features/student/first_feature/RiddleApiTest.java new file mode 100644 index 00000000..27c2eec2 --- /dev/null +++ b/src/test/java/org/jointheleague/features/student/first_feature/RiddleApiTest.java @@ -0,0 +1,115 @@ +package org.jointheleague.features.student.first_feature; + +import org.jointheleague.api_wrapper.ReceivedMessage; +import org.jointheleague.features.help_embed.plain_old_java_objects.help_embed.HelpEmbed; +import org.jointheleague.features.templates.FeatureTemplate; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.never; + +public class RiddleApiTest { + private final String testChannelName = "test"; + private final wuQuote featureOne = new wuQuote(testChannelName); + + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; +@Mock + private ReceivedMessage messageCreateEvent; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + System.setOut(new PrintStream(outContent)); + } + + @AfterEach + public void itShouldNotPrintToSystemOut() { + String expected = ""; + String actual = outContent.toString(); + + assertEquals(expected, actual); + System.setOut(originalOut); + } + + @Test + void itShouldHaveACommand() { + //Given + + //When + String command = featureOne.COMMAND; + + //Then + + if(!(featureOne instanceof FeatureTemplate)){ + assertNotEquals("!command", command); + } + + assertNotEquals("", command); + assertNotEquals("!", command); + assertNotEquals("!command", command); + assertEquals('!', command.charAt(0)); + assertNotNull(command); + } + + @Test + void itShouldHandleMessagesWithCommand() { + //Given + HelpEmbed helpEmbed = new HelpEmbed(featureOne.COMMAND, "test"); + when(messageCreateEvent.getMessageContent()).thenReturn(featureOne.COMMAND); + + //When + featureOne.handle(messageCreateEvent); + + //Then + verify(messageCreateEvent, times(1)).sendResponse(anyString()); + } + + @Test + void itShouldNotHandleMessagesWithoutCommand() { + //Given + String command = ""; + when(messageCreateEvent.getMessageContent()).thenReturn(command); + + //When + featureOne.handle(messageCreateEvent); + + verify(messageCreateEvent, never()).sendResponse(""); + } + + @Test + void itShouldHaveAHelpEmbed() { + //Given + + //When + HelpEmbed actualHelpEmbed = featureOne.getHelpEmbed(); + + //Then + assertNotNull(actualHelpEmbed); + } + + @Test + void itShouldHaveTheCommandAsTheTitleOfTheHelpEmbed() { + //Given + + //When + String helpEmbedTitle = featureOne.getHelpEmbed().getTitle(); + String command = featureOne.COMMAND; + + //Then + assertEquals(command, helpEmbedTitle); + } + +} + diff --git a/src/test/java/org/jointheleague/features/student/first_feature/capitalsGameTest.java b/src/test/java/org/jointheleague/features/student/first_feature/capitalsGameTest.java new file mode 100644 index 00000000..aa6ebf0f --- /dev/null +++ b/src/test/java/org/jointheleague/features/student/first_feature/capitalsGameTest.java @@ -0,0 +1,119 @@ +package org.jointheleague.features.student.first_feature; + +import org.jointheleague.api_wrapper.ReceivedMessage; +import org.jointheleague.features.help_embed.plain_old_java_objects.help_embed.HelpEmbed; +import org.jointheleague.features.templates.FeatureTemplate; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.never; + +public class capitalsGameTest { + private final String testChannelName = "test"; + private final wuQuote featureOne = new wuQuote(testChannelName); + + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + + @Mock + private ReceivedMessage messageCreateEvent; + + @Mock + private ReceivedMessage textChannel; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + System.setOut(new PrintStream(outContent)); + } + + @AfterEach + public void itShouldNotPrintToSystemOut() { + String expected = ""; + String actual = outContent.toString(); + + assertEquals(expected, actual); + System.setOut(originalOut); + } + + @Test + void itShouldHaveACommand() { + //Given + + //When + String command = featureOne.COMMAND; + + //Then + + if(!(featureOne instanceof FeatureTemplate)){ + assertNotEquals("!command", command); + } + + assertNotEquals("", command); + assertNotEquals("!", command); + assertNotEquals("!command", command); + assertEquals('!', command.charAt(0)); + assertNotNull(command); + } + + @Test + void itShouldHandleMessagesWithCommand() { + //Given + HelpEmbed helpEmbed = new HelpEmbed(featureOne.COMMAND, "test"); + when(messageCreateEvent.getMessageContent()).thenReturn(featureOne.COMMAND); + + //When + featureOne.handle(messageCreateEvent); + + //Then + verify(messageCreateEvent, times(1)).sendResponse(anyString()); + } + + @Test + void itShouldNotHandleMessagesWithoutCommand() { + //Given + String command = ""; + when(messageCreateEvent.getMessageContent()).thenReturn(command); + + //When + featureOne.handle(messageCreateEvent); + + //Then + verify(messageCreateEvent, never()).sendResponse(""); + } + + @Test + void itShouldHaveAHelpEmbed() { + //Given + + //When + HelpEmbed actualHelpEmbed = featureOne.getHelpEmbed(); + + //Then + assertNotNull(actualHelpEmbed); + } + + @Test + void itShouldHaveTheCommandAsTheTitleOfTheHelpEmbed() { + //Given + + //When + String helpEmbedTitle = featureOne.getHelpEmbed().getTitle(); + String command = featureOne.COMMAND; + + //Then + assertEquals(command, helpEmbedTitle); + } + +} diff --git a/src/test/java/org/jointheleague/features/student/first_feature/wuQuoteTest.java b/src/test/java/org/jointheleague/features/student/first_feature/wuQuoteTest.java new file mode 100644 index 00000000..599d3455 --- /dev/null +++ b/src/test/java/org/jointheleague/features/student/first_feature/wuQuoteTest.java @@ -0,0 +1,117 @@ +package org.jointheleague.features.student.first_feature; + +import org.jointheleague.api_wrapper.ReceivedMessage; +import org.jointheleague.api_wrapper.ReceivedMessage; +import org.jointheleague.features.help_embed.plain_old_java_objects.help_embed.HelpEmbed; +import org.jointheleague.features.templates.FeatureTemplate; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.never; + +public class wuQuoteTest { + private final String testChannelName = "test"; + private final wuQuote featureOne = new wuQuote(testChannelName); + + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + private final PrintStream originalOut = System.out; + + @Mock + private ReceivedMessage messageCreateEvent; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + System.setOut(new PrintStream(outContent)); + } + + @AfterEach + public void itShouldNotPrintToSystemOut() { + String expected = ""; + String actual = outContent.toString(); + + assertEquals(expected, actual); + System.setOut(originalOut); + } + + @Test + void itShouldHaveACommand() { + //Given + + //When + String command = featureOne.COMMAND; + + //Then + + if(!(featureOne instanceof FeatureTemplate)){ + assertNotEquals("!command", command); + } + + assertNotEquals("", command); + assertNotEquals("!", command); + assertNotEquals("!command", command); + assertEquals('!', command.charAt(0)); + assertNotNull(command); + } + + @Test + void itShouldHandleMessagesWithCommand() { + //Given + HelpEmbed helpEmbed = new HelpEmbed(featureOne.COMMAND, "test"); + when(messageCreateEvent.getMessageContent()).thenReturn(featureOne.COMMAND); + + //When + featureOne.handle(messageCreateEvent); + + //Then + verify(messageCreateEvent, times(1)).sendResponse(anyString()); + } + + @Test + void itShouldNotHandleMessagesWithoutCommand() { + //Given + String command = ""; + when(messageCreateEvent.getMessageContent()).thenReturn(command); + + //When + featureOne.handle(messageCreateEvent); + + //Then + verify(messageCreateEvent, never()).sendResponse(""); + } + + @Test + void itShouldHaveAHelpEmbed() { + //Given + + //When + HelpEmbed actualHelpEmbed = featureOne.getHelpEmbed(); + + //Then + assertNotNull(actualHelpEmbed); + } + + @Test + void itShouldHaveTheCommandAsTheTitleOfTheHelpEmbed() { + //Given + + //When + String helpEmbedTitle = featureOne.getHelpEmbed().getTitle(); + String command = featureOne.COMMAND; + + //Then + assertEquals(command, helpEmbedTitle); + } + +}