/****************************************************************************** * * Copyright 2014 Paphus Solutions Inc. * * Licensed under the Eclipse Public License, Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.botlibre.sense.facebook; import java.util.Date; import java.util.logging.Level; import org.botlibre.api.knowledge.Network; import org.botlibre.api.knowledge.Vertex; import org.botlibre.knowledge.Primitive; import org.botlibre.thought.language.Language; import org.botlibre.thought.language.Language.LanguageState; import org.botlibre.util.Utils; import facebook4j.Message; import facebook4j.RawAPIResponse; import facebook4j.internal.org.json.JSONArray; import facebook4j.internal.org.json.JSONObject; import net.sf.json.JSONSerializer; /** * Enables receiving a sending messages through Facebook. */ public class FacebookMessaging extends Facebook { public FacebookMessaging() { this.languageState = LanguageState.Answering; } public FacebookMessaging(boolean isEnabled) { super(isEnabled); this.languageState = LanguageState.Answering; } /** * Check profile for messages. */ @Override public void checkProfile() { log("Checking messages.", Level.FINE); initProperties(); checkDirectMessages(); log("Done checking messages.", Level.FINE); } /** * Check direct messages and reply. */ public void checkDirectMessages() { if (!getReplyToMessages()) { return; } try { if (getConnection() == null) { connect(); } if (!isPage()) { log("Only pages can check messages", Level.WARNING); return; } RawAPIResponse res = getConnection().callGetAPI("/" + getConnection().getPage().getId() + "/conversations"); JSONObject result = res.asJSONObject(); JSONArray conversations = result.getJSONArray("data"); if (conversations != null && conversations.length() > 0) { Network memory = getBot().memory().newMemory(); Vertex facebook = memory.createVertex(getPrimitive()); Vertex vertex = facebook.getRelationship(Primitive.LASTDIRECTMESSAGE); long lastMessage = 0; if (vertex != null) { lastMessage = ((Number)vertex.getData()).longValue(); } long max = 0; for (int index = 0; index < conversations.length(); index++) { JSONObject conversation = conversations.getJSONObject(index); String conversationId = conversation.getString("id"); log("Processing conversation", Level.FINE, conversationId); res = getConnection().callGetAPI("/" + conversationId + "/messages?fields=id,created_time,from,message"); result = res.asJSONObject(); JSONArray messages = result.getJSONArray("data"); if (messages != null && messages.length() > 0) { for (int i = 0; i < messages.length(); i++) { JSONObject message = messages.getJSONObject(i); Date createdTime = Utils.parseDate(message.getString("created_time"), "yyyy-MM-dd'T'HH:mm:ssX").getTime(); if ((System.currentTimeMillis() - createdTime.getTime()) > DAY) { log("Day old message", Level.FINE, createdTime, conversationId); continue; } if (createdTime.getTime() > lastMessage) { String fromUser = message.getJSONObject("from").getString("name"); String fromUserId = message.getJSONObject("from").getString("id"); if (!fromUserId.equals(this.userName)) { String text = message.getString("message").trim(); log("Processing message", Level.INFO, fromUser, createdTime, conversationId, text); this.messagesProcessed++; inputSentence(text, fromUser, this.userName, conversationId, memory); if (createdTime.getTime() > max) { max = createdTime.getTime(); } } else { log("Ignoring own message", Level.FINE, createdTime, conversationId); } } else { log("Old message", Level.FINE, createdTime, conversationId); } } } else { log("No messages", Level.FINE, conversationId); } } if (max != 0) { if (vertex != null) { vertex.setPinned(false); } Vertex maxVertex = memory.createVertex(max); maxVertex.setPinned(true); facebook.setRelationship(Primitive.LASTDIRECTMESSAGE, maxVertex); memory.save(); } /* InboxResponseList<Message> messages = getConnection().getInbox(); System.out.println(messages); if (!messages.isEmpty()) { Network memory = getBot().memory().newMemory(); Vertex facebook = memory.createVertex(getPrimitive()); Vertex vertex = facebook.getRelationship(Primitive.LASTDIRECTMESSAGE); long lastMessage = 0; if (vertex != null) { lastMessage = ((Number)vertex.getData()).longValue(); } long max = 0; for (Message message : messages) { System.out.println(message); System.out.println(message.getId()); System.out.println(message.getFrom()); System.out.println(message.getMessage()); System.out.println(message.getCreatedTime()); if ((System.currentTimeMillis() - message.getCreatedTime().getTime()) > DAY) { continue; } if (message.getCreatedTime().getTime() > lastMessage) { input(message); if (message.getCreatedTime().getTime() > max) { max = message.getCreatedTime().getTime(); } } } if (max != 0) { facebook.setRelationship(Primitive.LASTDIRECTMESSAGE, memory.createVertex(max)); memory.save(); }*/ } else { log("No conversations", Level.FINE); } } catch (Exception exception) { log(exception); } } /** * Process the direct message. */ @Override public void input(Object input, Network network) { if (!isEnabled()) { return; } try { if (input instanceof Message) { Message message = (Message)input; String fromUser = message.getFrom().getName(); String text = message.getMessage().trim(); log("Processing message.", Level.INFO, text, fromUser); this.messagesProcessed++; inputSentence(text, fromUser, this.userName, message.getId(), network); } } catch (Exception exception) { log(exception); } } /** * Create an input based on the sentence. */ protected Vertex createInput(String text, Network network) { Vertex sentence = network.createSentence(text); Vertex input = network.createInstance(Primitive.INPUT); input.setName(text); input.addRelationship(Primitive.SENSE, getPrimitive()); input.addRelationship(Primitive.INPUT, sentence); sentence.addRelationship(Primitive.INSTANTIATION, Primitive.DIRECTMESSAGE); return input; } /** * Process the text sentence. */ public void inputSentence(String text, String userName, String targetUserName, String id, Network network) { Vertex input = createInput(text.trim(), network); Vertex user = network.createSpeaker(userName); Vertex self = network.createVertex(Primitive.SELF); input.addRelationship(Primitive.SPEAKER, user); input.addRelationship(Primitive.TARGET, self); user.addRelationship(Primitive.INPUT, input); Vertex conversation = network.createVertex(id); conversation.addRelationship(Primitive.INSTANTIATION, Primitive.CONVERSATION); conversation.addRelationship(Primitive.TYPE, Primitive.DIRECTMESSAGE); conversation.addRelationship(Primitive.ID, network.createVertex(id)); conversation.addRelationship(Primitive.SPEAKER, user); conversation.addRelationship(Primitive.SPEAKER, self); Language.addToConversation(input, conversation); network.save(); getBot().memory().addActiveMemory(input); } /** * Process the text sentence. */ public void inputFacebookMessengerMessage(String text, String targetUserName, String senderId, Network network) { String senderName = null; try { if (getConnection() == null) { connect(); } String url = "https://graph.facebook.com/v2.6/" + senderId + "?fields=first_name,last_name&access_token=" + getFacebookMessengerAccessToken(); String json = Utils.httpGET(url); net.sf.json.JSONObject user = (net.sf.json.JSONObject)JSONSerializer.toJSON(json); if (user != null) { Object firstName = user.get("first_name"); Object lastName = user.get("last_name"); if (firstName instanceof String) { senderName = (String)firstName; } if (lastName instanceof String) { if (senderName == null) { senderName = ""; } senderName = senderName + " " + (String)lastName; } } } catch (Exception exception) { String url = "https://graph.facebook.com/v2.6/" + senderId + "?fields=first_name,last_name&access_token=" + getFacebookMessengerAccessToken(); log(url, Level.INFO); url = "https://graph.facebook.com/v2.6/" + senderId + "?fields=first_name,last_name&access_token=" + getToken(); log(url, Level.INFO); log(exception); } if (senderName == null || senderName.isEmpty()) { senderName = senderId; } Vertex input = createInput(text.trim(), network); Vertex user = network.createSpeaker(senderName); Vertex self = network.createVertex(Primitive.SELF); input.addRelationship(Primitive.SPEAKER, user); input.addRelationship(Primitive.TARGET, self); user.addRelationship(Primitive.INPUT, input); Vertex conversation = network.createVertex(senderId); conversation.addRelationship(Primitive.INSTANTIATION, Primitive.CONVERSATION); conversation.addRelationship(Primitive.TYPE, Primitive.DIRECTMESSAGE); conversation.addRelationship(Primitive.TYPE, Primitive.FACEBOOKMESSENGER); conversation.addRelationship(Primitive.ID, network.createVertex(senderId)); conversation.addRelationship(Primitive.SPEAKER, user); conversation.addRelationship(Primitive.SPEAKER, self); Language.addToConversation(input, conversation); network.save(); getBot().memory().addActiveMemory(input); } /** * Output the status or direct message reply. */ @Override public void output(Vertex output) { if (!isEnabled()) { return; } Vertex sense = output.mostConscious(Primitive.SENSE); // If not output to twitter, ignore. if ((sense == null) || (!getPrimitive().equals(sense.getData()))) { return; } String text = printInput(output); Vertex target = output.mostConscious(Primitive.TARGET); String replyTo = target.mostConscious(Primitive.WORD).getData().toString(); Vertex conversation = output.getRelationship(Primitive.CONVERSATION); Vertex id = conversation.getRelationship(Primitive.ID); String conversationId = id.printString(); Vertex command = output.mostConscious(Primitive.COMMAND); if (conversation.hasRelationship(Primitive.TYPE, Primitive.FACEBOOKMESSENGER)) { if(command==null || command.toString().length() == 0) sendFacebookMessengerMessage(text, replyTo, conversationId); else sendFacebookMessengerButtonMessage(text, command.toString(), replyTo, conversationId); } else { sendMessage(text, replyTo, conversationId); } } /* Facebook /conversations response {"data": [ {"id":"t_mid.1439494778225:8df1f7618937f24b83","snippet":"what time is it?","updated_time":"2015-08-13T19:41:36+0000","message_count":2, "tags": {"data":[{"name":"inbox"},{"name":"read"},{"name":"seen"},{"name":"source:chat"}]}, "participants":{"data": [{"name":"Brain Bot","email":"1603485376574546\u0040facebook.com","id":"1603485376574546"}, {"name":"Pablo Grandinetti","email":"10153500543273168\u0040facebook.com","id":"10153500543273168"} ]}, "senders":{"data":[{"name":"Pablo Grandinetti","email":"10153500543273168\u0040facebook.com","id":"10153500543273168"}]}, "can_reply":true,"is_subscribed":true,"link":"\/brainchatbot\/manager\/messages\/?mercurythreadid=user\u00253A580418167&threadid=mid.1439494778225\u00253A8df1f7618937f24b83&folder=inbox", "messages":{ "data":[{ "id":"m_mid.1439494896455:2990ae164ba7414921", "created_time":"2015-08-13T19:41:36+0000", "tags":{"data":[{"name":"inbox"},{"name":"read"},{"name":"source:chat"}]}, "from":{"name":"Pablo Grandinetti","email":"10153500543273168\u0040facebook.com","id":"10153500543273168"}, "to":{"data":[{"name":"Brain Bot","email":"1603485376574546\u0040facebook.com","id":"1603485376574546"}]}, "message":"what time is it?"}, {"id":"m_mid.1439494778225:8df1f7618937f24b83", "created_time":"2015-08-13T19:39:38+0000", "tags":{"data":[{"name":"inbox"},{"name":"read"},{"name":"source:chat"}]}, "from":{"name":"Pablo Grandinetti","email":"10153500543273168\u0040facebook.com","id":"10153500543273168"}, "to":{"data":[{"name":"Brain Bot","email":"1603485376574546\u0040facebook.com","id":"1603485376574546"}]}, "message":"Hi"}], "paging":{"previous":"https:\/\/graph.facebook.com\/v2.3\/t_mid.1439494778225:8df1f7618937f24b83\/messages?access_token=CAANJOepfuhYBAPjv8MjyKwiglMvUyi11sTZAldP6GHiF6iMoFAIXTOGroUH1UXSOhoPFVUbATGPU4pzb0I3dMzrM0tIrSXHbPsw2j9k8Lu0iHtCfZAfdI73Y2Mbe89QYFowBzSX00z9bfSB9OQ4CGQVpb3hKpiXtoWch0MEofPEBrYacti&limit=25&since=1439494896&__paging_token=enc_AdA4B01qhifCqJuw7vqrZB6TbGgb6vdqh3jGnbWNAmr6tDrFBxH1wsXu74ZAsjvZAoFqWiZBdzQ7nnWlwVm8ZAyZBggWlX7r8lm67ETKZCmYr9tr5nmHQZDZD&__previous=1","next":"https:\/\/graph.facebook.com\/v2.3\/t_mid.1439494778225:8df1f7618937f24b83\/messages?access_token=CAANJOepfuhYBAPjv8MjyKwiglMvUyi11sTZAldP6GHiF6iMoFAIXTOGroUH1UXSOhoPFVUbATGPU4pzb0I3dMzrM0tIrSXHbPsw2j9k8Lu0iHtCfZAfdI73Y2Mbe89QYFowBzSX00z9bfSB9OQ4CGQVpb3hKpiXtoWch0MEofPEBrYacti&limit=25&until=1439494778&__paging_token=enc_AdCEazJZArKYZButGDMhKO7F8zIfHeDhFUd3dammZB5r4lZCRtQScIBQQpiNrFBynPcgRljWyWSWPKdRvxyM33TPZAp6i11AdYPR4CX7pZCJI4uZBvnggZDZD"}}}, {"id":"t_mid.1439004373957:4fa6dcadd69692ea95","snippet":"\u53ef\u4ee5\u5e2e\u6211\u4e2a\u5fd9\u5417\uff1f","updated_time":"2015-08-08T03:26:27+0000","message_count":2, "tags":{"data":[{"name":"inbox"},{"name":"read"},{"name":"seen"},{"name":"source:chat"}]}, "participants":{"data":[{"name":"\u9ec4\u91d1\u4f1f","email":"1623400744598654\u0040facebook.com","id":"1623400744598654"},{"name":"Brain Bot","email":"1603485376574546\u0040facebook.com","id":"1603485376574546"}]}, "senders":{"data":[{"name":"\u9ec4\u91d1\u4f1f","email":"1623400744598654\u0040facebook.com","id":"1623400744598654"}]}, "can_reply":true,"is_subscribed":true,"link":"\/brainchatbot\/manager\/messages\/?mercurythreadid=user\u00253A100007862318965&threadid=mid.1439004373957\u00253A4fa6dcadd69692ea95&folder=inbox", "messages":{"data":[{"id":"m_mid.1439004387183:c47081ffee6bf33c17","created_time":"2015-08-08T03:26:27+0000","tags":{"data":[{"name":"inbox"},{"name":"read"},{"name":"source:chat"}]},"from":{"name":"\u9ec4\u91d1\u4f1f","email":"1623400744598654\u0040facebook.com","id":"1623400744598654"},"to":{"data":[{"name":"Brain Bot","email":"1603485376574546\u0040facebook.com","id":"1603485376574546"}]},"message":"\u53ef\u4ee5\u5e2e\u6211\u4e2a\u5fd9\u5417\uff1f"},{"id":"m_mid.1439004373957:4fa6dcadd69692ea95","created_time":"2015-08-08T03:26:14+0000","tags":{"data":[{"name":"inbox"},{"name":"read"},{"name":"source:chat"}]},"from":{"name":"\u9ec4\u91d1\u4f1f","email":"1623400744598654\u0040facebook.com","id":"1623400744598654"},"to":{"data":[{"name":"Brain Bot","email":"1603485376574546\u0040facebook.com","id":"1603485376574546"}]},"message":"hi"}],"paging":{"previous":"https:\/\/graph.facebook.com\/v2.3\/t_mid.1439004373957:4fa6dcadd69692ea95\/messages?access_token=CAANJOepfuhYBAPjv8MjyKwiglMvUyi11sTZAldP6GHiF6iMoFAIXTOGroUH1UXSOhoPFVUbATGPU4pzb0I3dMzrM0tIrSXHbPsw2j9k8Lu0iHtCfZAfdI73Y2Mbe89QYFowBzSX00z9bfSB9OQ4CGQVpb3hKpiXtoWch0MEofPEBrYacti&limit=25&since=1439004387&__paging_token=enc_AdCAUpDVhuv8zNYZCXq79E0pzeFdeAfRYyJO5SGzZADYDaHJM4pn7frJKgVVQZA2JQbc9iCZC7JKR5Ezd9ZBMcpQZAQPvvdzBkwHmF9rPcjMKCcz2UGgZDZD&__previous=1","next":"https:\/\/graph.facebook.com\/v2.3\/t_mid.1439004373957:4fa6dcadd69692ea95\/messages?access_token=CAANJOepfuhYBAPjv8MjyKwiglMvUyi11sTZAldP6GHiF6iMoFAIXTOGroUH1UXSOhoPFVUbATGPU4pzb0I3dMzrM0tIrSXHbPsw2j9k8Lu0iHtCfZAfdI73Y2Mbe89QYFowBzSX00z9bfSB9OQ4CGQVpb3hKpiXtoWch0MEofPEBrYacti&limit=25&until=1439004374&__paging_token=enc_AdA6mkmptPXZCn4t7EF2clICSM74wWY8ZBAz9rlAQqsduhaIjtjdZA9WoKsjBqgZCuvWzW4JR9HAWJ8EMQ7qYXxuQw75J68oXxyQluloJbFZCK0o97gZDZD"}}}], "paging":{"previous":"https:\/\/graph.facebook.com\/v2.3\/1603485376574546\/conversations?access_token=CAANJOepfuhYBAPjv8MjyKwiglMvUyi11sTZAldP6GHiF6iMoFAIXTOGroUH1UXSOhoPFVUbATGPU4pzb0I3dMzrM0tIrSXHbPsw2j9k8Lu0iHtCfZAfdI73Y2Mbe89QYFowBzSX00z9bfSB9OQ4CGQVpb3hKpiXtoWch0MEofPEBrYacti&limit=25&since=1439494896&__paging_token=enc_AdCpLMo6RAqVIg5SGXL9h8lr8eYeAHAnNTUOTeWS5TUo9spjYBd2vvILmjjkuzSl5MlI49T25HZA47ZB37RHNB7SRCW19ZBP4KZCHrPE1pCbBxlLhgZDZD&__previous=1","next":"https:\/\/graph.facebook.com\/v2.3\/1603485376574546\/conversations?access_token=CAANJOepfuhYBAPjv8MjyKwiglMvUyi11sTZAldP6GHiF6iMoFAIXTOGroUH1UXSOhoPFVUbATGPU4pzb0I3dMzrM0tIrSXHbPsw2j9k8Lu0iHtCfZAfdI73Y2Mbe89QYFowBzSX00z9bfSB9OQ4CGQVpb3hKpiXtoWch0MEofPEBrYacti&limit=25&until=1439004387&__paging_token=enc_AdBAP3Q6Yky9Q0bmmnsnsPsuQLUtfJXmXSk8NY0TxSSe0ZBSp2K6wRkRAtRgdChlyLF17NRBxDnPr3XKaRjkFdnzjuco0BY51ipMJEMIXAgEBTAZDZD"}} } */ }