Skip to content

Commit fe4eec0

Browse files
committed
feat: overhaul webhooks and add tests for the API
1 parent 8ad36fa commit fe4eec0

45 files changed

Lines changed: 538 additions & 186 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/discord4jWrapper/java/org/discordbots/api/discord4j/Discord4JPostCommandsTransformer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import discord4j.common.JacksonResources;
55
import discord4j.core.DiscordClient;
66
import java.util.concurrent.CompletionStage;
7-
import org.discordbots.api.client.io.PostCommandsTransformer;
7+
import org.discordbots.api.io.PostCommandsTransformer;
88

99
public class Discord4JPostCommandsTransformer implements PostCommandsTransformer {
1010
private final DiscordClient client;

src/dropwizardWebhooks/java/org/discordbots/webhooks/dropwizard/DropwizardWebhooks.java renamed to src/dropwizardWebhooks/java/org/discordbots/webhooks/dropwizard/DiscordBotListWebhooks.java

Lines changed: 25 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,34 @@
2121
import java.util.stream.Collectors;
2222
import javax.crypto.Mac;
2323
import javax.crypto.spec.SecretKeySpec;
24-
import org.discordbots.webhooks.IntegrationCreatePayload;
25-
import org.discordbots.webhooks.IntegrationDeletePayload;
26-
import org.discordbots.webhooks.Payload;
27-
import org.discordbots.webhooks.TestPayload;
28-
import org.discordbots.webhooks.VoteCreatePayload;
29-
30-
public class DropwizardWebhooks {
31-
private final byte[] authorization;
24+
import org.discordbots.webhooks.payload.IntegrationCreatePayload;
25+
import org.discordbots.webhooks.payload.IntegrationDeletePayload;
26+
import org.discordbots.webhooks.payload.Payload;
27+
import org.discordbots.webhooks.payload.TestPayload;
28+
import org.discordbots.webhooks.payload.VoteCreatePayload;
29+
30+
public abstract class DiscordBotListWebhooks implements DiscordBotListWebhooksListener {
31+
private byte[] secret;
3232
private final Gson gson;
33-
private final DropwizardWebhooks.Listener listener;
3433

35-
public DropwizardWebhooks(
36-
final String authorization, final DropwizardWebhooks.Listener listener) {
37-
this.authorization = authorization.getBytes(StandardCharsets.UTF_8);
34+
public DiscordBotListWebhooks(final String secret) {
35+
this.secret = secret.getBytes(StandardCharsets.UTF_8);
3836
this.gson =
3937
new GsonBuilder()
4038
.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeConverter())
4139
.create();
42-
this.listener = listener;
40+
}
41+
42+
public String getSecret() {
43+
return new String(secret, StandardCharsets.UTF_8);
44+
}
45+
46+
public void setSecret(final String newSecret) {
47+
secret = newSecret.getBytes(StandardCharsets.UTF_8);
4348
}
4449

4550
@POST
51+
@SuppressWarnings("UseSpecificCatch")
4652
public Response handle(@Context HttpServletRequest request) throws WebApplicationException {
4753
try {
4854
final String signatureHeader = request.getHeader("x-topgg-signature");
@@ -64,7 +70,7 @@ public Response handle(@Context HttpServletRequest request) throws WebApplicatio
6470

6571
assert signature != null && timestamp != null;
6672

67-
final SecretKeySpec key = new SecretKeySpec(authorization, "HmacSHA256");
73+
final SecretKeySpec key = new SecretKeySpec(secret, "HmacSHA256");
6874
final Mac hmac = Mac.getInstance("HmacSHA256");
6975

7076
hmac.init(key);
@@ -86,17 +92,14 @@ public Response handle(@Context HttpServletRequest request) throws WebApplicatio
8692
try {
8793
return switch (payload.getType()) {
8894
case "integration.create" ->
89-
listener.onIntegrationCreate(
90-
payload.getData(gson, IntegrationCreatePayload.class), trace);
95+
onIntegrationCreate(payload.getData(gson, IntegrationCreatePayload.class), trace);
9196
case "integration.delete" ->
92-
listener.onIntegrationDelete(
93-
payload.getData(gson, IntegrationDeletePayload.class), trace);
94-
case "webhook.test" -> listener.onTest(payload.getData(gson, TestPayload.class), trace);
95-
case "vote.create" ->
96-
listener.onVoteCreate(payload.getData(gson, VoteCreatePayload.class), trace);
97+
onIntegrationDelete(payload.getData(gson, IntegrationDeletePayload.class), trace);
98+
case "webhook.test" -> onTest(payload.getData(gson, TestPayload.class), trace);
99+
case "vote.create" -> onVoteCreate(payload.getData(gson, VoteCreatePayload.class), trace);
97100
default -> Response.status(Response.Status.BAD_REQUEST).entity("Bad Request").build();
98101
};
99-
} catch (Throwable ignored) {
102+
} catch (final Throwable ignored) {
100103
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
101104
.entity("Internal Server Error")
102105
.build();
@@ -115,22 +118,4 @@ public Response handle(@Context HttpServletRequest request) throws WebApplicatio
115118
}
116119
}
117120
}
118-
119-
public interface Listener {
120-
default Response onIntegrationCreate(IntegrationCreatePayload payload, String trace) {
121-
return Response.status(Response.Status.NO_CONTENT).build();
122-
}
123-
124-
default Response onIntegrationDelete(IntegrationDeletePayload payload, String trace) {
125-
return Response.status(Response.Status.NO_CONTENT).build();
126-
}
127-
128-
default Response onTest(TestPayload payload, String trace) {
129-
return Response.status(Response.Status.NO_CONTENT).build();
130-
}
131-
132-
default Response onVoteCreate(VoteCreatePayload payload, String trace) {
133-
return Response.status(Response.Status.NO_CONTENT).build();
134-
}
135-
}
136121
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.discordbots.webhooks.dropwizard;
2+
3+
import jakarta.ws.rs.core.Response;
4+
import org.discordbots.webhooks.payload.IntegrationCreatePayload;
5+
import org.discordbots.webhooks.payload.IntegrationDeletePayload;
6+
import org.discordbots.webhooks.payload.TestPayload;
7+
import org.discordbots.webhooks.payload.VoteCreatePayload;
8+
9+
public interface DiscordBotListWebhooksListener {
10+
default Response onIntegrationCreate(IntegrationCreatePayload payload, String trace) {
11+
return Response.status(Response.Status.NO_CONTENT).build();
12+
}
13+
14+
default Response onIntegrationDelete(IntegrationDeletePayload payload, String trace) {
15+
return Response.status(Response.Status.NO_CONTENT).build();
16+
}
17+
18+
default Response onTest(TestPayload payload, String trace) {
19+
return Response.status(Response.Status.NO_CONTENT).build();
20+
}
21+
22+
default Response onVoteCreate(VoteCreatePayload payload, String trace) {
23+
return Response.status(Response.Status.NO_CONTENT).build();
24+
}
25+
}

src/eclipseJettyWebhooks/java/org/discordbots/webhooks/eclipsejetty/EclipseJettyWebhooks.java renamed to src/eclipseJettyWebhooks/java/org/discordbots/webhooks/eclipsejetty/DiscordBotListWebhooks.java

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,34 @@
2020
import java.util.stream.Collectors;
2121
import javax.crypto.Mac;
2222
import javax.crypto.spec.SecretKeySpec;
23-
import org.discordbots.webhooks.IntegrationCreatePayload;
24-
import org.discordbots.webhooks.IntegrationDeletePayload;
25-
import org.discordbots.webhooks.Payload;
26-
import org.discordbots.webhooks.TestPayload;
27-
import org.discordbots.webhooks.VoteCreatePayload;
28-
29-
public class EclipseJettyWebhooks extends HttpServlet {
30-
private final byte[] authorization;
23+
import org.discordbots.webhooks.payload.IntegrationCreatePayload;
24+
import org.discordbots.webhooks.payload.IntegrationDeletePayload;
25+
import org.discordbots.webhooks.payload.Payload;
26+
import org.discordbots.webhooks.payload.TestPayload;
27+
import org.discordbots.webhooks.payload.VoteCreatePayload;
28+
29+
public class DiscordBotListWebhooks extends HttpServlet implements DiscordBotListWebhooksListener {
30+
private byte[] secret;
3131
private final Gson gson;
32-
private final EclipseJettyWebhooks.Listener listener;
3332

34-
public EclipseJettyWebhooks(
35-
final String authorization, final EclipseJettyWebhooks.Listener listener) {
36-
this.authorization = authorization.getBytes(StandardCharsets.UTF_8);
33+
public DiscordBotListWebhooks(final String secret) {
34+
this.secret = secret.getBytes(StandardCharsets.UTF_8);
3735
this.gson =
3836
new GsonBuilder()
3937
.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeConverter())
4038
.create();
41-
this.listener = listener;
39+
}
40+
41+
public String getSecret() {
42+
return new String(secret, StandardCharsets.UTF_8);
43+
}
44+
45+
public void setSecret(final String newSecret) {
46+
secret = newSecret.getBytes(StandardCharsets.UTF_8);
4247
}
4348

4449
@Override
50+
@SuppressWarnings("UseSpecificCatch")
4551
protected void doPost(HttpServletRequest request, HttpServletResponse response)
4652
throws IOException, ServletException {
4753
try {
@@ -64,7 +70,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
6470

6571
assert signature != null && timestamp != null;
6672

67-
final SecretKeySpec key = new SecretKeySpec(authorization, "HmacSHA256");
73+
final SecretKeySpec key = new SecretKeySpec(secret, "HmacSHA256");
6874
final Mac hmac = Mac.getInstance("HmacSHA256");
6975

7076
hmac.init(key);
@@ -87,18 +93,16 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
8793
try {
8894
switch (payload.getType()) {
8995
case "integration.create" ->
90-
listener.onIntegrationCreate(
96+
onIntegrationCreate(
9197
response, payload.getData(gson, IntegrationCreatePayload.class), trace);
9298
case "integration.delete" ->
93-
listener.onIntegrationDelete(
99+
onIntegrationDelete(
94100
response, payload.getData(gson, IntegrationDeletePayload.class), trace);
95-
case "webhook.test" ->
96-
listener.onTest(response, payload.getData(gson, TestPayload.class), trace);
101+
case "webhook.test" -> onTest(response, payload.getData(gson, TestPayload.class), trace);
97102
case "vote.create" ->
98-
listener.onVoteCreate(
99-
response, payload.getData(gson, VoteCreatePayload.class), trace);
103+
onVoteCreate(response, payload.getData(gson, VoteCreatePayload.class), trace);
100104
}
101-
} catch (Throwable ignored) {
105+
} catch (final Throwable ignored) {
102106
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
103107
response.getWriter().write("Internal Server Error");
104108
}
@@ -117,25 +121,4 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response)
117121
}
118122
}
119123
}
120-
121-
public interface Listener {
122-
default void onIntegrationCreate(
123-
HttpServletResponse response, IntegrationCreatePayload payload, String trace) {
124-
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
125-
}
126-
127-
default void onIntegrationDelete(
128-
HttpServletResponse response, IntegrationDeletePayload payload, String trace) {
129-
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
130-
}
131-
132-
default void onTest(HttpServletResponse response, TestPayload payload, String trace) {
133-
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
134-
}
135-
136-
default void onVoteCreate(
137-
HttpServletResponse response, VoteCreatePayload payload, String trace) {
138-
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
139-
}
140-
}
141124
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.discordbots.webhooks.eclipsejetty;
2+
3+
import jakarta.servlet.http.HttpServletResponse;
4+
import org.discordbots.webhooks.payload.IntegrationCreatePayload;
5+
import org.discordbots.webhooks.payload.IntegrationDeletePayload;
6+
import org.discordbots.webhooks.payload.TestPayload;
7+
import org.discordbots.webhooks.payload.VoteCreatePayload;
8+
9+
public interface DiscordBotListWebhooksListener {
10+
default void onIntegrationCreate(
11+
HttpServletResponse response, IntegrationCreatePayload payload, String trace) {
12+
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
13+
}
14+
15+
default void onIntegrationDelete(
16+
HttpServletResponse response, IntegrationDeletePayload payload, String trace) {
17+
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
18+
}
19+
20+
default void onTest(HttpServletResponse response, TestPayload payload, String trace) {
21+
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
22+
}
23+
24+
default void onVoteCreate(HttpServletResponse response, VoteCreatePayload payload, String trace) {
25+
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
26+
}
27+
}

src/jdaWrapper/java/org/discordbots/api/jda/JDAPostCommandsTransformer.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import net.dv8tion.jda.api.JDA;
77
import net.dv8tion.jda.api.interactions.commands.Command;
88
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
9-
import org.discordbots.api.client.io.PostCommandsTransformer;
9+
import org.discordbots.api.io.PostCommandsTransformer;
1010

1111
public class JDAPostCommandsTransformer implements PostCommandsTransformer {
1212
private final JDA jda;
@@ -17,8 +17,7 @@ public JDAPostCommandsTransformer(final JDA jda) {
1717

1818
@Override
1919
public CompletionStage<String> toJsonString() {
20-
return this.jda
21-
.retrieveCommands()
20+
return jda.retrieveCommands()
2221
.submit()
2322
.thenApply(
2423
commands -> {

0 commit comments

Comments
 (0)