From 462882b95d1bd8c1ca6c9654fb9a7559634acd5d Mon Sep 17 00:00:00 2001 From: Hunter Jackson Date: Wed, 20 Dec 2023 17:51:29 -0500 Subject: [PATCH 1/2] rely on getting the instagram fb source page from the Plugin --- .../meta/cp4m/message/FBMessageHandler.java | 25 ++++------- .../meta/cp4m/message/FBMessengerConfig.java | 41 +++++++++---------- .../cp4m/message/FBMessageHandlerTest.java | 4 +- .../cp4m/message/FBMessengerConfigTest.java | 13 +++++- 4 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/meta/cp4m/message/FBMessageHandler.java b/src/main/java/com/meta/cp4m/message/FBMessageHandler.java index 2d3704b..a84625b 100644 --- a/src/main/java/com/meta/cp4m/message/FBMessageHandler.java +++ b/src/main/java/com/meta/cp4m/message/FBMessageHandler.java @@ -44,7 +44,7 @@ public class FBMessageHandler implements MessageHandler { private final String appSecret; private final String accessToken; - private final @Nullable String connectedFacebookPageForInstagram; + private final boolean instagramMode; private final Deduplicator messageDeduplicator = new Deduplicator<>(10_000); private Function baseURLFactory = @@ -64,31 +64,25 @@ public class FBMessageHandler implements MessageHandler { }; public FBMessageHandler( - String verifyToken, - String pageAccessToken, - String appSecret, - @Nullable String connectedFacebookPageForInstagram) { + String verifyToken, String pageAccessToken, String appSecret, boolean instagramMode) { this.verifyToken = verifyToken; this.appSecret = appSecret; this.accessToken = pageAccessToken; - this.connectedFacebookPageForInstagram = connectedFacebookPageForInstagram; + this.instagramMode = instagramMode; } public FBMessageHandler(String verifyToken, String pageAccessToken, String appSecret) { this.verifyToken = verifyToken; this.appSecret = appSecret; this.accessToken = pageAccessToken; - this.connectedFacebookPageForInstagram = null; + this.instagramMode = false; } FBMessageHandler(FBMessengerConfig config) { this.verifyToken = config.verifyToken(); this.appSecret = config.appSecret(); this.accessToken = config.pageAccessToken(); - this.connectedFacebookPageForInstagram = - config.connectedFacebookPageForInstagram().isPresent() - ? config.connectedFacebookPageForInstagram().get() - : null; + this.instagramMode = config.instagramMode(); } @TestOnly @@ -178,11 +172,7 @@ private void send(String message, Identifier recipient, Identifier sender) throw try { bodyString = MAPPER.writeValueAsString(body); url = - new URIBuilder( - baseURLFactory.apply( - connectedFacebookPageForInstagram == null - ? sender - : Identifier.from(connectedFacebookPageForInstagram))) + new URIBuilder(baseURLFactory.apply(sender)) .addParameter("access_token", accessToken) .build(); } catch (JsonProcessingException | URISyntaxException e) { @@ -226,8 +216,7 @@ public List> routeDetails() { throw new BadRequestResponse("unable to parse body"); } // TODO: need better validation - String expectedObjectValue = - connectedFacebookPageForInstagram == null ? "page" : "instagram"; + String expectedObjectValue = instagramMode ? "instagram" : "page"; @Nullable JsonNode objectNode = body.get("object"); if (objectNode != null && objectNode.textValue().equals(expectedObjectValue)) { return Optional.of(body); diff --git a/src/main/java/com/meta/cp4m/message/FBMessengerConfig.java b/src/main/java/com/meta/cp4m/message/FBMessengerConfig.java index dc47a47..bef2611 100644 --- a/src/main/java/com/meta/cp4m/message/FBMessengerConfig.java +++ b/src/main/java/com/meta/cp4m/message/FBMessengerConfig.java @@ -10,10 +10,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.base.Preconditions; -import org.checkerframework.checker.nullness.qual.Nullable; - -import java.util.Optional; import java.util.UUID; +import org.checkerframework.checker.nullness.qual.Nullable; public class FBMessengerConfig implements HandlerConfig { @@ -21,14 +19,14 @@ public class FBMessengerConfig implements HandlerConfig { private final String verifyToken; private final String appSecret; private final String pageAccessToken; - private final @Nullable String connectedFacebookPageForInstagram; + private final boolean instagramMode; - private FBMessengerConfig( - @JsonProperty("name") String name, - @JsonProperty("verify_token") String verifyToken, - @JsonProperty("app_secret") String appSecret, - @JsonProperty("page_access_token") String pageAccessToken, - @JsonProperty("connected_facebook_page_for_instagram") @Nullable String connectedFacebookPageForInstagram) { + private FBMessengerConfig( + @JsonProperty("name") String name, + @JsonProperty("verify_token") String verifyToken, + @JsonProperty("app_secret") String appSecret, + @JsonProperty("page_access_token") String pageAccessToken, + @JsonProperty("instagram_mode") @Nullable Boolean instagramMode) { Preconditions.checkArgument(name != null && !name.isBlank(), "name cannot be blank"); Preconditions.checkArgument( @@ -42,19 +40,20 @@ private FBMessengerConfig( this.verifyToken = verifyToken; this.appSecret = appSecret; this.pageAccessToken = pageAccessToken; - this.connectedFacebookPageForInstagram = connectedFacebookPageForInstagram; + this.instagramMode = instagramMode != null && instagramMode; } - public static FBMessengerConfig of(String verifyToken, String appSecret, String pageAccessToken, @Nullable String connectedFacebookPageForInstagram) { - // human readability of the name only matters when it's coming from a config - return new FBMessengerConfig( - UUID.randomUUID().toString(), verifyToken, appSecret, pageAccessToken, connectedFacebookPageForInstagram); + public static FBMessengerConfig of( + String verifyToken, String appSecret, String pageAccessToken, boolean instagramMode) { + // human readability of the name only matters when it's coming from a config + return new FBMessengerConfig( + UUID.randomUUID().toString(), verifyToken, appSecret, pageAccessToken, instagramMode); } public static FBMessengerConfig of(String verifyToken, String appSecret, String pageAccessToken) { - // human readability of the name only matters when it's coming from a config - return new FBMessengerConfig( - UUID.randomUUID().toString(), verifyToken, appSecret, pageAccessToken, null); + // human readability of the name only matters when it's coming from a config + return new FBMessengerConfig( + UUID.randomUUID().toString(), verifyToken, appSecret, pageAccessToken, false); } @Override @@ -79,7 +78,7 @@ public String pageAccessToken() { return pageAccessToken; } - public Optional connectedFacebookPageForInstagram() { - return Optional.ofNullable(connectedFacebookPageForInstagram); + public boolean instagramMode() { + return instagramMode; } -} \ No newline at end of file +} diff --git a/src/test/java/com/meta/cp4m/message/FBMessageHandlerTest.java b/src/test/java/com/meta/cp4m/message/FBMessageHandlerTest.java index 7bcd33e..398d378 100644 --- a/src/test/java/com/meta/cp4m/message/FBMessageHandlerTest.java +++ b/src/test/java/com/meta/cp4m/message/FBMessageHandlerTest.java @@ -330,9 +330,9 @@ void invalidMessage( FBMessageHandler messageHandler; if (isInstagram) { - messageHandler = new FBMessageHandler("0", token, secret, pageId.toString()); + messageHandler = new FBMessageHandler("0", token, secret, true); } else { - messageHandler = new FBMessageHandler("0", token, secret); + messageHandler = new FBMessageHandler("0", token, secret, false); } DummyLLMPlugin llmHandler = new DummyLLMPlugin<>("this is a dummy message"); MemoryStore memoryStore = MemoryStoreConfig.of(1, 1).toStore(); diff --git a/src/test/java/com/meta/cp4m/message/FBMessengerConfigTest.java b/src/test/java/com/meta/cp4m/message/FBMessengerConfigTest.java index ebb36c0..91200ca 100644 --- a/src/test/java/com/meta/cp4m/message/FBMessengerConfigTest.java +++ b/src/test/java/com/meta/cp4m/message/FBMessengerConfigTest.java @@ -49,7 +49,12 @@ class FBMessengerConfigTest { .required(true) .validValues("123") .invalidValues("", " ") - .getter(FBMessengerConfig::pageAccessToken)); + .getter(FBMessengerConfig::pageAccessToken), + ConfigParamTestSpec.of(FBMessengerConfig.class, "instagram_mode") + .required(false) + .validValues(true, false) + .invalidValues("anything that's not a boolean", 3.14) + .getter(FBMessengerConfig::instagramMode)); static Stream>> required() { return PARAMS.stream().filter(ConfigParamTestSpec::required).map(p -> Named.of(p.name(), p)); @@ -94,6 +99,12 @@ void allInvalid(ConfigParamTestSpec param) { for (JsonNode invalidValue : param.invalidValues()) { config.set(param.name(), invalidValue); assertThatThrownBy(() -> mapper.convertValue(config, FBMessengerConfig.class)) + .withFailMessage( + "expecting the value of '" + + invalidValue + + "' to be invalid for field '" + + param.name() + + "'") .isInstanceOf(IllegalArgumentException.class); } } From 4b69153b48535aba8905518a0c7ad7b282ca27a0 Mon Sep 17 00:00:00 2001 From: Hunter Jackson Date: Wed, 20 Dec 2023 18:03:02 -0500 Subject: [PATCH 2/2] optionally get access token from fb message --- .../java/com/meta/cp4m/message/FBMessage.java | 17 +++++++++++++++-- .../com/meta/cp4m/message/FBMessageHandler.java | 6 ++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/meta/cp4m/message/FBMessage.java b/src/main/java/com/meta/cp4m/message/FBMessage.java index 8846130..618d7b4 100644 --- a/src/main/java/com/meta/cp4m/message/FBMessage.java +++ b/src/main/java/com/meta/cp4m/message/FBMessage.java @@ -10,6 +10,7 @@ import com.meta.cp4m.Identifier; import java.time.Instant; +import org.checkerframework.checker.nullness.qual.Nullable; public record FBMessage( Instant timestamp, @@ -17,5 +18,17 @@ public record FBMessage( Identifier senderId, Identifier recipientId, String message, - Role role) - implements Message {} + Role role, + @Nullable String accessToken) + implements Message { + + public FBMessage( + Instant timestamp, + Identifier instanceId, + Identifier senderId, + Identifier recipientId, + String message, + Role role) { + this(timestamp, instanceId, senderId, recipientId, message, role, null); + } +} diff --git a/src/main/java/com/meta/cp4m/message/FBMessageHandler.java b/src/main/java/com/meta/cp4m/message/FBMessageHandler.java index a84625b..6a4369c 100644 --- a/src/main/java/com/meta/cp4m/message/FBMessageHandler.java +++ b/src/main/java/com/meta/cp4m/message/FBMessageHandler.java @@ -158,12 +158,14 @@ private List postHandler(Context ctx, JsonNode body) { @Override public void respond(FBMessage message) throws IOException { List chunkedText = CHUNKER.chunks(message.message()).toList(); + String accessToken = message.accessToken() == null ? this.accessToken : message.accessToken(); for (String text : chunkedText) { - send(text, message.recipientId(), message.senderId()); + send(text, message.recipientId(), message.senderId(), accessToken); } } - private void send(String message, Identifier recipient, Identifier sender) throws IOException { + private void send(String message, Identifier recipient, Identifier sender, String accessToken) + throws IOException { URI url; ObjectNode body = MAPPER.createObjectNode(); body.put("messaging_type", "RESPONSE").putObject("recipient").put("id", recipient.toString());