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

#75 机器人客服会话关联agentuser, agentservice

This commit is contained in:
Hai Liang Wang 2018-09-12 17:37:14 +08:00
parent 0266d4e353
commit 7e4f5c9115
9 changed files with 196 additions and 102 deletions

View File

@ -335,6 +335,28 @@ public class UKDataContext {
}
}
// 服务处理类型
public enum OptTypeEnum {
CHATBOT("机器人客服", 1),
HUMAN("人工客服", 2);
private final String name;
private final int index;
private OptTypeEnum(String name, int index) {
this.name = name;
this.index = index;
}
public String toLetters() {
return super.toString().toLowerCase();
}
public String toString() {
return this.name;
}
}
// 外呼计划状态
public enum CallOutDialplanStatusEnum {
RUNNING("执行中", 1),

View File

@ -25,7 +25,6 @@ import java.util.Set;
public class Constants {
public final static String OPT_TYPE = "webim";
public final static String MINIO_BUCKET = "chatopera";
/**

View File

@ -523,47 +523,44 @@ public class ServiceQuene {
/**
* 为访客 分配坐席 ACD策略此处 AgentStatus 是建议 坐席 如果启用了 历史服务坐席 优先策略 则会默认检查历史坐席是否空闲如果空闲则分配如果不空闲 分配当前建议的坐席
*
* @param agentStatus
* @param agentUser
* @param orgi
* @return
* @throws Exception
*/
public static AgentService processAiService(AiUser aiUser, String orgi) throws Exception {
public static AgentService processChatbotService(final AgentUser agentUser, final String orgi) {
AgentService agentService = new AgentService(); //放入缓存的对象
AgentServiceRepository agentServiceRes = UKDataContext.getContext().getBean(AgentServiceRepository.class);
if (!StringUtils.isBlank(aiUser.getAgentserviceid())) {
agentService = agentServiceRes.findByIdAndOrgi(aiUser.getAgentserviceid(), orgi);
agentService.setEndtime(new Date());
Date now = new Date();
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
agentService = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), orgi);
agentService.setEndtime(now);
if (agentService.getServicetime() != null) {
agentService.setSessiontimes(System.currentTimeMillis() - agentService.getServicetime().getTime());
}
agentService.setStatus(UKDataContext.AgentUserStatusEnum.END.toString());
} else {
agentService.setServicetime(new Date());
agentService.setLogindate(new Date());
agentService.setServicetime(now);
agentService.setLogindate(now);
agentService.setOrgi(orgi);
agentService.setOwner(aiUser.getContextid());
agentService.setSessionid(aiUser.getSessionid());
if (aiUser.getIpdata() != null) {
agentService.setRegion(aiUser.getIpdata().getRegion());
}
agentService.setOwner(agentUser.getContextid());
agentService.setSessionid(agentUser.getSessionid());
agentService.setRegion(agentUser.getRegion());
agentService.setUsername(agentUser.getUsername());
agentService.setChannel(agentUser.getChannel());
agentService.setUsername(aiUser.getUsername());
agentService.setChannel(aiUser.getChannel());
if (!StringUtils.isBlank(aiUser.getContextid())) {
agentService.setContextid(aiUser.getContextid());
if (StringUtils.isNotBlank(agentUser.getContextid())) {
agentService.setContextid(agentUser.getContextid());
} else {
agentService.setContextid(aiUser.getSessionid());
agentService.setContextid(agentUser.getSessionid());
}
agentService.setUserid(aiUser.getUserid());
agentService.setAiid(aiUser.getAiid());
agentService.setUserid(agentUser.getUserid());
agentService.setAiid(agentUser.getAgentno());
agentService.setAiservice(true);
agentService.setStatus(UKDataContext.AgentUserStatusEnum.INSERVICE.toString());
agentService.setAppid(aiUser.getAppid());
agentService.setAppid(agentUser.getAppid());
agentService.setLeavemsg(false);
}

View File

@ -258,7 +258,7 @@ public class CallOutWireTask implements MessageListener {
onlineUser.setCreater(onlineUser.getId());
onlineUser.setCreatetime(createtime);
onlineUser.setUpdatetime(createtime);
onlineUser.setOptype(Constants.OPT_TYPE);
onlineUser.setOptype(UKDataContext.OptTypeEnum.HUMAN.toString());
onlineUser.setAppid(channel);
} else {
onlineUser.setOlduser("1"); // 不是 老访客

View File

@ -599,39 +599,33 @@ public class OnlineUserUtils {
*/
public static void offline(String user, String orgi) throws Exception {
if (UKDataContext.getContext() != null) {
try {
OnlineUser onlineUser = (OnlineUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user, orgi);
if (onlineUser != null) {
CousultInvite invite = OnlineUserUtils.cousult(onlineUser.getAppid(), onlineUser.getOrgi(), UKDataContext.getContext().getBean(ConsultInviteRepository.class));
if (invite.isTraceuser()) {
onlineUser.setStatus(UKDataContext.OnlineUserOperatorStatus.OFFLINE.toString());
onlineUser.setInvitestatus(UKDataContext.OnlineUserInviteStatus.DEFAULT.toString());
onlineUser.setBetweentime((int) (new Date().getTime() - onlineUser.getLogintime().getTime()));
onlineUser.setUpdatetime(new Date());
OnlineUserRepository service = UKDataContext.getContext().getBean(
OnlineUserRepository.class);
service.save(onlineUser);
OnlineUser onlineUser = (OnlineUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user, orgi);
if (onlineUser != null) {
CousultInvite invite = OnlineUserUtils.cousult(onlineUser.getAppid(), onlineUser.getOrgi(), UKDataContext.getContext().getBean(ConsultInviteRepository.class));
if (invite.isTraceuser()) {
onlineUser.setStatus(UKDataContext.OnlineUserOperatorStatus.OFFLINE.toString());
onlineUser.setInvitestatus(UKDataContext.OnlineUserInviteStatus.DEFAULT.toString());
onlineUser.setBetweentime((int) (new Date().getTime() - onlineUser.getLogintime().getTime()));
onlineUser.setUpdatetime(new Date());
OnlineUserRepository service = UKDataContext.getContext().getBean(
OnlineUserRepository.class);
service.save(onlineUser);
OnlineUserHisRepository onlineHisUserRes = UKDataContext.getContext().getBean(OnlineUserHisRepository.class);
{
List<OnlineUserHis> hisList = onlineHisUserRes.findBySessionidAndOrgi(onlineUser.getSessionid(), orgi);
OnlineUserHis his = null;
if (hisList.size() > 0) {
his = hisList.get(0);
} else {
his = new OnlineUserHis();
}
UKTools.copyProperties(onlineUser, his);
his.setDataid(onlineUser.getId());
onlineHisUserRes.save(his);
OnlineUserHisRepository onlineHisUserRes = UKDataContext.getContext().getBean(OnlineUserHisRepository.class);
{
List<OnlineUserHis> hisList = onlineHisUserRes.findBySessionidAndOrgi(onlineUser.getSessionid(), orgi);
OnlineUserHis his = null;
if (hisList.size() > 0) {
his = hisList.get(0);
} else {
his = new OnlineUserHis();
}
UKTools.copyProperties(onlineUser, his);
his.setDataid(onlineUser.getId());
onlineHisUserRes.save(his);
}
}
} catch (ClassCastException e) {
// #TODO workaround for
// https://github.com/chatopera/cosin/issues/75
// AiUser is not saved, just remove from cache.
}
CacheHelper.getOnlineUserCacheBean().delete(user, orgi);
}

View File

@ -16,12 +16,15 @@
package com.chatopera.cc.webim.util.server.handler;
import com.chatopera.cc.core.UKDataContext;
import com.chatopera.cc.util.IP;
import com.chatopera.cc.util.IPTools;
import com.chatopera.cc.util.UKTools;
import com.chatopera.cc.util.client.NettyClients;
import com.chatopera.cc.webim.service.acd.ServiceQuene;
import com.chatopera.cc.webim.service.cache.CacheHelper;
import com.chatopera.cc.webim.service.repository.AgentUserRepository;
import com.chatopera.cc.webim.service.repository.ConsultInviteRepository;
import com.chatopera.cc.webim.service.repository.OnlineUserRepository;
import com.chatopera.cc.webim.util.MessageUtils;
import com.chatopera.cc.webim.util.OnlineUserUtils;
import com.chatopera.cc.webim.util.router.OutMessageRouter;
@ -48,6 +51,9 @@ public class ChatbotEventHandler {
protected SocketIOServer server;
private AgentUserRepository agentUserRes;
private OnlineUserRepository onlineUserRes;
@Autowired
public ChatbotEventHandler(SocketIOServer server) {
this.server = server;
@ -57,22 +63,23 @@ public class ChatbotEventHandler {
public void onConnect(SocketIOClient client) {
try {
String user = client.getHandshakeData().getSingleUrlParam("userid");
String nickname = client.getHandshakeData().getSingleUrlParam("nickname");
String orgi = client.getHandshakeData().getSingleUrlParam("orgi");
// String session = client.getHandshakeData().getSingleUrlParam("session") ;
String session = client.getHandshakeData().getSingleUrlParam("session");
String appid = client.getHandshakeData().getSingleUrlParam("appid");
String aiid = client.getHandshakeData().getSingleUrlParam("aiid");
// String agent = client.getHandshakeData().getSingleUrlParam("agent") ;
// String skill = client.getHandshakeData().getSingleUrlParam("skill") ;
logger.info("[chatbot socket.io] onConnect user {}, orgi {}, appid {}, aiid {}", user, orgi, appid, aiid);
Date now = new Date();
if (StringUtils.isNotBlank(user)) {
// /**
// * 加入到 缓存列表
// */
NettyClients.getInstance().putIMEventClient(user, client);
NettyClients.getInstance().putChatbotEventClient(user, client);
MessageOutContent outMessage = new MessageOutContent();
CousultInvite invite = OnlineUserUtils.cousult(appid, orgi, UKDataContext.getContext().getBean(ConsultInviteRepository.class));
if (invite != null && !StringUtils.isBlank(invite.getAisuccesstip())) {
if (invite != null && StringUtils.isNotBlank(invite.getAisuccesstip())) {
outMessage.setMessage(invite.getAisuccesstip());
} else {
outMessage.setMessage("欢迎使用华夏春松机器人客服!");
@ -80,43 +87,91 @@ public class ChatbotEventHandler {
outMessage.setMessageType(UKDataContext.MessageTypeEnum.MESSAGE.toString());
outMessage.setCalltype(UKDataContext.CallTypeEnum.IN.toString());
outMessage.setNickName("AI");
outMessage.setCreatetime(UKTools.dateFormate.format(new Date()));
outMessage.setNickName(invite.getAiname());
outMessage.setCreatetime(UKTools.dateFormate.format(now));
client.sendEvent(UKDataContext.MessageTypeEnum.STATUS.toString(), outMessage);
InetSocketAddress address = (InetSocketAddress) client.getRemoteAddress();
String ip = UKTools.getIpAddr(client.getHandshakeData().getHttpHeaders(), address.getHostString());
AiUser aiUser = new AiUser(user, user, System.currentTimeMillis(), orgi, IPTools.getInstance().findGeography(ip));
aiUser.setSessionid(UKTools.getContextID(client.getSessionId().toString()));
aiUser.setAppid(appid);
aiUser.setAiid(aiid);
aiUser.setUsername(UKDataContext.GUEST_USER + "_" + UKTools.genIDByKey(aiUser.getId()));
aiUser.setChannel(UKDataContext.ChannelTypeEnum.WEBIM.toString());
OnlineUser onlineUser = getOnlineUserRes().findOne(user);
AgentService agentService = ServiceQuene.processAiService(aiUser, orgi);
aiUser.setAgentserviceid(agentService.getId());
if (onlineUser == null) {
onlineUser = new OnlineUser();
onlineUser.setAppid(appid);
if (StringUtils.isNotBlank(nickname)) {
onlineUser.setUsername(nickname);
} else {
onlineUser.setUsername(UKDataContext.GUEST_USER + "_" + UKTools.genIDByKey(user));
}
CacheHelper.getOnlineUserCacheBean().put(user, aiUser, UKDataContext.SYSTEM_ORGI);
onlineUser.setSessionid(session);
onlineUser.setOptype(UKDataContext.OptTypeEnum.CHATBOT.toString());
onlineUser.setUserid(user);
onlineUser.setId(user);
onlineUser.setOrgi(orgi);
onlineUser.setChannel(UKDataContext.ChannelTypeEnum.WEBIM.toString());
onlineUser.setIp(ip);
onlineUser.setUpdatetime(now);
onlineUser.setLogintime(now);
onlineUser.setCreatetime(now);
IP ipdata = IPTools.getInstance().findGeography(ip);
onlineUser.setCity(ipdata.getCity());
onlineUser.setCountry(ipdata.getCountry());
onlineUser.setProvince(ipdata.getProvince());
onlineUser.setIsp(ipdata.getIsp());
onlineUser.setRegion(ipdata.getRegion());
onlineUser.setStatus(UKDataContext.OnlineUserOperatorStatus.ONLINE.toString());
}
// 在线客服访客咨询记录
AgentUser agentUser = new AgentUser(onlineUser.getId(),
UKDataContext.ChannelTypeEnum.WEBIM.toString(), // callout
onlineUser.getId(),
onlineUser.getUsername(),
UKDataContext.SYSTEM_ORGI,
appid);
agentUser.setServicetime(now);
agentUser.setCreatetime(now);
agentUser.setUpdatetime(now);
agentUser.setSessionid(session);
// 聊天机器人处理的请求
agentUser.setOpttype(UKDataContext.OptTypeEnum.CHATBOT.toString());
agentUser.setAgentno(aiid); // 聊天机器人ID
agentUser.setCity(onlineUser.getCity());
agentUser.setProvince(onlineUser.getProvince());
agentUser.setCountry(onlineUser.getCountry());
AgentService agentService = ServiceQuene.processChatbotService(agentUser, orgi);
agentUser.setAgentserviceid(agentService.getId());
getAgentUserRes().save(agentUser);
getOnlineUserRes().save(onlineUser);
CacheHelper.getAgentUserCacheBean().put(user, agentUser, orgi);
CacheHelper.getOnlineUserCacheBean().put(user, onlineUser, orgi);
}
} catch (Exception e) {
e.printStackTrace();
}
}
//添加@OnDisconnect事件客户端断开连接时调用刷新客户端信息
@OnDisconnect
public void onDisconnect(SocketIOClient client) throws Exception {
String user = client.getHandshakeData().getSingleUrlParam("userid");
String orgi = client.getHandshakeData().getSingleUrlParam("orgi");
if (!StringUtils.isBlank(user)) {
NettyClients.getInstance().removeIMEventClient(user, UKTools.getContextID(client.getSessionId().toString()));
AiUser aiUser = (AiUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user, orgi);
if (aiUser != null) {
ServiceQuene.processAiService(aiUser, orgi);
CacheHelper.getOnlineUserCacheBean().delete(user, UKDataContext.SYSTEM_ORGI);
if (StringUtils.isNotBlank(user)) {
NettyClients.getInstance().removeChatbotEventClient(user, UKTools.getContextID(client.getSessionId().toString()));
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(user, orgi);
OnlineUser onlineUser = (OnlineUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user, orgi);
if (agentUser != null) {
ServiceQuene.processChatbotService(agentUser, orgi);
CacheHelper.getAgentUserCacheBean().delete(user, UKDataContext.SYSTEM_ORGI);
CacheHelper.getOnlineUserCacheBean().delete(user, orgi);
agentUser.setStatus(UKDataContext.OnlineUserOperatorStatus.OFFLINE.toString());
onlineUser.setStatus(UKDataContext.OnlineUserOperatorStatus.OFFLINE.toString());
getAgentUserRes().save(agentUser);
getOnlineUserRes().save(onlineUser);
}
}
client.disconnect();
@ -159,22 +214,21 @@ public class ChatbotEventHandler {
* 处理表情
*/
data.setMessage(UKTools.processEmoti(data.getMessage()));
data.setTousername(UKDataContext.ChannelTypeEnum.AI.toString());
data.setTousername(invite.getAiname());
data.setAiid(aiid);
Object cacheData = (AiUser) CacheHelper.getOnlineUserCacheBean().getCacheObject(user, orgi);
if (cacheData != null && cacheData instanceof AiUser) {
AiUser aiUser = (AiUser) cacheData;
data.setAgentserviceid(aiUser.getAgentserviceid());
data.setChannel(aiUser.getChannel());
AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(user, orgi);
if (agentUser != null) {
data.setAgentserviceid(agentUser.getAgentserviceid());
data.setChannel(agentUser.getChannel());
/**
* 一定要设置 ContextID
*/
data.setContextid(aiUser.getAgentserviceid());
data.setContextid(agentUser.getAgentserviceid());
}
MessageOutContent outMessage = MessageUtils.createAiMessage(data, data.getAppid(), data.getChannel(), UKDataContext.CallTypeEnum.IN.toString(), UKDataContext.AiItemType.USERINPUT.toString(), UKDataContext.MediaTypeEnum.TEXT.toString(), data.getUserid());
if (!StringUtils.isBlank(data.getUserid()) && UKDataContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())) {
if (StringUtils.isNotBlank(data.getUserid()) && UKDataContext.MessageTypeEnum.MESSAGE.toString().equals(data.getType())) {
if (!StringUtils.isBlank(data.getTouser())) {
OutMessageRouter router = null;
router = (OutMessageRouter) UKDataContext.getContext().getBean(data.getChannel());
@ -182,11 +236,33 @@ public class ChatbotEventHandler {
router.handler(data.getTouser(), UKDataContext.MessageTypeEnum.MESSAGE.toString(), data.getAppid(), outMessage);
}
}
if (cacheData != null && cacheData instanceof AiUser) {
AiUser aiUser = (AiUser) cacheData;
aiUser.setTime(System.currentTimeMillis());
CacheHelper.getOnlineUserCacheBean().put(user, aiUser, UKDataContext.SYSTEM_ORGI);
if (agentUser != null) {
Date now = new Date();
agentUser.setUpdatetime(now);
agentUser.setLastmessage(now);
agentUser.setLastmsg(data.getMessage());
CacheHelper.getAgentUserCacheBean().put(user, agentUser, UKDataContext.SYSTEM_ORGI);
}
}
}
}
/**
* Lazy load
* @return
*/
public AgentUserRepository getAgentUserRes() {
if (agentUserRes == null)
agentUserRes = UKDataContext.getContext().getBean(AgentUserRepository.class);
return agentUserRes;
}
/**
* Lazy load
* @return
*/
public OnlineUserRepository getOnlineUserRes() {
if (onlineUserRes == null)
onlineUserRes = UKDataContext.getContext().getBean(OnlineUserRepository.class);
return onlineUserRes;
}
}

View File

@ -298,20 +298,16 @@ public class IMController extends Handler {
contacts = processContacts(orgi, contacts, appid, userid);
}
if (StringUtils.isNotBlank(sign)) {
try {
OnlineUserUtils.online(super.getIMUser(request, sign, contacts != null ? contacts.getName() : null),
orgi,
sessionid,
UKDataContext.OnlineUserTypeStatus.WEBIM.toString(),
request,
UKDataContext.ChannelTypeEnum.WEBIM.toString(),
appid,
contacts,
invite);
} catch (java.lang.ClassCastException e) {
// #TODO workaround for
// https://github.com/chatopera/cosin/issues/75
}
OnlineUserUtils.online(super.getIMUser(request, sign, contacts != null ? contacts.getName() : null),
orgi,
sessionid,
UKDataContext.OnlineUserTypeStatus.WEBIM.toString(),
request,
UKDataContext.ChannelTypeEnum.WEBIM.toString(),
appid,
contacts,
invite);
}
OnlineUserUtils.webIMClients.putClient(userid, new WebIMClient(userid, client, emitter));
}

View File

@ -79,7 +79,8 @@ public class AgentUser implements Serializable, Comparable<AgentUser> {
private Date waittingtimestart = new Date();
private Date lastgetmessage = new Date();
private String lastmsg;
private String opttype;
private String skill ; //请求的技能组
private String agent ; //请求的坐席
@ -565,6 +566,14 @@ public class AgentUser implements Serializable, Comparable<AgentUser> {
this.skillname = skillname;
}
public String getOpttype() {
return opttype;
}
public void setOpttype(String opttype) {
this.opttype = opttype;
}
@Override
public int compareTo(AgentUser o) {
int ret = 0 ;

View File

@ -650,6 +650,7 @@ CREATE TABLE `uk_agentuser` (
`datadept` varchar(255) DEFAULT NULL COMMENT '创建人部门',
`intime` int(32) DEFAULT NULL COMMENT '接入时间',
`batid` varchar(32) DEFAULT NULL COMMENT '批次ID',
`opttype` varchar(32) DEFAULT NULL COMMENT '服务处理类型',
`ipaddr` varchar(50) DEFAULT NULL COMMENT 'IP地址',
`osname` varchar(100) DEFAULT NULL COMMENT '操作系统名称',
`browser` varchar(100) DEFAULT NULL COMMENT '浏览器',