mirror of
https://github.com/chatopera/cosin.git
synced 2025-06-16 18:30:03 +08:00
Release new version 5.0.0
This commit is contained in:
parent
4e764b6c0a
commit
e7b233dafd
20
.drone.yml
20
.drone.yml
@ -1,20 +0,0 @@
|
||||
pipeline:
|
||||
build-contact-center:
|
||||
group: build
|
||||
image: plugins/docker
|
||||
context: contact-center
|
||||
dockerfile: contact-center/Dockerfile
|
||||
repo: chatopera/contact-center
|
||||
tags: develop
|
||||
secrets: [ docker_username, docker_password ]
|
||||
|
||||
build-cc-switch:
|
||||
group: build
|
||||
image: plugins/docker
|
||||
context: cc-switch/app
|
||||
dockerfile: cc-switch/app/Dockerfile
|
||||
repo: chatopera/cc-switch
|
||||
tags: develop
|
||||
secrets: [ docker_username, docker_password ]
|
||||
|
||||
branches: develop
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,3 +19,4 @@ backups/
|
||||
.env
|
||||
build.gradle
|
||||
.vscode/
|
||||
private
|
||||
|
15
.vscode/sftp.json
vendored
15
.vscode/sftp.json
vendored
@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "sftp",
|
||||
"remotePath": "git/cosinee",
|
||||
"protocol": "sftp",
|
||||
"uploadOnSave": true,
|
||||
"port": 22,
|
||||
"profiles": {
|
||||
"gamera": {
|
||||
"name": "gamera",
|
||||
"host": "gamera",
|
||||
"username": "hain",
|
||||
"privateKeyPath": "/Users/hain/.ssh/id_rsa"
|
||||
}
|
||||
}
|
||||
}
|
249
README.md
249
README.md
@ -1,8 +1,247 @@
|
||||
# 春松客服企业版
|
||||
[](https://microbadger.com/images/chatopera/contact-center:develop "Get your own image badge on microbadger.com") [](https://microbadger.com/images/chatopera/contact-center:develop "Get your own version badge on microbadger.com") [](https://hub.docker.com/r/chatopera/contact-center/) [](https://hub.docker.com/r/chatopera/contact-center/) [](https://microbadger.com/images/chatopera/contact-center:develop "Get your own commit badge on microbadger.com")
|
||||
|
||||
https://gitlab.chatopera.com/chatopera
|
||||
<p align="center">
|
||||
<b>春松客服QQ交流群:185659917, <a href="https://jq.qq.com/?_wv=1027&k=5I1cJLP" target="_blank">点击链接加入群聊</a></b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44917177-432d9700-ad6a-11e8-9420-46b0281073e6.png" width="200">
|
||||
</p>
|
||||
|
||||
## License
|
||||
# 春松客服: 全渠道智能客服
|
||||
|
||||
Copyright 2019 北京华夏春松科技有限公司 <https://www.chatopera.com>. All rights reserved.
|
||||
This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
春松客服是帮助中小型企业快速而低成本的获得好用的智能客服系统。
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/3538629/61031891-fc311900-a3f2-11e9-80cf-c8d0700538a0.png" width="600">
|
||||
|
||||
春松客服是 Chatopera 自主研发以及基于且增强其它开源软件的方式实现的,春松客服会不断增强客服系统的智能化,这包括利用自然语言处理、机器学习和语音识别等技术让客服工作更有效率、客服满意度更高、成本更低。
|
||||
|
||||
**开源项目地址:** [https://github.com/chatopera/cosin](https://github.com/chatopera/cosin)
|
||||
|
||||
**开发环境搭建:** [https://github.com/chatopera/cosin/wiki/春松客服:开发环境](https://github.com/chatopera/cosin/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%EF%BC%9A%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83)
|
||||
|
||||
## 内容结构
|
||||
|
||||
[产品演示](https://github.com/chatopera/cosin#%E4%BA%A7%E5%93%81%E6%BC%94%E7%A4%BA)
|
||||
|
||||
[功能](https://github.com/chatopera/cosin#%E5%8A%9F%E8%83%BD)
|
||||
|
||||
[开发文档](https://github.com/chatopera/cosin#%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3)
|
||||
|
||||
[产品截图](https://github.com/chatopera/cosin#%E4%BA%A7%E5%93%81%E6%88%AA%E5%9B%BE)
|
||||
|
||||
[产品体系](https://github.com/chatopera/cosin#%E4%BA%A7%E5%93%81%E4%BD%93%E7%B3%BB)
|
||||
|
||||
[立即部署](https://github.com/chatopera/cosin#%E7%AB%8B%E5%8D%B3%E9%83%A8%E7%BD%B2)
|
||||
|
||||
[鸣谢](https://github.com/chatopera/cosin#%E9%B8%A3%E8%B0%A2)
|
||||
|
||||
[开源许可协议](https://github.com/chatopera/cosin#%E5%BC%80%E6%BA%90%E8%AE%B8%E5%8F%AF%E5%8D%8F%E8%AE%AE)
|
||||
|
||||
## 产品演示
|
||||
|
||||
- 坐席工作台
|
||||
|
||||
[http://cc.chatopera.com/](http://cc.chatopera.com/)
|
||||
|
||||
| **登录账号** | **密码** |
|
||||
| ------------ | --------- |
|
||||
| admin | admin1234 |
|
||||
|
||||
- 网页端访客程序
|
||||
|
||||
[http://cc.chatopera.com/testclient.html](http://cc.chatopera.com/testclient.html)
|
||||
|
||||
## 功能
|
||||
|
||||
- 账号及组织机构管理:按组织、角色分配账号权限
|
||||
|
||||
- 联系人管理:细粒度维护客户信息
|
||||
|
||||
- 网页聊天组件:一分钟接入对话窗口
|
||||
|
||||
- 坐席工作台:汇聚多渠道访客请求
|
||||
|
||||
- 机器人客服:集成机器人平台服务,完成多轮对话和知识库问答
|
||||
|
||||
- 外呼系统:自动外呼,手动外呼,监听和报表等
|
||||
|
||||
<b> 《春松客服产品系列视频》 </b>
|
||||
|
||||
<table align="center">
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>内容</th>
|
||||
<th>腾讯视频</th>
|
||||
<th>百度网盘</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 1</td>
|
||||
<td>产品概述</td>
|
||||
<td><a href="https://v.qq.com/x/page/z0776g0osqu.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1BzUveFSkCtfyeU1gUIjp1Q" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 2</td>
|
||||
<td>安装部署</td>
|
||||
<td><a href="https://v.qq.com/x/page/b07760u7f8t.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1CnZBIIuWpDWATjKTMluzUA" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 3</td>
|
||||
<td>功能演示</td>
|
||||
<td><a href="https://v.qq.com/x/page/h077670ceg2.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1bCAqUWwk_KQGyfUyvUMt9w" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 4</td>
|
||||
<td>账号体系</td>
|
||||
<td><a href="https://v.qq.com/x/page/b0776jwl6w1.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/18QA9jvXYtwa8Zt78Di9wrg" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 5</td>
|
||||
<td>客户关系管理</td>
|
||||
<td><a href="https://v.qq.com/x/page/d0776p8ghpr.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1stfkufWkF4byWqvF-ch9Dw" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 6</td>
|
||||
<td>即时通信</td>
|
||||
<td><a href="https://v.qq.com/x/page/r0776rdgt6z.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1eYEO5OtVu0gyxDI9a-xqJQ" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 7</td>
|
||||
<td>呼叫中心</td>
|
||||
<td><a href="https://v.qq.com/x/page/i07785u58jm.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1qQOSNMHgcNdXuq0Xib1wXA" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 8</td>
|
||||
<td>数据报表</td>
|
||||
<td><a href="https://v.qq.com/x/page/e0778ptg6b0.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1iQOz9HR3dkO4lgf5VI4CVw" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
[_下载视频合集_](https://pan.baidu.com/s/1YH7d7nMm5wZQp7P8kID3KA)
|
||||
|
||||
## 使用说明
|
||||
|
||||
关于产品的具体使用说明,请参考[文档中心](https://docs.chatopera.com/omni-channel-customer-support-system.html)。
|
||||
|
||||
## 来自真实用户的反馈
|
||||
|
||||
```
|
||||
项目代码写的挺好的,容易维护,是不错的开源项目。
|
||||
```
|
||||
|
||||
-- 海洋 (深圳银之杰项目经理)
|
||||
|
||||
```
|
||||
Amazing! 要的就是这个效果。
|
||||
```
|
||||
|
||||
-- 常经理 (某电器世界五百强企业)
|
||||
|
||||
```
|
||||
我要在APP内集成,我看了好多项目了,就你们这个最好,基本就是一个商用化的项目。
|
||||
```
|
||||
|
||||
-- Engine X (某二手车出售平台技术负责人)
|
||||
|
||||
## 开发文档
|
||||
|
||||
<p align="center">
|
||||
<b><a href="https://github.com/chatopera/cosin/wiki" target="_blank">开发文档</a></b><br>
|
||||
<a href="https://github.com/chatopera/cosin/wiki" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44992890-38be0800-afcb-11e8-8fde-a5a671d29764.png" width="300">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 产品截图
|
||||
|
||||
<p align="center">
|
||||
<b>欢迎页</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915395-6bff5d80-ad65-11e8-817a-8abb812fb5ee.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>坐席工作台</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915582-eb8d2c80-ad65-11e8-8876-86c8b5bb5cc7.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>坐席监控</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915711-432b9800-ad66-11e8-899b-1ea02244925d.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>外呼计划</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915831-ab7a7980-ad66-11e8-88a5-a2cd23b8c689.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>通话记录</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915218-feebc800-ad64-11e8-90fc-36ce96b0c09a.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>集成客服机器人</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/51080565-4b82df00-1719-11e9-8cc4-dbbec0459224.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>客服机器人应答</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/51080567-50479300-1719-11e9-85d8-d209370c9d10.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>更多功能,敬请期待 ...</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44916014-28a5ee80-ad67-11e8-936a-a2cdbe62f529.png" width="900">
|
||||
</p>
|
||||
|
||||
## 产品体系
|
||||
|
||||
<p align="center">
|
||||
<b>观看视频介绍</b><br>
|
||||
<a href="https://pan.baidu.com/s/1tqxqfYSvtjDGhh6bDQ-Vog" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/45403926-6a039b80-b68f-11e8-86e2-5d1f04e3a7c7.png" width="900">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 立即部署
|
||||
|
||||
- 企业版
|
||||
|
||||
通过青云 AppCenter 部署,青云 AppCenter 是开发运维一体化(DevOps)管理企业应用的平台,Chatopera 的春松客服在 2018 年 10 月登录 AppCenter,并借助 PaaS 平台强大的计算能力实现计算节点集群、存储节点 HADR。从而保证了服务高可靠性、高性能、动态伸缩、一键备份和一键回滚等功能。
|
||||
|
||||
青云 AppCenter 以其提供的资源秒级计算特点,企业使用 AppCenter 中的春松客服应用,可以按需付费,灵活升配和降配,Chatopera 也非常推荐客户使用青云服务。
|
||||
|
||||
<p align="center">
|
||||
<b>春松客服 on QingCloud</b><br>
|
||||
<a href="https://appcenter.qingcloud.com/apps/app-zdh88kz7/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/47984143-a17f4900-e110-11e8-95c9-d8302e000c34.png" width="900">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
更为详细的部署文档见[春松客服上架青云 AppCenter](https://github.com/chatopera/cosin/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%E4%B8%8A%E6%9E%B6%E9%9D%92%E4%BA%91AppCenter)。
|
||||
|
||||
- 社区版
|
||||
|
||||
参考部署[开源社区版本文档](https://github.com/chatopera/cosin/wiki/%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%83%A8%E7%BD%B2)。
|
||||
|
||||
## 鸣谢
|
||||
|
||||
[优客服](https://gitee.com/beimigame/ukefu)
|
||||
|
||||
[FreeSWITCH 中国社区](http://www.freeswitch.org.cn/)
|
||||
|
||||
## 开源许可协议
|
||||
|
||||
Copyright (2018) <a href="https://www.chatopera.com/" target="_blank">北京华夏春松科技有限公司</a>
|
||||
|
||||
[Apache License Version 2.0](https://github.com/chatopera/cosin/blob/master/LICENSE)
|
||||
|
||||
[![chatoper banner][co-banner-image]][co-url]
|
||||
|
||||
[co-banner-image]: https://user-images.githubusercontent.com/3538629/42383104-da925942-8168-11e8-8195-868d5fcec170.png
|
||||
[co-url]: https://www.chatopera.com
|
||||
|
18
cc-chatbot/.gitignore
vendored
18
cc-chatbot/.gitignore
vendored
@ -1,18 +0,0 @@
|
||||
*.swp
|
||||
*.swo
|
||||
*.sublime-*
|
||||
*.pyc
|
||||
jmeter.log
|
||||
__pycache__
|
||||
tmp/
|
||||
node_modules/
|
||||
sftp-config.json
|
||||
.DS_Store
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
*.idea
|
||||
~$*.xls*
|
||||
~$*.ppt*
|
||||
~$*.doc*
|
||||
app/target/
|
@ -1,73 +0,0 @@
|
||||
# cc-chatbot
|
||||
Chatopera智能问答引擎的Java SDK.
|
||||
https://docs.chatopera.com/
|
||||
|
||||
支持
|
||||
|
||||
* 创建聊天机器人
|
||||
* 查询聊天机器人列表
|
||||
* 更新聊天机器人画像
|
||||
* 查询聊天机器人使用情况
|
||||
* 管理和检索多轮对话
|
||||
* 管理和检索知识库
|
||||
* 检索意图识别
|
||||
|
||||
|
||||
# 配置
|
||||
|
||||
使用maven,需要配置Chatopera的Nexus OSS仓库,具体见[文档](https://github.com/chatopera/cosin/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%EF%BC%9A%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83#%E4%BF%AE%E6%94%B9maven2%E9%85%8D%E7%BD%AE)。
|
||||
|
||||
```
|
||||
<dependency>
|
||||
<groupId>com.chatopera.chatbot</groupId>
|
||||
<artifactId>sdk</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
# API
|
||||
|
||||
## Chatbot v1
|
||||
|
||||
聊天机器人类,构造参数(tcp协议,hostname, 端口, 版本)
|
||||
|
||||
### Chatbot#getChatbots
|
||||
获取聊天机器人列表,支持检索查询,分页
|
||||
|
||||
### Chatbot#getChatbot
|
||||
通过聊天机器人ID获得聊天机器人详情
|
||||
|
||||
### Chatbot#conversation
|
||||
与指定的聊天机器人进行多轮对话
|
||||
|
||||
### Chatbot#faq
|
||||
与指定的聊天机器人进行知识库问答
|
||||
|
||||
|
||||
# 测试
|
||||
|
||||
```
|
||||
mvn test
|
||||
```
|
||||
|
||||
# 示例
|
||||
|
||||
```
|
||||
Chatbot cb = new Chatbot("http", "lhc-dev", 8003, "v1");
|
||||
JSONObject resp = cb.conversation("co_bot_1", "sdktest", "华夏春松在哪里", false);
|
||||
```
|
||||
|
||||
返回值参考 [智能问答引擎文档](https://docs.chatopera.com/chatbot-engine.html)。
|
||||
|
||||
|
||||
## 开源许可协议
|
||||
|
||||
Copyright (2018) <a href="https://www.chatopera.com/" target="_blank">北京华夏春松科技有限公司</a>
|
||||
|
||||
[Apache License Version 2.0](https://github.com/chatopera/cosin/blob/master/LICENSE)
|
||||
|
||||
[![chatoper banner][co-banner-image]][co-url]
|
||||
|
||||
[co-banner-image]: https://user-images.githubusercontent.com/3538629/42383104-da925942-8168-11e8-8195-868d5fcec170.png
|
||||
[co-url]: https://www.chatopera.com
|
||||
|
@ -1,13 +0,0 @@
|
||||
#! /bin/bash
|
||||
###########################################
|
||||
#
|
||||
###########################################
|
||||
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
# functions
|
||||
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
cd $baseDir/../app
|
||||
mvn clean deploy -Dmaven.test.skip=true
|
@ -1,13 +0,0 @@
|
||||
#! /bin/bash
|
||||
###########################################
|
||||
#
|
||||
###########################################
|
||||
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
# functions
|
||||
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
cd $baseDir/../app
|
||||
mvn idea:idea
|
@ -1,13 +0,0 @@
|
||||
#! /bin/bash
|
||||
###########################################
|
||||
#
|
||||
###########################################
|
||||
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
# functions
|
||||
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
cd $baseDir/../app
|
||||
mvn package
|
@ -1,13 +0,0 @@
|
||||
#! /bin/bash
|
||||
###########################################
|
||||
#
|
||||
###########################################
|
||||
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
# functions
|
||||
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
cd $baseDir/../app
|
||||
mvn test
|
@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="target/generated-sources/annotations">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="ignore_optional_problems" value="true"/>
|
||||
<attribute name="m2e-apt" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="ignore_optional_problems" value="true"/>
|
||||
<attribute name="m2e-apt" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>sdk</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -1,4 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
encoding/<project>=UTF-8
|
@ -1,2 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.apt.aptEnabled=false
|
@ -1,7 +0,0 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.processAnnotations=disabled
|
||||
org.eclipse.jdt.core.compiler.release=disabled
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
@ -1,4 +0,0 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
@ -1,141 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.chatopera.chatbot</groupId>
|
||||
<artifactId>sdk</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>sdk</name>
|
||||
<description>Java SDK for Chatopera Conversational Engine.</description>
|
||||
<url>https://www.chatopera.com</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.3.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpasyncclient</artifactId>
|
||||
<version>4.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpmime</artifactId>
|
||||
<version>4.3.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20140107</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mashape.unirest</groupId>
|
||||
<artifactId>unirest-java</artifactId>
|
||||
<version>1.4.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>2.9</version>
|
||||
</plugin>
|
||||
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.20.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>2.5.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>2.8.2</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>chatopera</id>
|
||||
<url>http://192.168.2.217:8029/repository/maven-snapshots/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>chatopera</id>
|
||||
<url>http://192.168.2.217:8029/repository/maven-releases/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>hain</id>
|
||||
<name>Hai Liang Wang</name>
|
||||
<email>hailiang.hl.wang@gmail.com</email>
|
||||
<url>https://github.com/Samurais</url>
|
||||
<organization>Chatopera Inc.</organization>
|
||||
<organizationUrl>http://www.chatopera.com</organizationUrl>
|
||||
<roles>
|
||||
<role>architect</role>
|
||||
<role>developer</role>
|
||||
</roles>
|
||||
<timezone>Asia/Shanghai</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
<reporting>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
</project>
|
@ -1,332 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.chatbot;
|
||||
|
||||
import com.mashape.unirest.http.exceptions.UnirestException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ChatbotAPI {
|
||||
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<String, Object> queryString = new HashMap<String, Object>();
|
||||
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<String, Object> body = new HashMap<String, Object>();
|
||||
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
|
||||
* @param description
|
||||
* @param fallback
|
||||
* @param welcome
|
||||
* @return
|
||||
* @throws ChatbotAPIRuntimeException
|
||||
*/
|
||||
public boolean updateByChatbotID(final String chatbotID,
|
||||
final String name,
|
||||
final String description,
|
||||
final String fallback,
|
||||
final String welcome) throws ChatbotAPIRuntimeException {
|
||||
if (StringUtils.isBlank(chatbotID))
|
||||
throw new ChatbotAPIRuntimeException("不合法的参数,【chatbotID】不能为空。");
|
||||
|
||||
HashMap<String, Object> body = new HashMap<String, Object>();
|
||||
if (StringUtils.isNotBlank(description))
|
||||
body.put("description", description);
|
||||
if (StringUtils.isNotBlank(fallback))
|
||||
body.put("fallback", fallback);
|
||||
if (StringUtils.isNotBlank(welcome))
|
||||
body.put("welcome", welcome);
|
||||
if (StringUtils.isNotBlank(name))
|
||||
body.put("name", name);
|
||||
|
||||
try {
|
||||
JSONObject result = RestAPI.put(this.baseUrl + "/chatbot/" + chatbotID, body, null);
|
||||
if (result.getInt("rc") == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (UnirestException e) {
|
||||
throw new ChatbotAPIRuntimeException(e.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除聊天机器人
|
||||
*
|
||||
* @param chatbotID
|
||||
* @return
|
||||
* @throws ChatbotAPIRuntimeException
|
||||
*/
|
||||
public boolean deleteByChatbotID(final String chatbotID) throws ChatbotAPIRuntimeException {
|
||||
if (StringUtils.isBlank(chatbotID))
|
||||
throw new ChatbotAPIRuntimeException("聊天机器人ID不能为空。");
|
||||
try {
|
||||
JSONObject result = RestAPI.delete(this.getBaseUrl() + "/chatbot/" + chatbotID, null);
|
||||
if (result.getInt("rc") == 0)
|
||||
return true;
|
||||
return false;
|
||||
} 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<String, Object> body = new HashMap<String, Object>();
|
||||
body.put("fromUserId", fromUserId);
|
||||
body.put("textMessage", textMessage);
|
||||
body.put("isDebug", debug);
|
||||
|
||||
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 clientId
|
||||
* @param textMessage
|
||||
* @return
|
||||
* @throws UnirestException
|
||||
*/
|
||||
public JSONObject intent(final String chatbotID, final String clientId, final String textMessage) throws ChatbotAPIRuntimeException {
|
||||
if(StringUtils.isBlank(chatbotID) || StringUtils.isBlank(clientId) || StringUtils.isBlank(textMessage))
|
||||
throw new ChatbotAPIRuntimeException("参数不合法,不能为空。");
|
||||
|
||||
HashMap<String, Object> body = new HashMap<String, Object>();
|
||||
body.put("clientId", clientId);
|
||||
body.put("query", textMessage);
|
||||
try {
|
||||
JSONObject result = RestAPI.post(this.baseUrl + "/chatbot/" + chatbotID, body);
|
||||
return result;
|
||||
} 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<String, Object> body = new HashMap<String, Object>();
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.chatbot;
|
||||
|
||||
import com.mashape.unirest.http.exceptions.UnirestException;
|
||||
|
||||
public class ChatbotAPIRuntimeException extends Exception{
|
||||
public ChatbotAPIRuntimeException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.chatbot;
|
||||
|
||||
import com.mashape.unirest.http.HttpResponse;
|
||||
import com.mashape.unirest.http.JsonNode;
|
||||
import com.mashape.unirest.http.Unirest;
|
||||
import com.mashape.unirest.http.exceptions.UnirestException;
|
||||
import com.mashape.unirest.request.GetRequest;
|
||||
import com.mashape.unirest.request.HttpRequestWithBody;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* RestAPI接口
|
||||
*/
|
||||
public class RestAPI {
|
||||
|
||||
/**
|
||||
* patch headers
|
||||
*
|
||||
* @param headers
|
||||
*/
|
||||
private static void x(HashMap<String, String> headers) {
|
||||
if (headers == null) {
|
||||
headers = new HashMap<String, String>();
|
||||
headers.put("accept", "application/json");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!headers.containsKey("Content-Type"))
|
||||
headers.put("Content-Type", "application/json");
|
||||
|
||||
|
||||
if (!headers.containsKey("accept"))
|
||||
headers.put("accept", "application/json");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Post
|
||||
*
|
||||
* @param url
|
||||
* @param body
|
||||
* @param query
|
||||
* @param headers
|
||||
* @return
|
||||
* @throws UnirestException
|
||||
*/
|
||||
public static JSONObject post(final String url, final HashMap<String, Object> body, final HashMap<String, Object> query, HashMap<String, String> headers) throws UnirestException {
|
||||
HttpRequestWithBody request = Unirest.post(url);
|
||||
x(headers);
|
||||
HttpResponse<JsonNode> resp = request
|
||||
.headers(headers)
|
||||
.queryString(query)
|
||||
.fields(body)
|
||||
.asJson();
|
||||
|
||||
// parse response
|
||||
JSONObject obj = resp.getBody().getObject();
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static JSONObject post(final String url, final HashMap<String, Object> body) throws UnirestException {
|
||||
return post(url, body, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get
|
||||
*
|
||||
* @param url
|
||||
* @param queryString
|
||||
* @param headers
|
||||
* @return
|
||||
* @throws UnirestException
|
||||
*/
|
||||
public static JSONObject get(final String url, final HashMap<String, Object> queryString, HashMap<String, String> headers) throws UnirestException {
|
||||
GetRequest request = Unirest.get(url);
|
||||
x(headers);
|
||||
HttpResponse<JsonNode> resp = request
|
||||
.headers(headers)
|
||||
.queryString(queryString)
|
||||
.asJson();
|
||||
// parse response
|
||||
JSONObject obj = resp.getBody().getObject();
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static JSONObject get(final String url) throws UnirestException {
|
||||
return get(url, null, null);
|
||||
}
|
||||
|
||||
public static JSONObject get(final String url, HashMap<String, Object> queryString) throws UnirestException {
|
||||
return get(url, queryString, null);
|
||||
}
|
||||
|
||||
public static JSONObject delete(final String url, HashMap<String, String> headers) throws UnirestException {
|
||||
x(headers);
|
||||
return Unirest.delete(url).headers(headers).asJson().getBody().getObject();
|
||||
}
|
||||
|
||||
public static JSONObject put(final String url, HashMap<String, Object> body, HashMap<String, String> headers) throws UnirestException {
|
||||
x(headers);
|
||||
return Unirest.put(url).headers(headers).fields(body).asJson().getBody().getObject();
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project name="sdk" xmlns="http://maven.apache.org/DECORATION/1.8.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/DECORATION/1.8.0 http://maven.apache.org/xsd/decoration-1.8.0.xsd">
|
||||
<bannerLeft>
|
||||
<name>sdk</name>
|
||||
<src>https://maven.apache.org/images/apache-maven-project.png</src>
|
||||
<href>https://www.apache.org/</href>
|
||||
</bannerLeft>
|
||||
|
||||
<bannerRight>
|
||||
<src>https://maven.apache.org/images/maven-logo-black-on-white.png</src>
|
||||
<href>https://maven.apache.org/</href>
|
||||
</bannerRight>
|
||||
|
||||
<skin>
|
||||
<groupId>org.apache.maven.skins</groupId>
|
||||
<artifactId>maven-fluido-skin</artifactId>
|
||||
<version>1.7</version>
|
||||
</skin>
|
||||
|
||||
<body>
|
||||
<menu ref="parent" />
|
||||
<menu ref="reports" />
|
||||
</body>
|
||||
</project>
|
@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.chatbot;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
*/
|
||||
public class ChatbotAPITest
|
||||
extends TestCase {
|
||||
private ChatbotAPI cb;
|
||||
|
||||
/**
|
||||
* Create the test case
|
||||
*
|
||||
* @param testName name of the test case
|
||||
*/
|
||||
public ChatbotAPITest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the suite of tests being tested
|
||||
*/
|
||||
public static Test suite() {
|
||||
return new TestSuite(ChatbotAPITest.class);
|
||||
}
|
||||
|
||||
public void setUp() {
|
||||
this.cb = new ChatbotAPI("http", "lhc-dev", 8003, "v1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Rigourous Test :-)
|
||||
*/
|
||||
public void testChatbot() {
|
||||
assertEquals(this.cb.getPort(), 8003);
|
||||
}
|
||||
|
||||
public void testGetChatbot() {
|
||||
try {
|
||||
JSONObject resp = this.cb.getChatbot("co_bot_1");
|
||||
System.out.println("[testGetChatbot] " + resp.toString());
|
||||
} catch (ChatbotAPIRuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetChatbots() {
|
||||
try {
|
||||
JSONObject resp = this.cb.getChatbots("name chatbotID", null, 0, 10);
|
||||
System.out.println("[testGetChatbots] resp " + resp.toString());
|
||||
} catch (ChatbotAPIRuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void testConversation() {
|
||||
try {
|
||||
JSONObject resp = this.cb.conversation("co_bot_1", "sdktest", "华夏春松在哪里", false);
|
||||
System.out.println("[testConversation] resp " + resp.toString());
|
||||
} catch (ChatbotAPIRuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void testFaq() {
|
||||
try {
|
||||
JSONObject resp = this.cb.faq("co_bot_1", "sdktest", "华夏春松在哪里", false);
|
||||
System.out.print("[testFaq] resp " + resp.toString());
|
||||
} catch (ChatbotAPIRuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void testParseUrl() {
|
||||
try {
|
||||
ChatbotAPI c = new ChatbotAPI("https://local:8000/");
|
||||
System.out.println("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",
|
||||
"我不了解。",
|
||||
"小云机器人",
|
||||
"你好,我是小云。");
|
||||
} catch (ChatbotAPIRuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
# functions
|
||||
|
||||
# main
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
cd $baseDir/../app
|
||||
mvn clean package
|
||||
|
3
contact-center/app/.gitignore
vendored
3
contact-center/app/.gitignore
vendored
@ -2,6 +2,7 @@
|
||||
src/main/java/com/chatopera/cc/plugins/
|
||||
|
||||
# ignore views within plugins
|
||||
!src/main/resources/templates/admin/channel/callout/
|
||||
!src/main/resources/templates/admin/channel/im/
|
||||
src/main/resources/templates/admin/channel/*
|
||||
src/main/resources/templates/apps/callout
|
||||
src/main/resources/templates/apps/chatbot
|
||||
|
@ -6,7 +6,7 @@
|
||||
<version>5.0.0</version>
|
||||
<packaging>war</packaging>
|
||||
<name>cskefu</name>
|
||||
<description>春松客服企业版:多媒体呼叫中心,下一代呼叫中心</description>
|
||||
<description>春松客服:多渠道智能客服系统</description>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -65,52 +65,34 @@ public class Application {
|
||||
/**
|
||||
* 记载模块
|
||||
*/
|
||||
// 外呼模块
|
||||
private final static boolean isCalloutModule = SystemEnvHelper.parseModuleFlag("cskefu.module.callout");
|
||||
|
||||
// CRM模块
|
||||
private final static boolean isContactsModule = SystemEnvHelper.parseModuleFlag("cskefu.module.contacts");
|
||||
|
||||
// 聊天机器人模块
|
||||
private final static boolean isChatbotModule = SystemEnvHelper.parseModuleFlag("cskefu.module.chatbot");
|
||||
|
||||
// 访客聊天监控模块
|
||||
private final static boolean isCcaModule = SystemEnvHelper.parseModuleFlag("cskefu.module.cca");
|
||||
|
||||
// 企业聊天模块
|
||||
private final static boolean isEntImModule = SystemEnvHelper.parseModuleFlag("cskefu.module.entim");
|
||||
|
||||
// 渠道:Skype渠道
|
||||
private final static boolean isSkypeModule = SystemEnvHelper.isClassExistByFullName(
|
||||
PluginRegistry.PLUGIN_ENTRY_SKYPE);
|
||||
|
||||
static {
|
||||
// 外呼模块
|
||||
if (isCalloutModule) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CALLOUT);
|
||||
}
|
||||
// CRM模块
|
||||
if (isContactsModule) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CONTACTS);
|
||||
}
|
||||
// 聊天机器人模块
|
||||
if (isChatbotModule) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CHATBOT);
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CONTACTS);
|
||||
|
||||
// 会话监控模块 Customer Chats Audit
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CCA);
|
||||
|
||||
// 企业聊天模块
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_ENTIM);
|
||||
|
||||
/**
|
||||
* 插件组
|
||||
*/
|
||||
// 外呼模块
|
||||
if (SystemEnvHelper.isClassExistByFullName(
|
||||
PluginRegistry.PLUGIN_ENTRY_CALLOUT)) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CALLOUT);
|
||||
}
|
||||
|
||||
// skype模块
|
||||
if (isSkypeModule) {
|
||||
if (SystemEnvHelper.isClassExistByFullName(
|
||||
PluginRegistry.PLUGIN_ENTRY_SKYPE)) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_SKYPE);
|
||||
}
|
||||
|
||||
// 会话监控模块 Customer Chats Audit
|
||||
if (isCcaModule) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CCA);
|
||||
|
||||
}
|
||||
// 企业聊天模块
|
||||
if (isEntImModule) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_ENTIM);
|
||||
// 聊天机器人模块
|
||||
if (SystemEnvHelper.isClassExistByFullName(PluginRegistry.PLUGIN_ENTRY_CHATBOT)) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CHATBOT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.bot.exception.ChatbotException;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.handler.api.request.RestUtils;
|
||||
import com.chatopera.cc.socketio.message.ChatMessage;
|
||||
import com.chatopera.cc.proxy.ChatbotProxy;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.Chatbot;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.ChatbotRepository;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import org.json.JSONException;
|
||||
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.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* 发送消息给聊天机器人并处理返回结果
|
||||
*/
|
||||
@Component
|
||||
public class ChatbotEventSubscription {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ChatbotEventSubscription.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private ChatbotRepository chatbotRes;
|
||||
|
||||
@Value("${bot.baseurl}")
|
||||
private static String botBaseUrl;
|
||||
|
||||
@Autowired
|
||||
private ChatbotProxy chatbotProxy;
|
||||
|
||||
/**
|
||||
* 接收发送消息给聊天机器人的请求
|
||||
*
|
||||
* @param payload
|
||||
*/
|
||||
@JmsListener(destination = Constants.INSTANT_MESSAGING_MQ_QUEUE_CHATBOT, containerFactory = "jmsListenerContainerQueue")
|
||||
public void onMessage(final String payload) {
|
||||
ChatMessage message = SerializeUtil.deserialize(payload);
|
||||
try {
|
||||
chat(message);
|
||||
} catch (MalformedURLException e) {
|
||||
logger.error("[onMessage] error", e);
|
||||
} catch (ChatbotException e) {
|
||||
logger.error("[onMessage] error", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void chat(final ChatMessage request) throws MalformedURLException, ChatbotException, JSONException {
|
||||
Chatbot c = chatbotRes
|
||||
.findOne(request.getAiid());
|
||||
|
||||
logger.info(
|
||||
"[chat] chat request baseUrl {}, chatbot {}, fromUserId {}, textMessage {}", botBaseUrl, c.getName(),
|
||||
request.getUserid(), request.getMessage());
|
||||
// Get response from Conversational Engine.
|
||||
com.chatopera.bot.sdk.Chatbot bot = new com.chatopera.bot.sdk.Chatbot(
|
||||
c.getClientId(), c.getSecret(), botBaseUrl);
|
||||
JSONObject result = bot.conversation(request.getUserid(), request.getMessage());
|
||||
|
||||
// parse response
|
||||
if (result != null) {
|
||||
logger.info("[chat] chat response {}", result.toString());
|
||||
if (result.getInt(RestUtils.RESP_KEY_RC) == 0) {
|
||||
// reply
|
||||
JSONObject data = result.getJSONObject("data");
|
||||
ChatMessage resp = new ChatMessage();
|
||||
resp.setCalltype(MainContext.CallType.OUT.toString());
|
||||
resp.setAppid(resp.getAppid());
|
||||
resp.setOrgi(request.getOrgi());
|
||||
resp.setAiid(request.getAiid());
|
||||
resp.setMessage(data.getString("string"));
|
||||
resp.setTouser(request.getUserid());
|
||||
resp.setAgentserviceid(request.getAgentserviceid());
|
||||
resp.setMsgtype(request.getMsgtype());
|
||||
resp.setUserid(request.getUserid());
|
||||
resp.setType(request.getType());
|
||||
resp.setChannel(request.getChannel());
|
||||
if (data.has("params")) {
|
||||
resp.setExpmsg(data.get("params").toString());
|
||||
}
|
||||
resp.setContextid(request.getContextid());
|
||||
resp.setSessionid(request.getSessionid());
|
||||
resp.setUsession(request.getUsession());
|
||||
resp.setUsername(c.getName());
|
||||
resp.setUpdatetime(System.currentTimeMillis());
|
||||
|
||||
// 更新聊天机器人累计值
|
||||
updateAgentUserWithRespData(request.getUserid(), request.getOrgi(), data);
|
||||
// 保存并发送
|
||||
chatbotProxy.saveAndPublish(resp);
|
||||
} else {
|
||||
logger.warn("[chat] can not get expected response {}", result.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据聊天机器人返回数据更新agentUser
|
||||
*
|
||||
* @param userid
|
||||
* @param data
|
||||
*/
|
||||
private void updateAgentUserWithRespData(final String userid, final String orgi, final JSONObject data) throws JSONException {
|
||||
cache.findOneAgentUserByUserIdAndOrgi(userid, orgi).ifPresent(p -> {
|
||||
p.setChatbotround(p.getChatbotround() + 1);
|
||||
if (data.has("logic_is_unexpected") && data.getBoolean("logic_is_unexpected")) {
|
||||
p.setChatbotlogicerror(p.getChatbotlogicerror() + 1);
|
||||
}
|
||||
agentUserRes.save(p);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.config.conditions.CalloutBeanCondition;
|
||||
import com.chatopera.cc.persistence.interfaces.CalloutWireEvent;
|
||||
import com.chatopera.cc.schedule.CalloutWireTask;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* FreeSWITCH
|
||||
*/
|
||||
@Component
|
||||
@Conditional(CalloutBeanCondition.class)
|
||||
public class PbxEventSubscription {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(PbxEventSubscription.class);
|
||||
|
||||
@PostConstruct
|
||||
public void setup() {
|
||||
logger.info("ActiveMQ Subscription is setup successfully.");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private BrokerPublisher brokerPublisher;
|
||||
|
||||
@Autowired
|
||||
private CalloutWireTask callOutWireTask;
|
||||
|
||||
public void publish(final String dest, final String payload) {
|
||||
brokerPublisher.send(dest, payload);
|
||||
}
|
||||
|
||||
@JmsListener(destination = Constants.INSTANT_MESSAGING_MQ_QUEUE_PBX, containerFactory = "jmsListenerContainerQueue")
|
||||
public void onMessage(final String payload) {
|
||||
logger.info("[onMessage] payload {}", payload);
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject j = parser.parse(payload).getAsJsonObject();
|
||||
// validate message
|
||||
if (!(j.has("type")
|
||||
&& j.has("to")
|
||||
&& j.has("ops")
|
||||
&& j.has("channel")
|
||||
&& j.has("createtime"))) {
|
||||
logger.error(String.format("[callout wire] 接线数据格式不对, %s", payload));
|
||||
} else {
|
||||
try {
|
||||
CalloutWireEvent event = CalloutWireEvent.parse(j);
|
||||
switch (event.getEventType()) {
|
||||
case 1: // 自动外呼接通
|
||||
logger.info("[callout wire] 自动外呼接通 {}", j.toString());
|
||||
callOutWireTask.callOutConnect(event);
|
||||
break;
|
||||
case 2: // 自动外呼挂断
|
||||
logger.info("[callout wire] 自动外呼挂断 {}", j.toString());
|
||||
callOutWireTask.callOutDisconnect(event);
|
||||
break;
|
||||
case 3: // 自动外呼失败
|
||||
logger.info("[callout wire] 自动外呼失败 {}", j.toString());
|
||||
callOutWireTask.callOutFail(event);
|
||||
break;
|
||||
case 4: // 手动外呼接通
|
||||
logger.info("[callout wire] 手动外呼接通 {}", j.toString());
|
||||
callOutWireTask.callOutConnect(event);
|
||||
break;
|
||||
case 5: // 手动外呼挂断
|
||||
logger.info("[callout wire] 手动外呼挂断 {}", j.toString());
|
||||
callOutWireTask.callOutDisconnect(event);
|
||||
break;
|
||||
case 6: // 手动外呼失败
|
||||
logger.info("[callout wire] 手动外呼失败 {}", j.toString());
|
||||
callOutWireTask.callOutFail(event);
|
||||
break;
|
||||
case 7: // 呼入接通
|
||||
logger.info("[callin wire] 呼入接通 {}", j.toString());
|
||||
break;
|
||||
case 8: // 呼入挂断
|
||||
logger.info("[callin wire] 呼入挂断 {}", j.toString());
|
||||
break;
|
||||
case 9: // 呼入失败
|
||||
logger.info("[callin wire] 呼入失败 {}", j.toString());
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("[callout wire] ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,6 @@ import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.AgentStatus;
|
||||
import com.chatopera.cc.persistence.repository.AgentStatusRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
@ -33,16 +32,13 @@ import java.util.Date;
|
||||
* 处理SocketIO的离线事件
|
||||
*/
|
||||
@Component
|
||||
public class ConnectionEventSubscription {
|
||||
public class SocketioConnEventSubscription {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ConnectionEventSubscription.class);
|
||||
private final static Logger logger = LoggerFactory.getLogger(SocketioConnEventSubscription.class);
|
||||
|
||||
@Autowired
|
||||
private AgentStatusRepository agentStatusRes;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.aop;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -86,7 +86,7 @@ public class Constants {
|
||||
/**
|
||||
* Modules
|
||||
*/
|
||||
public final static String CSKEFU_MODULE_CALLOUT = "sales";
|
||||
public final static String CSKEFU_MODULE_CALLOUT = "callout";
|
||||
public final static String CSKEFU_MODULE_CHATBOT = "chatbot";
|
||||
public final static String CSKEFU_MODULE_CONTACTS = "contacts";
|
||||
public final static String CSKEFU_MODULE_SKYPE = "skype";
|
||||
|
@ -1,8 +0,0 @@
|
||||
package com.chatopera.cc.basic;
|
||||
|
||||
/**
|
||||
* 国际化字段
|
||||
*/
|
||||
public class I18N {
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -786,6 +786,7 @@ public class MainContext {
|
||||
MESSAGE,
|
||||
END,
|
||||
TRANS,
|
||||
TRANSOUT, // 当前会话被转接出去
|
||||
STATUS,
|
||||
AGENTSTATUS,
|
||||
SERVICE,
|
||||
@ -1031,26 +1032,6 @@ public class MainContext {
|
||||
return csKeFuResourceMap.get(resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否开启机器人客服模块
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static boolean isEnableChatbotModule() {
|
||||
return modules.contains(Constants.CSKEFU_MODULE_CHATBOT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否开启外呼模块
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static boolean isEnableCalloutModule() {
|
||||
return modules.contains(Constants.CSKEFU_MODULE_CALLOUT);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Redis底层接口
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.basic.plugins;
|
||||
|
||||
public interface IPluginDescriptor {
|
||||
String getPluginName();
|
||||
String getIOEventHandler();
|
||||
}
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.basic.plugins;
|
||||
|
||||
/**
|
||||
@ -10,5 +25,7 @@ public class PluginRegistry {
|
||||
*/
|
||||
public final static String PLUGIN_CHANNEL_MESSAGER_SUFFIX = "ChannelMessager";
|
||||
public final static String PLUGIN_ENTRY_SKYPE = "com.chatopera.cc.plugins.skype.PluginDescriptor";
|
||||
public final static String PLUGIN_ENTRY_CALLOUT = "com.chatopera.cc.plugins.callout.PluginDescriptor";
|
||||
public final static String PLUGIN_ENTRY_CHATBOT = "com.chatopera.cc.plugins.chatbot.PluginDescriptor";
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.basic.plugins;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 插架装载器
|
||||
* TODO Placeholder
|
||||
* 插架装载器
|
||||
* TODO Placeholder
|
||||
*/
|
||||
public class PluginsLoader {
|
||||
private final static Logger logger = LoggerFactory.getLogger(PluginsLoader.class);
|
||||
|
||||
|
||||
/**
|
||||
* 通过插件entry获得PluginName
|
||||
*
|
||||
* @param pluginEntry
|
||||
* @return
|
||||
*/
|
||||
public static String getPluginName(final String pluginEntry) {
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(pluginEntry);
|
||||
IPluginDescriptor clazzInst = (IPluginDescriptor) clazz.newInstance();
|
||||
Method method = clazz.getMethod("getPluginName");
|
||||
return (String) method.invoke(clazzInst);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
|
||||
logger.info("[postConstruct] error", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 通过插件entry获得Plugin SocketIO Event Handler
|
||||
*
|
||||
* @param pluginEntry
|
||||
* @return
|
||||
*/
|
||||
public static String getIOEventHandler(final String pluginEntry) {
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(pluginEntry);
|
||||
IPluginDescriptor clazzInst = (IPluginDescriptor) clazz.newInstance();
|
||||
Method method = clazz.getMethod("getIOEventHandler");
|
||||
return (String) method.invoke(clazzInst);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
|
||||
logger.info("[postConstruct] error", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,12 +1,12 @@
|
||||
/**
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* webapps/LICENSE-Rivulet
|
||||
* 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,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,7 +16,7 @@
|
||||
*/
|
||||
package com.chatopera.cc.config;
|
||||
|
||||
import com.chatopera.cc.config.conditions.CalloutBeanCondition;
|
||||
import com.chatopera.cc.config.plugins.CalloutPluginPresentCondition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -60,7 +60,7 @@ public class ExecutorConfig {
|
||||
* 外呼线程池
|
||||
* @return
|
||||
*/
|
||||
@Conditional(CalloutBeanCondition.class)
|
||||
@Conditional(CalloutPluginPresentCondition.class)
|
||||
@Bean(name = "callOutTaskExecutor")
|
||||
public ThreadPoolTaskExecutor callout() {
|
||||
ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.coyote.http11.Http11NioProtocol;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.Ssl;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class WebServerConfiguration {
|
||||
private Integer maxthread = 2000;
|
||||
|
||||
private Integer maxconnections = 2000;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerFactory createEmbeddedServletContainerFactory() throws IOException, NoSuchAlgorithmException {
|
||||
TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();
|
||||
tomcatFactory.addConnectorCustomizers(new UKeFuTomcatConnectorCustomizer(maxthread, maxconnections));
|
||||
File sslFile = new File(path, "ssl/https.properties");
|
||||
if (sslFile.exists()) {
|
||||
Properties sslProperties = new Properties();
|
||||
FileInputStream in = new FileInputStream(sslFile);
|
||||
sslProperties.load(in);
|
||||
in.close();
|
||||
if (!StringUtils.isBlank(sslProperties.getProperty("key-store")) && !StringUtils.isBlank(
|
||||
sslProperties.getProperty("key-store-password"))) {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore(new File(path, "ssl/" + sslProperties.getProperty("key-store")).getAbsolutePath());
|
||||
ssl.setKeyStorePassword(MainUtils.decryption(sslProperties.getProperty("key-store-password")));
|
||||
tomcatFactory.setSsl(ssl);
|
||||
}
|
||||
}
|
||||
return tomcatFactory;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class UKeFuTomcatConnectorCustomizer implements TomcatConnectorCustomizer {
|
||||
private Integer maxthread;
|
||||
private Integer maxconnection;
|
||||
|
||||
UKeFuTomcatConnectorCustomizer(Integer maxthread, Integer maxconnection) {
|
||||
this.maxthread = maxthread;
|
||||
this.maxconnection = maxconnection;
|
||||
}
|
||||
|
||||
public void customize(Connector connector) {
|
||||
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
|
||||
//设置最大连接数
|
||||
protocol.setMaxConnections(maxthread != null ? maxthread : 2000);
|
||||
//设置最大线程数
|
||||
protocol.setMaxThreads(maxconnection != null ? maxconnection : 2000);
|
||||
protocol.setConnectionTimeout(30000);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.coyote.http11.Http11NioProtocol;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class WebServerContainerConfigure {
|
||||
|
||||
@Value("${server.threads.max}")
|
||||
private Integer maxthread;
|
||||
|
||||
@Value("${server.connection.max}")
|
||||
private Integer maxconnections;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerFactory createEmbeddedServletContainerFactory() throws IOException, NoSuchAlgorithmException {
|
||||
TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();
|
||||
tomcatFactory.addConnectorCustomizers(new CSKeFuTomcatConnectorCustomizer(maxthread, maxconnections));
|
||||
return tomcatFactory;
|
||||
}
|
||||
|
||||
class CSKeFuTomcatConnectorCustomizer implements TomcatConnectorCustomizer {
|
||||
private Integer maxthread;
|
||||
private Integer maxconnection;
|
||||
|
||||
CSKeFuTomcatConnectorCustomizer(Integer maxthread, Integer maxconnection) {
|
||||
this.maxthread = maxthread;
|
||||
this.maxconnection = maxconnection;
|
||||
}
|
||||
|
||||
public void customize(Connector connector) {
|
||||
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
|
||||
//设置最大连接数
|
||||
protocol.setMaxConnections(maxthread != null ? maxthread : 2000);
|
||||
//设置最大线程数
|
||||
protocol.setMaxThreads(maxconnection != null ? maxconnection : 2000);
|
||||
protocol.setConnectionTimeout(30000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.config;
|
||||
|
||||
import com.chatopera.cc.cache.RedisKey;
|
||||
|
@ -8,8 +8,9 @@
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
package com.chatopera.cc.config.conditions;
|
||||
package com.chatopera.cc.config.plugins;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
@ -19,9 +20,9 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
* Init bean based on conditions
|
||||
* https://javapapers.com/spring/spring-conditional-annotation/
|
||||
*/
|
||||
public class CalloutBeanCondition implements Condition {
|
||||
public class CalloutPluginPresentCondition implements Condition {
|
||||
@Override
|
||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
|
||||
return MainContext.isEnableCalloutModule();
|
||||
return MainContext.hasModule(Constants.CSKEFU_MODULE_CALLOUT);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
package com.chatopera.cc.config.plugins;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
/**
|
||||
* Init bean based on conditions
|
||||
* https://javapapers.com/spring/spring-conditional-annotation/
|
||||
*/
|
||||
public class ChatbotPluginPresentCondition implements Condition {
|
||||
@Override
|
||||
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
|
||||
return MainContext.hasModule(Constants.CSKEFU_MODULE_CHATBOT);
|
||||
}
|
||||
}
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.config.plugins;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.exception;
|
||||
|
||||
public class CalloutRecordException extends Exception {
|
||||
|
||||
public CalloutRecordException(String msg){
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.exception;
|
||||
|
||||
public class CalloutRuntimeException extends Exception {
|
||||
|
||||
public CalloutRuntimeException(String msg){
|
||||
super(msg);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -20,7 +20,7 @@ import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.basic.Viewport;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.handler.api.rest.QueryParams;
|
||||
import com.chatopera.cc.handler.api.QueryParams;
|
||||
import com.chatopera.cc.model.StreamingFile;
|
||||
import com.chatopera.cc.model.SystemConfig;
|
||||
import com.chatopera.cc.model.Tenant;
|
||||
@ -102,7 +102,7 @@ public class Handler {
|
||||
user.setSessionid(user.getId());
|
||||
}
|
||||
} else {
|
||||
user.setSessionid(user.getId());
|
||||
user.setSessionid(MainUtils.getContextID(request.getSession().getId()));
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -18,7 +18,6 @@ package com.chatopera.cc.handler;
|
||||
|
||||
import com.chatopera.cc.acd.AutomaticServiceDist;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.I18N;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
@ -177,51 +176,54 @@ public class LoginController extends Handler {
|
||||
user.getUsername(), MainUtils.md5(user.getPassword()), false);
|
||||
if (loginUser != null && StringUtils.isNotBlank(loginUser.getId())) {
|
||||
view = this.processLogin(request, loginUser, referer);
|
||||
if (StringUtils.isNotBlank(sla) && sla.equals("1")) {
|
||||
|
||||
// 自动登录
|
||||
if (StringUtils.equals("1", sla)) {
|
||||
Cookie flagid = new Cookie(
|
||||
Constants.CSKEFU_SYSTEM_COOKIES_FLAG, MainUtils.encryption(loginUser.getId()));
|
||||
flagid.setMaxAge(7 * 24 * 60 * 60);
|
||||
response.addCookie(flagid);
|
||||
// add authorization code for rest api
|
||||
final String orgi = loginUser.getOrgi();
|
||||
String auth = MainUtils.getUUID();
|
||||
cache.putLoginUserByAuthAndOrgi(auth, loginUser, orgi);
|
||||
userRepository.save(loginUser); // 更新登录状态到数据库
|
||||
response.addCookie((new Cookie("authorization", auth)));
|
||||
}
|
||||
|
||||
// 该登录用户是坐席,并且具有坐席对话的角色
|
||||
if ((loginUser.isAgent() &&
|
||||
loginUser.getRoleAuthMap().containsKey("A01") &&
|
||||
((boolean) loginUser.getRoleAuthMap().get("A01") == true))
|
||||
|| loginUser.isSuperuser()) {
|
||||
try {
|
||||
/****************************************
|
||||
* 登录成功,设置该坐席为就绪状态(默认)
|
||||
****************************************/
|
||||
// https://gitlab.chatopera.com/chatopera/cosinee.w4l/issues/306
|
||||
final AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentnoAndOrgi(
|
||||
loginUser.getId(), orgi, loginUser.getSkills());
|
||||
agentStatus.setBusy(false);
|
||||
agentProxy.ready(loginUser, agentStatus);
|
||||
// add authorization code for rest api
|
||||
final String orgi = loginUser.getOrgi();
|
||||
String auth = MainUtils.getUUID();
|
||||
cache.putLoginUserByAuthAndOrgi(auth, loginUser, orgi);
|
||||
userRepository.save(loginUser); // 更新登录状态到数据库
|
||||
response.addCookie((new Cookie("authorization", auth)));
|
||||
|
||||
// 更新缓存和数据库
|
||||
cache.putAgentStatusByOrgi(agentStatus, loginUser.getOrgi());
|
||||
agentStatusRes.save(agentStatus);
|
||||
// 该登录用户是坐席,并且具有坐席对话的角色
|
||||
if ((loginUser.isAgent() &&
|
||||
loginUser.getRoleAuthMap().containsKey("A01") &&
|
||||
((boolean) loginUser.getRoleAuthMap().get("A01") == true))
|
||||
|| loginUser.isSuperuser()) {
|
||||
try {
|
||||
/****************************************
|
||||
* 登录成功,设置该坐席为就绪状态(默认)
|
||||
****************************************/
|
||||
// https://gitlab.chatopera.com/chatopera/cosinee.w4l/issues/306
|
||||
final AgentStatus agentStatus = agentProxy.resolveAgentStatusByAgentnoAndOrgi(
|
||||
loginUser.getId(), orgi, loginUser.getSkills());
|
||||
agentStatus.setBusy(false);
|
||||
agentProxy.ready(loginUser, agentStatus);
|
||||
|
||||
// 工作状态记录
|
||||
AutomaticServiceDist.recordAgentStatus(agentStatus.getAgentno(),
|
||||
agentStatus.getUsername(),
|
||||
agentStatus.getAgentno(),
|
||||
user.isSuperuser(), // 0代表admin
|
||||
agentStatus.getAgentno(),
|
||||
MainContext.AgentStatusEnum.OFFLINE.toString(),
|
||||
MainContext.AgentStatusEnum.READY.toString(),
|
||||
MainContext.AgentWorkType.MEIDIACHAT.toString(),
|
||||
orgi, null);
|
||||
// 更新缓存和数据库
|
||||
cache.putAgentStatusByOrgi(agentStatus, loginUser.getOrgi());
|
||||
agentStatusRes.save(agentStatus);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("[login] set agent status", e);
|
||||
}
|
||||
// 工作状态记录
|
||||
AutomaticServiceDist.recordAgentStatus(agentStatus.getAgentno(),
|
||||
agentStatus.getUsername(),
|
||||
agentStatus.getAgentno(),
|
||||
user.isSuperuser(), // 0代表admin
|
||||
agentStatus.getAgentno(),
|
||||
MainContext.AgentStatusEnum.OFFLINE.toString(),
|
||||
MainContext.AgentStatusEnum.READY.toString(),
|
||||
MainContext.AgentWorkType.MEIDIACHAT.toString(),
|
||||
orgi, null);
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("[login] set agent status", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -260,6 +262,8 @@ public class LoginController extends Handler {
|
||||
// 更新redis session信息,用以支持sso
|
||||
agentSessionProxy.updateUserSession(
|
||||
loginUser.getId(), MainUtils.getContextID(request.getSession().getId()), loginUser.getOrgi());
|
||||
loginUser.setSessionid(MainUtils.getContextID(request.getSession().getId()));
|
||||
|
||||
|
||||
if (StringUtils.isNotBlank(referer)) {
|
||||
view = new ModelAndView("redirect:" + referer);
|
||||
@ -327,7 +331,7 @@ public class LoginController extends Handler {
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param code 登出的代码
|
||||
* @param code 登出的代码
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/logout")
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -14,7 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.handler.admin.skill;
|
||||
package com.chatopera.cc.handler.admin;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -14,7 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.handler.admin.area;
|
||||
package com.chatopera.cc.handler.admin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -14,7 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.handler.admin.organ;
|
||||
package com.chatopera.cc.handler.admin;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -14,7 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.handler.admin.role;
|
||||
package com.chatopera.cc.handler.admin;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.handler.Handler;
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -14,8 +14,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.handler.admin.users;
|
||||
package com.chatopera.cc.handler.admin;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
@ -78,8 +79,8 @@ public class UsersController extends Handler {
|
||||
Sort.Direction.ASC,
|
||||
"createtime"
|
||||
)
|
||||
)
|
||||
);
|
||||
)
|
||||
);
|
||||
return request(super.createAdminTempletResponse("/admin/user/index"));
|
||||
}
|
||||
|
||||
@ -193,8 +194,10 @@ public class UsersController extends Handler {
|
||||
tempUser.setSipaccount(user.getSipaccount());
|
||||
//切换成非坐席 判断是否坐席 以及 是否有对话
|
||||
if (!user.isAgent()) {
|
||||
AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig((super.getUser(request)).getId(), super.getOrgi(request));
|
||||
if (!(agentStatus == null && cache.getInservAgentUsersSizeByAgentnoAndOrgi(super.getUser(request).getId(), super.getOrgi(request)) == 0)) {
|
||||
AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(
|
||||
(super.getUser(request)).getId(), super.getOrgi(request));
|
||||
if (!(agentStatus == null && cache.getInservAgentUsersSizeByAgentnoAndOrgi(
|
||||
super.getUser(request).getId(), super.getOrgi(request)) == 0)) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/user/index.html?msg=t1"));
|
||||
}
|
||||
}
|
||||
@ -258,7 +261,9 @@ public class UsersController extends Handler {
|
||||
return msg;
|
||||
}
|
||||
|
||||
if (user.getUsername().equals(oldUser.getUsername()) && user.getEmail().equals(oldUser.getEmail()) && user.getMobile().equals(oldUser.getMobile()) && validUserCallcenterParams(user)) {
|
||||
if (user.getUsername().equals(oldUser.getUsername()) && user.getEmail().equals(
|
||||
oldUser.getEmail()) && user.getMobile().equals(oldUser.getMobile()) && validUserCallcenterParams(
|
||||
user)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -292,7 +297,7 @@ public class UsersController extends Handler {
|
||||
* @return
|
||||
*/
|
||||
private boolean validUserCallcenterParams(final User user) {
|
||||
if (user.isCallcenter() && MainContext.isEnableCalloutModule()) {
|
||||
if (user.isCallcenter() && MainContext.hasModule(Constants.CSKEFU_MODULE_CALLOUT)) {
|
||||
List<User> tempUserList = userRepository.findBySipaccountAndDatastatus(user.getSipaccount(), false);
|
||||
return tempUserList.size() == 0 || user.getSipaccount() == "";
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,7 +21,7 @@ import com.chatopera.cc.handler.Handler;
|
||||
import com.chatopera.cc.model.Extention;
|
||||
import com.chatopera.cc.model.PbxHost;
|
||||
import com.chatopera.cc.model.User;
|
||||
import com.chatopera.cc.proxy.CalloutQueneProxy;
|
||||
import com.chatopera.cc.proxy.CallcenterOutboundProxy;
|
||||
import com.chatopera.cc.persistence.repository.*;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.freeswitch.model.CallCenterAgent;
|
||||
@ -187,7 +187,7 @@ public class CallCenterExtentionController extends Handler {
|
||||
ext.setUpdatetime(new Date());
|
||||
extentionRes.save(ext);
|
||||
|
||||
List<CallCenterAgent> callOutAgentList = CalloutQueneProxy.extention(ext.getExtention());
|
||||
List<CallCenterAgent> callOutAgentList = CallcenterOutboundProxy.extention(ext.getExtention());
|
||||
for (CallCenterAgent callOutAgent : callOutAgentList) {
|
||||
callOutAgent.setSiptrunk(ext.getSiptrunk());
|
||||
cache.putCallCenterAgentByIdAndOrgi(callOutAgent.getUserid(), callOutAgent.getOrgi(), callOutAgent);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.handler.admin.channel;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.handler.Handler;
|
||||
import com.chatopera.cc.model.CousultInvite;
|
||||
import com.chatopera.cc.model.SNSAccount;
|
||||
import com.chatopera.cc.model.Secret;
|
||||
import com.chatopera.cc.persistence.repository.ConsultInviteRepository;
|
||||
import com.chatopera.cc.persistence.repository.SNSAccountRepository;
|
||||
import com.chatopera.cc.persistence.repository.SecretRepository;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callout")
|
||||
public class CalloutChannelController extends Handler {
|
||||
@Autowired
|
||||
private SNSAccountRepository snsAccountRes;
|
||||
|
||||
@Autowired
|
||||
private ConsultInviteRepository invite;
|
||||
|
||||
@Autowired
|
||||
private SecretRepository secRes;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "callout", subtype = "channel", access = false, admin = true)
|
||||
public ModelAndView index(ModelMap map, HttpServletRequest request, @Valid String execute, @RequestParam(name = "status", required = false) String status) {
|
||||
map.addAttribute("snsAccountList", snsAccountRes.findBySnstypeAndOrgi(MainContext.ChannelType.PHONE.toString(), super.getOrgi(request), new PageRequest(super.getP(request), super.getPs(request))));
|
||||
map.addAttribute("status", status);
|
||||
List<Secret> secretConfig = secRes.findByOrgi(super.getOrgi(request));
|
||||
if (secretConfig != null && secretConfig.size() > 0) {
|
||||
map.addAttribute("secret", secretConfig.get(0));
|
||||
}
|
||||
if (StringUtils.isNotBlank(execute) && execute.equals("false")) {
|
||||
map.addAttribute("execute", execute);
|
||||
}
|
||||
return request(super.createAdminTempletResponse("/admin/channel/callout/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "callout", subtype = "channel", access = false, admin = true)
|
||||
public ModelAndView add(ModelMap map, HttpServletRequest request) {
|
||||
return request(super.createRequestPageTempletResponse("/admin/channel/callout/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "callout", subtype = "channel")
|
||||
public ModelAndView save(HttpServletRequest request, @Valid SNSAccount snsAccount) throws NoSuchAlgorithmException, CSKefuException {
|
||||
String status = "new_webim_fail";
|
||||
if (StringUtils.isNotBlank(snsAccount.getBaseURL())) {
|
||||
snsAccount.setSnsid(snsAccount.getBaseURL()); // set sns ID the same SNSAccount
|
||||
int count = snsAccountRes.countBySnsidAndOrgi(snsAccount.getSnsid(), super.getOrgi(request));
|
||||
if (count == 0) {
|
||||
status = "new_webim_success";
|
||||
snsAccount.setOrgi(super.getOrgi(request));
|
||||
snsAccount.setSnstype(MainContext.ChannelType.PHONE.toString());
|
||||
snsAccount.setCreatetime(new Date());
|
||||
snsAccountRes.save(snsAccount);
|
||||
|
||||
/**
|
||||
* 同时创建CousultInvite 记录
|
||||
*/
|
||||
CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(snsAccount.getSnsid(), super.getOrgi(request));
|
||||
if (coultInvite == null) {
|
||||
coultInvite = new CousultInvite();
|
||||
coultInvite.setSnsaccountid(snsAccount.getSnsid());
|
||||
coultInvite.setCreate_time(new Date());
|
||||
coultInvite.setOrgi(super.getOrgi(request));
|
||||
coultInvite.setName(snsAccount.getName());
|
||||
invite.save(coultInvite);
|
||||
}
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callout/index.html?status=" + status));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "callout", subtype = "delete")
|
||||
public ModelAndView delete(ModelMap map, HttpServletRequest request, @Valid String id, @Valid String confirm) {
|
||||
boolean execute = false;
|
||||
if (execute = MainUtils.secConfirm(secRes, super.getOrgi(request), confirm)) {
|
||||
SNSAccount snsAccount = snsAccountRes.findByIdAndOrgi(id, super.getOrgi(request));
|
||||
if (snsAccountRes != null) {
|
||||
snsAccountRes.delete(snsAccount);
|
||||
CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(snsAccount.getSnsid(), super.getOrgi(request));
|
||||
if (coultInvite != null) {
|
||||
invite.delete(coultInvite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callout/index.html?execute=" + execute));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "callout", subtype = "channel", access = false, admin = true)
|
||||
public ModelAndView edit(ModelMap map, HttpServletRequest request, @Valid String id) {
|
||||
map.addAttribute("snsAccount", snsAccountRes.findByIdAndOrgi(id, super.getOrgi(request)));
|
||||
return request(super.createRequestPageTempletResponse("/admin/channel/callout/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@Menu(type = "callout", subtype = "channel", access = false, admin = true)
|
||||
public ModelAndView update(HttpServletRequest request, @Valid SNSAccount snsAccount) throws NoSuchAlgorithmException {
|
||||
SNSAccount oldSnsAccount = snsAccountRes.findByIdAndOrgi(snsAccount.getId(), super.getOrgi(request));
|
||||
if (oldSnsAccount != null) {
|
||||
oldSnsAccount.setName(snsAccount.getName());
|
||||
oldSnsAccount.setBaseURL(snsAccount.getBaseURL());
|
||||
oldSnsAccount.setUpdatetime(new Date());
|
||||
/**
|
||||
* SNSID如果有变更,需要同时变更 CoultInvite 表的 记录
|
||||
*/
|
||||
if (StringUtils.isNotBlank(oldSnsAccount.getSnsid())) {
|
||||
CousultInvite coultInvite = invite.findBySnsaccountidAndOrgi(oldSnsAccount.getSnsid(), super.getOrgi(request));
|
||||
if (coultInvite == null) {
|
||||
/**
|
||||
* 同时创建CousultInvite 记录
|
||||
*/
|
||||
coultInvite = new CousultInvite();
|
||||
coultInvite.setSnsaccountid(oldSnsAccount.getSnsid());
|
||||
coultInvite.setCreate_time(new Date());
|
||||
coultInvite.setOrgi(super.getOrgi(request));
|
||||
coultInvite.setName(snsAccount.getName());
|
||||
invite.save(coultInvite);
|
||||
}
|
||||
}
|
||||
|
||||
oldSnsAccount.setSnstype(MainContext.ChannelType.PHONE.toString());
|
||||
snsAccountRes.save(oldSnsAccount);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callout/index.html"));
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018-2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* 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.handler.api;
|
||||
|
||||
import com.chatopera.cc.acd.AutomaticServiceDist;
|
||||
import com.chatopera.cc.basic.MainContext.*;
|
||||
import com.chatopera.cc.basic.MainUtils;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.handler.Handler;
|
||||
import com.chatopera.cc.handler.api.request.RestUtils;
|
||||
import com.chatopera.cc.model.*;
|
||||
import com.chatopera.cc.peer.PeerSyncIM;
|
||||
import com.chatopera.cc.persistence.repository.AgentServiceRepository;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.proxy.AgentAuditProxy;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import com.chatopera.cc.socketio.message.Message;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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 javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ACD服务 获取当前对话中的访客
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/agentuser")
|
||||
public class ApiAgentUserController extends Handler {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ApiAgentUserController.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private PeerSyncIM peerSyncIM;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private AgentServiceRepository agentServiceRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserProxy agentUserProxy;
|
||||
|
||||
@Autowired
|
||||
private AgentAuditProxy agentAuditProxy;
|
||||
|
||||
/**
|
||||
* 获取当前对话中的访客
|
||||
* 坐席相关 RestAPI
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@Menu(type = "apps", subtype = "agentuser", access = true)
|
||||
public ResponseEntity<String> operations(HttpServletRequest request, @RequestBody final String body, @Valid String q) {
|
||||
logger.info("[operations] body {}, q {}", body, q);
|
||||
final JsonObject j = StringUtils.isBlank(body) ? (new JsonObject()) : (new JsonParser()).parse(
|
||||
body).getAsJsonObject();
|
||||
JsonObject json = new JsonObject();
|
||||
HttpHeaders headers = RestUtils.header();
|
||||
|
||||
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 "inserv":
|
||||
json = inserv(request, j);
|
||||
break;
|
||||
case "withdraw":
|
||||
json = withdraw(request, j);
|
||||
break;
|
||||
case "end":
|
||||
json = end(request, j);
|
||||
break;
|
||||
case "transout":
|
||||
json = transout(request, j);
|
||||
break;
|
||||
default:
|
||||
json.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_2);
|
||||
json.addProperty(RestUtils.RESP_KEY_ERROR, "不合法的操作。");
|
||||
}
|
||||
}
|
||||
|
||||
return new ResponseEntity<String>(json.toString(), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行坐席转接
|
||||
* 将会话转接给别人
|
||||
*
|
||||
* @param request
|
||||
* @param payload
|
||||
* @return
|
||||
*/
|
||||
private JsonObject transout(final HttpServletRequest request, final JsonObject payload) {
|
||||
logger.info("[transout] payload ", payload.toString());
|
||||
final String orgi = super.getOrgi(request);
|
||||
final User logined = super.getUser(request);
|
||||
JsonObject resp = new JsonObject();
|
||||
|
||||
/**
|
||||
* 必填参数
|
||||
*/
|
||||
// 目标坐席
|
||||
final String transAgentId = payload.get("agentno").getAsString();
|
||||
// 当前会话的ID
|
||||
final String agentUserId = payload.get("agentUserId").getAsString();
|
||||
// 坐席服务ID
|
||||
final String agentServiceId = payload.get("agentServiceId").getAsString();
|
||||
|
||||
if (StringUtils.isNotBlank(agentUserId) &&
|
||||
StringUtils.isNotBlank(transAgentId) &&
|
||||
StringUtils.isNotBlank(agentServiceId)) {
|
||||
final User targetAgent = userRes.findOne(transAgentId);
|
||||
final AgentService agentService = agentServiceRes.findByIdAndOrgi(agentServiceId, orgi);
|
||||
|
||||
/**
|
||||
* 更新AgentUser
|
||||
*/
|
||||
final AgentUser agentUser = agentUserProxy.findOne(agentUserId).orElseGet(null);
|
||||
if (agentUser != null) {
|
||||
final AgentUserAudit agentAudits = cache.findOneAgentUserAuditByOrgiAndId(orgi, agentUserId).orElseGet(
|
||||
null);
|
||||
|
||||
// 当前服务于访客的坐席
|
||||
final String currentAgentno = agentUser.getAgentno();
|
||||
// 当前访客的ID
|
||||
final String userId = agentUser.getUserid();
|
||||
|
||||
// 检查权限
|
||||
if ((!logined.isSuperuser()) && (!StringUtils.equals(
|
||||
agentUser.getAgentno(),
|
||||
logined.getId())) && (!isTransPermissionAllowed(
|
||||
agentAudits, logined))) {
|
||||
// 1. 不是超级用户;2. 也是不是会话的所有者; 3. 也不是坐席监控人员
|
||||
logger.info("[end] Permission not fulfill.");
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Permission denied.");
|
||||
return resp;
|
||||
}
|
||||
|
||||
agentUser.setAgentno(transAgentId);
|
||||
agentUser.setAgentname(targetAgent.getUname());
|
||||
agentUserRes.save(agentUser);
|
||||
|
||||
/**
|
||||
* 坐席状态
|
||||
*/
|
||||
// 转接目标坐席
|
||||
final AgentStatus transAgentStatus = cache.findOneAgentStatusByAgentnoAndOrig(transAgentId, orgi);
|
||||
|
||||
// 转接源坐席
|
||||
final AgentStatus currentAgentStatus = cache.findOneAgentStatusByAgentnoAndOrig(currentAgentno, orgi);
|
||||
|
||||
if (StringUtils.equals(
|
||||
AgentUserStatusEnum.INSERVICE.toString(),
|
||||
agentUser.getStatus())) { //转接 , 发送消息给 目标坐席
|
||||
// 更新当前坐席的服务访客列表
|
||||
if (currentAgentStatus != null) {
|
||||
cache.deleteOnlineUserIdFromAgentStatusByUseridAndAgentnoAndOrgi(userId, currentAgentno, orgi);
|
||||
AutomaticServiceDist.updateAgentStatus(currentAgentStatus, orgi);
|
||||
}
|
||||
|
||||
if (transAgentStatus != null) {
|
||||
agentService.setAgentno(transAgentId);
|
||||
agentService.setAgentusername(transAgentStatus.getUsername());
|
||||
}
|
||||
|
||||
// 转接坐席提示消息
|
||||
Message outMessage = new Message();
|
||||
outMessage.setMessage(
|
||||
AutomaticServiceDist.getSuccessMessage(agentService, agentUser.getChannel(), orgi));
|
||||
outMessage.setMessageType(MediaType.TEXT.toString());
|
||||
outMessage.setCalltype(CallType.IN.toString());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
outMessage.setAgentUser(agentUser);
|
||||
outMessage.setAgentService(agentService);
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getUserid())) {
|
||||
peerSyncIM.send(
|
||||
ReceiverType.VISITOR,
|
||||
ChannelType.toValue(agentUser.getChannel()),
|
||||
agentUser.getAppid(),
|
||||
MessageType.STATUS,
|
||||
agentUser.getUserid(),
|
||||
outMessage,
|
||||
true);
|
||||
}
|
||||
|
||||
// 通知转接消息给新坐席
|
||||
outMessage.setChannelMessage(agentUser);
|
||||
outMessage.setAgentUser(agentUser);
|
||||
peerSyncIM.send(
|
||||
ReceiverType.AGENT, ChannelType.WEBIM,
|
||||
agentUser.getAppid(), MessageType.NEW, agentService.getAgentno(),
|
||||
outMessage, true);
|
||||
|
||||
// 通知消息给前坐席
|
||||
if (!StringUtils.equals(logined.getId(), currentAgentno)) {
|
||||
// 如果当前坐席不是登录用户,因为登录用户会从RestAPI返回转接的结果
|
||||
// 该登录用户可能是坐席监控或当前坐席,那么,如果是坐席监控,就有必要
|
||||
// 通知前坐席这个事件
|
||||
peerSyncIM.send(ReceiverType.AGENT, ChannelType.WEBIM, agentUser.getAppid(),
|
||||
MessageType.TRANSOUT,
|
||||
currentAgentno, outMessage, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (agentService != null) {
|
||||
agentService.setAgentno(transAgentId);
|
||||
if (payload.has("memo") && StringUtils.isNotBlank(payload.get("memo").getAsString())) {
|
||||
agentService.setTransmemo(payload.get("memo").getAsString());
|
||||
}
|
||||
agentService.setTrans(true);
|
||||
agentService.setTranstime(new Date());
|
||||
agentServiceRes.save(agentService);
|
||||
}
|
||||
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.addProperty(RestUtils.RESP_KEY_DATA, "success");
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Can not find agent user.");
|
||||
}
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_5);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Invalid params.");
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束坐席会话
|
||||
*
|
||||
* @param request
|
||||
* @param payload
|
||||
* @return
|
||||
*/
|
||||
private JsonObject end(final HttpServletRequest request, final JsonObject payload) {
|
||||
logger.info("[end] payload ", payload.toString());
|
||||
final String orgi = super.getOrgi(request);
|
||||
final User logined = super.getUser(request);
|
||||
JsonObject resp = new JsonObject();
|
||||
|
||||
final AgentUser agentUser = agentUserRes.findByIdAndOrgi(payload.get("id").getAsString(), orgi);
|
||||
if (agentUser != null) {
|
||||
if ((StringUtils.equals(
|
||||
logined.getId(), agentUser.getAgentno()) || logined.isSuperuser())) {
|
||||
// 删除访客-坐席关联关系,包括缓存
|
||||
try {
|
||||
AutomaticServiceDist.deleteAgentUser(agentUser, orgi);
|
||||
} catch (CSKefuException e) {
|
||||
// 未能删除成功
|
||||
logger.error("[end]", e);
|
||||
}
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.addProperty(RestUtils.RESP_KEY_DATA, "success");
|
||||
} else {
|
||||
logger.info("[end] Permission not fulfill.");
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_3);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Permission denied.");
|
||||
}
|
||||
} else {
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_FAIL_4);
|
||||
resp.addProperty(RestUtils.RESP_KEY_ERROR, "Agent User not found.");
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤退一个坐席
|
||||
* 将当前坐席服务中的访客分配给其他就绪的坐席
|
||||
*
|
||||
* @param request
|
||||
* @param j
|
||||
* @return
|
||||
*/
|
||||
private JsonObject withdraw(final HttpServletRequest request, final JsonObject j) {
|
||||
JsonObject resp = new JsonObject();
|
||||
AutomaticServiceDist.withdrawAgent(super.getOrgi(request), super.getUser(request).getId());
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
return resp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得当前访客服务中的访客信息
|
||||
* 获取当前正在对话的访客信息,包含多种渠道来源的访客
|
||||
*
|
||||
* @param request
|
||||
* @param j
|
||||
* @return
|
||||
*/
|
||||
private JsonObject inserv(final HttpServletRequest request, final JsonObject j) {
|
||||
JsonObject resp = new JsonObject();
|
||||
JsonArray data = new JsonArray();
|
||||
|
||||
List<AgentUser> lis = cache.findInservAgentUsersByAgentnoAndOrgi(
|
||||
super.getUser(request).getId(), super.getOrgi(request));
|
||||
for (final AgentUser au : lis) {
|
||||
JsonObject obj = new JsonObject();
|
||||
obj.addProperty("id", au.getId());
|
||||
obj.addProperty("userid", au.getUserid());
|
||||
obj.addProperty("status", au.getStatus());
|
||||
obj.addProperty("agentno", au.getAgentno());
|
||||
obj.addProperty("channel", au.getChannel());
|
||||
obj.addProperty("nickname", au.getNickname());
|
||||
data.add(obj);
|
||||
}
|
||||
resp.addProperty(RestUtils.RESP_KEY_RC, RestUtils.RESP_RC_SUCC);
|
||||
resp.add("data", data);
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否具备该会话的坐席监控权限
|
||||
*
|
||||
* @param agentUserAudit
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
private boolean isTransPermissionAllowed(final AgentUserAudit agentUserAudit, final User user) {
|
||||
if (agentUserAudit != null && agentUserAudit.getSubscribers().containsKey(user.getId())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* Copyright (C) 2018-2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
@ -8,7 +8,7 @@
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
package com.chatopera.cc.handler.api.rest;
|
||||
package com.chatopera.cc.handler.api;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user