From bf5f2142d73a5745124d03f6b6f06c59873e47de Mon Sep 17 00:00:00 2001
From: Vitaly Takmazov
Date: Wed, 27 Dec 2017 16:23:28 +0300
Subject: Messenger bot
---
juick-api/build.gradle | 1 +
.../src/main/java/com/juick/api/MessengerBot.java | 33 -----
.../main/java/com/juick/api/MessengerManager.java | 143 +++++++++++++++++++++
.../juick/api/configuration/ApiInitializer.java | 2 +-
.../api/configuration/MessengerConfiguration.java | 39 ------
.../juick/api/controllers/MessengerWebhook.java | 11 +-
6 files changed, 151 insertions(+), 78 deletions(-)
delete mode 100644 juick-api/src/main/java/com/juick/api/MessengerBot.java
create mode 100644 juick-api/src/main/java/com/juick/api/MessengerManager.java
delete mode 100644 juick-api/src/main/java/com/juick/api/configuration/MessengerConfiguration.java
(limited to 'juick-api')
diff --git a/juick-api/build.gradle b/juick-api/build.gradle
index db2f080b..39475d94 100644
--- a/juick-api/build.gradle
+++ b/juick-api/build.gradle
@@ -16,6 +16,7 @@ dependencies {
compile 'io.springfox:springfox-swagger-ui:2.7.0'
compile 'com.github.pengrad:java-telegram-bot-api:3.5.2'
+ compile 'com.github.messenger4j:messenger4j:1.0.0-M2'
compile 'org.apache.commons:commons-email:1.5'
compile 'org.imgscalr:imgscalr-lib:4.2'
diff --git a/juick-api/src/main/java/com/juick/api/MessengerBot.java b/juick-api/src/main/java/com/juick/api/MessengerBot.java
deleted file mode 100644
index 8a568c42..00000000
--- a/juick-api/src/main/java/com/juick/api/MessengerBot.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package com.juick.api;
-
-/**
- * Created by vitalyster on 27.03.2017.
- */
-public class MessengerBot {
- private String verifyToken;
-
- public String getVerifyToken() {
- return verifyToken;
- }
-
- public void setVerifyToken(String verifyToken) {
- this.verifyToken = verifyToken;
- }
-}
diff --git a/juick-api/src/main/java/com/juick/api/MessengerManager.java b/juick-api/src/main/java/com/juick/api/MessengerManager.java
new file mode 100644
index 00000000..9587dc11
--- /dev/null
+++ b/juick-api/src/main/java/com/juick/api/MessengerManager.java
@@ -0,0 +1,143 @@
+package com.juick.api;
+
+import com.github.messenger4j.Messenger;
+import com.github.messenger4j.exception.MessengerApiException;
+import com.github.messenger4j.exception.MessengerIOException;
+import com.github.messenger4j.exception.MessengerVerificationException;
+import com.github.messenger4j.send.MessagePayload;
+import com.github.messenger4j.send.message.TemplateMessage;
+import com.github.messenger4j.send.message.TextMessage;
+import com.github.messenger4j.send.message.template.ButtonTemplate;
+import com.github.messenger4j.send.message.template.button.UrlButton;
+import com.github.messenger4j.userprofile.UserProfile;
+import com.github.messenger4j.webhook.event.TextMessageEvent;
+import com.juick.Message;
+import com.juick.User;
+import com.juick.server.component.MessageEvent;
+import com.juick.service.MessagesService;
+import com.juick.service.MessengerService;
+import com.juick.service.SubscriptionService;
+import com.juick.service.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Nonnull;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Instant;
+import java.util.Collections;
+import java.util.Optional;
+
+import static com.juick.formatters.PlainTextFormatter.formatPost;
+import static com.juick.formatters.PlainTextFormatter.formatUrl;
+
+@Component
+public class MessengerManager implements ApplicationListener {
+ private static final Logger logger = LoggerFactory.getLogger(MessengerManager.class);
+ @Inject
+ private MessagesService messagesService;
+ @Inject
+ private SubscriptionService subscriptionService;
+ @Inject
+ private UserService userService;
+ @Inject
+ private MessengerService messengerService;
+ @Inject
+ private ApiServer apiServer;
+
+ @Value("${fb_page_access_token}")
+ private String facebookPageAccessToken;
+ @Value("${fb_verify_token}")
+ private String facebookVerifyToken;
+ @Value("${fb_secret}")
+ private String facebookSecret;
+
+ private Messenger messenger;
+
+ @PostConstruct
+ public void init() {
+ messenger = Messenger.create(facebookPageAccessToken, facebookSecret, facebookVerifyToken);
+ }
+
+ public String getFacebookVerifyToken() {
+ return facebookVerifyToken;
+ }
+
+ public void processUpdate(String signature , String data) throws MessengerVerificationException {
+ messenger.onReceiveEvents(data, Optional.of(signature), event -> {
+ final String senderId = event.senderId();
+ final Instant timestamp = event.timestamp();
+
+ User user_from = userService.getUserByUID(messengerService.getUserId(senderId)).orElse(new User());
+ logger.info("Found juick user {}", user_from.getUid());
+ if (user_from.getUid() == 0) {
+ try {
+ UserProfile profile = messenger.queryUserProfile(senderId);
+ signupNotify(senderId, messengerService.getSignUpHash(senderId, profile.firstName()));
+ } catch (MessengerApiException | MessengerIOException | MalformedURLException e) {
+ logger.warn("messenger profile error", e);
+ try {
+ signupNotify(senderId, messengerService.getSignUpHash(senderId, "anonymous"));
+ } catch (MalformedURLException | MessengerApiException | MessengerIOException e1) {
+ logger.warn("signup error", e1);
+ }
+ }
+ } else {
+ if (event.isTextMessageEvent()) {
+ final TextMessageEvent textMessageEvent = event.asTextMessageEvent();
+ final String messageId = textMessageEvent.messageId();
+ final String text = textMessageEvent.text();
+ logger.info("Received text message from '{}' at '{}' with content: {} (mid: {})",
+ senderId, timestamp, text, messageId);
+ apiServer.processMessage(user_from, text, null);
+ messengerNotify(senderId, "Message sent", null);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onApplicationEvent(@Nonnull MessageEvent event) {
+ Message msg = event.getMessage();
+ if (msg.getRid() == 0) {
+ String subject = formatPost(msg);
+ subscriptionService.getSubscribedUsers(msg.getUser().getUid(), msg.getMid())
+ .forEach(user -> messengerService.getSenderId(user)
+ .ifPresent(t -> messengerNotify(t, subject, formatUrl(msg))));
+ } else {
+ // get quote
+ com.juick.Message jmsg = messagesService.getReply(msg.getMid(), msg.getRid());
+ String subject = formatPost(jmsg);
+ subscriptionService.getUsersSubscribedToComments(msg.getMid(), msg.getUser().getUid())
+ .forEach(user -> messengerService.getSenderId(user)
+ .ifPresent(t -> messengerNotify(t, subject, formatUrl(jmsg))));
+ }
+ }
+
+ void messengerNotify(String messengerUser, String text, String url) {
+ try {
+ if (!StringUtils.isEmpty(url)) {
+ final UrlButton showMessage = UrlButton.create("VIEW MESSAGE", new URL(url));
+ ButtonTemplate template = ButtonTemplate.create(text, Collections.singletonList(showMessage));
+ messenger.send(MessagePayload.create(messengerUser, TemplateMessage.create(template)));
+ } else {
+ messenger.send(MessagePayload.create(messengerUser, TextMessage.create(text)));
+ }
+ } catch (MessengerApiException | MessengerIOException | MalformedURLException e) {
+ logger.warn("messenger error", e);
+ }
+ }
+ void signupNotify(String messengerUser, String hash) throws MalformedURLException, MessengerApiException, MessengerIOException {
+ final UrlButton urlButton = UrlButton.create("LOGIN",
+ new URL("https://juick.com/signup?type=messenger&hash=" + hash));
+ ButtonTemplate template = ButtonTemplate.create("Login to receive notifications",
+ Collections.singletonList(urlButton));
+ messenger.send(MessagePayload.create(messengerUser, TemplateMessage.create(template)));
+ }
+}
diff --git a/juick-api/src/main/java/com/juick/api/configuration/ApiInitializer.java b/juick-api/src/main/java/com/juick/api/configuration/ApiInitializer.java
index 3380df10..32a88a0c 100644
--- a/juick-api/src/main/java/com/juick/api/configuration/ApiInitializer.java
+++ b/juick-api/src/main/java/com/juick/api/configuration/ApiInitializer.java
@@ -43,7 +43,7 @@ public class ApiInitializer extends AbstractAnnotationConfigDispatcherServletIni
@Override
protected Class>[] getServletConfigClasses() {
- return new Class>[]{ MessengerConfiguration.class };
+ return null;
}
@Override
diff --git a/juick-api/src/main/java/com/juick/api/configuration/MessengerConfiguration.java b/juick-api/src/main/java/com/juick/api/configuration/MessengerConfiguration.java
deleted file mode 100644
index a9f07af4..00000000
--- a/juick-api/src/main/java/com/juick/api/configuration/MessengerConfiguration.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2008-2017, Juick
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see .
- */
-
-package com.juick.api.configuration;
-
-import com.juick.api.MessengerBot;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Created by vital on 28.03.2017.
- */
-@Configuration
-public class MessengerConfiguration {
- @Value("${fb_verify_token}")
- private String messengerBotVerifyToken;
-
- @Bean
- public MessengerBot fbBot() {
- MessengerBot bot = new MessengerBot();
- bot.setVerifyToken(messengerBotVerifyToken);
- return bot;
- }
-}
diff --git a/juick-api/src/main/java/com/juick/api/controllers/MessengerWebhook.java b/juick-api/src/main/java/com/juick/api/controllers/MessengerWebhook.java
index fa57c017..835165ba 100644
--- a/juick-api/src/main/java/com/juick/api/controllers/MessengerWebhook.java
+++ b/juick-api/src/main/java/com/juick/api/controllers/MessengerWebhook.java
@@ -17,7 +17,8 @@
package com.juick.api.controllers;
-import com.juick.api.MessengerBot;
+import com.github.messenger4j.exception.MessengerVerificationException;
+import com.juick.api.MessengerManager;
import com.juick.server.util.HttpForbiddenException;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
@@ -41,21 +42,21 @@ public class MessengerWebhook {
private static Logger logger = LoggerFactory.getLogger(MessengerWebhook.class);
@Inject
- MessengerBot fbBot;
+ private MessengerManager messengerManager;
@RequestMapping(value = "/fbwbhk", method = RequestMethod.GET)
public ResponseEntity verifyHook(@RequestParam(name = "hub.mode") String hubMode,
@RequestParam(name = "hub.challenge") Integer hubChallenge,
@RequestParam(name = "hub.verify_token") String verifyToken) {
- if (hubMode.equals("subscribe") && verifyToken.equals(fbBot.getVerifyToken())) {
+ if (hubMode.equals("subscribe") && verifyToken.equals(messengerManager.getFacebookVerifyToken())) {
return new ResponseEntity<>(hubChallenge, HttpStatus.OK);
}
throw new HttpForbiddenException();
}
@RequestMapping(value = "/fbwbhk", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
- public void processUpdate(InputStream body) throws IOException {
+ public void processUpdate(@RequestHeader(name = "X-Hub-Signature", required = false) String signature, InputStream body) throws IOException, MessengerVerificationException {
String data = IOUtils.toString(body, StandardCharsets.UTF_8);
- logger.info("got data: {}", data);
+ messengerManager.processUpdate(signature, data);
}
}
--
cgit v1.2.3