Skip to content

Commit

Permalink
Adding Basic IG Message Handler
Browse files Browse the repository at this point in the history
  • Loading branch information
colinmccloskey committed Nov 20, 2023
1 parent 8bab6be commit 96d8247
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ build/
### custom ###
src/main/java/com/meta/cp4m/mccloskeytest.java
/dependency-reduced-pom.xml
CP4M.toml
2 changes: 1 addition & 1 deletion src/main/java/com/meta/cp4m/message/FBMessageHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public List<FBMessage> processRequest(Context ctx) {
} catch (JsonProcessingException | NullPointerException e) {
LOGGER
.atWarn()
.setMessage("Unable to parse message form Meta webhook")
.setMessage("Unable to parse message from Meta webhook")
.setCause(e)
.addKeyValue("body", ctx.body())
.addKeyValue("headers", ctx.headerMap())
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/com/meta/cp4m/message/FBMessengerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class FBMessengerConfig implements HandlerConfig {
private final String appSecret;
private final String pageAccessToken;

private FBMessengerConfig(
public FBMessengerConfig(
@JsonProperty("name") String name,
@JsonProperty("verify_token") String verifyToken,
@JsonProperty("app_secret") String appSecret,
Expand All @@ -39,6 +39,7 @@ private FBMessengerConfig(
this.pageAccessToken = pageAccessToken;
}


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(
Expand All @@ -65,5 +66,6 @@ public FBMessageHandler toMessageHandler() {

public String pageAccessToken() {
return pageAccessToken;
}
}
} // EAAICn2ZAELtYBO2pwykJbOqqEra8msZAjp98AZCFDr5raSYQBgkG5RVq40N0txHFnxMuPdmZArB3gY2R6YwQEk8Gk1LDeO98DZCZCmbyLg6S6conUSBdRgGTz99fBIPtn41ZAhSulBhQ5cg5Fu3Tw1zjlrnUZCNp2sBMuTZAsp1C3jfrIEMbMvZBR9ml7iksNbRZCFrEjvUlWeyZAPJsAiPdQyeRM00sqCDqSya2hB8R7QIc
} // EAAICn2ZAELtYBO3tZB7c3sObbkw6aHxrkCuZA7k2ECfZAunCJVkrAmgbvlDSAEMRjLl4FDPOiuBkZCkGYayMZBJrGCPJDkgdBqcf21StChoE4uOexspURdDiZCPTtdcxXGljsT4Xh0uieoM19M2Evm7O5LWjKPluRoGwUZBZC4lX4iF3TEw8JCa9npkIRnV823ZCvOyPP9QBo2uGScZCX1ZA

122 changes: 122 additions & 0 deletions src/main/java/com/meta/cp4m/message/IGMessageHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.meta.cp4m.message;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.meta.cp4m.Identifier;
import io.javalin.http.Context;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class IGMessageHandler extends FBMessageHandler{

private final String verifyToken;
private final String appSecret;

private final String accessToken;
private static final JsonMapper MAPPER = new JsonMapper();
private static final Logger LOGGER = LoggerFactory.getLogger(IGMessageHandler.class);
private final Deduplicator<Identifier> messageDeduplicator = new Deduplicator<>(10_000);

public IGMessageHandler(String verifyToken, String pageAccessToken, String appSecret) {
super(verifyToken, appSecret, pageAccessToken);
this.verifyToken = verifyToken;
this.appSecret = appSecret;
this.accessToken = pageAccessToken;

}

IGMessageHandler(IGMessengerConfig config) {
super(config);
this.verifyToken = config.verifyToken();
this.appSecret = config.appSecret();
this.accessToken = config.pageAccessToken();

}

private List<FBMessage> postHandler(Context ctx) throws JsonProcessingException {
MetaHandlerUtils.postHeaderValidator(ctx, appSecret);

String bodyString = ctx.body();
JsonNode body = MAPPER.readTree(bodyString);
String object = body.get("object").textValue();
if (!object.equals("instagram")) {
LOGGER
.atWarn()
.setMessage("received body that has a different value for 'object' than 'page'")
.addKeyValue("body", bodyString)
.log();
return Collections.emptyList();
}
// TODO: need better validation
JsonNode entries = body.get("entry");
ArrayList<FBMessage> output = new ArrayList<>();
for (JsonNode entry : entries) {
@Nullable JsonNode messaging = entry.get("messaging");
if (messaging == null) {
continue;
}
for (JsonNode message : messaging) {
@Nullable JsonNode messageObject = message.get("message");

if (messageObject != null) {
if(messageObject.get("is_echo").asText().equals("true")){
return Collections.emptyList();
}

Identifier senderId = Identifier.from(message.get("sender").get("id").asLong());
Identifier recipientId = Identifier.from(message.get("recipient").get("id").asLong());
Instant timestamp = Instant.ofEpochMilli(message.get("timestamp").asLong());

// https://developers.facebook.com/docs/messenger-platform/reference/webhook-events/messages
Identifier messageId = Identifier.from(messageObject.get("mid").textValue());
if (messageDeduplicator.addAndGetIsDuplicate(messageId)) {
continue;
}

@Nullable JsonNode textObject = messageObject.get("text");
if (textObject != null && textObject.isTextual()) {
FBMessage m =
new FBMessage(
timestamp,
messageId,
senderId,
recipientId,
textObject.textValue(),
Message.Role.USER);
output.add(m);
} else {
LOGGER
.atWarn()
.setMessage("received message without text, unable to handle this")
.addKeyValue("body", bodyString)
.log();
}
} else {
LOGGER
.atWarn()
.setMessage(
"received a message without a 'message' key, unable to handle this message type")
.addKeyValue("body", bodyString)
.log();
}
}
}

return output;
}
}
30 changes: 30 additions & 0 deletions src/main/java/com/meta/cp4m/message/IGMessengerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

package com.meta.cp4m.message;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;

import java.util.UUID;

public class IGMessengerConfig extends FBMessengerConfig {

IGMessengerConfig( @JsonProperty("name") String name,
@JsonProperty("verify_token") String verifyToken,
@JsonProperty("app_secret") String appSecret,
@JsonProperty("page_access_token") String pageAccessToken){
super(name, verifyToken, appSecret, pageAccessToken);
}

@Override
public IGMessageHandler toMessageHandler() {
return new IGMessageHandler(this);
}

}

0 comments on commit 96d8247

Please sign in to comment.