1
0
mirror of https://github.com/chatopera/cosin.git synced 2025-08-01 16:38:02 +08:00

#75 支持和问答引擎的初步集成

This commit is contained in:
Hai Liang Wang 2018-09-13 03:24:49 +08:00
parent a0d26b1dbf
commit 87f4055b53
10 changed files with 1544 additions and 1477 deletions

View File

@ -16,47 +16,34 @@
*/
package com.chatopera.cc.app.basic;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.chatopera.cc.util.*;
import com.chatopera.cc.util.asr.AsrResult;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.repository.*;
import com.chatopera.cc.concurrent.chatbot.ChatbotEvent;
import com.chatopera.cc.concurrent.multiupdate.MultiUpdateEvent;
import com.chatopera.cc.concurrent.user.UserDataEvent;
import com.chatopera.cc.exchange.UserEvent;
import com.chatopera.cc.util.*;
import com.chatopera.cc.util.WebIMReport;
import com.chatopera.cc.util.asr.AsrResult;
import com.chatopera.cc.util.mail.MailSender;
import com.chatopera.cc.app.cache.CacheHelper;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.googlecode.aviator.AviatorEvaluator;
import com.lmax.disruptor.dsl.Disruptor;
import freemarker.template.Configuration;
import freemarker.template.TemplateException;
import io.netty.handler.codec.http.HttpHeaders;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtils;
@ -76,46 +63,21 @@ import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.web.multipart.MultipartFile;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.googlecode.aviator.AviatorEvaluator;
import com.lmax.disruptor.dsl.Disruptor;
import com.chatopera.cc.app.persistence.repository.AdTypeRepository;
import com.chatopera.cc.app.persistence.repository.AreaTypeRepository;
import com.chatopera.cc.app.persistence.repository.AttachmentRepository;
import com.chatopera.cc.app.persistence.repository.SecretRepository;
import com.chatopera.cc.app.persistence.repository.SystemConfigRepository;
import com.chatopera.cc.app.persistence.repository.SystemMessageRepository;
import com.chatopera.cc.app.persistence.repository.TablePropertiesRepository;
import com.chatopera.cc.app.persistence.repository.TemplateRepository;
import com.chatopera.cc.app.model.AdType;
import com.chatopera.cc.app.model.AttachmentFile;
import com.chatopera.cc.app.model.JobDetail;
import com.chatopera.cc.app.model.JobTask;
import com.chatopera.cc.app.model.Secret;
import com.chatopera.cc.app.model.SysDic;
import com.chatopera.cc.app.model.SystemConfig;
import com.chatopera.cc.app.model.SystemMessage;
import com.chatopera.cc.app.model.TableProperties;
import com.chatopera.cc.app.model.Template;
import com.chatopera.cc.app.model.UKeFuDic;
import com.chatopera.cc.app.model.User;
import com.chatopera.cc.app.model.WorkOrders;
import com.chatopera.cc.app.model.WorkSession;
import freemarker.template.Configuration;
import freemarker.template.TemplateException;
import io.netty.handler.codec.http.HttpHeaders;
import net.coobird.thumbnailator.Thumbnails;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MainUtils {
@ -129,6 +91,7 @@ public class MainUtils {
/**
* 当前时间+已过随机生成的 长整形数字
*
* @return
*/
public static String genID() {
@ -184,8 +147,7 @@ public class MainUtils {
}
writeMethod.invoke(target, value);
}
}
catch (Throwable ex) {
} catch (Throwable ex) {
throw new FatalBeanException(
"Could not copy property '" + targetPd.getName() + "' from source to target", ex);
}
@ -220,6 +182,7 @@ public class MainUtils {
return ((ip >> 24) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "."
+ ((ip >> 8) & 0xFF) + "." + (ip & 0xFF);
}
/***
* ID编码 发送对话的时候使用
* @param id
@ -248,11 +211,12 @@ public class MainUtils {
@SuppressWarnings("unchecked")
Disruptor<UserDataEvent> disruptor = (Disruptor<UserDataEvent>) MainContext.getContext().getBean("disruptor");
long seq = disruptor.getRingBuffer().next();
disruptor.getRingBuffer().get(seq).setEvent(event); ;
disruptor.getRingBuffer().get(seq).setEvent(event);
;
disruptor.getRingBuffer().publish(seq);
}
/**
*
* @param request
* @return
*/
@ -283,7 +247,6 @@ public class MainUtils {
}
/**
*
* @param request
* @return
*/
@ -305,6 +268,7 @@ public class MainUtils {
/**
* 获取一天的开始时间
*
* @return
*/
public static Date getStartTime() {
@ -318,6 +282,7 @@ public class MainUtils {
/**
* 获取一天的开始时间
*
* @return
*/
public static Date getWeekStartTime() {
@ -329,6 +294,7 @@ public class MainUtils {
/**
* 获取一天的开始时间
*
* @return
*/
public static Date getLast30Day() {
@ -343,6 +309,7 @@ public class MainUtils {
/**
* 获取一天的开始时间
*
* @return
*/
public static Date getLastDay(int days) {
@ -357,6 +324,7 @@ public class MainUtils {
/**
* 获取一天的结束时间
*
* @return
*/
public static Date getEndTime() {
@ -370,6 +338,7 @@ public class MainUtils {
/**
* 获取一天的结束时间
*
* @return
*/
public static Date getLastTime(int secs) {
@ -400,62 +369,48 @@ public class MainUtils {
//=================OS=======================
if (userAgent.toLowerCase().indexOf("windows") >= 0 )
{
if (userAgent.toLowerCase().indexOf("windows") >= 0) {
os = "windows";
} else if(userAgent.toLowerCase().indexOf("mac") >= 0)
{
} else if (userAgent.toLowerCase().indexOf("mac") >= 0) {
os = "mac";
} else if(userAgent.toLowerCase().indexOf("x11") >= 0)
{
} else if (userAgent.toLowerCase().indexOf("x11") >= 0) {
os = "unix";
} else if(userAgent.toLowerCase().indexOf("android") >= 0)
{
} else if (userAgent.toLowerCase().indexOf("android") >= 0) {
os = "android";
} else if(userAgent.toLowerCase().indexOf("iphone") >= 0)
{
} else if (userAgent.toLowerCase().indexOf("iphone") >= 0) {
os = "iphone";
} else {
os = "UnKnown";
}
//===============Browser===========================
if(user.contains("qqbrowser"))
{
if (user.contains("qqbrowser")) {
browser = "QQBrowser";
}else if (user.contains("msie") || user.indexOf("rv:11") > -1)
{
} else if (user.contains("msie") || user.indexOf("rv:11") > -1) {
if (user.indexOf("rv:11") >= 0) {
browser = "IE11";
} else {
String substring = userAgent.substring(userAgent.indexOf("MSIE")).split(";")[0];
browser = substring.split(" ")[0].replace("MSIE", "IE") + substring.split(" ")[1];
}
}else if (user.contains("trident"))
{
} else if (user.contains("trident")) {
browser = "IE 11";
}else if (user.contains("edge"))
{
} else if (user.contains("edge")) {
browser = "Edge";
} else if (user.contains("safari") && user.contains("version"))
{
} else if (user.contains("safari") && user.contains("version")) {
browser = (userAgent.substring(userAgent.indexOf("Safari")).split(" ")[0]).split("/")[0];
version = (userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
} else if ( user.contains("opr") || user.contains("opera"))
{
} else if (user.contains("opr") || user.contains("opera")) {
if (user.contains("opera"))
browser = (userAgent.substring(userAgent.indexOf("Opera")).split(" ")[0]).split("/")[0] + "-" + (userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
else if (user.contains("opr"))
browser = ((userAgent.substring(userAgent.indexOf("OPR")).split(" ")[0]).replace("/", "-")).replace("OPR", "Opera");
} else if (user.contains("chrome"))
{
} else if (user.contains("chrome")) {
browser = "Chrome";
} else if ((user.indexOf("mozilla/7.0") > -1) || (user.indexOf("netscape6") != -1) || (user.indexOf("mozilla/4.7") != -1) || (user.indexOf("mozilla/4.78") != -1) || (user.indexOf("mozilla/4.08") != -1) || (user.indexOf("mozilla/3") != -1) )
{
} else if ((user.indexOf("mozilla/7.0") > -1) || (user.indexOf("netscape6") != -1) || (user.indexOf("mozilla/4.7") != -1) || (user.indexOf("mozilla/4.78") != -1) || (user.indexOf("mozilla/4.08") != -1) || (user.indexOf("mozilla/3") != -1)) {
//browser=(userAgent.substring(userAgent.indexOf("MSIE")).split(" ")[0]).replace("/", "-");
browser = "Netscape-?";
}else if ((user.indexOf("mozilla") > -1))
{
} else if ((user.indexOf("mozilla") > -1)) {
//browser=(userAgent.substring(userAgent.indexOf("MSIE")).split(" ")[0]).replace("/", "-");
if (browserDetails.indexOf(" ") > 0) {
browser = browserDetails.substring(0, browserDetails.indexOf(" "));
@ -463,14 +418,11 @@ public class MainUtils {
browser = "Mozilla";
}
} else if (user.contains("firefox"))
{
} else if (user.contains("firefox")) {
browser = (userAgent.substring(userAgent.indexOf("Firefox")).split(" ")[0]).replace("/", "-");
} else if(user.contains("rv"))
{
} else if (user.contains("rv")) {
browser = "ie";
} else
{
} else {
browser = "UnKnown";
}
client.setUseragent(browserDetails);
@ -480,8 +432,10 @@ public class MainUtils {
return client;
}
/**
* 活动JPA统计结果
*
* @param values
* @return
*/
@ -499,6 +453,7 @@ public class MainUtils {
/**
* 活动JPA统计结果
*
* @param values
* @return
*/
@ -525,6 +480,7 @@ public class MainUtils {
/**
* 活动JPA统计结果
*
* @param values
* @return
*/
@ -547,6 +503,7 @@ public class MainUtils {
/**
* 活动JPA统计结果
*
* @param values
* @return
*/
@ -572,6 +529,7 @@ public class MainUtils {
/**
* 活动JPA统计结果
*
* @param values
* @return
*/
@ -598,6 +556,7 @@ public class MainUtils {
/**
* 活动JPA统计结果
*
* @param values
* @return
*/
@ -655,14 +614,11 @@ public class MainUtils {
}
public static void populate(Object bean, Map<Object, Object> properties) throws IllegalAccessException, InvocationTargetException {
ConvertUtils.register(new Converter()
{
ConvertUtils.register(new Converter() {
@SuppressWarnings("rawtypes")
@Override
public Object convert(Class arg0, Object arg1)
{
if(arg1 == null)
{
public Object convert(Class arg0, Object arg1) {
if (arg1 == null) {
return null;
}
if (arg1 instanceof Date) {
@ -671,8 +627,7 @@ public class MainUtils {
throw new ConversionException("只支持字符串转换 !");
}
String str = (String) arg1;
if(str.trim().equals(""))
{
if (str.trim().equals("")) {
return null;
}
@ -680,8 +635,7 @@ public class MainUtils {
try {
return sd.parse(str);
} catch(Exception e)
{
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -712,7 +666,6 @@ public class MainUtils {
}
/**
*
* @param str
* @return
* @throws NoSuchAlgorithmException
@ -724,7 +677,6 @@ public class MainUtils {
}
/**
*
* @param str
* @return
* @throws NoSuchAlgorithmException
@ -765,8 +717,10 @@ public class MainUtils {
}
return strb.toString();
}
/**
* 处理 对话消息中的图片
*
* @param message
* @return
*/
@ -784,6 +738,7 @@ public class MainUtils {
/**
* 检查当前时间是否是在 时间范围内 时间范围的格式为 08:30~11:30,13:30~17:30
*
* @param timeRanges
* @return
*/
@ -929,8 +884,10 @@ public class MainUtils {
}
}
/**
* 获取系统配置
*
* @return
*/
public static SystemConfig getSystemConfig() {
@ -941,8 +898,10 @@ public class MainUtils {
}
return systemConfig;
}
/**
* 初始化呼叫中心功能里需要隐藏号码的字段
*
* @param tpRes
*/
public static void initSystemSecField(TablePropertiesRepository tpRes) {
@ -951,8 +910,10 @@ public class MainUtils {
CacheHelper.getSystemCacheBean().put(MainContext.UKEFU_SYSTEM_SECFIELD, tpList, MainContext.SYSTEM_ORGI);
}
}
/**
* 获取系统地区配置
*
* @return
*/
public static void initSystemArea() {
@ -963,6 +924,7 @@ public class MainUtils {
/**
* 缓存 广告位
*
* @return
*/
public static void initAdv(String orgi) {
@ -980,8 +942,10 @@ public class MainUtils {
}
return templet;
}
/**
* 按照权重获取广告
*
* @param adpos
* @return
*/
@ -999,7 +963,8 @@ public class MainUtils {
if (sysDicList != null) {
for (SysDic dic : sysDicList) {
if (dic.getCode().equals(adpos)) {
sysDic = dic ; break ;
sysDic = dic;
break;
}
}
}
@ -1012,10 +977,12 @@ public class MainUtils {
}
return weitht(adTypeList);
}
private static Random random = new Random();
/**
*
* 按照权重获取广告内容
*
* @param adList
* @return
*/
@ -1029,7 +996,8 @@ public class MainUtils {
int n = random.nextInt(weight), m = 0;
for (AdType ad : adList) {
if (m <= n && n < m + ad.getWeight()) {
adType = ad ; break;
adType = ad;
break;
}
m += ad.getWeight();
}
@ -1053,7 +1021,6 @@ public class MainUtils {
}
/**
*
* @throws IOException
* @throws TemplateException
*/
@ -1077,6 +1044,7 @@ public class MainUtils {
/**
* 发送邮件
*
* @param email
* @param cc
* @param subject
@ -1103,6 +1071,7 @@ public class MainUtils {
}
return null;
}
@SuppressWarnings("unchecked")
public static <T> T decode(String str, Class<T> clazz) {
Base64 base64 = new Base64();
@ -1113,15 +1082,16 @@ public class MainUtils {
}
return null;
}
public static String processContentEncode(String str) throws Exception {
return Base64.encodeBase64String(str.getBytes("UTF-8")).replaceAll("\\+", "-");
}
public static String processContentDecode(String str) throws Exception {
return new String(Base64.decodeBase64(str.replaceAll("-", "\\+").getBytes()), "UTF-8");
}
/**
*
* @param defaultFormatValue
* @param text
* @return
@ -1136,6 +1106,7 @@ public class MainUtils {
return getDays(text, defaultFormatValue != null && defaultFormatValue.length() > 0 ? defaultFormatValue : formatValue);
}
/***
* 计算T+1
* @param text
@ -1178,8 +1149,8 @@ public class MainUtils {
return AviatorEvaluator.execute(text, context);
}
/**
*
* @param value
* @return
* @throws ParseException
@ -1191,8 +1162,8 @@ public class MainUtils {
}
return value != null ? value.toString() : "0";
}
/**
*
* @param value
* @return
* @throws ParseException
@ -1219,8 +1190,8 @@ public class MainUtils {
}
return value != null ? value.toString() : "0";
}
/**
*
* @return
*/
public static double processDays() {
@ -1228,7 +1199,6 @@ public class MainUtils {
}
/**
*
* @return
*/
public static double processMonth() {
@ -1238,7 +1208,6 @@ public class MainUtils {
}
/**
*
* @return
*/
public static double processYear() {
@ -1246,6 +1215,7 @@ public class MainUtils {
}
private static final ObjectMapper JSON = new ObjectMapper();
static {
JSON.setSerializationInclusion(Include.NON_NULL);
JSON.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);
@ -1260,8 +1230,8 @@ public class MainUtils {
return null;
}
/**
*
* @param message
*/
public static AsrResult parseAsrResult(String id, String message, int speakms) {
@ -1282,6 +1252,7 @@ public class MainUtils {
/**
* 发送短信
*
* @param phone
* @param id
* @param tpId
@ -1353,7 +1324,6 @@ public class MainUtils {
}
/**
*
* @param userid
* @param client
* @param session
@ -1388,7 +1358,6 @@ public class MainUtils {
}
/**
*
* @param plan
* @return
*/
@ -1419,8 +1388,8 @@ public class MainUtils {
}
return nextFireDate;
}
/**
*
* @param dialNum
* @param distype
* @return

View File

@ -21,6 +21,7 @@ import java.util.concurrent.Executors;
import com.chatopera.cc.concurrent.chatbot.ChatbotDisruptorExceptionHandler;
import com.chatopera.cc.concurrent.chatbot.ChatbotEventFactory;
import com.chatopera.cc.concurrent.chatbot.ChatbotEventHandler;
import com.chatopera.cc.concurrent.multiupdate.MultiUpdateEventFactory;
import com.chatopera.cc.concurrent.multiupdate.MultiUpdateEventHandler;
import org.springframework.context.annotation.Bean;
@ -65,7 +66,7 @@ public class DisruptorConfigure {
Executor executor = Executors.newCachedThreadPool();
ChatbotEventFactory factory = new ChatbotEventFactory();
Disruptor<UserDataEvent> disruptor = new Disruptor<UserDataEvent>(factory, 1024, executor, ProducerType.SINGLE , new SleepingWaitStrategy());
disruptor.handleEventsWith(new MultiUpdateEventHandler());
disruptor.handleEventsWith(new ChatbotEventHandler());
disruptor.setDefaultExceptionHandler(new ChatbotDisruptorExceptionHandler());
disruptor.start();
return disruptor;

View File

@ -17,21 +17,23 @@ package com.chatopera.cc.app.im.handler;
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.im.util.ChatbotUtils;
import com.chatopera.cc.util.IP;
import com.chatopera.cc.util.IPTools;
import com.chatopera.cc.app.basic.MainUtils;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.persistence.repository.AgentUserRepository;
import com.chatopera.cc.app.persistence.repository.ConsultInviteRepository;
import com.chatopera.cc.app.persistence.repository.OnlineUserRepository;
import com.chatopera.cc.app.im.router.OutMessageRouter;
import com.chatopera.cc.util.OnlineUserUtils;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.im.message.AgentStatusMessage;
import com.chatopera.cc.app.im.message.ChatMessage;
import com.chatopera.cc.app.im.message.NewRequestMessage;
import com.chatopera.cc.app.im.util.ChatbotUtils;
import com.chatopera.cc.app.model.*;
import com.chatopera.cc.app.persistence.repository.AgentUserRepository;
import com.chatopera.cc.app.persistence.repository.ChatbotRepository;
import com.chatopera.cc.app.persistence.repository.ConsultInviteRepository;
import com.chatopera.cc.app.persistence.repository.OnlineUserRepository;
import com.chatopera.cc.concurrent.chatbot.ChatbotEvent;
import com.chatopera.cc.util.Constants;
import com.chatopera.cc.util.IP;
import com.chatopera.cc.util.IPTools;
import com.chatopera.cc.util.OnlineUserUtils;
import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
@ -53,6 +55,7 @@ public class ChatbotEventHandler {
private AgentUserRepository agentUserRes;
private OnlineUserRepository onlineUserRes;
private ChatbotRepository chatbotRes;
@Autowired
public ChatbotEventHandler(SocketIOServer server) {
@ -73,9 +76,9 @@ public class ChatbotEventHandler {
Date now = new Date();
if (StringUtils.isNotBlank(user)) {
// /**
// * 加入到 缓存列表
// */
/**
* 加入到 缓存列表
*/
NettyClients.getInstance().putChatbotEventClient(user, client);
MessageOutContent outMessage = new MessageOutContent();
CousultInvite invite = OnlineUserUtils.cousult(appid, orgi, MainContext.getContext().getBean(ConsultInviteRepository.class));
@ -195,62 +198,71 @@ public class ChatbotEventHandler {
String orgi = client.getHandshakeData().getSingleUrlParam("orgi");
String aiid = client.getHandshakeData().getSingleUrlParam("aiid");
String user = client.getHandshakeData().getSingleUrlParam("userid");
if (data.getType() == null) {
data.setType("message");
logger.info("[chatbot] onEvent message: orgi {}, aiid {}, userid {}, dataType {}", orgi, aiid, user, data.getType());
// ignore event if dataType is not message.
if (!StringUtils.equals(data.getType(), Constants.IM_MESSAGE_TYPE_MESSAGE)) {
return;
}
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(user, orgi);
// ignore event if no agentUser found.
if (agentUser == null)
return;
/**
* 以下代码主要用于检查 访客端的字数限制
*/
CousultInvite invite = OnlineUserUtils.cousult(data.getAppid(), data.getOrgi(), MainContext.getContext().getBean(ConsultInviteRepository.class));
if (invite != null && invite.getMaxwordsnum() > 0) {
if (!StringUtils.isBlank(data.getMessage()) && data.getMessage().length() > invite.getMaxwordsnum()) {
// ignore event if no invite found.
if (invite == null)
return;
// ignore if Chatbot is turnoff.
if (!invite.isAi())
return;
Date now = new Date();
if (invite.getMaxwordsnum() > 0) {
if (StringUtils.isNotBlank(data.getMessage()) && data.getMessage().length() > invite.getMaxwordsnum()) {
data.setMessage(data.getMessage().substring(0, invite.getMaxwordsnum()));
}
} else if (!StringUtils.isBlank(data.getMessage()) && data.getMessage().length() > 300) {
} else if (StringUtils.isNotBlank(data.getMessage()) && data.getMessage().length() > 300) {
data.setMessage(data.getMessage().substring(0, 300));
}
data.setSessionid(MainUtils.getContextID(client.getSessionId().toString()));
/**
* 处理表情
*/
data.setMessage(MainUtils.processEmoti(data.getMessage()));
data.setMessage(MainUtils.processEmoti(data.getMessage())); // 处理表情
data.setTousername(invite.getAiname());
data.setAiid(aiid);
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(user, orgi);
if (agentUser != null) {
data.setAgentserviceid(agentUser.getAgentserviceid());
data.setChannel(agentUser.getChannel());
/**
* 一定要设置 ContextID
*/
data.setContextid(agentUser.getAgentserviceid());
}
MessageOutContent outMessage = ChatbotUtils.createTextMessage(data, data.getAppid(), data.getChannel(), MainContext.CallTypeEnum.IN.toString(), MainContext.ChatbotItemType.USERINPUT.toString(), data.getUserid());
if (StringUtils.isNotBlank(data.getUserid()) && MainContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())) {
if (!StringUtils.isBlank(data.getTouser())) {
OutMessageRouter router = null;
router = (OutMessageRouter) MainContext.getContext().getBean(data.getChannel());
if (router != null) {
router.handler(data.getTouser(), MainContext.MessageTypeEnum.MESSAGE.toString(), data.getAppid(), outMessage);
}
}
if (agentUser != null) {
Date now = new Date();
data.setContextid(agentUser.getAgentserviceid()); // 一定要设置 ContextID
data.setCalltype(MainContext.CallTypeEnum.IN.toString());
ChatbotUtils.createTextMessage(data,
MainContext.CallTypeEnum.IN.toString(),
MainContext.ChatbotItemType.USERINPUT.toString());
// 更新访客咨询记录
agentUser.setUpdatetime(now);
agentUser.setLastmessage(now);
agentUser.setLastmsg(data.getMessage());
CacheHelper.getAgentUserCacheBean().put(user, agentUser, MainContext.SYSTEM_ORGI);
}
}
CacheHelper.getAgentUserCacheBean().put(user, agentUser, orgi);
getAgentUserRes().save(agentUser);
// 发送消息给Bot
MainUtils.chatbot(new ChatbotEvent<ChatMessage>(data,
getChatbotRes(),
Constants.CHATBOT_EVENT_TYPE_CHAT));
}
/**
* Lazy load
*
* @return
*/
public AgentUserRepository getAgentUserRes() {
private AgentUserRepository getAgentUserRes() {
if (agentUserRes == null)
agentUserRes = MainContext.getContext().getBean(AgentUserRepository.class);
return agentUserRes;
@ -258,11 +270,19 @@ public class ChatbotEventHandler {
/**
* Lazy load
*
* @return
*/
public OnlineUserRepository getOnlineUserRes() {
private OnlineUserRepository getOnlineUserRes() {
if (onlineUserRes == null)
onlineUserRes = MainContext.getContext().getBean(OnlineUserRepository.class);
return onlineUserRes;
}
private ChatbotRepository getChatbotRes() {
if (chatbotRes == null)
chatbotRes = MainContext.getContext().getBean(ChatbotRepository.class);
return chatbotRes;
}
}

View File

@ -16,18 +16,23 @@
package com.chatopera.cc.app.im.util;
import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.im.message.ChatMessage;
import com.chatopera.cc.app.model.AgentUser;
import com.chatopera.cc.app.model.Chatbot;
import com.chatopera.cc.app.model.MessageOutContent;
import com.chatopera.cc.app.cache.CacheHelper;
import com.chatopera.cc.app.persistence.repository.ChatMessageRepository;
import com.chatopera.cc.app.persistence.repository.ChatbotRepository;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.HashSet;
public class ChatbotUtils {
private final static Logger logger = LoggerFactory.getLogger(ChatbotUtils.class);
public static final HashSet<String> VALID_LANGS = new HashSet<String>(Arrays.asList(new String[]{"zh_CN", "en_US"}));
public static final String CHATBOT_FIRST = "机器人客服优先";
public static final String HUMAN_FIRST = "人工客服优先";
@ -35,6 +40,9 @@ public class ChatbotUtils {
public static final String SNS_TYPE_WEBIM = "app";
private static ChatbotRepository chatbotRes;
private static ChatMessageRepository chatMessageRes;
/**
* 使用snsid得到ChatbotID
@ -56,6 +64,48 @@ public class ChatbotUtils {
return StringUtils.remove(chatbotID, clientId.toLowerCase() + "_");
}
/**
* @param data
* @param direction
* @param chatype
* @param msgtype
* @return
*/
private static MessageOutContent createMessage(ChatMessage data, String direction, String chatype, String msgtype) {
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(data.getUserid(), data.getOrgi());
if (agentUser == null)
return null;
// 设置发送消息体
MessageOutContent outMessage = new MessageOutContent();
outMessage.setMessage(data.getMessage());
outMessage.setMessageType(msgtype);
outMessage.setCalltype(direction);
outMessage.setAgentUser(null);
outMessage.setSnsAccount(null);
if (StringUtils.isNotBlank(data.getSuggestmsg())) {
outMessage.setSuggest(data.getSuggest());
}
outMessage.setContextid(data.getUserid());
outMessage.setFromUser(data.getUserid());
outMessage.setToUser(data.getTouser());
outMessage.setChannelMessage(data);
outMessage.setNickName(data.getUsername());
outMessage.setCreatetime(data.getCreatetime());
/**
* 保存消息
*/
getChatMessageRes().save(data);
//将消息发送给 访客
NettyClients.getInstance().sendChatbotEventMessage(data.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), data);
return outMessage;
}
/**
* 发送聊天机器人消息
*
@ -68,81 +118,53 @@ public class ChatbotUtils {
* @param userid
* @return
*/
protected static MessageOutContent createMessage(ChatMessage data, String appid, String channel, String direction, String chatype, String msgtype, String userid) {
MessageOutContent outMessage = new MessageOutContent();
protected static MessageOutContent createMessage(final ChatMessage data,
final String appid,
final String channel,
final String direction,
final String chatype,
final String msgtype,
final String userid,
final String orgi) {
Chatbot c = getChatbotRes().findBySnsAccountIdentifierAndOrgi(appid, orgi);
if (c == null) // ignore event if chatbot not exist.
return null;
outMessage.setMessage(data.getMessage());
outMessage.setMessageType(msgtype);
outMessage.setCalltype(direction);
outMessage.setAgentUser(null);
outMessage.setSnsAccount(null);
{
data.setAiid(c.getId());
data.setOrgi(orgi);
data.setUserid(userid);
data.setUsername(data.getUsername());
data.setTouser(userid);
data.setAgentuser(userid);
data.setAgentserviceid(data.getContextid());
data.setChatype(chatype);
data.setChannel(channel);
data.setAppid(data.getAppid());
data.setOrgi(data.getOrgi());
data.setMsgtype(msgtype);
data.setUsername(data.getUsername());
data.setUsession(data.getUserid()); //agentUser作为 session id
data.setContextid(data.getContextid());
data.setCalltype(direction);
outMessage.setContextid(data.getContextid());
outMessage.setFromUser(data.getUserid());
outMessage.setToUser(data.getTouser());
outMessage.setChannelMessage(data);
outMessage.setNickName(data.getUsername());
outMessage.setCreatetime(data.getCreatetime());
if (!StringUtils.isBlank(data.getSuggestmsg())) {
outMessage.setSuggest(data.getSuggest());
}
data.setUpdatetime(System.currentTimeMillis());
/**
* 保存消息
*/
if (MainContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())) {
MainContext.getContext().getBean(ChatMessageRepository.class).save(data);
}
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(userid, MainContext.SYSTEM_ORGI);
if (agentUser != null && !StringUtils.isBlank(agentUser.getAgentno())) {
//将消息发送给 坐席
if (MainContext.CallTypeEnum.OUT.toString().equals(direction)) {
data.setUserid(agentUser.getAgentno());
}
NettyClients.getInstance().sendAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.MESSAGE.toString(), data);
}
}
return outMessage;
return createMessage(data, direction, chatype, msgtype);
}
/**
* 发送文字消息
*
* @param data
* @param appid
* @param channel
* @param direction
* @param chatype
* @param userid
* @return
*/
public static MessageOutContent createTextMessage(ChatMessage data, String appid, String channel, String direction, String chatype, String userid) {
return createMessage(data, appid, channel, direction, chatype, MainContext.MediaTypeEnum.TEXT.toString(), userid);
public static MessageOutContent createTextMessage(ChatMessage data, String direction, String chatype) {
return createMessage(data, direction, chatype, MainContext.MediaTypeEnum.TEXT.toString());
}
private static ChatbotRepository getChatbotRes() {
if (chatbotRes == null)
chatbotRes = MainContext.getContext().getBean(ChatbotRepository.class);
return chatbotRes;
}
private static ChatMessageRepository getChatMessageRes() {
if (chatMessageRes == null)
chatMessageRes = MainContext.getContext().getBean(ChatMessageRepository.class);
return chatMessageRes;
}
}

View File

@ -147,7 +147,7 @@ public class RichMediaUtils {
if (StringUtils.isNotBlank(userid)) {
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(userid, MainContext.SYSTEM_ORGI);
if ((agentUser != null) && StringUtils.equals(agentUser.getOpttype(), MainContext.OptTypeEnum.CHATBOT.toString())) {
ChatbotUtils.createMessage(data, appid, channel, MainContext.CallTypeEnum.IN.toString(), MainContext.ChatbotItemType.USERINPUT.toString(), msgtype, data.getUserid());
ChatbotUtils.createMessage(data, appid, channel, MainContext.CallTypeEnum.IN.toString(), MainContext.ChatbotItemType.USERINPUT.toString(), msgtype, data.getUserid(), orgi);
} else {
HumanUtils.createMessage(data, msgtype, userid);
}

View File

@ -17,6 +17,8 @@ public abstract interface ChatbotRepository extends JpaRepository<Chatbot, Strin
public abstract List<Chatbot> findByIdAndOrgi(String id, String orgi);
public abstract Chatbot findBySnsAccountIdentifierAndOrgi(String snsid, String orgi);
@Query(value = "select c from Chatbot c where " +
"(:myorgans is null or c.organ IN :myorgans)")
public Page<Chatbot> findByOrgans(@Param("myorgans") List<String> myorgans, Pageable pageRequest);

View File

@ -16,17 +16,18 @@
package com.chatopera.cc.concurrent.chatbot;
import com.chatopera.cc.app.persistence.hibernate.BaseService;
import com.chatopera.cc.app.persistence.repository.ChatbotRepository;
import com.chatopera.cc.exchange.UserEvent;
public class ChatbotEvent<S> implements UserEvent {
private S data;
private BaseService<?> crudRes;
private ChatbotRepository chatbotRes;
private String eventype;
public ChatbotEvent(S data, BaseService<?> crudRes, String eventype) {
public ChatbotEvent(S data, ChatbotRepository chatbotRes, String eventype) {
this.data = data;
this.crudRes = crudRes;
this.chatbotRes = chatbotRes;
this.eventype = eventype;
}
@ -38,12 +39,12 @@ public class ChatbotEvent<S> implements UserEvent {
this.data = data;
}
public BaseService<?> getCrudRes() {
return crudRes;
public ChatbotRepository getChatbotRes() {
return chatbotRes;
}
public void setCrudRes(BaseService<?> crudRes) {
this.crudRes = crudRes;
public void setChatbotRes(ChatbotRepository chatbotRes) {
this.chatbotRes = chatbotRes;
}
public String getEventype() {

View File

@ -15,22 +15,69 @@
*/
package com.chatopera.cc.concurrent.chatbot;
import com.chatopera.cc.app.basic.MainContext;
import com.chatopera.cc.app.handler.api.request.RestUtils;
import com.chatopera.cc.app.im.client.NettyClients;
import com.chatopera.cc.app.im.message.ChatMessage;
import com.chatopera.cc.app.model.Chatbot;
import com.chatopera.cc.concurrent.user.UserDataEvent;
import com.chatopera.cc.util.Constants;
import com.chatopera.chatbot.ChatbotAPIRuntimeException;
import com.lmax.disruptor.EventHandler;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.MalformedURLException;
@SuppressWarnings("rawtypes")
public class ChatbotEventHandler implements EventHandler<UserDataEvent> {
private final static Logger logger = LoggerFactory.getLogger(ChatbotEventHandler.class);
private void chat(final ChatbotEvent payload) throws MalformedURLException, ChatbotAPIRuntimeException {
ChatMessage request = (ChatMessage) payload.getData();
Chatbot c = payload.getChatbotRes()
.findOne(request.getAiid());
logger.info("[chatbot disruptor] chat request baseUrl {}, chatbotID {}, fromUserId {}, textMessage {}", c.getBaseUrl(), c.getChatbotID(), request.getUserid(), request.getMessage());
// Get response from Conversational Engine.
JSONObject result = c.getApi()
.conversation(c.getChatbotID(), request.getUserid(), request.getMessage(), false);
// parse response
logger.info("[chatbot disruptor] chat response {}", result.toString());
if(result.getInt(RestUtils.RESP_KEY_RC) == 0){
// reply
ChatMessage resp = new ChatMessage();
resp.setCalltype(MainContext.CallTypeEnum.OUT.toString());
resp.setOrgi(request.getOrgi());
resp.setAiid(request.getAiid());
resp.setMessage(result.getJSONObject("data").getString("string"));
resp.setTouser(request.getUsername());
resp.setMsgtype(request.getMsgtype());
resp.setUserid(request.getUserid());
resp.setChannel(request.getChannel());
resp.setContextid(resp.getContextid());
resp.setSessionid(resp.getSessionid());
resp.setUsername(c.getName());
NettyClients.getInstance().sendChatbotEventMessage(request.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), resp);
} else {
// TODO handle exceptions
}
}
@Override
public void onEvent(UserDataEvent event, long arg1, boolean arg2)
throws Exception {
if (event.getEvent() != null) {
ChatbotEvent x = (ChatbotEvent) event.getEvent();
// TODO #75
logger.info("onEvent");
ChatbotEvent payload = (ChatbotEvent) event.getEvent();
switch (payload.getEventype()) {
case Constants
.CHATBOT_EVENT_TYPE_CHAT:
chat(payload);
break;
default:
logger.warn("[chatbot disruptor] onEvent unknown.");
}
}

View File

@ -27,6 +27,9 @@ public class Constants {
public final static String MINIO_BUCKET = "chatopera";
public final static String IM_MESSAGE_TYPE_MESSAGE = "message";
public final static String CHATBOT_EVENT_TYPE_CHAT = "chat";
/**
* Formatter
*/

View File

@ -62,16 +62,17 @@
if(this.count("text") == 0){
strValue= "" ;
}
if(words != this.count("text")){
socket.emit('message', {
appid : "${appid!''}",
userid:"${userid!''}",
type:"writing",
session:"${sessionid!''}",
orgi:"${orgi!''}",
message : strValue
});
}
// ignore writting in Chatbot Service
// if(words != this.count("text")){
// socket.emit('message', {
// appid : "${appid!''}",
// userid:"${userid!''}",
// type:"writing",
// session:"${sessionid!''}",
// orgi:"${orgi!''}",
// message : strValue
// });
// }
words = this.count("text") ;
document.getElementById('surplus').innerHTML = count+"/"+limitNum+" , " + pattern; //输入显示
////////
@ -488,6 +489,7 @@
}
})
socket.on('message', function(data) {
console.log("[chatbot io] message ", data);
var chat=document.getElementsByClassName('chatting-left').innerText;
chat = data.message;
if(data.messageType == "image"){
@ -496,9 +498,9 @@
chat = "<div class='ukefu-message-file'><div class='ukefu-file-icon'><img src='/im/img/file.png'></div><div class='ukefu-file-desc'><a href='"+data.message+"' target='_blank'><div>"+data.filename+"</div><div>"+(data.filesize/1024).toFixed(3)+"Kb</div></a></div></div>" ;
}
if(data.calltype == "呼入"){
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">'+data.createtime+'</label><label class="user">'+data.nickName+'</label> </div><div class="chatting-right"><i class="arrow arrow${inviteData.consult_dialog_color!''}"></i><div class="chat-content theme${inviteData.consult_dialog_color!''}">'+chat+'</div></div>' , "chat-block");
output('<div class="chat-right"> <img class="user-img" src="/im/img/user.png" alt=""><div class="chat-message"><label class="time">'+data.createtime+'</label> </div><div class="chatting-right"><i class="arrow arrow${inviteData.consult_dialog_color!''}"></i><div class="chat-content theme${inviteData.consult_dialog_color!''}">'+chat+'</div></div>' , "chat-block");
}else if(data.calltype == "呼出"){
output('<div class="chat-left"> <img class="user-img" src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>" alt=""><div class="chat-message"><label class="user">'+data.nickName+'</label><label class="time">'+data.createtime+'</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content">'+chat+'</div></div>' , "chat-block");
output('<div class="chat-left"> <img class="user-img" src="<#if inviteData?? && inviteData.consult_dialog_headimg??>/res/image.html?id=${inviteData.consult_dialog_headimg?url}<#else>/images/agent.png</#if>" alt=""><div class="chat-message"><label class="user">'+data.username+'</label><label class="time">'+data.createtime+'</label> </div><div class="chatting-left"><i class="arrow"></i><div class="chat-content">'+chat+'</div></div>' , "chat-block");
R3Ajax.audioplayer('audioplane', newmessage, false); // 播放
}
});