diff --git a/cc-chatbot/app/pom.xml b/cc-chatbot/app/pom.xml
index 9b2c6a0b..67a195a1 100644
--- a/cc-chatbot/app/pom.xml
+++ b/cc-chatbot/app/pom.xml
@@ -6,7 +6,7 @@
com.chatopera.chatbot
sdk
- 1.0-SNAPSHOT
+ 1.0.1
jar
sdk
@@ -121,6 +121,10 @@
chatopera
http://192.168.2.217:8029/repository/maven-snapshots/
+
+ chatopera
+ http://192.168.2.217:8029/repository/maven-releases/
+
diff --git a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/Chatbot.java b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/Chatbot.java
deleted file mode 100644
index 28bdae01..00000000
--- a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/Chatbot.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.chatopera.chatbot;
-
-import com.mashape.unirest.http.exceptions.UnirestException;
-import org.apache.commons.lang3.StringUtils;
-import org.json.JSONObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-
-public class Chatbot {
- private static final Logger logger = LoggerFactory.getLogger(Chatbot.class);
- private String schema;
- private String hostname;
- private int port;
- private String baseUrl;
-
- private Chatbot() {
- }
-
- public Chatbot(final String schema, final String hostname, final int port, final String version) {
- this.schema = schema;
- this.hostname = hostname;
- this.port = port;
- this.baseUrl = schema + "://" + hostname + ":" + Integer.toString(this.port) + "/api/" + version;
- }
-
- public Chatbot(final String schema, final String hostname, final int port) {
- this(schema, hostname, port, "v1");
- }
-
- public Chatbot(final String hostname, final int port) {
- this("http", hostname, port);
- }
-
- public String getSchema() {
- return schema;
- }
-
- public String getHostname() {
- return hostname;
- }
-
- public int getPort() {
- return port;
- }
-
- public String getBaseUrl() {
- return baseUrl;
- }
-
- /**
- * 获取聊天机器人列表
- *
- * @return
- * @throws ChatbotRuntimeException
- */
- public JSONObject getChatbots(final String fields, final String q, final int page, final int limit) throws ChatbotRuntimeException {
- try {
- HashMap queryString = new HashMap();
- if (StringUtils.isNotBlank(fields)) {
- queryString.put("fields", fields);
- }
-
- if (StringUtils.isNotBlank(q)) {
- queryString.put("q", q);
- }
-
- queryString.put("page", page);
-
- if (limit > 0) {
- queryString.put("limit", limit);
- }
-
- return RestAPI.get(this.getBaseUrl() + "/chatbot", queryString);
- } catch (UnirestException e) {
- throw new ChatbotRuntimeException(e.toString());
- }
- }
-
- /**
- * 获取聊天机器人详情
- *
- * @param chatbotID
- * @return
- * @throws ChatbotRuntimeException
- */
- public JSONObject getChatbot(final String chatbotID) throws ChatbotRuntimeException {
- try {
- return RestAPI.get(this.getBaseUrl() + "/chatbot/" + chatbotID);
- } catch (UnirestException e) {
- throw new ChatbotRuntimeException(e.toString());
- }
- }
-
- /**
- * validate params
- * @param chatbotID
- * @param fromUserId
- * @param textMessage
- */
- private void v(final String chatbotID, final String fromUserId, final String textMessage) throws ChatbotRuntimeException {
- if(StringUtils.isBlank(chatbotID))
- throw new ChatbotRuntimeException("[conversation] 不合法的聊天机器人标识。");
-
- if(StringUtils.isBlank(fromUserId))
- throw new ChatbotRuntimeException("[conversation] 不合法的用户标识。");
-
- if(StringUtils.isBlank(textMessage))
- throw new ChatbotRuntimeException("[conversation] 不合法的消息内容。");
- }
-
- /**
- * 与聊天机器人进行多轮对话
- * @param fromUserId
- * @param textMessage
- * @param debug
- * @return
- */
- public JSONObject conversation(final String chatbotID, final String fromUserId, final String textMessage, boolean debug) throws ChatbotRuntimeException {
- v(chatbotID, fromUserId, textMessage);
- HashMap body = new HashMap();
- body.put("fromUserId", fromUserId);
- body.put("textMessage", textMessage);
- body.put("isDebug", debug);
-
- logger.info("conversation body {}", body);
-
- try {
- JSONObject resp = RestAPI.post(this.getBaseUrl() + "/chatbot/" + chatbotID + "/conversation/query", body);
- return resp;
- } catch (UnirestException e) {
- throw new ChatbotRuntimeException(e.toString());
- }
- }
-
- /**
- * 检索知识库
- * @param chatbotID
- * @param fromUserId
- * @param textMessage
- * @param isDebug
- * @return
- */
- public JSONObject faq(final String chatbotID, final String fromUserId, final String textMessage, final boolean isDebug) throws ChatbotRuntimeException {
- v(chatbotID, fromUserId, textMessage);
- HashMap body = new HashMap();
- body.put("fromUserId", fromUserId);
- body.put("query", textMessage);
- body.put("isDebug", isDebug);
- try {
- JSONObject resp = RestAPI.post(this.getBaseUrl() + "/chatbot/" + chatbotID + "/faq/query", body);
- return resp;
- } catch (UnirestException e) {
- throw new ChatbotRuntimeException(e.toString());
- }
- }
-
-}
diff --git a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotAPI.java b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotAPI.java
new file mode 100644
index 00000000..6a356349
--- /dev/null
+++ b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotAPI.java
@@ -0,0 +1,237 @@
+package com.chatopera.chatbot;
+
+import com.mashape.unirest.http.exceptions.UnirestException;
+import org.apache.commons.lang3.StringUtils;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+
+public class ChatbotAPI {
+ private static final Logger logger = LoggerFactory.getLogger(ChatbotAPI.class);
+ private String schema;
+ private String hostname;
+ private int port;
+ private String baseUrl;
+
+ private ChatbotAPI() {
+ }
+
+
+ public ChatbotAPI(final String baseUrl) throws ChatbotAPIRuntimeException, MalformedURLException {
+ if (StringUtils.isBlank(baseUrl))
+ throw new ChatbotAPIRuntimeException("智能问答引擎URL不能为空。");
+
+ URL url = new URL(baseUrl);
+ this.schema = url.getProtocol();
+ this.hostname = url.getHost();
+ this.port = url.getPort();
+
+ if (port == -1) {
+ this.baseUrl = this.schema + "://" + this.hostname + "/api/v1";
+ } else {
+ this.baseUrl = this.schema + "://" + this.hostname + ":" + this.port + "/api/v1";
+ }
+
+ }
+
+ public ChatbotAPI(final String schema, final String hostname, final int port, final String version) {
+ this.schema = schema;
+ this.hostname = hostname;
+ this.port = port;
+ this.baseUrl = schema + "://" + hostname + ":" + Integer.toString(this.port) + "/api/" + version;
+ }
+
+ public ChatbotAPI(final String schema, final String hostname, final int port) {
+ this(schema, hostname, port, "v1");
+ }
+
+ public ChatbotAPI(final String hostname, final int port) {
+ this("http", hostname, port);
+ }
+
+ public String getSchema() {
+ return schema;
+ }
+
+ public String getHostname() {
+ return hostname;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ /**
+ * 获取聊天机器人列表
+ *
+ * @return
+ * @throws ChatbotAPIRuntimeException
+ */
+ public JSONObject getChatbots(final String fields, final String q, final int page, final int limit) throws ChatbotAPIRuntimeException {
+ try {
+ HashMap queryString = new HashMap();
+ if (StringUtils.isNotBlank(fields)) {
+ queryString.put("fields", fields);
+ }
+
+ if (StringUtils.isNotBlank(q)) {
+ queryString.put("q", q);
+ }
+
+ queryString.put("page", page);
+
+ if (limit > 0) {
+ queryString.put("limit", limit);
+ }
+
+ return RestAPI.get(this.getBaseUrl() + "/chatbot", queryString);
+ } catch (UnirestException e) {
+ throw new ChatbotAPIRuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * 通过ChatbotID检查一个聊天机器人是否存在
+ *
+ * @param chatbotID
+ * @return
+ */
+ public boolean exists(final String chatbotID) throws ChatbotAPIRuntimeException {
+ try {
+ JSONObject result = this.getChatbot(chatbotID);
+ int rc = result.getInt("rc");
+ if (rc == 0) {
+ return true;
+ } else if (rc == 3) {
+ return false;
+ } else {
+ throw new ChatbotAPIRuntimeException("查询聊天机器人异常返回。");
+ }
+ } catch (Exception e) {
+ throw new ChatbotAPIRuntimeException(e.toString());
+ }
+ }
+
+
+ /**
+ * 创建聊天机器人
+ * @param chatbotID 聊天机器人标识,由[a-zA-Z0-9-]组成,字母开头
+ * @param name 拟人化的名字
+ * @param primaryLanguage 首选语言,支持 [zh_CN|en_US]
+ * @param fallback 兜底回复
+ * @param description 描述
+ * @param welcome 欢迎语
+ * @return
+ */
+ public JSONObject createBot(final String chatbotID,
+ final String name,
+ final String primaryLanguage,
+ final String fallback,
+ final String description,
+ final String welcome) throws ChatbotAPIRuntimeException {
+ HashMap body = new HashMap();
+ body.put("chatbotID", chatbotID);
+ body.put("name", name);
+ body.put("primaryLanguage", primaryLanguage);
+ body.put("description", description);
+ body.put("fallback", fallback);
+ body.put("welcome", welcome);
+
+ try {
+ return RestAPI.post(this.getBaseUrl() + "/chatbot/" + chatbotID, body);
+ } catch (UnirestException e) {
+ throw new ChatbotAPIRuntimeException(e.toString());
+ }
+ }
+
+
+ /**
+ * 获取聊天机器人详情
+ *
+ * @param chatbotID
+ * @return
+ * @throws ChatbotAPIRuntimeException
+ */
+ public JSONObject getChatbot(final String chatbotID) throws ChatbotAPIRuntimeException {
+ try {
+ return RestAPI.get(this.getBaseUrl() + "/chatbot/" + chatbotID);
+ } catch (UnirestException e) {
+ throw new ChatbotAPIRuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * validate params
+ *
+ * @param chatbotID
+ * @param fromUserId
+ * @param textMessage
+ */
+ private void v(final String chatbotID, final String fromUserId, final String textMessage) throws ChatbotAPIRuntimeException {
+ if (StringUtils.isBlank(chatbotID))
+ throw new ChatbotAPIRuntimeException("[conversation] 不合法的聊天机器人标识。");
+
+ if (StringUtils.isBlank(fromUserId))
+ throw new ChatbotAPIRuntimeException("[conversation] 不合法的用户标识。");
+
+ if (StringUtils.isBlank(textMessage))
+ throw new ChatbotAPIRuntimeException("[conversation] 不合法的消息内容。");
+ }
+
+ /**
+ * 与聊天机器人进行多轮对话
+ *
+ * @param fromUserId
+ * @param textMessage
+ * @param debug
+ * @return
+ */
+ public JSONObject conversation(final String chatbotID, final String fromUserId, final String textMessage, boolean debug) throws ChatbotAPIRuntimeException {
+ v(chatbotID, fromUserId, textMessage);
+ HashMap body = new HashMap();
+ body.put("fromUserId", fromUserId);
+ body.put("textMessage", textMessage);
+ body.put("isDebug", debug);
+
+ logger.info("conversation body {}", body);
+
+ try {
+ JSONObject resp = RestAPI.post(this.getBaseUrl() + "/chatbot/" + chatbotID + "/conversation/query", body);
+ return resp;
+ } catch (UnirestException e) {
+ throw new ChatbotAPIRuntimeException(e.toString());
+ }
+ }
+
+ /**
+ * 检索知识库
+ *
+ * @param chatbotID
+ * @param fromUserId
+ * @param textMessage
+ * @param isDebug
+ * @return
+ */
+ public JSONObject faq(final String chatbotID, final String fromUserId, final String textMessage, final boolean isDebug) throws ChatbotAPIRuntimeException {
+ v(chatbotID, fromUserId, textMessage);
+ HashMap body = new HashMap();
+ body.put("fromUserId", fromUserId);
+ body.put("query", textMessage);
+ body.put("isDebug", isDebug);
+ try {
+ JSONObject resp = RestAPI.post(this.getBaseUrl() + "/chatbot/" + chatbotID + "/faq/query", body);
+ return resp;
+ } catch (UnirestException e) {
+ throw new ChatbotAPIRuntimeException(e.toString());
+ }
+ }
+
+}
diff --git a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotRuntimeException.java b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotAPIRuntimeException.java
similarity index 52%
rename from cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotRuntimeException.java
rename to cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotAPIRuntimeException.java
index 76fe8c3f..6be8bc30 100644
--- a/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotRuntimeException.java
+++ b/cc-chatbot/app/src/main/java/com/chatopera/chatbot/ChatbotAPIRuntimeException.java
@@ -2,8 +2,8 @@ package com.chatopera.chatbot;
import com.mashape.unirest.http.exceptions.UnirestException;
-public class ChatbotRuntimeException extends Exception{
- public ChatbotRuntimeException(String msg) {
+public class ChatbotAPIRuntimeException extends Exception{
+ public ChatbotAPIRuntimeException(String msg) {
super(msg);
}
}
diff --git a/cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotTest.java b/cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotAPITest.java
similarity index 50%
rename from cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotTest.java
rename to cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotAPITest.java
index 90197a54..515ead54 100644
--- a/cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotTest.java
+++ b/cc-chatbot/app/src/test/java/com/chatopera/chatbot/ChatbotAPITest.java
@@ -7,20 +7,22 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.MalformedURLException;
+
/**
* Unit test for simple App.
*/
-public class ChatbotTest
+public class ChatbotAPITest
extends TestCase {
- private static final Logger logger = LoggerFactory.getLogger(ChatbotTest.class);
- private Chatbot cb;
+ private static final Logger logger = LoggerFactory.getLogger(ChatbotAPITest.class);
+ private ChatbotAPI cb;
/**
* Create the test case
*
* @param testName name of the test case
*/
- public ChatbotTest(String testName) {
+ public ChatbotAPITest(String testName) {
super(testName);
}
@@ -28,11 +30,11 @@ public class ChatbotTest
* @return the suite of tests being tested
*/
public static Test suite() {
- return new TestSuite(ChatbotTest.class);
+ return new TestSuite(ChatbotAPITest.class);
}
public void setUp() {
- this.cb = new Chatbot("http", "lhc-dev", 8003, "v1");
+ this.cb = new ChatbotAPI("http", "lhc-dev", 8003, "v1");
}
/**
@@ -46,7 +48,7 @@ public class ChatbotTest
try {
JSONObject resp = this.cb.getChatbot("co_bot_1");
logger.info("[testGetChatbot] {}", resp.toString());
- } catch (ChatbotRuntimeException e) {
+ } catch (ChatbotAPIRuntimeException e) {
e.printStackTrace();
}
}
@@ -55,27 +57,65 @@ public class ChatbotTest
try {
JSONObject resp = this.cb.getChatbots("name chatbotID", null, 0, 10);
logger.info("[testGetChatbots] resp {}", resp.toString());
- } catch (ChatbotRuntimeException e) {
+ } catch (ChatbotAPIRuntimeException e) {
e.printStackTrace();
}
}
- public void testConversation(){
+ public void testConversation() {
try {
JSONObject resp = this.cb.conversation("co_bot_1", "sdktest", "华夏春松在哪里", false);
logger.info("[testConversation] resp {}", resp.toString());
- } catch (ChatbotRuntimeException e) {
+ } catch (ChatbotAPIRuntimeException e) {
e.printStackTrace();
}
}
- public void testFaq(){
+ public void testFaq() {
try {
JSONObject resp = this.cb.faq("co_bot_1", "sdktest", "华夏春松在哪里", false);
logger.info("[testFaq] resp {}", resp.toString());
- } catch (ChatbotRuntimeException e) {
+ } catch (ChatbotAPIRuntimeException e) {
e.printStackTrace();
}
}
+ public void testParseUrl() {
+ try {
+ ChatbotAPI c = new ChatbotAPI("https://local:8000/");
+ logger.info("chatbot baseUrl {}", c.getBaseUrl());
+ assertEquals("https://local:8000/api/v1", c.getBaseUrl());
+ } catch (ChatbotAPIRuntimeException e) {
+ e.printStackTrace();
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void testExists() {
+ JSONObject profile = null;
+ try {
+ assertTrue(this.cb.exists("co_bot_1"));
+ } catch (ChatbotAPIRuntimeException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void testCreateBot() {
+ try {
+ JSONObject j = this.cb.createBot("cc_bot_2",
+ "小云2",
+ "zh_CN",
+ "我不了解。",
+ "小云机器人",
+ "你好,我是小云。");
+ logger.info("[testCreateBot] {}", j);
+ } catch (ChatbotAPIRuntimeException e) {
+ e.printStackTrace();
+ }
+ }
+
+
}
+
+
diff --git a/contact-center/app/pom.xml b/contact-center/app/pom.xml
index 1b3a2dad..81f6eab9 100644
--- a/contact-center/app/pom.xml
+++ b/contact-center/app/pom.xml
@@ -1,4 +1,5 @@
-
+
4.0.0
com.chatopera.cc
contact-center
@@ -308,6 +309,11 @@
aliyun-java-sdk-dysmsapi
1.0.0
+
+ com.chatopera.chatbot
+ sdk
+ 1.0.1
+
diff --git a/contact-center/app/src/main/java/com/chatopera/cc/webim/service/repository/ChatbotRepository.java b/contact-center/app/src/main/java/com/chatopera/cc/webim/service/repository/ChatbotRepository.java
new file mode 100644
index 00000000..b9db054c
--- /dev/null
+++ b/contact-center/app/src/main/java/com/chatopera/cc/webim/service/repository/ChatbotRepository.java
@@ -0,0 +1,10 @@
+package com.chatopera.cc.webim.service.repository;
+
+import com.chatopera.cc.webim.web.model.Chatbot;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public abstract interface ChatbotRepository extends JpaRepository {
+
+ public abstract boolean existsByChatbotIDAndOrgi(String chatbotID, String orgi);
+ public abstract boolean existsBySnsAccountIdentifierAndOrgi(String snsid, String orgi);
+}
diff --git a/contact-center/app/src/main/java/com/chatopera/cc/webim/service/repository/SNSAccountRepository.java b/contact-center/app/src/main/java/com/chatopera/cc/webim/service/repository/SNSAccountRepository.java
index 01105550..1481f5f7 100644
--- a/contact-center/app/src/main/java/com/chatopera/cc/webim/service/repository/SNSAccountRepository.java
+++ b/contact-center/app/src/main/java/com/chatopera/cc/webim/service/repository/SNSAccountRepository.java
@@ -27,7 +27,9 @@ public abstract interface SNSAccountRepository
extends JpaRepository
{
public abstract SNSAccount findByIdAndOrgi(String paramString, String orgi);
-
+
+ public abstract boolean existsBySnsidAndSnstypeAndOrgi(String snsid, String snsType, String orgi);
+
public abstract SNSAccount findBySnsid(String snsid);
public abstract SNSAccount findBySnsidAndOrgi(String snsid, String orgi);
diff --git a/contact-center/app/src/main/java/com/chatopera/cc/webim/web/handler/api/rest/ApiChatbotController.java b/contact-center/app/src/main/java/com/chatopera/cc/webim/web/handler/api/rest/ApiChatbotController.java
new file mode 100644
index 00000000..28a3fc29
--- /dev/null
+++ b/contact-center/app/src/main/java/com/chatopera/cc/webim/web/handler/api/rest/ApiChatbotController.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2018 Chatopera Inc,
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 com.chatopera.cc.webim.web.handler.api.rest;
+
+import com.chatopera.cc.util.Menu;
+import com.chatopera.cc.util.UKTools;
+import com.chatopera.cc.util.exception.CallOutRecordException;
+import com.chatopera.cc.webim.service.repository.ChatbotRepository;
+import com.chatopera.cc.webim.service.repository.SNSAccountRepository;
+import com.chatopera.cc.webim.web.handler.Handler;
+import com.chatopera.cc.webim.web.handler.api.request.RestUtils;
+import com.chatopera.cc.webim.web.model.Chatbot;
+import com.chatopera.cc.webim.web.model.User;
+import com.chatopera.chatbot.ChatbotAPI;
+import com.chatopera.chatbot.ChatbotAPIRuntimeException;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.MalformedURLException;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+
+@RestController
+@RequestMapping("/api/chatbot")
+@Api(value = "聊天机器人", description = "请求聊天机器人服务")
+public class ApiChatbotController extends Handler {
+ private final static Logger logger = LoggerFactory.getLogger(ApiChatbotController.class);
+ private final HashSet VALID_LANGS = new HashSet(Arrays.asList(new String[]{"zh_CN", "en_US"}));
+ private final HashSet VALID_WORKMODELS = new HashSet(Arrays.asList(new String[]{"客服机器人优先", "人工客服优先"}));
+ private final String SNS_TYPE_WEBIM = "webim";
+
+ @Value("${license.client.id}")
+ private String clientId;
+
+ @Autowired
+ private ChatbotRepository chatbotRes;
+
+ @Autowired
+ private SNSAccountRepository snsAccountRes;
+
+ @RequestMapping(method = RequestMethod.POST)
+ @Menu(type = "apps", subtype = "chatbot", access = true)
+ @ApiOperation("聊天机器人")
+ public ResponseEntity operations(HttpServletRequest request, @RequestBody final String body) throws CallOutRecordException {
+ final JsonObject j = (new JsonParser()).parse(body).getAsJsonObject();
+ logger.info("[chatbot] operations payload {}", j.toString());
+ JsonObject json = new JsonObject();
+ HttpHeaders headers = RestUtils.header();
+ User curruser = super.getUser(request);
+
+ if (!j.has("ops")) {
+ json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_1);
+ json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的请求参数。");
+ } else {
+ switch (StringUtils.lowerCase(j.get("ops").getAsString())) {
+ case "create":
+ json = create(j, curruser.getId(), curruser.getOrgan(), curruser.getOrgi());
+ break;
+ default:
+ json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_2);
+ json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的操作。");
+ }
+ }
+ return new ResponseEntity(json.toString(), headers, HttpStatus.OK);
+ }
+
+ /**
+ * 使用snsid得到ChatbotID
+ *
+ * @param snsid
+ * @return
+ */
+ private String resolveChatbotIDWithSnsid(String snsid) {
+ return clientId + "_" + snsid;
+ }
+
+
+ /**
+ * 使用chatbotID得到snsid
+ *
+ * @param chatbotID
+ * @return
+ */
+ private String resolveSnsidWithChatbotID(String chatbotID) {
+ return StringUtils.remove(chatbotID, clientId + "_");
+ }
+
+ /**
+ * 创建聊天机器人
+ *
+ * @param j
+ * @param creater
+ * @param organ
+ * @param orgi
+ * @return
+ */
+ private JsonObject create(JsonObject j, String creater, String organ, String orgi) {
+ JsonObject resp = new JsonObject();
+ String baseUrl = null;
+ String chatbotID = null;
+ String name = null;
+ String description = null;
+ String fallback = null;
+ String welcome = null;
+ String primaryLanguage = null;
+ String snsid = null;
+ String workmode = null;
+
+ // 验证数据: 必须字段
+ if ((!j.has("baseUrl")) || StringUtils.isBlank(j.get("baseUrl").getAsString())) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【baseUrl】。");
+ return resp;
+ } else {
+ baseUrl = j.get("baseUrl").getAsString();
+ }
+
+ if ((!j.has("name")) || StringUtils.isBlank(j.get("name").getAsString())) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【name】。");
+ return resp;
+ } else {
+ name = j.get("name").getAsString();
+ }
+
+ if (!(j.has("primaryLanguage") && VALID_LANGS.contains(j.get("primaryLanguage").getAsString()))) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入有效【primaryLanguage】。");
+ return resp;
+ } else {
+ primaryLanguage = j.get("primaryLanguage").getAsString();
+ }
+
+ if (!(j.has("workmode") && VALID_WORKMODELS.contains(j.get("workmode").getAsString()))) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入有效【workmode】。");
+ return resp;
+ } else {
+ workmode = j.get("workmode").getAsString();
+ }
+
+ if ((!j.has("snsid")) || StringUtils.isBlank(j.get("snsid").getAsString())) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入有效【snsid】。");
+ return resp;
+ } else {
+ snsid = j.get("snsid").getAsString();
+ // #TODO 仅支持webim
+ if (!snsAccountRes.existsBySnsidAndSnstypeAndOrgi(snsid, SNS_TYPE_WEBIM, orgi)) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入有效【snsid】。");
+ return resp;
+ }
+
+ if (chatbotRes.existsBySnsAccountIdentifierAndOrgi(snsid, orgi)) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,该渠道【snsid】已经存在聊天机器人。");
+ return resp;
+ }
+ }
+
+ chatbotID = resolveChatbotIDWithSnsid(snsid);
+ if (chatbotRes.existsByChatbotIDAndOrgi(chatbotID, orgi)) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,数据库中存在该聊天机器人。");
+ return resp;
+ }
+
+ if ((!j.has("fallback")) || StringUtils.isBlank(j.get("fallback").getAsString())) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的参数,未传入【fallback】。");
+ return resp;
+ } else {
+ fallback = j.get("fallback").getAsString();
+ }
+
+ // 可选字段
+ if (j.has("description"))
+ description = j.get("description").getAsString();
+
+ if (j.has("welcome"))
+ welcome = j.get("welcome").getAsString();
+
+ try {
+ ChatbotAPI capi = new ChatbotAPI(baseUrl);
+ JSONObject result = capi.createBot(chatbotID,
+ name,
+ primaryLanguage,
+ fallback,
+ description,
+ welcome);
+
+ if (result.getInt("rc") == 0) {
+ // 创建成功
+ Chatbot c = new Chatbot();
+ c.setId(UKTools.getUUID());
+ c.setBaseUrl(capi.getBaseUrl());
+ c.setChatbotID(chatbotID);
+ c.setDescription(description);
+ c.setFallback(fallback);
+ c.setPrimaryLanguage(primaryLanguage);
+ c.setWelcome(welcome);
+ c.setName(name);
+
+ // 默认不开启
+ c.setEnabled(false);
+ c.setCreater(creater);
+ c.setOrgan(organ);
+ c.setOrgi(orgi);
+ c.setChannel(SNS_TYPE_WEBIM);
+ c.setSnsAccountIdentifier(snsid);
+ Date dt = new Date();
+ c.setCreatetime(dt);
+ c.setUpdatetime(dt);
+ c.setWorkmode(workmode);
+
+ chatbotRes.save(c);
+
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
+ resp.addProperty(RestUtils.RESP_KEY_DATA, "创建成功。");
+ return resp;
+ } else {
+ // 创建失败
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_6);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "创建失败,失败原因 [" + result.getString("error") + "]");
+ return resp;
+ }
+ } catch (ChatbotAPIRuntimeException e) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "智能问答引擎服务异常。" + e.toString());
+ return resp;
+ } catch (MalformedURLException e) {
+ resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
+ resp.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的智能问答引擎服务URL。");
+ return resp;
+ }
+ }
+
+}
diff --git a/contact-center/app/src/main/java/com/chatopera/cc/webim/web/model/Chatbot.java b/contact-center/app/src/main/java/com/chatopera/cc/webim/web/model/Chatbot.java
new file mode 100644
index 00000000..38a681e0
--- /dev/null
+++ b/contact-center/app/src/main/java/com/chatopera/cc/webim/web/model/Chatbot.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2018 Chatopera Inc,
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * 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 com.chatopera.cc.webim.web.model;
+
+import com.chatopera.chatbot.ChatbotAPI;
+import com.chatopera.chatbot.ChatbotAPIRuntimeException;
+import org.hibernate.annotations.GenericGenerator;
+
+import javax.persistence.*;
+import java.net.MalformedURLException;
+import java.util.Date;
+
+@Entity
+@Table(name = "cs_chatbot")
+@org.hibernate.annotations.Proxy(lazy = false)
+public class Chatbot {
+
+ private String id;
+ private String name;
+
+ @Column(unique=true)
+ private String chatbotID;
+
+ private String description;
+ private String primaryLanguage;
+ private String fallback;
+ private String welcome;
+ private String baseUrl; // 智能问答引擎服务地址
+ private String orgi; // 租户标识
+ private String organ; // 组织机构
+ private String creater; // 创建者
+ private String channel; // 渠道类型
+
+ @Column(unique=true)
+ private String snsAccountIdentifier; // 渠道唯一标识
+ private boolean enabled; // 当前是否被启用
+ private String workmode; // 工作模式, 机器人优先还是人工客服优先
+
+ private ChatbotAPI api;
+ private Date createtime;
+ private Date updatetime;
+
+
+ @Id
+ @Column(length = 32)
+ @GeneratedValue(generator = "system-uuid")
+ @GenericGenerator(name = "system-uuid", strategy = "assigned")
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getChatbotID() {
+ return chatbotID;
+ }
+
+ public void setChatbotID(String chatbotID) {
+ this.chatbotID = chatbotID;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getPrimaryLanguage() {
+ return primaryLanguage;
+ }
+
+ public void setPrimaryLanguage(String primaryLanguage) {
+ this.primaryLanguage = primaryLanguage;
+ }
+
+ public String getFallback() {
+ return fallback;
+ }
+
+ public void setFallback(String fallback) {
+ this.fallback = fallback;
+ }
+
+ public String getWelcome() {
+ return welcome;
+ }
+
+ public void setWelcome(String welcome) {
+ this.welcome = welcome;
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ public void setBaseUrl(String baseUrl) {
+ this.baseUrl = baseUrl;
+ }
+
+ public String getOrgi() {
+ return orgi;
+ }
+
+ public void setOrgi(String orgi) {
+ this.orgi = orgi;
+ }
+
+ public String getOrgan() {
+ return organ;
+ }
+
+ public void setOrgan(String organ) {
+ this.organ = organ;
+ }
+
+ public String getCreater() {
+ return creater;
+ }
+
+ public void setCreater(String creater) {
+ this.creater = creater;
+ }
+
+ public String getChannel() {
+ return channel;
+ }
+
+ public void setChannel(String channel) {
+ this.channel = channel;
+ }
+
+ public String getSnsAccountIdentifier() {
+ return snsAccountIdentifier;
+ }
+
+ public void setSnsAccountIdentifier(String snsAccountIdentifier) {
+ this.snsAccountIdentifier = snsAccountIdentifier;
+ }
+
+ public String getWorkmode() {
+ return workmode;
+ }
+
+ public void setWorkmode(String workmode) {
+ this.workmode = workmode;
+ }
+
+ @Transient
+ public ChatbotAPI getApi() throws MalformedURLException, ChatbotAPIRuntimeException {
+ if(api == null){
+ api = new ChatbotAPI(this.baseUrl);
+ }
+ return api;
+ }
+
+ public Date getCreatetime() {
+ return createtime;
+ }
+
+ public void setCreatetime(Date createtime) {
+ this.createtime = createtime;
+ }
+
+ public Date getUpdatetime() {
+ return updatetime;
+ }
+
+ public void setUpdatetime(Date updatetime) {
+ this.updatetime = updatetime;
+ }
+}
+
+
diff --git a/contact-center/config/postman/Chatopera_cc_v1.postman_collection.json b/contact-center/config/postman/Chatopera_cc_v1.postman_collection.json
index 84631c88..8cf9a428 100644
--- a/contact-center/config/postman/Chatopera_cc_v1.postman_collection.json
+++ b/contact-center/config/postman/Chatopera_cc_v1.postman_collection.json
@@ -525,6 +525,39 @@
}
},
"response": []
+ },
+ {
+ "name": "机器人客服:创建",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "authorization",
+ "value": "00bf99785103475c896435ef7216ebd1"
+ },
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"ops\": \"create\",\n \"primaryLanguage\": \"zh_CN\",\n \"snsid\": \"104EAc\",\n \"name\": \"小C\",\n \"baseUrl\": \"http://lhc-dev:8003\",\n \"description\": \"描述\",\n \"fallback\": \"我不理解。\",\n \"welcome\": \"你好\",\n \"workmode\": \"客服机器人优先\"\n}"
+ },
+ "url": {
+ "raw": "http://{{IP}}:{{PORT}}/api/chatbot",
+ "protocol": "http",
+ "host": [
+ "{{IP}}"
+ ],
+ "port": "{{PORT}}",
+ "path": [
+ "api",
+ "chatbot"
+ ]
+ }
+ },
+ "response": []
}
],
"event": [
diff --git a/contact-center/config/sql/cskefu-MySQL-slim.sql b/contact-center/config/sql/cskefu-MySQL-slim.sql
index 5e207bb9..3c7ec841 100644
--- a/contact-center/config/sql/cskefu-MySQL-slim.sql
+++ b/contact-center/config/sql/cskefu-MySQL-slim.sql
@@ -3349,6 +3349,35 @@ CREATE TABLE `uk_skill` (
PRIMARY KEY (`ID`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='技能组表';
+
+-- ----------------------------
+-- Table structure for cs_chatbot
+-- ----------------------------
+DROP TABLE IF EXISTS `cs_chatbot`;
+CREATE TABLE `cs_chatbot` (
+ `ID` varchar(32) NOT NULL COMMENT '主键ID',
+ `base_url` varchar(255) NOT NULL COMMENT '基础URL',
+ `creater` varchar(32) NOT NULL COMMENT '创建人',
+ `orgi` varchar(255) NOT NULL COMMENT '租户ID',
+ `organ` varchar(32) NOT NULL COMMENT '部门ID',
+ `createtime` datetime NOT NULL COMMENT '创建时间',
+ `updatetime` datetime NOT NULL COMMENT '更新时间',
+ `chatbotid` varchar(255) NOT NULL COMMENT '聊天机器人ID',
+ `name` varchar(255) NOT NULL COMMENT '聊天机器人名字',
+ `description` varchar(255) NOT NULL COMMENT '描述',
+ `primary_language` varchar(20) NOT NULL COMMENT '首选语言',
+ `fallback` varchar(255) DEFAULT NULL COMMENT '兜底回复',
+ `welcome` varchar(255) DEFAULT NULL COMMENT '欢迎语',
+ `channel` varchar(32) NOT NULL COMMENT '渠道类型',
+ `sns_account_identifier` varchar(255) NOT NULL COMMENT '渠道标识',
+ `enabled` tinyint(1) DEFAULT '0' COMMENT '是否开启',
+ `workmode` varchar(32) NOT NULL COMMENT '工作模式',
+ PRIMARY KEY (`ID`) USING BTREE,
+ UNIQUE KEY `snsid` (`sns_account_identifier`,`orgi`) USING BTREE COMMENT '按照渠道标识唯一',
+ UNIQUE KEY `chatbotID` (`chatbotid`,`orgi`) USING BTREE COMMENT '按照ChatbotID唯一'
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='机器人客服表';
+
+
-- ----------------------------
-- Table structure for uk_snsaccount
-- ----------------------------