Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ gradle-app.setting
# End of https://www.toptal.com/developers/gitignore/api/netbeans,intellij,java,gradle,eclipse
application/db/
config.json
application/config.json
*.db
*.db-shm
*.db-wal
Expand Down
3 changes: 3 additions & 0 deletions application/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@ dependencies {

implementation 'org.jooq:jooq:3.15.3'

implementation 'io.mikael:urlbuilder:2.0.9'

implementation 'org.scilab.forge:jlatexmath:1.0.7'
implementation 'org.scilab.forge:jlatexmath-font-greek:1.0.7'
implementation 'org.scilab.forge:jlatexmath-font-cyrillic:1.0.7'

implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.13.0'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.0'
implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.13.0'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'

implementation 'com.github.freva:ascii-table:1.2.0'
Expand Down
3 changes: 2 additions & 1 deletion application/config.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@
"hostBlacklist": ["bit.ly"],
"suspiciousHostKeywords": ["discord", "nitro", "premium"],
"isHostSimilarToKeywordDistanceThreshold": 2
}
},
"wolframAlphaAppId": "79J52T-6239TVXHR7"
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.togetherjava.tjbot.commands.free.FreeChannelMonitor;
import org.togetherjava.tjbot.commands.free.FreeCommand;
import org.togetherjava.tjbot.commands.mathcommands.TeXCommand;
import org.togetherjava.tjbot.commands.mathcommands.wolframalpha.WolframAlphaCommand;
import org.togetherjava.tjbot.commands.moderation.*;
import org.togetherjava.tjbot.commands.moderation.scam.ScamBlocker;
import org.togetherjava.tjbot.commands.moderation.scam.ScamHistoryPurgeRoutine;
Expand Down Expand Up @@ -105,6 +106,7 @@ public enum Features {
features.add(new QuarantineCommand(actionsStore, config));
features.add(new UnquarantineCommand(actionsStore, config));
features.add(new WhoIsCommand());
features.add(new WolframAlphaCommand(config));

// Mixtures
features.add(new FreeCommand(config, freeChannelMonitor));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.togetherjava.tjbot.commands.mathcommands.wolframalpha;

import io.mikael.urlbuilder.UrlBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.callbacks.IDeferrableCallback;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.requests.restaction.WebhookMessageUpdateAction;
import org.jetbrains.annotations.NotNull;
import org.togetherjava.tjbot.commands.SlashCommandAdapter;
import org.togetherjava.tjbot.commands.SlashCommandVisibility;
import org.togetherjava.tjbot.config.Config;

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;

/**
* Command to send a query to the <a href="https://www.wolframalpha.com/">Wolfram Alpha</a> API.
* Renders its response as images.
*/
public final class WolframAlphaCommand extends SlashCommandAdapter {
private static final String QUERY_OPTION = "query";
/**
* WolframAlpha API endpoint to connect to.
*
* @see <a href=
* "https://products.wolframalpha.com/docs/WolframAlpha-API-Reference.pdf">WolframAlpha API
* Reference</a>.
*/
private static final String API_ENDPOINT = "http://api.wolframalpha.com/v2/query";
private static final HttpClient CLIENT = HttpClient.newHttpClient();

private final String appId;

/**
* Creates a new instance.
*
* @param config the config to use
*/
public WolframAlphaCommand(@NotNull Config config) {
super("wolfram-alpha", "Renders mathematical queries using WolframAlpha",
SlashCommandVisibility.GUILD);
getData().addOption(OptionType.STRING, QUERY_OPTION, "the query to send to WolframAlpha",
true);
appId = config.getWolframAlphaAppId();
}

@Override
public void onSlashCommand(@NotNull SlashCommandInteractionEvent event) {
String query = event.getOption(QUERY_OPTION).getAsString();
WolframAlphaHandler handler = new WolframAlphaHandler(query);

// The API call takes a bit
event.deferReply().queue();

// Send query
HttpRequest request = HttpRequest
.newBuilder(UrlBuilder.fromString(API_ENDPOINT)
.addParameter("appid", appId)
.addParameter("format", "image,plaintext")
.addParameter("input", query)
.toUri())
.GET()
.build();

CompletableFuture<HttpResponse<String>> apiResponse =
CLIENT.sendAsync(request, HttpResponse.BodyHandlers.ofString());

// Parse and respond
apiResponse.thenApply(handler::handleApiResponse)
.thenAccept(response -> sendResponse(response, event));
}

private static void sendResponse(@NotNull WolframAlphaHandler.HandlerResponse response,
@NotNull IDeferrableCallback event) {
WebhookMessageUpdateAction<Message> action =
event.getHook().editOriginalEmbeds(response.embeds());

for (WolframAlphaHandler.Attachment attachment : response.attachments()) {
action = action.addFile(attachment.data(), attachment.name());
}

action.queue();
}
}
Loading