新疆后端项目
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>health-im</artifactId>
|
||||
<groupId>com.renkang</groupId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>health-im-api</artifactId>
|
||||
<dependencies>
|
||||
<!-- feign -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
<!-- 控制openfeign中bcpkix依赖的版本 -->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcpkix-jdk18on</artifactId>
|
||||
</dependency>
|
||||
<!-- sentinel限流熔断降级-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-base-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>${maven-source-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.renkang.im;
|
||||
|
||||
public enum ImSendEnum {
|
||||
|
||||
TIMTextElem("1", "TIMTextElem", "文本消息元素"),
|
||||
TIMLocationElem("2", "TIMLocationElem", "地理位置消息元素"),
|
||||
TIMFaceElem("3", "TIMFaceElem", "表情消息元素"),
|
||||
TIMCustomElem("4", "TIMCustomElem", "自定义消息元素"),
|
||||
TIMSoundElem("5", "TIMSoundElem", "语音消息元素"),
|
||||
TIMImageElem("6", "TIMImageElem", "图像消息元素"),
|
||||
TIMFileElem("7", "TIMFileElem", "文件消息元素"),
|
||||
TIMVideoFileElem("8", "TIMVideoFileElem", "视频消息元素");
|
||||
private String type;
|
||||
private String value;
|
||||
private String desc;
|
||||
|
||||
ImSendEnum(String type, String value, String desc) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.renkang.im.api;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.renkang.im.api.fallback.IMHelloFallback;
|
||||
import com.renkang.im.entity.*;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@FeignClient(
|
||||
value = "health-im",
|
||||
url = "${renkang.service-url.im:}",
|
||||
fallbackFactory = IMHelloFallback.class
|
||||
)
|
||||
public interface IMHelloApi {
|
||||
|
||||
/**
|
||||
* im hello 微服务接口
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/im/hello")
|
||||
String callHello();
|
||||
|
||||
|
||||
@GetMapping(value = "/wnapp/getMessageAndroid")
|
||||
Result<List> getMessageAndroid(@RequestParam("groupId") String groupId);
|
||||
|
||||
@GetMapping(value = "/imMsgRecordAll/queryTimeDifferenz")
|
||||
Result<List<Map<Object, Object>>> queryTimeDifferenz(@RequestParam(name = "groupId") String groupId);
|
||||
|
||||
@GetMapping(value = "/wnapp/sendSysMsg")
|
||||
IMBaseDO sendSysMsg(@RequestParam("groupId") String groupId, @RequestParam("msgContent") String msgContent);
|
||||
|
||||
@PostMapping(value = "/wnapp/sendGroupMsg")
|
||||
IMGroupMsgResDO sendGroupMsg(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO);
|
||||
|
||||
@PostMapping(value = "/wnapp/sendGroupMsgTextNew")
|
||||
IMGroupMsgResDO sendGroupMsgTextNew(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO);
|
||||
|
||||
@PostMapping(value = "/wnapp/accountReg")
|
||||
Result<String> accountReg(@RequestBody ConSessionRequestDO conSessionRequestDO);
|
||||
|
||||
@GetMapping(value = "/wnapp/sendGroupNotifyToUser")
|
||||
IMBaseDO sendGroupNotifyToUser(@RequestParam("groupId") String groupId, @RequestParam("userIds") List<String> userIds, @RequestParam("msgContent") String msgContent);
|
||||
|
||||
@PostMapping(value = "/wnapp/creatGroupMagNew")
|
||||
Result<Map<String, Object>> creatGroupMagNew(@RequestBody ConSessionRequestDO conSessionRequestDO);
|
||||
|
||||
|
||||
@PostMapping(value = "/wnapp/creatGroupMagNewHelper")
|
||||
Result<Map<String, Object>> creatGroupMagNewHelper(@RequestBody ConSessionRequestDO conSessionRequestDO);
|
||||
|
||||
@GetMapping(value = "/txImMessage/selectImMessageList")
|
||||
Result<List<ImMsgRecordAll>> selectImMessageList(@RequestParam("sessionId") String sessionId);
|
||||
|
||||
@GetMapping(value = "/txImMessage/selectImMessagePageList")
|
||||
Result<Page<ImMsgRecordAll>> selectImMessagePageList(@RequestParam("groupId") String groupId,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize);
|
||||
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.renkang.im.api.fallback;
|
||||
|
||||
import com.renkang.im.api.IMHelloApi;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.cloud.openfeign.FallbackFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author JeecgBoot
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class IMHelloFallback implements FallbackFactory<IMHelloApi> {
|
||||
@Setter
|
||||
private Throwable cause;
|
||||
|
||||
@Override
|
||||
public IMHelloApi create(Throwable throwable) {
|
||||
log.error("微服务接口调用失败: {}", cause);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import org.jeecg.common.system.vo.LoginUserNew;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ConSessionRequestDO {
|
||||
|
||||
private String name;
|
||||
private String userId;
|
||||
private List<LoginUserNew> accountList;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class IMBaseDO implements Serializable {
|
||||
|
||||
/**
|
||||
* 请求处理的结果,OK 表示处理成功,FAIL 表示失败
|
||||
*/
|
||||
private String ActionStatus;//
|
||||
/**
|
||||
* 错误码,0表示成功,非0表示失败
|
||||
*/
|
||||
private Integer ErrorCode; //
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String ErrorInfo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 接收IM消息响应 DO
|
||||
*
|
||||
* @author SiZhanXiang
|
||||
* @date 2021/06/09
|
||||
*/
|
||||
@Data
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class IMGroupMsgResDO extends IMBaseDO {
|
||||
|
||||
//消息发送的时间戳,对应后台 server 时间
|
||||
private Integer MsgTime;
|
||||
|
||||
//消息序列号,唯一标示一条消息
|
||||
private Integer MsgSeq;
|
||||
|
||||
private String MsgKey;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
* @Description: IM 测试demo
|
||||
* @Author: JeecgBoot
|
||||
* @Date: 2022-04-25
|
||||
* @Version:V1.0
|
||||
*/
|
||||
@Data
|
||||
public class IMHelloEntity {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 发送IM消息请求 DO
|
||||
*
|
||||
* @author SiZhanXiang
|
||||
* @date 2021/06/09
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ImGroupMsgTextReqDO implements Serializable {
|
||||
|
||||
|
||||
@Schema(title = "群组id")
|
||||
private String groupId;
|
||||
@Schema(title = "发送方用户id")
|
||||
private String fromUserId;
|
||||
@Schema(title = "发送的数据")
|
||||
private String content;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
|
||||
/**
|
||||
* 群组消息同步表
|
||||
*/
|
||||
@Schema(description = "群组消息同步表")
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName(value = "im_group_sync_record")
|
||||
public class ImGroupSyncRecord implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
@Schema(description = "主键")
|
||||
private String id;
|
||||
/**
|
||||
* 群组ID
|
||||
*/
|
||||
@TableField(value = "group_id")
|
||||
@Schema(description = "群组ID")
|
||||
private String groupId;
|
||||
/**
|
||||
* 获取到消息数量
|
||||
*/
|
||||
@TableField(value = "fetch_msg_count")
|
||||
@Schema(description = "获取到消息数量")
|
||||
private Integer fetchMsgCount;
|
||||
/**
|
||||
* 已存在消息数量
|
||||
*/
|
||||
@TableField(value = "exist_msg_count")
|
||||
@Schema(description = "已存在消息数量")
|
||||
private Integer existMsgCount;
|
||||
/**
|
||||
* 新同步消息数量
|
||||
*/
|
||||
@TableField(value = "sync_msg_count")
|
||||
@Schema(description = "新同步消息数量")
|
||||
private Integer syncMsgCount;
|
||||
/**
|
||||
* 同步状态 0-未开始 1-正在同步 2-同步结束 3-同步错误
|
||||
*/
|
||||
@TableField(value = "sync_status")
|
||||
@Schema(description = "同步状态 0-未开始 1-正在同步 2-同步结束 3-同步错误")
|
||||
private Integer syncStatus;
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
@TableField(value = "error_msg")
|
||||
@Schema(description = "错误信息")
|
||||
private String errorMsg;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
@TableField(value = "start_time")
|
||||
@Schema(description = "开始时间")
|
||||
private Date startTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@TableField(value = "end_time")
|
||||
@Schema(description = "结束时间")
|
||||
private Date endTime;
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@TableField(value = "create_time")
|
||||
@Schema(description = "创建时间")
|
||||
private Date createTime;
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Description: im_msg_record_all
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2023-05-15
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Data
|
||||
@TableName("im_msg_record_all")
|
||||
@Accessors(chain = true)
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Schema(title = "im_msg_record_all对象", description = "im_msg_record_all")
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImMsgRecordAll implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId(type = IdType.ASSIGN_ID)
|
||||
@Schema(title = "id")
|
||||
private String id;
|
||||
/**
|
||||
* 群组ID
|
||||
*/
|
||||
@Excel(name = "群组ID", width = 15)
|
||||
@Schema(title = "群组ID")
|
||||
private String groupid;
|
||||
/**
|
||||
* 发送者账号
|
||||
*/
|
||||
@Excel(name = "发送者账号", width = 15)
|
||||
@Schema(title = "发送者账号")
|
||||
private String fromAccount;
|
||||
/**
|
||||
* 接受者账号
|
||||
*/
|
||||
@Excel(name = "接受者账号", width = 15)
|
||||
@Schema(title = "接受者账号")
|
||||
private String toAccount;
|
||||
/**
|
||||
* 发送时间
|
||||
*/
|
||||
@Excel(name = "发送时间", width = 15, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Schema(title = "发送时间")
|
||||
private Date sendtime;
|
||||
/**
|
||||
* 消息类型 1单聊 2群聊
|
||||
*/
|
||||
@Excel(name = "消息类型 1单聊 2群聊", width = 15)
|
||||
@Schema(title = "消息类型 1单聊 2群聊")
|
||||
private String msgtype;
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
@Excel(name = "消息内容", width = 15)
|
||||
@Schema(title = "消息内容")
|
||||
private String msgcontent;
|
||||
/**
|
||||
* 消息元素类别;目前支持的消息对象包括:TIMTextElem(文本消息),TIMLocationElem(位置消息),TIMFaceElem(表情消息),TIMCustomElem(自定义消息),TIMSoundElem(语音消息),TIMImageElem(图像消息),TIMFileElem(文件消息),TIMVideoFileElem(视频消息)
|
||||
*/
|
||||
@Excel(name = "消息元素类别;目前支持的消息对象包括:TIMTextElem(文本消息),TIMLocationElem(位置消息),TIMFaceElem(表情消息),TIMCustomElem(自定义消息),TIMSoundElem(语音消息),TIMImageElem(图像消息),TIMFileElem(文件消息),TIMVideoFileElem(视频消息)", width = 15)
|
||||
@Schema(title = "消息元素类别;目前支持的消息对象包括:TIMTextElem(文本消息),TIMLocationElem(位置消息),TIMFaceElem(表情消息),TIMCustomElem(自定义消息),TIMSoundElem(语音消息),TIMImageElem(图像消息),TIMFileElem(文件消息),TIMVideoFileElem(视频消息)")
|
||||
private String contenttype;
|
||||
/**
|
||||
* 消息序列
|
||||
*/
|
||||
@Excel(name = "消息序列", width = 15)
|
||||
@Schema(title = "消息序列")
|
||||
private Integer msgseq;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
@Excel(name = "通话结束时间", width = 15, format = "yyyy-MM-dd")
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
@Schema(title = "通话结束时间")
|
||||
private Date endTime;
|
||||
|
||||
@Schema(title = "通话结束时间")
|
||||
private Date createTime;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(title = "通话结束时间")
|
||||
private String fromAccountName;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(title = "通话结束时间")
|
||||
private String toAccountName;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(title = "状态")
|
||||
private String contentStatus;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(title = "头像")
|
||||
private String fromAccountHead;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SystemMessageD0 {
|
||||
|
||||
private String GroupId;
|
||||
|
||||
private String Content;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.renkang.im.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class IMHelloPage {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>health-im</artifactId>
|
||||
<groupId>com.renkang</groupId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>health-im-biz</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>health-im-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-system-cloud-api</artifactId>
|
||||
</dependency>
|
||||
<!--腾讯云即时对话pom-->
|
||||
<dependency>
|
||||
<groupId>com.github.tencentyun</groupId>
|
||||
<artifactId>tls-sig-api-v2</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>javax.persistence-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-starter-job</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>health-consultation-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>${maven-source-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.renkang.im.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Data
|
||||
public class GroupHistoryTransfer {
|
||||
|
||||
private Integer minSeq = 0;
|
||||
|
||||
private Integer fetchCount = 0;
|
||||
|
||||
private Integer existCount = 0;
|
||||
|
||||
private Integer syncCount = 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.renkang.im.bean;
|
||||
|
||||
import com.renkang.im.entity.ImGroupSyncRecord;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.jeecg.base.Criteria;
|
||||
import org.jeecg.base.PageInfo;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2024/10/5
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Data
|
||||
@Schema(description = "群组同步筛选")
|
||||
public class GroupSyncFilter extends PageInfo<ImGroupSyncRecord> {
|
||||
|
||||
@Schema(description = "群组ID")
|
||||
@Criteria
|
||||
private String groupId;
|
||||
|
||||
@Schema(description = "同步开始时间-开始")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Criteria(value = Criteria.Mode.GE, property = "startTime")
|
||||
private Date startTimeStart;
|
||||
|
||||
@Schema(description = "同步开始时间-结束")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@Criteria(value = Criteria.Mode.LE, property = "startTime")
|
||||
private Date startTimeEnd;
|
||||
|
||||
@Schema(description = "同步状态")
|
||||
@Criteria
|
||||
private Integer syncStatus;
|
||||
|
||||
}
|
||||
+328
@@ -0,0 +1,328 @@
|
||||
package com.renkang.im.common;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.common.TencentCloudImApiConstant
|
||||
* @description: 腾讯im相关API接口
|
||||
* @User jinbo
|
||||
* @create: 2023-04-21 15:39
|
||||
* @Version 1.0
|
||||
**/
|
||||
public class TencentCloudImApiConstant {
|
||||
/**
|
||||
* 账号管理
|
||||
* 发个班
|
||||
*/
|
||||
public static class AccountManage {
|
||||
/**
|
||||
* 导入单个帐号
|
||||
*/
|
||||
public static final String ACCOUNT_IMPORT = "v4/im_open_login_svc/account_import";
|
||||
/**
|
||||
* 导入多个帐号
|
||||
*/
|
||||
public static final String MULTI_ACCOUNT_IMPORT = "v4/im_open_login_svc/multiaccount_import";
|
||||
/**
|
||||
* 删除帐号
|
||||
*/
|
||||
public static final String ACCOUNT_DELETE = "v4/im_open_login_svc/account_delete";
|
||||
/**
|
||||
* 查询帐号
|
||||
*/
|
||||
public static final String ACCOUNT_CHECK = "v4/im_open_login_svc/account_check";
|
||||
/**
|
||||
* 失效帐号登录状态
|
||||
*/
|
||||
public static final String ACCOUNT_KICK = "v4/im_open_login_svc/kick";
|
||||
/**
|
||||
* 查询账号在线状态
|
||||
*/
|
||||
public static final String ACCOUNT_QUERY_STATE = "v4/openim/querystate";
|
||||
}
|
||||
|
||||
/**
|
||||
* 单聊消息
|
||||
*/
|
||||
public static class SingleChatManage {
|
||||
/**
|
||||
* 单发单聊消息
|
||||
*/
|
||||
public static final String SEND_MSG = "v4/openim/sendmsg";
|
||||
/**
|
||||
* 批量发单聊消息
|
||||
*/
|
||||
public static final String BATCH_SEND_MSG = "v4/openim/batchsendmsg";
|
||||
/**
|
||||
* 导入单聊消息
|
||||
*/
|
||||
public static final String IMPORT_MSG = "v4/openim/importmsg";
|
||||
/**
|
||||
* 查询单聊消息
|
||||
*/
|
||||
public static final String ADMIN_GET_ROAM_MSG = "v4/openim/admin_getroammsg";
|
||||
/**
|
||||
* 撤回单聊消息
|
||||
*/
|
||||
public static final String ADMIN_MSG_WITH_DRAW = "v4/openim/admin_msgwithdraw";
|
||||
/**
|
||||
* 设置单聊消息已读
|
||||
*/
|
||||
public static final String ADMIN_SET_MSG_READ = "v4/openim/admin_set_msg_read";
|
||||
}
|
||||
|
||||
/**
|
||||
* 全员推送
|
||||
*/
|
||||
public static class AllPushManage {
|
||||
/**
|
||||
* 全员推送
|
||||
*/
|
||||
public static final String IM_PUSH = "v4/all_member_push/im_push";
|
||||
/**
|
||||
* 设置应用属性名称
|
||||
*/
|
||||
public static final String IM_SET_ATTR_NAME = "v4/all_member_push/im_set_attr_name";
|
||||
/**
|
||||
* 获取应用属性名称
|
||||
*/
|
||||
public static final String IM_GET_ATTR_NAME = "v4/all_member_push/im_get_attr_name";
|
||||
/**
|
||||
* 获取用户属性
|
||||
*/
|
||||
public static final String IM_GET_ATTR = "v4/all_member_push/im_get_attr";
|
||||
/**
|
||||
* 设置用户属性
|
||||
*/
|
||||
public static final String IM_SET_ATTR = "v4/all_member_push/im_set_attr";
|
||||
/**
|
||||
* 删除用户属性
|
||||
*/
|
||||
public static final String IM_REMOVE_ATTR = "v4/all_member_push/im_remove_attr";
|
||||
/**
|
||||
* 获取用户标签
|
||||
*/
|
||||
public static final String IM_GET_TAG = "v4/all_member_push/im_get_tag";
|
||||
/**
|
||||
* 添加用户标签
|
||||
*/
|
||||
public static final String IM_ADD_TAG = "v4/all_member_push/im_add_tag";
|
||||
/**
|
||||
* 删除用户标签
|
||||
*/
|
||||
public static final String IM_REMOVE_TAG = "v4/all_member_push/im_remove_tag";
|
||||
/**
|
||||
* 删除用户所有标签
|
||||
*/
|
||||
public static final String IM_REMOVE_ALL_TAGS = "v4/all_member_push/im_remove_all_tags";
|
||||
}
|
||||
|
||||
/**
|
||||
* 资料管理
|
||||
*/
|
||||
public static class PortraitManage {
|
||||
/**
|
||||
* 设置资料
|
||||
*/
|
||||
public static final String PORTRAIT_SET = "v4/profile/portrait_set";
|
||||
/**
|
||||
* 拉取资料
|
||||
*/
|
||||
public static final String PORTRAIT_GET = "v4/profile/portrait_get";
|
||||
}
|
||||
|
||||
/**
|
||||
* 关系链管理
|
||||
*/
|
||||
public static class RelationManage {
|
||||
/**
|
||||
* 添加好友
|
||||
*/
|
||||
public static final String FRIEND_ADD = "v4/sns/friend_add";
|
||||
/**
|
||||
* 导入好友
|
||||
*/
|
||||
public static final String FRIEND_IMPORT = "v4/sns/friend_import";
|
||||
/**
|
||||
* 更新好友
|
||||
*/
|
||||
public static final String FRIEND_UPDATE = "v4/sns/friend_update";
|
||||
/**
|
||||
* 删除好友
|
||||
*/
|
||||
public static final String FRIEND_DELETE = "v4/sns/friend_delete";
|
||||
/**
|
||||
* 删除所有好友
|
||||
*/
|
||||
public static final String FRIEND_DELETE_ALL = "v4/sns/friend_delete_all";
|
||||
/**
|
||||
* 校验好友
|
||||
*/
|
||||
public static final String FRIEND_CHECK = "v4/sns/friend_check";
|
||||
/**
|
||||
* 拉取好友
|
||||
*/
|
||||
public static final String FRIEND_GET = "v4/sns/friend_get";
|
||||
/**
|
||||
* 拉取指定好友
|
||||
*/
|
||||
public static final String FRIEND_GET_LIST = "v4/sns/friend_get_list";
|
||||
/**
|
||||
* 添加黑名单
|
||||
*/
|
||||
public static final String BLACK_LIST_ADD = "v4/sns/black_list_add";
|
||||
/**
|
||||
* 删除黑名单
|
||||
*/
|
||||
public static final String BLACK_LIST_DELETE = "v4/sns/black_list_delete";
|
||||
/**
|
||||
* 拉取黑名单
|
||||
*/
|
||||
public static final String BLACK_LIST_GET = "v4/sns/black_list_get";
|
||||
/**
|
||||
* 校验黑名单
|
||||
*/
|
||||
public static final String BLACK_LIST_CHECK = "v4/sns/black_list_check";
|
||||
/**
|
||||
* 添加分组
|
||||
*/
|
||||
public static final String GROUP_ADD = "v4/sns/group_add";
|
||||
/**
|
||||
* 删除分组
|
||||
*/
|
||||
public static final String GROUP_DELETE = "v4/sns/group_delete";
|
||||
/**
|
||||
* 拉取分组
|
||||
*/
|
||||
public static final String GROUP_GET = "v4/sns/group_get";
|
||||
}
|
||||
|
||||
/**
|
||||
* 群组管理
|
||||
*/
|
||||
public static class GroupManage {
|
||||
/**
|
||||
* 创建群组
|
||||
*/
|
||||
public static final String CREATE_GROUP = "v4/group_open_http_svc/create_group";
|
||||
/**
|
||||
* 获取群详细资料
|
||||
*/
|
||||
public static final String GET_GROUP_INFO = "v4/group_open_http_svc/get_group_info";
|
||||
/**
|
||||
* 获取群成员详细资料
|
||||
*/
|
||||
public static final String GET_GROUP_MEMBER_INFO = "v4/group_open_http_svc/get_group_member_info";
|
||||
/**
|
||||
* 修改群基础资料
|
||||
*/
|
||||
public static final String MODIFY_GROUP_BASE_INFO = "v4/group_open_http_svc/modify_group_base_info";
|
||||
/**
|
||||
* 增加群成员
|
||||
*/
|
||||
public static final String ADD_GROUP_MEMBER = "v4/group_open_http_svc/add_group_member";
|
||||
/**
|
||||
* 删除群成员
|
||||
*/
|
||||
public static final String DELETE_GROUP_MEMBER = "v4/group_open_http_svc/delete_group_member";
|
||||
/**
|
||||
* 修改群成员资料
|
||||
*/
|
||||
public static final String MODIFY_GROUP_MEMBER_INFO = "v4/group_open_http_svc/modify_group_member_info";
|
||||
/**
|
||||
* 解散群组
|
||||
*/
|
||||
public static final String DESTROY_GROUP = "v4/group_open_http_svc/destroy_group";
|
||||
/**
|
||||
* 获取用户所加入的群组
|
||||
*/
|
||||
public static final String GET_JOINED_GROUP_LIST = "v4/group_open_http_svc/get_joined_group_list";
|
||||
/**
|
||||
* 查询用户在群组中的身份
|
||||
*/
|
||||
public static final String GET_ROLE_IN_GROUP = "v4/group_open_http_svc/get_role_in_group";
|
||||
/**
|
||||
* 批量禁言和取消禁言
|
||||
*/
|
||||
public static final String FORBID_SEND_MSG = "v4/group_open_http_svc/forbid_send_msg";
|
||||
/**
|
||||
* 获取被禁言群成员列表
|
||||
*/
|
||||
public static final String GET_GROUP_SHUT_UIN = "v4/group_open_http_svc/get_group_shutted_uin";
|
||||
/**
|
||||
* 在群组中发送普通消息
|
||||
*/
|
||||
public static final String SEND_GROUP_MSG = "v4/group_open_http_svc/send_group_msg";
|
||||
/**
|
||||
* 在群组中发送系统通知
|
||||
*/
|
||||
public static final String SEND_GROUP_SYSTEM_NOTIFICATION = "v4/group_open_http_svc/send_group_system_notification";
|
||||
/**
|
||||
* 撤回群消息
|
||||
*/
|
||||
public static final String GROUP_MSG_RECALL = "v4/group_open_http_svc/group_msg_recall";
|
||||
/**
|
||||
* 转让群主
|
||||
*/
|
||||
public static final String CHANGE_GROUP_OWNER = "v4/group_open_http_svc/change_group_owner";
|
||||
/**
|
||||
* 导入群基础资料
|
||||
*/
|
||||
public static final String IMPORT_GROUP = "v4/group_open_http_svc/import_group";
|
||||
/**
|
||||
* 导入群消息
|
||||
*/
|
||||
public static final String IMPORT_GROUP_MSG = "v4/group_open_http_svc/import_group_msg";
|
||||
/**
|
||||
* 导入群成员
|
||||
*/
|
||||
public static final String IMPORT_GROUP_MEMBER = "v4/group_open_http_svc/import_group_member";
|
||||
/**
|
||||
* 设置成员未读消息计数
|
||||
*/
|
||||
public static final String SET_UNREAD_MSG_NUM = "v4/group_open_http_svc/set_unread_msg_num";
|
||||
/**
|
||||
* 删除指定用户发送的消息
|
||||
*/
|
||||
public static final String DELETE_GROUP_MSG_BY_SENDER = "v4/group_open_http_svc/delete_group_msg_by_sender";
|
||||
/**
|
||||
* 拉取群历史消息
|
||||
*/
|
||||
public static final String GROUP_MSG_GET_SIMPLE = "v4/group_open_http_svc/group_msg_get_simple";
|
||||
/**
|
||||
* 获取直播群在线人数
|
||||
*/
|
||||
public static final String GET_ONLINE_MEMBER_NUM = "v4/group_open_http_svc/get_online_member_num";
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局禁言管理
|
||||
*/
|
||||
public static class AllSinentManage {
|
||||
/**
|
||||
* 设置全局禁言
|
||||
*/
|
||||
public static final String SET_NO_SPEAKING = "v4/openconfigsvr/setnospeaking";
|
||||
/**
|
||||
* 查询全局禁言
|
||||
*/
|
||||
public static final String GET_NO_SPEAKING = "v4/openconfigsvr/getnospeaking";
|
||||
}
|
||||
|
||||
/**
|
||||
* 运营管理
|
||||
*/
|
||||
public static class OperationManage {
|
||||
/**
|
||||
* 拉取运营数据
|
||||
*/
|
||||
public static final String GET_APP_INFO = "v4/openconfigsvr/getappinfo";
|
||||
/**
|
||||
* 下载消息记录
|
||||
*/
|
||||
public static final String GET_HISTORY = "v4/open_msg_svc/get_history";
|
||||
/**
|
||||
* 获取服务器 IP 地址
|
||||
*/
|
||||
public static final String GET_IP_LIST = "v4/ConfigSvc/GetIPList";
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package com.renkang.im.common;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.common.TencentCloudImConstant
|
||||
* @description: 腾讯im相关常量
|
||||
* @User jinbo
|
||||
* @create: 2023-04-21 15:40
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
public interface TencentCloudImConstant {
|
||||
/**
|
||||
* IM请求处理结果
|
||||
*/
|
||||
String ACTION_STATUS = "ActionStatus";
|
||||
String ACTION_STATUS_OK = "OK";
|
||||
String ACTION_STATUS_FAIL = "FAIL";
|
||||
String ERROR_CODE = "ErrorCode";
|
||||
String IS_FINISHED = "IsFinished";
|
||||
|
||||
/**
|
||||
* IM发消息是否同步到发送方(1-同步,2-不同步)
|
||||
*/
|
||||
Integer SYNC_OTHER_MACHINE_YES = 1;
|
||||
Integer SYNC_OTHER_MACHINE_NO = 2;
|
||||
|
||||
/**
|
||||
* IM消息对象类型:
|
||||
* TIMTextElem 文本消息。
|
||||
* TIMLocationElem 地理位置消息。
|
||||
* TIMFaceElem 表情消息。
|
||||
* TIMCustomElem 自定义消息,当接收方为 iOS 系统且应用处在后台时,此消息类型可携带除文本以外的字段到 APNs。一条组合消息中只能包含一个 TIMCustomElem 自定义消息元素。
|
||||
* TIMSoundElem 语音消息。
|
||||
* TIMImageElem 图像消息。
|
||||
* TIMFileElem 文件消息。
|
||||
* TIMVideoFileElem 视频消息。
|
||||
*/
|
||||
String TIM_TEXT_ELEM = "TIMTextElem";
|
||||
String TIM_LOCATION_ELEM = "TIMLocationElem";
|
||||
String TIM_FACE_ELEM = "TIMFaceElem";
|
||||
String TIM_CUSTOM_ELEM = "TIMCustomElem";
|
||||
String TIM_SOUND_ELEM = "TIMSoundElem";
|
||||
String TIM_IMAGE_ELEM = "TIMImageElem";
|
||||
String TIM_FILE_ELEM = "TIMFileElem";
|
||||
String TIM_VIDEO_FILE_ELEM = "TIMVideoFileElem";
|
||||
|
||||
/**
|
||||
* 微信响应消息类型
|
||||
* WX_MSG_TYPE_EVENT:事件类型,事件类型对应"user_enter_tempsession"表示建立会话
|
||||
* WX_MSG_TYPE_TEXT:文本类型
|
||||
* WX_MSG_TYPE_TEXT:图片类型
|
||||
* WX_MSG_TYPE_TEXT:小程序卡片
|
||||
*/
|
||||
String WX_MSG_TYPE_EVENT = "event";
|
||||
String WX_MSG_TYPE_TEXT = "text";
|
||||
String WX_MSG_TYPE_IMAGE = "image";
|
||||
String WX_MSG_TYPE_APPLET_CARD = "miniprogrampage";
|
||||
|
||||
String CALLBACK_COMMAND = "CallbackCommand";
|
||||
String GROUP_CALLBACK_AFTER_SEND_MSG = "Group.CallbackAfterSendMsg";
|
||||
String GROUP_TYPE = "Type";
|
||||
String GROUP_TYPE_STRANGER = "Public";
|
||||
String RSP_MSG_LIST = "RspMsgList";
|
||||
String MSG_SEQ = "MsgSeq";
|
||||
String MSG_BODY = "MsgBody";
|
||||
String ONLINE_ONLY_FLAG = "OnlineOnlyFlag";
|
||||
String MSG_TYPE = "MsgType";
|
||||
String IS_PLACE_MSG = "IsPlaceMsg";
|
||||
String MSG_CONTENT = "MsgContent";
|
||||
String IMAGE_INFO_ARRAY = "ImageInfoArray";
|
||||
String CLOUD_CUSTOM_DATA = "CloudCustomData";
|
||||
String MSG_TIME = "MsgTime";
|
||||
String EVENT_TIME = "EventTime";
|
||||
String RANDOM = "Random";
|
||||
String MSG_RANDOM = "MsgRandom";
|
||||
String MSG_PRIORITY = "MsgPriority";
|
||||
String FROM_ACCOUNT = "From_Account";
|
||||
String OPERATOR_ACCOUNT = "Operator_Account";
|
||||
String GROUP_ID = "GroupId";
|
||||
String URL = "URL";
|
||||
String URL_LOW = "Url";
|
||||
String VIDEO_URL = "VideoUrl";
|
||||
String THUMB_URL = "ThumbUrl";
|
||||
String MSG_TIME_STAMP = "MsgTimeStamp";
|
||||
|
||||
String IM_RICH_RAW = "https://cn.imrich.qcloud.com";
|
||||
String IM_RICH_RP = "http://101.201.149.156:8609/qc";
|
||||
|
||||
String AP_GUANGZHOU_RAW = "https://cos.ap-guangzhou.myqcloud.com";
|
||||
String AP_GUANGZHOU_RP = "http://101.201.149.156:8609/gmc";
|
||||
|
||||
String MY_IM_RAW = "https://cn.rich.my-imcloud.com";
|
||||
String MY_IM_RP = "http://101.201.149.156:8609/ic";
|
||||
|
||||
String AP_SHANGHAI_RAW = "https://cos.ap-shanghai.myqcloud.com";
|
||||
String AP_SHANGHAI_RP = "http://101.201.149.156:8609/smc";
|
||||
|
||||
String AP_SHANGHAI_TC_RAW = "https://cos.ap-shanghai.tencentcos.cn";
|
||||
String AP_SHANGHAI_TC_RP = "http://101.201.149.156:8609/tc";
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.renkang.im.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.renkang.im.bean.GroupSyncFilter;
|
||||
import com.renkang.im.entity.ImGroupSyncRecord;
|
||||
import com.renkang.im.service.ImService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
* @author Shunzhi Jiang
|
||||
* @since 2024/10/5
|
||||
*/
|
||||
@RestController
|
||||
@Tag(name = "im/群组同步")
|
||||
@RequestMapping("/sync/group")
|
||||
public class GroupSyncController {
|
||||
|
||||
@Autowired
|
||||
private ImService imService;
|
||||
|
||||
@PostMapping("/terminate/{recordId}")
|
||||
@Operation(description = "强制结束同步")
|
||||
public Result<Void> forceTerminate(@PathVariable String recordId) {
|
||||
imService.forceTerminate(recordId);
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete/{recordId}")
|
||||
@Operation(description = "删除同步记录")
|
||||
public Result<Boolean> delete(@PathVariable String recordId) {
|
||||
return Result.ok(imService.deleteRecord(recordId));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(description = "分页查询同步记录")
|
||||
public Result<Page<ImGroupSyncRecord>> list(GroupSyncFilter filter) {
|
||||
return Result.ok(imService.listGroupSyncRecord(filter));
|
||||
}
|
||||
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package com.renkang.im.controller;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.renkang.im.service.ImService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.controller.ImCallbackController
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-05-17 10:16
|
||||
* @Version 1.0
|
||||
**/
|
||||
@RestController
|
||||
@RequestMapping("/ImCallbackController")
|
||||
@Slf4j
|
||||
public class ImCallbackController {
|
||||
|
||||
//im发个班
|
||||
|
||||
@Value("${IMConfig.sdkAppId}")
|
||||
private long sdkAppId;
|
||||
|
||||
@Autowired
|
||||
private ImService imService;
|
||||
|
||||
@PostMapping("/imEventCallback")
|
||||
public JSON imEventCallback(@RequestBody JSONObject jsonObject, HttpServletRequest request) {
|
||||
Map<String, String[]> parameterMap = request.getParameterMap();
|
||||
String[] sdkAppid = parameterMap.get("SdkAppid");
|
||||
if (ArrayUtil.isEmpty(sdkAppid)) {
|
||||
return new JSONObject()
|
||||
.fluentPut("ActionStatus", "FAIL")
|
||||
.fluentPut("ErrorInfo", "NO APPID")
|
||||
.fluentPut("ErrorCode", 10001);
|
||||
}
|
||||
if (sdkAppid[0].equals(String.valueOf(sdkAppId))) {
|
||||
imService.callback(jsonObject);
|
||||
}
|
||||
return new JSONObject()
|
||||
.fluentPut("ActionStatus", "OK")
|
||||
.fluentPut("ErrorInfo", "")
|
||||
.fluentPut("ErrorCode", 0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
package com.renkang.im.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.renkang.im.entity.ImMsgRecordAll;
|
||||
import com.renkang.im.service.IImMsgRecordAllService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.aspect.annotation.AutoLog;
|
||||
import org.jeecg.common.system.base.controller.JeecgController;
|
||||
import org.jeecg.common.system.query.QueryGenerator;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @Description: im_msg_record_all
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2023-05-15
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Tag(name = "im_msg_record_all")
|
||||
@RestController
|
||||
@RequestMapping("/imMsgRecordAll")
|
||||
@Slf4j
|
||||
public class ImMsgRecordAllController extends JeecgController<ImMsgRecordAll, IImMsgRecordAllService> {
|
||||
@Autowired
|
||||
private IImMsgRecordAllService imMsgRecordAllService;
|
||||
|
||||
/**
|
||||
* 分页列表查询
|
||||
*
|
||||
* @param imMsgRecordAll
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "im_msg_record_all-分页列表查询")
|
||||
@Operation(summary = "im_msg_record_all-分页列表查询", description = "im_msg_record_all-分页列表查询")
|
||||
@GetMapping(value = "/list")
|
||||
public Result<IPage<ImMsgRecordAll>> queryPageList(ImMsgRecordAll imMsgRecordAll,
|
||||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
HttpServletRequest req) {
|
||||
QueryWrapper<ImMsgRecordAll> queryWrapper = QueryGenerator.initQueryWrapper(imMsgRecordAll, req.getParameterMap());
|
||||
Page<ImMsgRecordAll> page = new Page<ImMsgRecordAll>(pageNo, pageSize);
|
||||
IPage<ImMsgRecordAll> pageList = imMsgRecordAllService.page(page, queryWrapper);
|
||||
return Result.OK(pageList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*
|
||||
* @param imMsgRecordAll
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "im_msg_record_all-添加")
|
||||
@Operation(summary = "im_msg_record_all-添加", description = "im_msg_record_all-添加")
|
||||
@RequiresPermissions("com.renkang.im:im_msg_record_all:add")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<String> add(@RequestBody ImMsgRecordAll imMsgRecordAll) {
|
||||
imMsgRecordAllService.save(imMsgRecordAll);
|
||||
return Result.OK("添加成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*
|
||||
* @param imMsgRecordAll
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "im_msg_record_all-编辑")
|
||||
@Operation(summary = "im_msg_record_all-编辑", description = "im_msg_record_all-编辑")
|
||||
@RequiresPermissions("com.renkang.im:im_msg_record_all:edit")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<String> edit(@RequestBody ImMsgRecordAll imMsgRecordAll) {
|
||||
imMsgRecordAllService.updateById(imMsgRecordAll);
|
||||
return Result.OK("编辑成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id删除
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "im_msg_record_all-通过id删除")
|
||||
@Operation(summary = "im_msg_record_all-通过id删除", description = "im_msg_record_all-通过id删除")
|
||||
@RequiresPermissions("com.renkang.im:im_msg_record_all:delete")
|
||||
@DeleteMapping(value = "/delete")
|
||||
public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
|
||||
imMsgRecordAllService.removeById(id);
|
||||
return Result.OK("删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@AutoLog(value = "im_msg_record_all-批量删除")
|
||||
@Operation(summary = "im_msg_record_all-批量删除", description = "im_msg_record_all-批量删除")
|
||||
@RequiresPermissions("com.renkang.im:im_msg_record_all:deleteBatch")
|
||||
@DeleteMapping(value = "/deleteBatch")
|
||||
public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
|
||||
this.imMsgRecordAllService.removeByIds(Arrays.asList(ids.split(",")));
|
||||
return Result.OK("批量删除成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id查询
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
//@AutoLog(value = "im_msg_record_all-通过id查询")
|
||||
@Operation(summary = "im_msg_record_all-通过id查询", description = "im_msg_record_all-通过id查询")
|
||||
@GetMapping(value = "/queryById")
|
||||
public Result<ImMsgRecordAll> queryById(@RequestParam(name = "id", required = true) String id) {
|
||||
ImMsgRecordAll imMsgRecordAll = imMsgRecordAllService.getById(id);
|
||||
if (imMsgRecordAll == null) {
|
||||
return Result.error("未找到对应数据");
|
||||
}
|
||||
return Result.OK(imMsgRecordAll);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出excel
|
||||
*
|
||||
* @param request
|
||||
* @param imMsgRecordAll
|
||||
*/
|
||||
@RequiresPermissions("com.renkang.im:im_msg_record_all:exportXls")
|
||||
@RequestMapping(value = "/exportXls")
|
||||
public ModelAndView exportXls(HttpServletRequest request, ImMsgRecordAll imMsgRecordAll) {
|
||||
return super.exportXls(request, imMsgRecordAll, ImMsgRecordAll.class, "im_msg_record_all");
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过excel导入数据
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@RequiresPermissions("com.renkang.im:im_msg_record_all:importExcel")
|
||||
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
|
||||
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
|
||||
return super.importExcel(request, response, ImMsgRecordAll.class);
|
||||
}
|
||||
|
||||
@Operation(summary = "通话时长")
|
||||
@GetMapping(value = "/queryTimeDifferenz")
|
||||
public Result<List<Map<Object, Object>>> queryTimeDifferenz(@RequestParam(name = "groupId") String groupId) {
|
||||
List<ImMsgRecordAll> imMsgRecordAlls = imMsgRecordAllService.getImMsgRecordAll(groupId);
|
||||
if (CollectionUtil.isEmpty(imMsgRecordAlls)) {
|
||||
return Result.error("未找到对应数据");
|
||||
}
|
||||
List<Map<Object, Object>> mapList = new ArrayList<>();
|
||||
Map<Object, Object> hashMap = new HashMap<>();
|
||||
imMsgRecordAlls.forEach(imMsgRecordAll -> {
|
||||
hashMap.put("sendtime", imMsgRecordAll.getSendtime());
|
||||
hashMap.put("endTime", imMsgRecordAll.getEndTime());
|
||||
hashMap.put("timeDifferenz", imMsgRecordAll.getEndTime().getTime() - imMsgRecordAll.getSendtime().getTime());
|
||||
mapList.add(hashMap);
|
||||
});
|
||||
return Result.OK(mapList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
package com.renkang.im.controller;
|
||||
|
||||
import com.alibaba.druid.util.StringUtils;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.renkang.consultation.api.ConSessionHelloApi;
|
||||
import com.renkang.consultation.entity.ConSessionDO;
|
||||
import com.renkang.im.entity.*;
|
||||
import com.renkang.im.service.IImMsgRecordAllService;
|
||||
import com.renkang.im.util.IdWorker;
|
||||
import com.renkang.im.util.TencentCloudImUtil;
|
||||
import com.renkang.im.util.UniqId;
|
||||
import com.renkang.im.entity.ImMsgRecordAll;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.system.vo.LoginUserNew;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.controller.TXController
|
||||
* @description: 腾讯IM实时对话
|
||||
* @User jinbo
|
||||
* @create: 2023-04-21 15:44
|
||||
* @Version 1.0
|
||||
**/
|
||||
@RestController
|
||||
@RequestMapping("/wnapp")
|
||||
@Tag(name = "腾讯IM实时对话")
|
||||
public class TXController {
|
||||
@Value("${IMConfig.sdkAppId}")
|
||||
private long sdkAppId;
|
||||
@Value("${IMConfig.secretKey}")
|
||||
private String secretKey;
|
||||
|
||||
@Autowired
|
||||
private TencentCloudImUtil tencentCloudImUtil;
|
||||
|
||||
@Autowired
|
||||
private IImMsgRecordAllService imMsgRecordAllService;
|
||||
|
||||
@Autowired
|
||||
private ISysBaseAPI iSysBaseAPI;
|
||||
|
||||
@Value("${IMConfig.headUrl}")
|
||||
private String headUrl;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ConSessionHelloApi conSessionHelloApi;
|
||||
|
||||
|
||||
|
||||
@GetMapping("/userSigAndroid")
|
||||
@Operation(summary = "获取userSigAndroid")
|
||||
public Result<Map> userSigAndroid() {
|
||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||
Map hashMap = new HashMap<>();
|
||||
String userSig = tencentCloudImUtil.userSigAndroid(sysUser.getId());
|
||||
|
||||
hashMap.put("userSig", userSig);
|
||||
hashMap.put("userId", sysUser.getId());
|
||||
hashMap.put("sdkAppId", String.valueOf(sdkAppId));
|
||||
return Result.OK(hashMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉取群组消息 v1
|
||||
* @param groupId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/groupMessageV1")
|
||||
@Operation(summary = "查询群聊消息")
|
||||
public String groupMessageV1(String groupId) {
|
||||
|
||||
Integer MsgSeq = null;
|
||||
boolean haveData = true;
|
||||
while(haveData){
|
||||
String s = tencentCloudImUtil.groupMessage(groupId,1,MsgSeq,0);
|
||||
JSONObject jsonObjectResult = JSONObject.parseObject(s);
|
||||
JSONArray rsqMsgList = jsonObjectResult.getJSONArray("RspMsgList");
|
||||
if(CollectionUtils.isEmpty(rsqMsgList)){
|
||||
haveData = false;
|
||||
break;
|
||||
}
|
||||
JSONObject one = rsqMsgList.getJSONObject(0);
|
||||
MsgSeq = one.getInteger("MsgSeq")+1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/groupMessage")
|
||||
@Operation(summary = "查询群聊消息")
|
||||
public Result<String> groupMessage() {
|
||||
|
||||
Result<List<ConSessionDO>> resultList = conSessionHelloApi.sekectSessionListByDate();
|
||||
|
||||
if(resultList.isSuccess()){
|
||||
|
||||
List<ConSessionDO> list = resultList.getResult();
|
||||
for (ConSessionDO conSessionDO : list) {
|
||||
boolean flag = true;
|
||||
Integer MsgSeq = null;
|
||||
while(flag){
|
||||
|
||||
if(MsgSeq != null && MsgSeq < 0){
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
String s = tencentCloudImUtil.groupMessage(conSessionDO.getImId(),1,MsgSeq,0);
|
||||
if(StringUtils.isEmpty(s)){
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
JSONObject jsonObjectResult = JSONObject.parseObject(s);
|
||||
JSONArray rsqMsgList = jsonObjectResult.getJSONArray("RspMsgList");
|
||||
if(CollectionUtils.isEmpty(rsqMsgList)){
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
JSONObject one = rsqMsgList.getJSONObject(0);
|
||||
Integer MsgSeqOne = one.getInteger("MsgSeq");
|
||||
|
||||
JSONArray msgBody = one.getJSONArray("MsgBody");
|
||||
JSONObject msgBodyOne = msgBody.getJSONObject(0);
|
||||
String msgType = msgBodyOne.getString("MsgType");
|
||||
if ("TIMImageElem".equalsIgnoreCase(msgType)) {
|
||||
System.out.println("进来了----------------------------------------------------------");
|
||||
List<String> imageList = new ArrayList<>();
|
||||
JSONObject MsgContent = msgBodyOne.getJSONObject("MsgContent");
|
||||
|
||||
JSONArray ImageInfoArray = MsgContent.getJSONArray("ImageInfoArray");
|
||||
for (Object o : ImageInfoArray) {
|
||||
JSONObject AA = (JSONObject)o;
|
||||
String oldUrl = AA.getString("URL");
|
||||
String newUrl = "";
|
||||
if(oldUrl.contains("https://cn.imrich.qcloud.com")){
|
||||
newUrl = oldUrl.replace("https://cn.imrich.qcloud.com", "http://101.201.149.156:8609/qc");
|
||||
}
|
||||
if(oldUrl.contains("https://cos.ap-guangzhou.myqcloud.com")){
|
||||
newUrl = oldUrl.replace("https://cos.ap-guangzhou.myqcloud.com", "http://101.201.149.156:8609/gmc");
|
||||
}
|
||||
if(oldUrl.contains("https://cn.rich.my-imcloud.com")){
|
||||
newUrl = oldUrl.replace("https://cn.rich.my-imcloud.com", "http://101.201.149.156:8609/ic");
|
||||
}
|
||||
if(oldUrl.contains("https://cos.ap-shanghai.myqcloud.com")){
|
||||
newUrl = oldUrl.replace("https://cos.ap-shanghai.myqcloud.com", "http://101.201.149.156:8609/smc");
|
||||
}
|
||||
if(oldUrl.contains("https://cos.ap-shanghai.tencentcos.cn")){
|
||||
newUrl = oldUrl.replace("https://cos.ap-shanghai.tencentcos.cn", " http://101.201.149.156:8609/tc");
|
||||
}
|
||||
if(!StringUtils.isEmpty(newUrl)){
|
||||
imageList.add(newUrl);
|
||||
}
|
||||
}
|
||||
Map<String,String> msgBodyMap = tencentCloudImUtil.changeUrelArray(imageList, msgType);
|
||||
for (Map.Entry<String, String> entry : msgBodyMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
s=s.replace(key,value);
|
||||
}
|
||||
}
|
||||
|
||||
ImMsgRecordAll imMsgRecordAll = new ImMsgRecordAll();
|
||||
imMsgRecordAll.setId(UniqId.getInstanceWithLog().getUniqID());
|
||||
imMsgRecordAll.setGroupid(jsonObjectResult.get("GroupId").toString());
|
||||
Date date = new Date();
|
||||
date.setTime(Long.parseLong(one.get("MsgTimeStamp").toString()) * 1000);
|
||||
imMsgRecordAll.setSendtime(date);
|
||||
imMsgRecordAll.setFromAccount(one.get("From_Account").toString());
|
||||
imMsgRecordAll.setMsgcontent(s);
|
||||
imMsgRecordAll.setMsgseq(MsgSeqOne);
|
||||
imMsgRecordAll.setMsgtype("2");
|
||||
imMsgRecordAll.setCreateTime(date);
|
||||
flag = imMsgRecordAllService.save(imMsgRecordAll);
|
||||
MsgSeq = MsgSeqOne-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result.OK();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 单发单聊消息
|
||||
*
|
||||
* @param syncOtherMachine 是否同步消息到发送方(1-同步,2-不同步)
|
||||
* @param fromUserId 发送方用户id
|
||||
* @param toUserId 接收方用户id
|
||||
* @param msgType 消息对象类型 TIMTextElem 文本消息 TIMLocationElem 位置消息 TIMFaceElem 表情消息 TIMCustomElem 自定义消息 TIMSoundElem 语音消息 TIMImageElem 图像消息 TIMFileElem 文件消息 TIMVideoFileElem 视频消息
|
||||
* @param msgContent 消息内容
|
||||
*/
|
||||
@GetMapping("/sendMsg")
|
||||
@Operation(summary = "单发单聊消息")
|
||||
public String sendMsg(Integer syncOtherMachine, String fromUserId, String toUserId, String msgType, String msgContent) {
|
||||
|
||||
String sendMsg = tencentCloudImUtil.sendMsg(syncOtherMachine, fromUserId, toUserId, msgType, msgContent);
|
||||
System.out.println(sendMsg);
|
||||
return sendMsg;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/sendSysMsg")
|
||||
@Operation(summary = "发送群聊系统消息")
|
||||
public IMBaseDO sendSysMsg(String groupId, String msgContent) {
|
||||
|
||||
IMBaseDO iMBaseDO = tencentCloudImUtil.sendGroupNotify(groupId, msgContent);
|
||||
|
||||
return iMBaseDO;
|
||||
}
|
||||
|
||||
@GetMapping("/sendGroupNotifyToUser")
|
||||
@Operation(summary = "发送群聊系统消息")
|
||||
public IMBaseDO sendGroupNotifyToUser(@RequestParam("groupId") String groupId, @RequestParam("userIds") List<String> userIds, @RequestParam("msgContent") String msgContent) {
|
||||
|
||||
IMBaseDO iMBaseDO = tencentCloudImUtil.sendGroupNotifyToUser(groupId, userIds, msgContent);
|
||||
|
||||
return iMBaseDO;
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "用户发送群消息", description = "用户发送群消息")
|
||||
@PostMapping("/sendGroupMsg")
|
||||
public IMGroupMsgResDO sendGroupMsg(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO) {
|
||||
|
||||
return tencentCloudImUtil.sendGroupMsgText(imGroupMsgTextReqDO);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "用户发送群消息", description = "用户发送群消息")
|
||||
@PostMapping("/sendGroupMsgTextNew")
|
||||
public IMGroupMsgResDO sendGroupMsgTextNew(@RequestBody @Validated ImGroupMsgTextReqDO imGroupMsgTextReqDO) {
|
||||
|
||||
return tencentCloudImUtil.sendGroupMsgTextNew(imGroupMsgTextReqDO);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/accountReg")
|
||||
@Operation(summary = "注册账号")
|
||||
public Result<String> accountReg(@RequestBody ConSessionRequestDO conSessionRequestDO) {
|
||||
|
||||
for (LoginUserNew loginUser : conSessionRequestDO.getAccountList()) {
|
||||
|
||||
if (loginUser != null) {
|
||||
String personType = loginUser.getPersonType();
|
||||
String aa = "";
|
||||
if (StringUtils.equals(personType, "2")) {
|
||||
aa = "(小助手)";
|
||||
}
|
||||
if (StringUtils.equals(personType, "3")) {
|
||||
aa = "(专家)";
|
||||
}
|
||||
String auatr = loginUser.getAvatar();
|
||||
if(!StringUtils.isEmpty(auatr)){
|
||||
auatr = auatr.replace("\\","/");
|
||||
auatr = encodeChineseCharacters(headUrl + auatr);
|
||||
}else{
|
||||
auatr = "";
|
||||
}
|
||||
tencentCloudImUtil.accountImport(loginUser.getId(), loginUser.getRealname() + aa, auatr);
|
||||
}
|
||||
}
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "创建群聊-应急")
|
||||
@PostMapping(value = "/creatGroupMagNew")
|
||||
public Result<Map<String, Object>> creatGroupMagNew(@RequestBody ConSessionRequestDO conSessionRequestDO) {
|
||||
String Owner_Account = "administrator";
|
||||
String Type = "Public";
|
||||
String GroupId = String.valueOf(new IdWorker(0, 1).nextId());
|
||||
|
||||
|
||||
List<String> idList = conSessionRequestDO.getAccountList().stream()
|
||||
.map(LoginUserNew::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
String rst = tencentCloudImUtil.multiAccountImport(idList);
|
||||
|
||||
for (LoginUserNew loginUser : conSessionRequestDO.getAccountList()) {
|
||||
|
||||
if (loginUser != null) {
|
||||
|
||||
String personType = loginUser.getPersonType();
|
||||
String aa = "";
|
||||
if (StringUtils.equals(personType, "2")) {
|
||||
aa = "(小助手)";
|
||||
}
|
||||
if (StringUtils.equals(personType, "3")) {
|
||||
aa = "(专家)";
|
||||
}
|
||||
String auatr = loginUser.getAvatar();
|
||||
if(!StringUtils.isEmpty(auatr)){
|
||||
auatr = auatr.replace("\\","/");
|
||||
auatr = encodeChineseCharacters(headUrl + auatr);
|
||||
}else{
|
||||
auatr = "";
|
||||
}
|
||||
tencentCloudImUtil.accountImport(loginUser.getId(), loginUser.getRealname() + aa, auatr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!JSONObject.parseObject(rst).get("ErrorCode").equals(0)) {
|
||||
Result.error("账号导入错误!");
|
||||
}
|
||||
List<Map<String, String>> groupList = new ArrayList();
|
||||
conSessionRequestDO.getAccountList().forEach(x -> {
|
||||
Map<String, String> hashMap = new HashMap();
|
||||
hashMap.put("Member_Account", x.getId());
|
||||
groupList.add(hashMap);
|
||||
});
|
||||
|
||||
String result = tencentCloudImUtil.creatGroup(Owner_Account, Type, GroupId, conSessionRequestDO.getName() + "_" + DateUtils.getCurrentTimestamp(), groupList);
|
||||
if (!JSONObject.parseObject(result).get("ErrorCode").equals(0)) {
|
||||
return Result.error("创建群聊失败!");
|
||||
}
|
||||
Map res = new HashMap<>();
|
||||
res.put("userId", conSessionRequestDO.getUserId());
|
||||
res.put("groupId", GroupId);
|
||||
res.put("resultcAccountImport", rst);
|
||||
res.put("resultcCreateGroup", result);
|
||||
return Result.OK(res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Operation(summary = "创建群聊-应急")
|
||||
@PostMapping(value = "/creatGroupMagNewHelper")
|
||||
public Result<Map<String, Object>> creatGroupMagNewHelper(@RequestBody ConSessionRequestDO conSessionRequestDO) {
|
||||
String Owner_Account = "administrator";
|
||||
String Type = "Public";
|
||||
String GroupId = String.valueOf(new IdWorker(0, 1).nextId());
|
||||
|
||||
|
||||
List<String> idList = conSessionRequestDO.getAccountList().stream()
|
||||
.map(LoginUserNew::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
String rst = tencentCloudImUtil.multiAccountImport(idList);
|
||||
|
||||
for (LoginUserNew loginUser : conSessionRequestDO.getAccountList()) {
|
||||
|
||||
if (loginUser != null) {
|
||||
String auatr = loginUser.getAvatar();
|
||||
if(!StringUtils.isEmpty(auatr)){
|
||||
auatr = auatr.replace("\\","/");
|
||||
auatr = encodeChineseCharacters(headUrl + auatr);
|
||||
}else{
|
||||
auatr = "";
|
||||
}
|
||||
tencentCloudImUtil.accountImport(loginUser.getId(), loginUser.getRealname(), auatr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!JSONObject.parseObject(rst).get("ErrorCode").equals(0)) {
|
||||
Result.error("账号导入错误!");
|
||||
}
|
||||
List<Map<String, String>> groupList = new ArrayList();
|
||||
conSessionRequestDO.getAccountList().forEach(x -> {
|
||||
Map<String, String> hashMap = new HashMap();
|
||||
hashMap.put("Member_Account", x.getId());
|
||||
groupList.add(hashMap);
|
||||
});
|
||||
|
||||
String result = tencentCloudImUtil.creatGroup(Owner_Account, Type, GroupId, conSessionRequestDO.getName() + "_" + DateUtils.getCurrentTimestamp(), groupList);
|
||||
if (!JSONObject.parseObject(result).get("ErrorCode").equals(0)) {
|
||||
return Result.error("创建群聊失败!");
|
||||
}
|
||||
Map res = new HashMap<>();
|
||||
res.put("userId", conSessionRequestDO.getUserId());
|
||||
res.put("groupId", GroupId);
|
||||
res.put("resultcAccountImport", rst);
|
||||
res.put("resultcCreateGroup", result);
|
||||
return Result.OK(res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private String encodeChineseCharacters(String str) {
|
||||
return str.codePoints()
|
||||
.mapToObj(c -> {
|
||||
try {
|
||||
String charStr = new String(Character.toChars(c));
|
||||
return charStr.matches("[\\u4E00-\\u9FA5]")
|
||||
? URLEncoder.encode(charStr, "UTF-8")
|
||||
: charStr;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
.collect(Collectors.joining());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.renkang.im.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.renkang.im.entity.ImMsgRecordAll;
|
||||
import com.renkang.im.service.IImMsgRecordAllService;
|
||||
import com.renkang.im.service.ImService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/txImMessage")
|
||||
public class TxImMessageConTroller {
|
||||
|
||||
@Autowired
|
||||
private IImMsgRecordAllService imMsgRecordAllService;
|
||||
@Autowired
|
||||
private ImService imService;
|
||||
|
||||
|
||||
/**
|
||||
* 查询im消息列表
|
||||
*
|
||||
* @param sessionId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/selectImMessageList")
|
||||
@Operation(summary = "获取消息列表")
|
||||
public Result<List<ImMsgRecordAll>> selectImMessageList(@RequestParam("sessionId") String sessionId) {
|
||||
return imMsgRecordAllService.selectImMessageList(sessionId);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/selectImMessagePageList")
|
||||
@Operation(summary = "获取消息列表")
|
||||
public Result<Page<ImMsgRecordAll>> selectImMessagePageList(@RequestParam("groupId") String groupId,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
|
||||
return imMsgRecordAllService.selectImMessagePageList(groupId, pageNo, pageSize);
|
||||
}
|
||||
|
||||
@GetMapping("/syncImMessage")
|
||||
public Result<Void> test(String groupId) {
|
||||
imService.syncGroupHistory(groupId);
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.FileMsgContent
|
||||
* @description: 文件对象
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 11:31
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class FileMsgContent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonProperty(value = "Download_Flag")
|
||||
@JSONField(name = "Download_Flag")
|
||||
private Integer Download_Flag;
|
||||
|
||||
@JsonProperty(value = "FileName")
|
||||
@JSONField(name = "FileName")
|
||||
private String FileName;
|
||||
|
||||
@JsonProperty(value = "Url")
|
||||
@JSONField(name = "Url")
|
||||
private String Url;
|
||||
|
||||
@JsonProperty(value = "UUID")
|
||||
@JSONField(name = "UUID")
|
||||
private String UUID;
|
||||
|
||||
@JsonProperty(value = "FileSize")
|
||||
@JSONField(name = "FileSize")
|
||||
private Long FileSize;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImCusArchivesCard
|
||||
* @description: TODO 档案
|
||||
* @User jinbo
|
||||
* @create: 2023-05-18 18:15
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImCusArchivesCard implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* businessID : archives
|
||||
* gender : 男
|
||||
* age : 35
|
||||
* imageList : [{"bigImageUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7","imageViewHeight":0,"imageViewWidth":0,"imageViewX":0,"imageViewY":0,"thumbnailUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7"},{"bigImageUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7","imageViewHeight":0,"imageViewWidth":0,"imageViewX":0,"imageViewY":0,"thumbnailUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7"},{"bigImageUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7","imageViewHeight":0,"imageViewWidth":0,"imageViewX":0,"imageViewY":0,"thumbnailUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7"},{"bigImageUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7","imageViewHeight":0,"imageViewWidth":0,"imageViewX":0,"imageViewY":0,"thumbnailUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7"},{"bigImageUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7","imageViewHeight":0,"imageViewWidth":0,"imageViewX":0,"imageViewY":0,"thumbnailUrl":"https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7"}]
|
||||
* name : 张三
|
||||
* symptomDescription : 常我不气,该去医院看看了
|
||||
* downloadStatus : 0
|
||||
* isGroup : false
|
||||
* msgTime : 0
|
||||
* status : 0
|
||||
* translationStatus : 0
|
||||
*/
|
||||
@JsonProperty(value = "businessID")
|
||||
@JSONField(name = "businessID")
|
||||
private String businessID;
|
||||
@JsonProperty(value = "gender")
|
||||
@JSONField(name = "gender")
|
||||
private String gender;
|
||||
@JsonProperty(value = "age")
|
||||
@JSONField(name = "age")
|
||||
private int age;
|
||||
@JsonProperty(value = "name")
|
||||
@JSONField(name = "name")
|
||||
private String name;
|
||||
@JsonProperty(value = "symptomDescription")
|
||||
@JSONField(name = "symptomDescription")
|
||||
private String symptomDescription;
|
||||
@JsonProperty(value = "downloadStatus")
|
||||
@JSONField(name = "downloadStatus")
|
||||
private int downloadStatus;
|
||||
@JsonProperty(value = "isGroup")
|
||||
@JSONField(name = "isGroup")
|
||||
private boolean isGroup;
|
||||
@JsonProperty(value = "msgTime")
|
||||
@JSONField(name = "msgTime")
|
||||
private int msgTime;
|
||||
@JsonProperty(value = "status")
|
||||
@JSONField(name = "status")
|
||||
private int status;
|
||||
@JsonProperty(value = "translationStatus")
|
||||
@JSONField(name = "translationStatus")
|
||||
private int translationStatus;
|
||||
@JsonProperty(value = "imageList")
|
||||
@JSONField(name = "imageList")
|
||||
private List<ImageListBean> imageList;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @@InterfaceName com.renkang.im.entity.ImCardDoctor
|
||||
* @description: TODO 医生名片
|
||||
* @User jinbo
|
||||
* @create: 2023-05-18 17:57
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImCusDoctorCard implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* businessID : business_card
|
||||
* doctorHeadImg : https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7
|
||||
* doctorName : 张医生
|
||||
* organization : 协和医院
|
||||
* version : 0
|
||||
* downloadStatus : 0
|
||||
* isGroup : false
|
||||
* msgTime : 0
|
||||
* status : 0
|
||||
* translationStatus : 0
|
||||
*/
|
||||
@JsonProperty(value = "businessID")
|
||||
@JSONField(name = "businessID")
|
||||
private String businessID;
|
||||
@JsonProperty(value = "doctorHeadImg")
|
||||
@JSONField(name = "doctorHeadImg")
|
||||
private String doctorHeadImg;
|
||||
@JsonProperty(value = "doctorName")
|
||||
@JSONField(name = "doctorName")
|
||||
private String doctorName;
|
||||
@JsonProperty(value = "organization")
|
||||
@JSONField(name = "organization")
|
||||
private String organization;
|
||||
@JsonProperty(value = "version")
|
||||
@JSONField(name = "version")
|
||||
private int version;
|
||||
@JsonProperty(value = "downloadStatus")
|
||||
@JSONField(name = "downloadStatus")
|
||||
private int downloadStatus;
|
||||
@JsonProperty(value = "isGroup")
|
||||
@JSONField(name = "isGroup")
|
||||
private boolean isGroup;
|
||||
@JsonProperty(value = "msgTime")
|
||||
@JSONField(name = "msgTime")
|
||||
private int msgTime;
|
||||
@JsonProperty(value = "status")
|
||||
@JSONField(name = "status")
|
||||
private int status;
|
||||
@JsonProperty(value = "translationStatus")
|
||||
@JSONField(name = "translationStatus")
|
||||
private int translationStatus;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImCusEvaluate
|
||||
* @description: TODO 自定义评价
|
||||
* @User jinbo
|
||||
* @create: 2023-05-18 18:08
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImCusEvaluationCard implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* businessID : evaluation
|
||||
* comment : 对本次服务评价
|
||||
* score : 2
|
||||
* version : 0
|
||||
*/
|
||||
@JsonProperty(value = "businessID")
|
||||
@JSONField(name = "businessID")
|
||||
private String businessID;
|
||||
@JsonProperty(value = "comment")
|
||||
@JSONField(name = "comment")
|
||||
private String comment;
|
||||
@JsonProperty(value = "score")
|
||||
@JSONField(name = "score")
|
||||
private int score;
|
||||
@JsonProperty(value = "version")
|
||||
@JSONField(name = "version")
|
||||
private int version;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImCusMedicalCard
|
||||
* @description: TODO 体检报告
|
||||
* @User jinbo
|
||||
* @create: 2023-05-18 18:11
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImCusMedicalCard implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* businessID : medical_examination_report
|
||||
* age : 30
|
||||
* createTime : 2022.12.16
|
||||
* gender : 女
|
||||
* hospital : 第二人民医院
|
||||
* name : 李四
|
||||
* downloadStatus : 0
|
||||
* isGroup : false
|
||||
* msgTime : 0
|
||||
* status : 0
|
||||
* translationStatus : 0
|
||||
*/
|
||||
@JsonProperty(value = "businessID")
|
||||
@JSONField(name = "businessID")
|
||||
private String businessID;
|
||||
@JsonProperty(value = "age")
|
||||
@JSONField(name = "age")
|
||||
private int age;
|
||||
@JsonProperty(value = "createTime")
|
||||
@JSONField(name = "createTime")
|
||||
private String createTime;
|
||||
@JsonProperty(value = "gender")
|
||||
@JSONField(name = "gender")
|
||||
private String gender;
|
||||
@JsonProperty(value = "hospital")
|
||||
@JSONField(name = "hospital")
|
||||
private String hospital;
|
||||
@JsonProperty(value = "name")
|
||||
@JSONField(name = "name")
|
||||
private String name;
|
||||
@JsonProperty(value = "downloadStatus")
|
||||
@JSONField(name = "downloadStatus")
|
||||
private int downloadStatus;
|
||||
@JsonProperty(value = "isGroup")
|
||||
@JSONField(name = "isGroup")
|
||||
private boolean isGroup;
|
||||
@JsonProperty(value = "msgTime")
|
||||
@JSONField(name = "msgTime")
|
||||
private int msgTime;
|
||||
@JsonProperty(value = "status")
|
||||
@JSONField(name = "status")
|
||||
private int status;
|
||||
@JsonProperty(value = "translationStatus")
|
||||
@JSONField(name = "translationStatus")
|
||||
private int translationStatus;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImCustom
|
||||
* @description: TODO 自定义卡片
|
||||
* @User jinbo
|
||||
* @create: 2023-05-18 17:52
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImCustom<T> implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Data :
|
||||
* Desc : 张医生
|
||||
* Ext : 名片
|
||||
* Sound :
|
||||
*/
|
||||
@JsonProperty(value = "Desc")
|
||||
@JSONField(name = "Desc")
|
||||
private String Desc;
|
||||
@JsonProperty(value = "Ext")
|
||||
@JSONField(name = "Ext")
|
||||
private String Ext;
|
||||
@JsonProperty(value = "Sound")
|
||||
@JSONField(name = "Sound")
|
||||
private String Sound;
|
||||
@JsonProperty(value = "Data")
|
||||
@JSONField(name = "Data")
|
||||
private T Data;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImMsgBody
|
||||
* @description: 消息列表对象
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 11:26
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImMsgBody<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(title = "消息的发送者")
|
||||
@JsonProperty(value = "From_Account")
|
||||
@JSONField(name = "From_Account")
|
||||
private String From_Account;
|
||||
|
||||
@Schema(title = "消息的接收者")
|
||||
@JsonProperty(value = "To_Account")
|
||||
@JSONField(name = "To_Account")
|
||||
private String To_Account;
|
||||
|
||||
@Schema(title = "消息 seq,用于标识唯一消息,值越小发送的越早")
|
||||
@JsonProperty(value = "MsgSeq")
|
||||
@JSONField(name = "MsgSeq")
|
||||
private int MsgSeq;
|
||||
|
||||
@Schema(title = "消息随机值,用于对消息去重")
|
||||
@JsonProperty(value = "MsgRandom")
|
||||
@JSONField(name = "MsgRandom")
|
||||
private int MsgRandom;
|
||||
|
||||
@Schema(title = "消息被发送的时间戳,server 的时间")
|
||||
@JsonProperty(value = "MsgTimeStamp")
|
||||
@JSONField(name = "MsgTimeStamp")
|
||||
private int MsgTimeStamp;
|
||||
|
||||
@Schema(title = "消息被发送的时间戳,client 的时间")
|
||||
@JsonProperty(value = "MsgClientTime")
|
||||
@JSONField(name = "MsgClientTime")
|
||||
private int MsgClientTime;
|
||||
|
||||
@Schema(title = "该条消息的属性,0表示正常消息,8表示被撤回的消息")
|
||||
@JsonProperty(value = "MsgFlagBits")
|
||||
@JSONField(name = "MsgFlagBits")
|
||||
private int MsgFlagBits;
|
||||
|
||||
@Schema(title = "消息接收方是否发送该条消息的已读回执。0表示未发送,1表示已发送,详情可参考本接口的功能说明。")
|
||||
@JsonProperty(value = "IsPeerRead")
|
||||
@JSONField(name = "IsPeerRead")
|
||||
private int IsPeerRead;
|
||||
|
||||
@Schema(title = "")
|
||||
@JsonProperty(value = "IsNeedReadReceipt")
|
||||
@JSONField(name = "IsNeedReadReceipt")
|
||||
private int IsNeedReadReceipt;
|
||||
|
||||
@Schema(title = "")
|
||||
@JsonProperty(value = "SupportMessageExtension")
|
||||
@JSONField(name = "SupportMessageExtension")
|
||||
private int SupportMessageExtension;
|
||||
|
||||
@Schema(title = "标识该条消息,可用于 REST API 撤回单聊消息")
|
||||
@JsonProperty(value = "MsgKey")
|
||||
@JSONField(name = "MsgKey")
|
||||
private String MsgKey;
|
||||
|
||||
@Schema(title = "消息版本")
|
||||
@JsonProperty(value = "MsgVersion")
|
||||
@JSONField(name = "MsgVersion")
|
||||
private int MsgVersion;
|
||||
|
||||
@Schema(title = "消息内容")
|
||||
@JsonProperty(value = "MsgBody")
|
||||
@JSONField(name = "MsgBody")
|
||||
private T MsgBody;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImPosition
|
||||
* @description: 位置
|
||||
* @User jinbo
|
||||
* @create: 2023-05-18 17:33
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImPosition implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* Desc : someinfo
|
||||
* Latitude : 29.340656774469956
|
||||
* Longitude : 116.77497920478824
|
||||
*/
|
||||
@JsonProperty(value = "Desc")
|
||||
@JSONField(name = "Desc")
|
||||
private String Desc;
|
||||
|
||||
@JsonProperty(value = "Latitude")
|
||||
@JSONField(name = "Latitude")
|
||||
private double Latitude;
|
||||
|
||||
@JsonProperty(value = "Longitude")
|
||||
@JSONField(name = "Longitude")
|
||||
private double Longitude;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImResult
|
||||
* @description: 消息结果
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 09:54
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImResult implements Serializable {
|
||||
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(title = "请求处理的结果,OK 表示处理成功,FAIL 表示失败")
|
||||
@JsonProperty(value = "ActionStatus")
|
||||
@JSONField(name = "ActionStatus")
|
||||
private String ActionStatus;
|
||||
|
||||
|
||||
@Schema(title = "错误码,0表示成功,非0表示失败")
|
||||
@JsonProperty(value = "ErrorCode")
|
||||
@JSONField(name = "ErrorCode")
|
||||
private String ErrorCode;
|
||||
|
||||
@Schema(title = "错误信息")
|
||||
@JsonProperty(value = "ErrorInfo")
|
||||
@JSONField(name = "ErrorInfo")
|
||||
private int ErrorInfo;
|
||||
|
||||
@Schema(title = "是否全部拉取,0表示未全部拉取,需要续拉,1表示已全部拉取")
|
||||
@JsonProperty(value = "Complete")
|
||||
@JSONField(name = "Complete")
|
||||
private int Complete;
|
||||
|
||||
@Schema(title = "本次拉取到的消息条数")
|
||||
@JsonProperty(value = "MsgCnt")
|
||||
@JSONField(name = "MsgCnt")
|
||||
private int MsgCnt;
|
||||
|
||||
@Schema(title = "本次拉取到的消息里的最后一条消息的时间")
|
||||
@JsonProperty(value = "LastMsgTime")
|
||||
@JSONField(name = "LastMsgTime")
|
||||
private int LastMsgTime;
|
||||
|
||||
@Schema(title = "本次拉取到的消息里的最后一条消息的标识")
|
||||
@JsonProperty(value = "LastMsgKey")
|
||||
@JSONField(name = "LastMsgKey")
|
||||
private String LastMsgKey;
|
||||
|
||||
@Schema(title = "返回的消息列表")
|
||||
@JsonProperty(value = "MsgList")
|
||||
@JSONField(name = "MsgList")
|
||||
private List<ImMsgBody> MsgList;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImEvaluate
|
||||
* @description: TODO 系统评价
|
||||
* @User jinbo
|
||||
* @create: 2023-05-18 17:41
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImSysEvaluate implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* businessID : system
|
||||
* content : 本次咨询已结束,请对本次服务进行评价!
|
||||
* messageImageUrl : https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7
|
||||
* type : 0
|
||||
* downloadStatus : 0
|
||||
* isGroup : false
|
||||
* msgTime : 0
|
||||
* status : 0
|
||||
* translationStatus : 0
|
||||
*/
|
||||
@JsonProperty(value = "businessID")
|
||||
@JSONField(name = "businessID")
|
||||
private String businessID;
|
||||
@JsonProperty(value = "content")
|
||||
@JSONField(name = "content")
|
||||
private String content;
|
||||
@JsonProperty(value = "messageImageUrl")
|
||||
@JSONField(name = "messageImageUrl")
|
||||
private String messageImageUrl;
|
||||
@JsonProperty(value = "Type")
|
||||
@JSONField(name = "Type")
|
||||
private int type;
|
||||
@JsonProperty(value = "downloadStatus")
|
||||
@JSONField(name = "downloadStatus")
|
||||
private int downloadStatus;
|
||||
@JsonProperty(value = "isGroup")
|
||||
@JSONField(name = "isGroup")
|
||||
private boolean isGroup;
|
||||
@JsonProperty(value = "msgTime")
|
||||
@JSONField(name = "msgTime")
|
||||
private int msgTime;
|
||||
@JsonProperty(value = "status")
|
||||
@JSONField(name = "status")
|
||||
private int status;
|
||||
@JsonProperty(value = "translationStatus")
|
||||
@JSONField(name = "translationStatus")
|
||||
private int translationStatus;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImageListBean
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-05-18 18:39
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImageListBean implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
/**
|
||||
* bigImageUrl : https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7
|
||||
* imageViewHeight : 0
|
||||
* imageViewWidth : 0
|
||||
* imageViewX : 0
|
||||
* imageViewY : 0
|
||||
* thumbnailUrl : https://tse2-mm.cn.bing.net/th/id/OIP-C.7o7kx5xj-SejpCy3GGUazgHaEK?w=288&h=180&c=7&r=0&o=5&pid=1.7
|
||||
*/
|
||||
@JsonProperty(value = "bigImageUrl")
|
||||
@JSONField(name = "bigImageUrl")
|
||||
private String bigImageUrl;
|
||||
@JsonProperty(value = "imageViewHeight")
|
||||
@JSONField(name = "imageViewHeight")
|
||||
private int imageViewHeight;
|
||||
@JsonProperty(value = "imageViewWidth")
|
||||
@JSONField(name = "imageViewWidth")
|
||||
private int imageViewWidth;
|
||||
@JsonProperty(value = "imageViewX")
|
||||
@JSONField(name = "imageViewX")
|
||||
private int imageViewX;
|
||||
@JsonProperty(value = "imageViewY")
|
||||
@JSONField(name = "imageViewY")
|
||||
private int imageViewY;
|
||||
@JsonProperty(value = "thumbnailUrl")
|
||||
@JSONField(name = "thumbnailUrl")
|
||||
private String thumbnailUrl;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImgMsg
|
||||
* @description: 图片
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 11:29
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImgMsg implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonProperty(value = "Type")
|
||||
@JSONField(name = "Type")
|
||||
private Integer Type;
|
||||
|
||||
@JsonProperty(value = "Size")
|
||||
@JSONField(name = "Size")
|
||||
private Integer Size;
|
||||
|
||||
@JsonProperty(value = "Height")
|
||||
@JSONField(name = "Height")
|
||||
private Integer Height;
|
||||
|
||||
@JsonProperty(value = "Width")
|
||||
@JSONField(name = "Width")
|
||||
private Integer Width;
|
||||
|
||||
@JsonProperty(value = "URL")
|
||||
@JSONField(name = "URL")
|
||||
private String URL;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ImgMsgContent
|
||||
* @description: 图片内容
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 11:28
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ImgMsgContent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonProperty(value = "ImageInfoArray")
|
||||
@JSONField(name = "ImageInfoArray")
|
||||
private List<ImgMsg> ImageInfoArray;
|
||||
|
||||
@JsonProperty(value = "UUID")
|
||||
@JSONField(name = "UUID")
|
||||
private String UUID;
|
||||
|
||||
@JsonProperty(value = "ImageFormat")
|
||||
@JSONField(name = "ImageFormat")
|
||||
private Integer ImageFormat;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.MessageAndroid
|
||||
* @description: TODO android需要的数据
|
||||
* @User jinbo
|
||||
* @create: 2023-05-19 17:36
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
public class MessageAndroid<T> implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* clientTime : 1684487726
|
||||
* cloudCustomBytes : [123,34,109,101,115,115,97,103,101,70,101,97,116,117,114,101,34,58,123,34,110,101,101,100,84,121,112,105,110,103,34,58,49,44,34,118,101,114,115,105,111,110,34,58,49,125,125]
|
||||
* excludedFromLastMessage : false
|
||||
* excludedFromUnreadCount : false
|
||||
* faceUrl : https://profile.csdnimg.cn/0/C/7/0_u010649509
|
||||
* friendRemark :
|
||||
* groupID : 1659487433428959232
|
||||
* hasSentReceipt : false
|
||||
* isBroadcastMessage : false
|
||||
* isForward : false
|
||||
* isMessageSender : true
|
||||
* isPeerRead : true
|
||||
* isSelfRead : true
|
||||
* lifeTime : 1
|
||||
* localCustomNumber : 0
|
||||
* localCustomString :
|
||||
* messageBaseElements : [{"data":[123,34,98,117,115,105,110,101,115,115,73,68,34,58,34,98,117,115,105,110,101,115,115,95,99,97,114,100,34,44,34,100,111,99,116,111,114,72,101,97,100,73,109,103,34,58,34,104,116,116,112,115,58,47,47,116,115,101,50,45,109,109,46,99,110,46,98,105,110,103,46,110,101,116,47,116,104,47,105,100,47,79,73,80,45,67,46,55,111,55,107,120,53,120,106,45,83,101,106,112,67,121,51,71,71,85,97,122,103,72,97,69,75,63,119,92,117,48,48,51,100,50,56,56,92,117,48,48,50,54,104,92,117,48,48,51,100,49,56,48,92,117,48,48,50,54,99,92,117,48,48,51,100,55,92,117,48,48,50,54,114,92,117,48,48,51,100,48,92,117,48,48,50,54,111,92,117,48,48,51,100,53,92,117,48,48,50,54,112,105,100,92,117,48,48,51,100,49,46,55,34,44,34,100,111,99,116,111,114,78,97,109,101,34,58,34,-27,-68,-96,-27,-116,-69,-25,-108,-97,34,44,34,111,114,103,97,110,105,122,97,116,105,111,110,34,58,34,-27,-115,-113,-27,-110,-116,-27,-116,-69,-23,-103,-94,34,44,34,118,101,114,115,105,111,110,34,58,48,44,34,100,111,119,110,108,111,97,100,83,116,97,116,117,115,34,58,48,44,34,105,115,71,114,111,117,112,34,58,102,97,108,115,101,44,34,109,115,103,84,105,109,101,34,58,48,44,34,115,116,97,116,117,115,34,58,48,44,34,116,114,97,110,115,108,97,116,105,111,110,83,116,97,116,117,115,34,58,48,125],"description":"张医生","elementType":2,"extension":[-27,-112,-115,-25,-119,-121]}]
|
||||
* messageGroupAtInfoList : []
|
||||
* messageStatus : 2
|
||||
* messageType : 2
|
||||
* messageVersion : 0
|
||||
* msgID : 144115242295249536-1684487726-3531159768
|
||||
* nameCard :
|
||||
* needReadReceipt : false
|
||||
* nickName : 张三
|
||||
* offlinePushInfo : {"androidConfig":{"description":"","fcmChannelID":"","huaweiCategory":"","notifyMode":0,"oppoChannelID":"","soundFilePath":"","title":"","vivoClassification":1,"xiaomiChannelID":""},"apnsConfig":{"badgeMode":0,"description":"","iOSPushType":0,"soundFilePath":"","title":""},"description":"","extension":[123,34,101,110,116,105,116,121,34,58,123,34,97,99,116,105,111,110,34,58,49,44,34,99,104,97,116,84,121,112,101,34,58,50,44,34,99,111,110,116,101,110,116,34,58,34,91,-24,-121,-86,-27,-82,-102,-28,-71,-119,-26,-74,-120,-26,-127,-81,93,34,44,34,102,97,99,101,85,114,108,34,58,34,34,44,34,110,105,99,107,110,97,109,101,34,58,34,-27,-70,-108,-26,-128,-91,-27,-80,-79,-27,-116,-69,34,44,34,115,101,110,100,84,105,109,101,34,58,48,44,34,115,101,110,100,101,114,34,58,34,49,54,53,57,52,56,55,52,51,51,52,50,56,57,53,57,50,51,50,34,44,34,118,101,114,115,105,111,110,34,58,49,125,125],"pushFlag":0,"title":""}
|
||||
* platform : 0
|
||||
* priority : 2
|
||||
* random : 3531159768
|
||||
* receiptPeerRead : false
|
||||
* receiptReadCount : 0
|
||||
* receiptUnreadCount : -1
|
||||
* receiverTinyID : 0
|
||||
* receiverUserID :
|
||||
* revokerTinyID : 0
|
||||
* revokerUserID :
|
||||
* senderTinyID : 144115242295249536
|
||||
* senderUserID : 001ba0c3a045462aa525d335a277407b
|
||||
* seq : 9
|
||||
* serverTime : 1684487726
|
||||
* supportMessageExtension : false
|
||||
* targetGroupMemberList : []
|
||||
*/
|
||||
|
||||
private int clientTime;
|
||||
private boolean excludedFromLastMessage;
|
||||
private boolean excludedFromUnreadCount;
|
||||
private String faceUrl;
|
||||
private String friendRemark;
|
||||
private String groupID;
|
||||
private boolean hasSentReceipt;
|
||||
private boolean isBroadcastMessage;
|
||||
private boolean isForward;
|
||||
private boolean isMessageSender;
|
||||
private boolean isPeerRead;
|
||||
private boolean isSelfRead;
|
||||
private int lifeTime;
|
||||
private int localCustomNumber;
|
||||
private String localCustomString;
|
||||
private int messageStatus;
|
||||
private int messageType;
|
||||
private int messageVersion;
|
||||
private String msgID;
|
||||
private String nameCard;
|
||||
private boolean needReadReceipt;
|
||||
private String nickName;
|
||||
private T offlinePushInfo;
|
||||
private int platform;
|
||||
private int priority;
|
||||
private long random;
|
||||
private boolean receiptPeerRead;
|
||||
private int receiptReadCount;
|
||||
private int receiptUnreadCount;
|
||||
private int receiverTinyID;
|
||||
private String receiverUserID;
|
||||
private int revokerTinyID;
|
||||
private String revokerUserID;
|
||||
private long senderTinyID;
|
||||
private String senderUserID;
|
||||
private int seq;
|
||||
private int serverTime;
|
||||
private boolean supportMessageExtension;
|
||||
private List<Integer> cloudCustomBytes;
|
||||
private List<?> messageBaseElements;
|
||||
private List<?> messageGroupAtInfoList;
|
||||
private List<?> targetGroupMemberList;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.MsgBody
|
||||
* @description: 消息内容
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 11:24
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MsgBody<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(title = "消息类型")
|
||||
@JsonProperty(value = "MsgType")
|
||||
@JSONField(name = "MsgType")
|
||||
private String MsgType;
|
||||
|
||||
@Schema(title = "消息内容")
|
||||
@JsonProperty(value = "MsgContent")
|
||||
@JSONField(name = "MsgContent")
|
||||
private T MsgContent;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.ObjectItem
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 15:53
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
@Data
|
||||
public class ObjectItem {
|
||||
private String objectName;
|
||||
private Long size;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.Result
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-04-25 11:26
|
||||
* @Version 1.0
|
||||
**/
|
||||
public class Result<T> {
|
||||
private boolean flag;
|
||||
//状态码
|
||||
private Integer status;
|
||||
//错误的状态信息
|
||||
private String message;
|
||||
//数据
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* 构造器(私有化),这里写了3个构造器。根据实际发开需要添加即可
|
||||
*/
|
||||
public Result(boolean flag, Integer status, String message, T data) {
|
||||
this.flag = flag;
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Result(boolean flag, Integer status, String message) {
|
||||
this.flag = flag;
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
private Result(Integer status, String message, T data) {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
private Result(Integer status, String message) {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
private Result(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回《状态码》《状态信息》《数据》
|
||||
* 状态码来自--->>枚举
|
||||
* 状态信息来自--->>开发人员
|
||||
* 数据来自--->>开发人员
|
||||
*/
|
||||
public static <T> Result<T> buildR(boolean flag, Status status, String message, T data) {
|
||||
return new Result<T>(flag, status.getCode(), message, data);
|
||||
}
|
||||
|
||||
public static <T> Result<T> buildR(Status status, String message, T data) {
|
||||
return new Result<T>(status.getCode(), message, data);
|
||||
|
||||
}
|
||||
|
||||
public static <T> Result<T> buildR(boolean flag, Status status, String message) {
|
||||
return new Result<T>(flag, status.getCode(), message);
|
||||
|
||||
}
|
||||
|
||||
//下面就是根据需要返回不同参数格式的方法
|
||||
|
||||
/**
|
||||
* 返回《状态码》《状态信息》《状态信息》
|
||||
* 状态码来自--->>枚举
|
||||
* 状态信息来自--->>开发人员
|
||||
*/
|
||||
public static <T> Result<T> buildR(Status status, String message) {
|
||||
return new Result<T>(status.getCode(), message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回《状态码》《状态信息》《数据》
|
||||
* 状态码来自--->>枚举
|
||||
* 状态信息来自--->>枚举
|
||||
* 数据来自--->>开发人员
|
||||
*/
|
||||
public static <T> Result<T> buildR(Status status, T data) {
|
||||
return new Result<T>(status.getCode(), status.getMessage(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回《状态码》《状态信息》《数据》
|
||||
* 状态码来自--->>枚举
|
||||
* 状态信息来自--->>枚举
|
||||
* 数据来自--->>开发人员
|
||||
*/
|
||||
public static <T> Result<T> buildR(Status status) {
|
||||
return new Result<T>(status.getCode(), status.getMessage());
|
||||
}
|
||||
|
||||
//get方法:获取状态码
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
//get方法:获取错误状态信息
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
//get方法:获取数据内容
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.SoundMsgContent
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-05-19 16:46
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Data
|
||||
public class SoundMsgContent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Download_Flag : 2
|
||||
* Second : 2
|
||||
* Size : 11895
|
||||
* UUID : 1400805830_001ba0c3a045462aa525d335a277407b_54c8d5dbb749fce1fcaca95c52f6c94b.m4a
|
||||
* Url : https://cos.ap-shanghai.myqcloud.com/50a8-shanghai-007-sharedv4-01-1303031839/0dd8-1400805830/7ce2-001ba0c3a045462aa525d335a277407b/54c8d5dbb749fce1fcaca95c52f6c94b.m4a
|
||||
*/
|
||||
|
||||
@JsonProperty(value = "Download_Flag")
|
||||
@JSONField(name = "Download_Flag")
|
||||
private int Download_Flag;
|
||||
|
||||
@JsonProperty(value = "Second")
|
||||
@JSONField(name = "Second")
|
||||
private int Second;
|
||||
|
||||
@JsonProperty(value = "Size")
|
||||
@JSONField(name = "Size")
|
||||
private int Size;
|
||||
|
||||
@JsonProperty(value = "UUID")
|
||||
@JSONField(name = "UUID")
|
||||
private String UUID;
|
||||
|
||||
@JsonProperty(value = "Url")
|
||||
@JSONField(name = "Url")
|
||||
private String Url;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @EnumName com.renkang.im.entity.Status
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-04-25 11:25
|
||||
* @Version 1.0
|
||||
**/
|
||||
public enum Status {
|
||||
OK(200, "请求成功"),
|
||||
SYSTEM_ERROR(101, "系统异常"),
|
||||
SQL_ERROR(109, "SQL语句异常");;
|
||||
//状态码
|
||||
private Integer code;
|
||||
//错误信息
|
||||
private String message;
|
||||
|
||||
//构造器
|
||||
Status(Integer code, String message) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
//只需要添加get方法就行
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return code + ":" + message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.renkang.im.entity;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.entity.VedioMsgContent
|
||||
* @description: 视频
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 11:30
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class VedioMsgContent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonProperty(value = "ThumbFormat")
|
||||
@JSONField(name = "ThumbFormat")
|
||||
private String ThumbFormat;
|
||||
|
||||
@JsonProperty(value = "ThumbSize")
|
||||
@JSONField(name = "ThumbSize")
|
||||
private Long ThumbSize;
|
||||
|
||||
@JsonProperty(value = "ThumbUUID")
|
||||
@JSONField(name = "ThumbUUID")
|
||||
private String ThumbUUID;
|
||||
|
||||
@JsonProperty(value = "VideoDownloadFlag")
|
||||
@JSONField(name = "VideoDownloadFlag")
|
||||
private Integer VideoDownloadFlag;
|
||||
|
||||
@JsonProperty(value = "ThumbUrl")
|
||||
@JSONField(name = "ThumbUrl")
|
||||
private String ThumbUrl;
|
||||
|
||||
@JsonProperty(value = "VideoFormat")
|
||||
@JSONField(name = "VideoFormat")
|
||||
private String VideoFormat;
|
||||
|
||||
@JsonProperty(value = "VideoUrl")
|
||||
@JSONField(name = "VideoUrl")
|
||||
private String VideoUrl;
|
||||
|
||||
@JsonProperty(value = "VideoUUID")
|
||||
@JSONField(name = "VideoUUID")
|
||||
private String VideoUUID;
|
||||
|
||||
@JsonProperty(value = "VideoSecond")
|
||||
@JSONField(name = "VideoSecond")
|
||||
private Integer VideoSecond;
|
||||
|
||||
@JsonProperty(value = "ThumbDownloadFlag")
|
||||
@JSONField(name = "ThumbDownloadFlag")
|
||||
private Integer ThumbDownloadFlag;
|
||||
|
||||
@JsonProperty(value = "VideoSize")
|
||||
@JSONField(name = "VideoSize")
|
||||
private Long VideoSize;
|
||||
|
||||
@JsonProperty(value = "ThumbHeight")
|
||||
@JSONField(name = "ThumbHeight")
|
||||
private Integer ThumbHeight;
|
||||
|
||||
@JsonProperty(value = "ThumbWidth")
|
||||
@JSONField(name = "ThumbWidth")
|
||||
private Integer ThumbWidth;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.renkang.im.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.renkang.im.entity.ImMsgBody;
|
||||
import com.renkang.im.entity.ImMsgRecordAll;
|
||||
import com.renkang.im.entity.ImResult;
|
||||
import com.renkang.im.service.IImMsgRecordAllService;
|
||||
import com.renkang.im.util.UniqId;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.handler.ImJobHandler
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-05-16 19:21
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ImJobHandler {
|
||||
|
||||
@Autowired
|
||||
private IImMsgRecordAllService imMsgRecordAllService;
|
||||
|
||||
public boolean saveBatch(String httpResult, String groupId) {
|
||||
ImResult imResult = JSON.parseObject(JSON.toJSONBytes(JSON.parse(httpResult)), ImResult.class);
|
||||
List<ImMsgBody> msgList = imResult.getMsgList();
|
||||
if (CollectionUtils.isNotEmpty(msgList)) {
|
||||
List<ImMsgRecordAll> imMsgRecordAllList = new ArrayList<>();
|
||||
msgList.forEach(imMsg -> {
|
||||
ImMsgRecordAll imMsgRecordAll = new ImMsgRecordAll();
|
||||
imMsgRecordAll.setId(UniqId.getInstanceWithLog().getUniqID());
|
||||
imMsgRecordAll.setGroupid(groupId);
|
||||
Date date = new Date();
|
||||
date.setTime(imMsg.getMsgClientTime());
|
||||
imMsgRecordAll.setSendtime(date);
|
||||
imMsgRecordAll.setFromAccount(imMsg.getFrom_Account());
|
||||
imMsgRecordAll.setToAccount(imMsg.getTo_Account());
|
||||
imMsgRecordAll.setMsgcontent((String) imMsg.getMsgBody());
|
||||
imMsgRecordAll.setMsgseq(imMsg.getMsgSeq());
|
||||
imMsgRecordAll.setMsgtype("2");
|
||||
imMsgRecordAllList.add(imMsgRecordAll);
|
||||
});
|
||||
return imMsgRecordAllService.saveBatch(imMsgRecordAllList);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.renkang.im.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.renkang.im.entity.ImGroupSyncRecord;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Mapper
|
||||
public interface ImGroupSyncRecordMapper extends BaseMapper<ImGroupSyncRecord> {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.renkang.im.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.renkang.im.entity.ImMsgRecordAll;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* @Description: im_msg_record_all
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2023-05-15
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Mapper
|
||||
public interface ImMsgRecordAllMapper extends BaseMapper<ImMsgRecordAll> {
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.renkang.im.mapper.ImGroupSyncRecordMapper">
|
||||
<resultMap id="BaseResultMap" type="com.renkang.im.entity.ImGroupSyncRecord">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table im_group_sync_record-->
|
||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
<result column="group_id" jdbcType="VARCHAR" property="groupId" />
|
||||
<result column="fetch_msg_count" jdbcType="INTEGER" property="fetchMsgCount" />
|
||||
<result column="exist_msg_count" jdbcType="INTEGER" property="existMsgCount" />
|
||||
<result column="sync_msg_count" jdbcType="INTEGER" property="syncMsgCount" />
|
||||
<result column="sync_status" jdbcType="TINYINT" property="syncStatus" />
|
||||
<result column="error_msg" jdbcType="VARCHAR" property="errorMsg" />
|
||||
<result column="start_time" jdbcType="TIMESTAMP" property="startTime" />
|
||||
<result column="end_time" jdbcType="TIMESTAMP" property="endTime" />
|
||||
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
<!--@mbg.generated-->
|
||||
id, group_id, fetch_msg_count, exist_msg_count, sync_msg_count, sync_status, error_msg,
|
||||
start_time, end_time, create_time
|
||||
</sql>
|
||||
</mapper>
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.renkang.im.mapper.ImMsgRecordAllMapper">
|
||||
</mapper>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.renkang.im.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.renkang.im.entity.ImMsgRecordAll;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: im_msg_record_all
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2023-05-15
|
||||
* @Version: V1.0
|
||||
*/
|
||||
public interface IImMsgRecordAllService extends IService<ImMsgRecordAll> {
|
||||
|
||||
List<ImMsgRecordAll> getImMsgRecordAll(String groupId);
|
||||
|
||||
Result<List<ImMsgRecordAll>> selectImMessageList(String sessionId);
|
||||
|
||||
Result<Page<ImMsgRecordAll>> selectImMessagePageList(String groupId, Integer pageNo, Integer pageSize);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.renkang.im.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.renkang.im.bean.GroupSyncFilter;
|
||||
import com.renkang.im.entity.ImGroupSyncRecord;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
public interface ImService {
|
||||
|
||||
/**
|
||||
* 同步群组消息
|
||||
*
|
||||
* @param groupId 群组ID
|
||||
*/
|
||||
void syncGroupHistory(String groupId);
|
||||
|
||||
/**
|
||||
* 处理回调消息
|
||||
*
|
||||
* @param requestJson 入参JSON
|
||||
*/
|
||||
void callback(JSONObject requestJson);
|
||||
|
||||
/**
|
||||
* 强制结束同步
|
||||
*
|
||||
* @param recordId 同步记录ID
|
||||
*/
|
||||
void forceTerminate(String recordId);
|
||||
|
||||
/**
|
||||
* 删除同步记录
|
||||
*
|
||||
* @param recordId 同步记录ID
|
||||
*/
|
||||
boolean deleteRecord(String recordId);
|
||||
|
||||
/**
|
||||
* 分页查询同步记录
|
||||
*
|
||||
* @param filter 群组同步筛选
|
||||
*/
|
||||
Page<ImGroupSyncRecord> listGroupSyncRecord(GroupSyncFilter filter);
|
||||
|
||||
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.renkang.im.service.impl;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.renkang.consultation.api.ConSessionHelloApi;
|
||||
import com.renkang.im.entity.ImMsgRecordAll;
|
||||
import com.renkang.im.mapper.ImMsgRecordAllMapper;
|
||||
import com.renkang.im.service.IImMsgRecordAllService;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: im_msg_record_all
|
||||
* @Author: jeecg-boot
|
||||
* @Date: 2023-05-15
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Service
|
||||
public class ImMsgRecordAllServiceImpl extends ServiceImpl<ImMsgRecordAllMapper, ImMsgRecordAll> implements IImMsgRecordAllService {
|
||||
|
||||
@Autowired
|
||||
private ImMsgRecordAllMapper imMsgRecordAllMapper;
|
||||
|
||||
@Autowired
|
||||
private ISysBaseAPI sysBaseAPI;
|
||||
|
||||
@Autowired
|
||||
private ConSessionHelloApi conSessionHelloApi;
|
||||
|
||||
@Override
|
||||
public List<ImMsgRecordAll> getImMsgRecordAll(String groupId) {
|
||||
QueryWrapper<ImMsgRecordAll> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("groupId", groupId);
|
||||
queryWrapper.orderByAsc("msgseq");
|
||||
return imMsgRecordAllMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<List<ImMsgRecordAll>> selectImMessageList(String groupId) {
|
||||
QueryWrapper<ImMsgRecordAll> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("groupId", groupId);
|
||||
queryWrapper.ne("from_account", "administrator");
|
||||
// queryWrapper.ne("to_account", "administrator");
|
||||
queryWrapper.orderByAsc("msgseq");
|
||||
List<ImMsgRecordAll> list = imMsgRecordAllMapper.selectList(queryWrapper);
|
||||
return Result.OK(list);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Result<Page<ImMsgRecordAll>> selectImMessagePageList(String groupId, Integer pageNo, Integer pageSize) {
|
||||
QueryWrapper<ImMsgRecordAll> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("groupId", groupId);
|
||||
queryWrapper.orderByDesc("msgseq");
|
||||
Page<ImMsgRecordAll> page = new Page<>(pageNo, pageSize);
|
||||
Page<ImMsgRecordAll> list = imMsgRecordAllMapper.selectPage(page,queryWrapper);
|
||||
return Result.OK(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
package com.renkang.im.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.renkang.consultation.api.ConSessionHelloApi;
|
||||
import com.renkang.im.bean.GroupHistoryTransfer;
|
||||
import com.renkang.im.bean.GroupSyncFilter;
|
||||
import com.renkang.im.entity.ImGroupSyncRecord;
|
||||
import com.renkang.im.entity.ImMsgRecordAll;
|
||||
import com.renkang.im.mapper.ImGroupSyncRecordMapper;
|
||||
import com.renkang.im.mapper.ImMsgRecordAllMapper;
|
||||
import com.renkang.im.service.ImService;
|
||||
import com.renkang.im.util.TencentCloudImUtil;
|
||||
import com.renkang.im.util.UniqId;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.jeecg.common.exception.JeecgBootException;
|
||||
import org.jeecg.common.util.MyUploadUtil;
|
||||
import org.jeecg.global.GlobalUtils;
|
||||
import org.jeecg.util.WrapperUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static com.renkang.im.common.TencentCloudImConstant.*;
|
||||
|
||||
/**
|
||||
* @author Jiang Shunzhi
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ImServiceImpl implements ImService {
|
||||
|
||||
public static final String ADMINISTRATOR = "administrator";
|
||||
private final ThreadLocal<String> ongoingRecordIdLocal = new ThreadLocal<>();
|
||||
private final ThreadLocal<String> groupIdLocal = new ThreadLocal<>();
|
||||
private final Map<String, Future<?>> taskMap = new ConcurrentHashMap<>();
|
||||
@Autowired
|
||||
private TencentCloudImUtil imUtil;
|
||||
@Autowired
|
||||
private ConSessionHelloApi conSessionHelloApi;
|
||||
@Autowired
|
||||
private ImMsgRecordAllMapper imMsgRecordAllMapper;
|
||||
@Autowired
|
||||
private ImGroupSyncRecordMapper imGroupSyncRecordMapper;
|
||||
@Autowired
|
||||
private AsyncTaskExecutor asyncTaskExecutor;
|
||||
@Autowired
|
||||
private HttpClient httpClient;
|
||||
|
||||
@Override
|
||||
public void syncGroupHistory(String groupId) {
|
||||
checkOngoingJob(groupId);
|
||||
String recordId = initRecord(groupId);
|
||||
Future<?> submit = asyncTaskExecutor.submit(() -> {
|
||||
ongoingRecordIdLocal.set(recordId);
|
||||
groupIdLocal.set(groupId);
|
||||
try {
|
||||
changeStatus(1);
|
||||
syncGroupHistoryExecute(null);
|
||||
changeStatus(2);
|
||||
} catch (Exception e) {
|
||||
log.error("同步群组【{}】消息出错", groupId, e);
|
||||
String msg;
|
||||
if (StrUtil.isEmpty(e.getMessage())) {
|
||||
msg = "";
|
||||
} else {
|
||||
if (e.getMessage().length() > 100) {
|
||||
msg = e.getMessage().substring(0, 100);
|
||||
} else {
|
||||
msg = "";
|
||||
}
|
||||
}
|
||||
changeStatus(3, msg);
|
||||
} finally {
|
||||
ongoingRecordIdLocal.remove();
|
||||
groupIdLocal.remove();
|
||||
}
|
||||
});
|
||||
taskMap.put(recordId, submit);
|
||||
}
|
||||
|
||||
private void checkOngoingJob(String groupId) {
|
||||
Wrapper<ImGroupSyncRecord> wrapper = Wrappers.lambdaQuery(ImGroupSyncRecord.class)
|
||||
.eq(ImGroupSyncRecord::getGroupId, groupId)
|
||||
.eq(ImGroupSyncRecord::getSyncStatus, 1);
|
||||
ImGroupSyncRecord imGroupSyncRecord = imGroupSyncRecordMapper.selectOne(wrapper, false);
|
||||
if (Objects.nonNull(imGroupSyncRecord)) {
|
||||
throw new JeecgBootException("该聊天正在同步中,请误重复操作");
|
||||
}
|
||||
}
|
||||
|
||||
private String initRecord(String groupId) {
|
||||
ImGroupSyncRecord record = ImGroupSyncRecord.builder()
|
||||
.groupId(groupId)
|
||||
.syncStatus(0)
|
||||
.build();
|
||||
int success = imGroupSyncRecordMapper.insert(record);
|
||||
if (success > 0) {
|
||||
return record.getId();
|
||||
} else {
|
||||
throw new JeecgBootException("系统异常,请稍后重试");
|
||||
}
|
||||
}
|
||||
|
||||
private void changeStatus(Integer status) {
|
||||
changeStatus(status, "");
|
||||
}
|
||||
|
||||
private void changeStatus(Integer status, String errorMsg) {
|
||||
ImGroupSyncRecord record = ImGroupSyncRecord.builder()
|
||||
.id(ongoingRecordIdLocal.get())
|
||||
.syncStatus(status)
|
||||
.errorMsg(errorMsg)
|
||||
.build();
|
||||
if (status == 1) {
|
||||
record.setStartTime(new Date());
|
||||
}
|
||||
if (status > 1) {
|
||||
record.setEndTime(new Date());
|
||||
}
|
||||
imGroupSyncRecordMapper.updateById(record);
|
||||
}
|
||||
|
||||
private void updateRecordCount(GroupHistoryTransfer transfer) {
|
||||
ImGroupSyncRecord record = imGroupSyncRecordMapper.selectById(ongoingRecordIdLocal.get());
|
||||
if (Objects.isNull(record.getFetchMsgCount())) {
|
||||
record.setFetchMsgCount(transfer.getFetchCount());
|
||||
} else {
|
||||
record.setFetchMsgCount(record.getFetchMsgCount() + transfer.getFetchCount());
|
||||
}
|
||||
if (Objects.isNull(record.getExistMsgCount())) {
|
||||
record.setExistMsgCount(transfer.getExistCount());
|
||||
} else {
|
||||
record.setExistMsgCount(record.getExistMsgCount() + transfer.getExistCount());
|
||||
}
|
||||
if (Objects.isNull(record.getSyncMsgCount())) {
|
||||
record.setSyncMsgCount(transfer.getSyncCount());
|
||||
} else {
|
||||
record.setSyncMsgCount(record.getSyncMsgCount() + transfer.getSyncCount());
|
||||
}
|
||||
imGroupSyncRecordMapper.updateById(record);
|
||||
}
|
||||
|
||||
private boolean checkMsgExist(Integer seq) {
|
||||
return checkMsgExist(groupIdLocal.get(), seq);
|
||||
}
|
||||
|
||||
private boolean checkMsgExist(String groupId, Integer seq) {
|
||||
Wrapper<ImMsgRecordAll> wrapper = Wrappers.lambdaQuery(ImMsgRecordAll.class)
|
||||
.eq(ImMsgRecordAll::getGroupid, groupId)
|
||||
.eq(ImMsgRecordAll::getMsgseq, seq);
|
||||
return imMsgRecordAllMapper.exists(wrapper);
|
||||
}
|
||||
|
||||
private String handleMsg(JSONObject rspMsg, GroupHistoryTransfer transfer) {
|
||||
Integer msgSeq = rspMsg.getInteger(MSG_SEQ);
|
||||
transfer.setMinSeq(msgSeq);
|
||||
ImMsgRecordAll record = convertMsgRecordForSync(rspMsg);
|
||||
if (checkMsgExist(msgSeq)) {
|
||||
transfer.setExistCount(transfer.getExistCount() + 1);
|
||||
} else {
|
||||
imMsgRecordAllMapper.insert(record);
|
||||
transfer.setSyncCount(transfer.getSyncCount() + 1);
|
||||
}
|
||||
if (!ADMINISTRATOR.equalsIgnoreCase(record.getFromAccount())) {
|
||||
return record.getFromAccount();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ImMsgRecordAll convertMsgRecordForSync(JSONObject rspMsg) {
|
||||
JSONObject msgContent = newMsgContent(rspMsg);
|
||||
ImMsgRecordAll imMsgRecordAll = new ImMsgRecordAll();
|
||||
imMsgRecordAll.setId(UniqId.getInstanceWithLog().getUniqID());
|
||||
imMsgRecordAll.setGroupid(groupIdLocal.get());
|
||||
imMsgRecordAll.setSendtime(new Date(rspMsg.getLong(MSG_TIME_STAMP) * 1000));
|
||||
imMsgRecordAll.setFromAccount(rspMsg.getString(FROM_ACCOUNT));
|
||||
imMsgRecordAll.setContenttype(msgContent.getString(MSG_TYPE));
|
||||
imMsgRecordAll.setMsgcontent(msgContent.toJSONString());
|
||||
imMsgRecordAll.setMsgseq(rspMsg.getInteger(MSG_SEQ));
|
||||
imMsgRecordAll.setMsgtype("2");
|
||||
imMsgRecordAll.setCreateTime(new Date());
|
||||
try {
|
||||
JSONObject customData = rspMsg.getJSONObject(CLOUD_CUSTOM_DATA);
|
||||
boolean fromAdmin = customData.getBooleanValue("fromAdmin");
|
||||
if (fromAdmin) {
|
||||
imMsgRecordAll.setToAccount(ADMINISTRATOR);
|
||||
} else {
|
||||
imMsgRecordAll.setToAccount(rspMsg.getString(FROM_ACCOUNT));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
imMsgRecordAll.setToAccount(rspMsg.getString(FROM_ACCOUNT));
|
||||
}
|
||||
|
||||
return imMsgRecordAll;
|
||||
}
|
||||
|
||||
private JSONObject newMsgContent(JSONObject rspMsg) {
|
||||
JSONArray msgBody = rspMsg.getJSONArray(MSG_BODY);
|
||||
String contentType = handleMsgBody(msgBody);
|
||||
return new JSONObject()
|
||||
.fluentPut(CALLBACK_COMMAND, GROUP_CALLBACK_AFTER_SEND_MSG)
|
||||
.fluentPut(ONLINE_ONLY_FLAG, 0)
|
||||
.fluentPut(GROUP_ID, groupIdLocal.get())
|
||||
.fluentPut(FROM_ACCOUNT, rspMsg.getString(FROM_ACCOUNT))
|
||||
.fluentPut(CLOUD_CUSTOM_DATA, rspMsg.getString(CLOUD_CUSTOM_DATA))
|
||||
.fluentPut(MSG_BODY, msgBody)
|
||||
.fluentPut(MSG_PRIORITY, convertPriority(rspMsg.getInteger(MSG_PRIORITY)))
|
||||
.fluentPut(MSG_SEQ, rspMsg.getInteger(MSG_SEQ))
|
||||
.fluentPut(RANDOM, rspMsg.getInteger(MSG_RANDOM))
|
||||
.fluentPut(MSG_TIME, rspMsg.getLong(MSG_TIME_STAMP))
|
||||
.fluentPut(EVENT_TIME, rspMsg.getLong(MSG_TIME_STAMP) * 1000)
|
||||
.fluentPut(GROUP_TYPE, GROUP_TYPE_STRANGER)
|
||||
.fluentPut(MSG_TYPE, contentType);
|
||||
}
|
||||
|
||||
private String handleMsgBody(JSONArray msgBody) {
|
||||
String msgType = "";
|
||||
for (int i = 0; i < msgBody.size(); i++) {
|
||||
msgType = handleMsgBody(msgBody.getJSONObject(i));
|
||||
}
|
||||
return msgType;
|
||||
}
|
||||
|
||||
private String convertPriority(Integer priority) {
|
||||
switch (priority) {
|
||||
case 1:
|
||||
return "High";
|
||||
case 2:
|
||||
return "Normal";
|
||||
case 3:
|
||||
return "Low";
|
||||
case 4:
|
||||
return "Lowest";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private void syncGroupHistoryExecute(Integer reqMsgSeq) {
|
||||
GroupHistoryTransfer transfer = new GroupHistoryTransfer();
|
||||
String resultStr = imUtil.groupMessage(groupIdLocal.get(), 20, reqMsgSeq, 0);
|
||||
if (StrUtil.isEmpty(resultStr)) {
|
||||
return;
|
||||
}
|
||||
JSONObject result = JSON.parseObject(resultStr);
|
||||
if (!ACTION_STATUS_OK.equals(result.getString(ACTION_STATUS))
|
||||
|| !Integer.valueOf(1).equals(result.getInteger(IS_FINISHED))) {
|
||||
updateRecordCount(transfer);
|
||||
return;
|
||||
}
|
||||
if (!Integer.valueOf(0).equals(result.getInteger(ERROR_CODE))) {
|
||||
updateRecordCount(transfer);
|
||||
throw new JeecgBootException(result.getString(ERROR_CODE));
|
||||
}
|
||||
JSONArray rspMsgList = result.getJSONArray(RSP_MSG_LIST);
|
||||
transfer.setFetchCount(rspMsgList.size());
|
||||
Set<String> callIds = new HashSet<>();
|
||||
for (int i = 0; i < rspMsgList.size(); i++) {
|
||||
String fromAccount = handleMsg(rspMsgList.getJSONObject(i), transfer);
|
||||
if (StrUtil.isNotEmpty(fromAccount)) {
|
||||
callIds.add(fromAccount);
|
||||
}
|
||||
}
|
||||
updateRecordCount(transfer);
|
||||
callConsultation(callIds);
|
||||
if (transfer.getMinSeq() > 1) {
|
||||
syncGroupHistoryExecute(transfer.getMinSeq() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void callConsultation(Set<String> callIds) {
|
||||
for (String callId : callIds) {
|
||||
callConsultationSingle(groupIdLocal.get(), callId);
|
||||
}
|
||||
}
|
||||
|
||||
private void callConsultationSingle(String groupId, String fromAccount) {
|
||||
try {
|
||||
conSessionHelloApi.startPictureTextSession(groupId, fromAccount);
|
||||
} catch (Exception e) {
|
||||
log.error("Call consultation session fail. \tGROUP_ID:{}\tFROM_ACCOUNT: {}", groupId, fromAccount, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String handleMsgBody(JSONObject msgBody) {
|
||||
String msgType = msgBody.getString(MSG_TYPE);
|
||||
JSONObject msgContent = msgBody.getJSONObject(MSG_CONTENT);
|
||||
switch (msgType) {
|
||||
case TIM_IMAGE_ELEM:
|
||||
handleImageElem(msgContent);
|
||||
break;
|
||||
case TIM_VIDEO_FILE_ELEM:
|
||||
handleVideoFileElem(msgContent);
|
||||
break;
|
||||
case TIM_FILE_ELEM:
|
||||
handleFileElem(msgContent);
|
||||
break;
|
||||
case TIM_SOUND_ELEM:
|
||||
handleSoundElem(msgContent);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
return msgType;
|
||||
}
|
||||
|
||||
private void handleImageElem(JSONObject msgContent) {
|
||||
JSONArray imageInfos = msgContent.getJSONArray(IMAGE_INFO_ARRAY);
|
||||
for (int i = 0; i < imageInfos.size(); i++) {
|
||||
JSONObject imageInfo = imageInfos.getJSONObject(i);
|
||||
imageInfo.put(URL, handleFile(imageInfo.getString(URL)));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVideoFileElem(JSONObject msgContent) {
|
||||
msgContent.put(VIDEO_URL, handleFile(msgContent.getString(VIDEO_URL)));
|
||||
msgContent.put(THUMB_URL, handleFile(msgContent.getString(THUMB_URL)));
|
||||
}
|
||||
|
||||
private void handleFileElem(JSONObject msgContent) {
|
||||
msgContent.put(URL_LOW, handleFile(msgContent.getString(URL_LOW)));
|
||||
}
|
||||
|
||||
private void handleSoundElem(JSONObject msgContent) {
|
||||
msgContent.put(URL_LOW, handleFile(msgContent.getString(URL_LOW)));
|
||||
}
|
||||
|
||||
private String handleFile(String url) {
|
||||
byte[] fileBytes;
|
||||
String fileName = UUID.randomUUID().toString();
|
||||
try {
|
||||
URI uri = new URI(urlReplace(url));
|
||||
String path = uri.getPath();
|
||||
fileName = fileName.concat(path.substring(path.lastIndexOf("/") + 1));
|
||||
HttpGet httpGet = new HttpGet(uri);
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
fileBytes = EntityUtils.toByteArray(response.getEntity());
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
log.error("Download file error: {}", url, e);
|
||||
return url;
|
||||
}
|
||||
ByteArrayInputStream fileStream = new ByteArrayInputStream(fileBytes);
|
||||
try {
|
||||
String fileServerUrl = MyUploadUtil.upload(fileStream, "IM", fileName);
|
||||
return StrUtil.isEmpty(fileServerUrl) ? url : fileServerUrl;
|
||||
} catch (Exception e) {
|
||||
log.error("Save file error: {}", url, e);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
private String urlReplace(String url) {
|
||||
if (url.startsWith(IM_RICH_RAW)) {
|
||||
return url.replace(IM_RICH_RAW, IM_RICH_RP);
|
||||
}
|
||||
if (url.startsWith(AP_GUANGZHOU_RAW)) {
|
||||
return url.replace(AP_GUANGZHOU_RAW, AP_GUANGZHOU_RP);
|
||||
}
|
||||
if (url.startsWith(MY_IM_RAW)) {
|
||||
return url.replace(MY_IM_RAW, MY_IM_RP);
|
||||
}
|
||||
if (url.startsWith(AP_SHANGHAI_RAW)) {
|
||||
return url.replace(AP_SHANGHAI_RAW, AP_SHANGHAI_RP);
|
||||
}
|
||||
if (url.startsWith(AP_SHANGHAI_TC_RAW)) {
|
||||
return url.replace(AP_SHANGHAI_TC_RAW, AP_SHANGHAI_TC_RP);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callback(JSONObject requestJson) {
|
||||
switch (requestJson.getString(CALLBACK_COMMAND)) {
|
||||
case GROUP_CALLBACK_AFTER_SEND_MSG:
|
||||
groupAfterSendMsg(requestJson);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private void groupAfterSendMsg(JSONObject requestJson) {
|
||||
log.info("群内发言之后回调:{}", requestJson);
|
||||
ImMsgRecordAll record = convertMsgRecordForCallback(requestJson);
|
||||
if (checkMsgExist(record.getGroupid(), record.getMsgseq())) {
|
||||
return;
|
||||
}
|
||||
imMsgRecordAllMapper.insert(record);
|
||||
if (!ADMINISTRATOR.equalsIgnoreCase(record.getFromAccount())) {
|
||||
GlobalUtils.setHttpFeignToken();
|
||||
callConsultationSingle(record.getGroupid(), record.getFromAccount());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ImMsgRecordAll convertMsgRecordForCallback(JSONObject requestJson) {
|
||||
JSONArray msgBody = requestJson.getJSONArray(MSG_BODY);
|
||||
String contentType = handleMsgBody(msgBody);
|
||||
ImMsgRecordAll imMsgRecordAll = new ImMsgRecordAll();
|
||||
imMsgRecordAll.setId(UniqId.getInstanceWithLog().getUniqID());
|
||||
imMsgRecordAll.setGroupid(requestJson.getString(GROUP_ID));
|
||||
imMsgRecordAll.setSendtime(new Date(requestJson.getLong(MSG_TIME) * 1000));
|
||||
imMsgRecordAll.setFromAccount(requestJson.getString(FROM_ACCOUNT));
|
||||
imMsgRecordAll.setToAccount(requestJson.getString(OPERATOR_ACCOUNT));
|
||||
imMsgRecordAll.setContenttype(contentType);
|
||||
imMsgRecordAll.setMsgcontent(requestJson.toJSONString());
|
||||
imMsgRecordAll.setMsgseq(requestJson.getInteger(MSG_SEQ));
|
||||
imMsgRecordAll.setMsgtype("2");
|
||||
imMsgRecordAll.setCreateTime(new Date());
|
||||
return imMsgRecordAll;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceTerminate(String recordId) {
|
||||
Future<?> future = taskMap.get(recordId);
|
||||
if (Objects.nonNull(future)) {
|
||||
future.cancel(true);
|
||||
}
|
||||
ImGroupSyncRecord imGroupSyncRecord = imGroupSyncRecordMapper.selectById(recordId);
|
||||
if (Objects.isNull(imGroupSyncRecord)) {
|
||||
return;
|
||||
}
|
||||
ongoingRecordIdLocal.set(recordId);
|
||||
switch (imGroupSyncRecord.getSyncStatus()) {
|
||||
case 0: {
|
||||
changeStatus(2, "未开始手动结束");
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
changeStatus(3, "进行中手动结束");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
ongoingRecordIdLocal.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteRecord(String recordId) {
|
||||
return imGroupSyncRecordMapper.deleteById(recordId) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ImGroupSyncRecord> listGroupSyncRecord(GroupSyncFilter filter) {
|
||||
LambdaQueryWrapper<ImGroupSyncRecord> wrapper = WrapperUtils.initLambdaWrapper(filter);
|
||||
return imGroupSyncRecordMapper.selectPage(filter.getPage(), wrapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package com.renkang.im.util;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.util.FileUtil
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-04-23 14:38
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Slf4j
|
||||
public class FileUtil {
|
||||
|
||||
public static File getFileInByUrl(String fileUrl) {
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
BufferedOutputStream stream = null;
|
||||
InputStream inputStream = null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
File file = null;
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
String imgName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
|
||||
URL imageUrl = new URL(fileUrl);
|
||||
conn = (HttpURLConnection) imageUrl.openConnection();
|
||||
// conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
|
||||
//设置请求头
|
||||
conn.setRequestProperty("Charsert", "UTF-8");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");//设置参数类型是json格式
|
||||
conn.setRequestProperty("Connection", "Keep-Alive");
|
||||
inputStream = conn.getInputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int len = 0;
|
||||
while ((len = inputStream.read(buffer)) != -1) {
|
||||
outStream.write(buffer, 0, len);
|
||||
}
|
||||
file = new File(imgName);
|
||||
fileOutputStream = new FileOutputStream(file);
|
||||
stream = new BufferedOutputStream(fileOutputStream);
|
||||
stream.write(outStream.toByteArray());
|
||||
} catch (Exception e) {
|
||||
log.error("获取文件,Error", e);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (fileOutputStream != null) {
|
||||
try {
|
||||
fileOutputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
outStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
public static InputStream getInputByUrl(String fileUrl) {
|
||||
InputStream inputStream = null;
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
URL imageUrl = new URL(fileUrl);
|
||||
conn = (HttpURLConnection) imageUrl.openConnection();
|
||||
conn.setRequestProperty("Charsert", "UTF-8");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");//设置参数类型是json格式
|
||||
conn.setRequestProperty("Connection", "Keep-Alive");
|
||||
inputStream = conn.getInputStream();
|
||||
} catch (Exception e) {
|
||||
log.error("获取文件,Error", e);
|
||||
} finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public static File getFileByUrl(String fileUrl) {
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
BufferedOutputStream stream = null;
|
||||
InputStream inputStream = null;
|
||||
FileOutputStream fileOutputStream = null;
|
||||
File file = null;
|
||||
HttpURLConnection conn = null;
|
||||
try {
|
||||
System.out.println("fileUrl=============" + fileUrl);
|
||||
String imgName = fileUrl.substring(0, fileUrl.indexOf("?") == -1 ? fileUrl.length() : fileUrl.indexOf("?"));
|
||||
imgName = imgName.substring(imgName.lastIndexOf("/") + 1);
|
||||
System.out.println("imgName=============" + imgName);
|
||||
URL imageUrl = new URL(fileUrl);
|
||||
conn = (HttpURLConnection) imageUrl.openConnection();
|
||||
// conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
|
||||
//设置请求头
|
||||
conn.setRequestProperty("Charsert", "UTF-8");
|
||||
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");//设置参数类型是json格式
|
||||
conn.setRequestProperty("Connection", "Keep-Alive");
|
||||
inputStream = conn.getInputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int len = 0;
|
||||
while ((len = inputStream.read(buffer)) != -1) {
|
||||
outStream.write(buffer, 0, len);
|
||||
}
|
||||
file = new File(imgName);
|
||||
fileOutputStream = new FileOutputStream(file);
|
||||
stream = new BufferedOutputStream(fileOutputStream);
|
||||
stream.write(outStream.toByteArray());
|
||||
} catch (Exception e) {
|
||||
log.error("获取文件,Error", e);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (fileOutputStream != null) {
|
||||
try {
|
||||
fileOutputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
outStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
public static String getFileType(String fileUrl) {
|
||||
String fileType = fileUrl.substring(fileUrl.lastIndexOf("."));
|
||||
// 如果从url获取的文件类型长度大于7个,说明不是正常文件类型
|
||||
if (fileType.length() > 7) {
|
||||
if (fileType.contains("jpg")) {
|
||||
fileType = ".jpg";
|
||||
} else if (fileType.contains("PNG")) {
|
||||
fileType = ".PNG";
|
||||
} else {
|
||||
fileType = ".PNG";
|
||||
}
|
||||
}
|
||||
return fileType;
|
||||
}
|
||||
|
||||
|
||||
public static void deleteAllFile(File rootFile) {
|
||||
if (rootFile != null) {
|
||||
if (rootFile.isFile()) {
|
||||
rootFile.delete();
|
||||
} else {
|
||||
File[] files = rootFile.listFiles();// 将非空文件夹转换成File数组
|
||||
for (File file : files) {//使用foreach语句遍历文件数组
|
||||
deleteAllFile(file);// 删除指定文件夹下的所有非空文件夹(包括file)
|
||||
}
|
||||
rootFile.delete();// 删除指定文件夹下的所有空文件夹
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFileNameByUrl(String fileUrl) {
|
||||
|
||||
return fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String fileNameByUrl = getFileNameByUrl("http:///20210131DE11UM_PayVoucher_2021-02-04.jpg");
|
||||
System.out.println(fileNameByUrl);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
package com.renkang.im.util;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.http.*;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.util.HttpUtil
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-04-21 15:20
|
||||
* @Version 1.0
|
||||
**/
|
||||
public class HttpUtil {
|
||||
private static final CloseableHttpClient httpclient = HttpClients.createDefault();
|
||||
|
||||
/**
|
||||
* 发送HttpGet请求
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static String sendGet(String url) {
|
||||
|
||||
HttpGet httpget = new HttpGet(url);
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
response = httpclient.execute(httpget);
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
String result = null;
|
||||
try {
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (entity != null) {
|
||||
result = EntityUtils.toString(entity);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送HttpPost请求,参数为map
|
||||
*
|
||||
* @param url
|
||||
* @param map
|
||||
* @return
|
||||
*/
|
||||
public static String sendPost(String url, Map<String, String> map) {
|
||||
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, Consts.UTF_8);
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
httppost.setEntity(entity);
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
response = httpclient.execute(httppost);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
HttpEntity httpEntity = response.getEntity();
|
||||
String result = null;
|
||||
try {
|
||||
result = EntityUtils.toString(httpEntity);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送不带参数的HttpPost请求
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static String sendPost(String url) {
|
||||
HttpPost httppost = new HttpPost(url);
|
||||
CloseableHttpResponse response = null;
|
||||
try {
|
||||
response = httpclient.execute(httppost);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
HttpEntity entity = response.getEntity();
|
||||
String result = null;
|
||||
try {
|
||||
result = EntityUtils.toString(entity);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String doPost(String url, JSONObject param) {
|
||||
HttpPost httpPost = null;
|
||||
String result = null;
|
||||
try {
|
||||
HttpClient client = new DefaultHttpClient();
|
||||
httpPost = new HttpPost(url);
|
||||
if (param != null) {
|
||||
StringEntity se = new StringEntity(param.toString(), "utf-8");
|
||||
httpPost.setEntity(se); // post方法中,加入json数据
|
||||
httpPost.setHeader("Content-Type", "application/json");
|
||||
httpPost.setHeader("Authorization", param.getString("authorization"));
|
||||
}
|
||||
|
||||
HttpResponse response = client.execute(httpPost);
|
||||
if (response != null) {
|
||||
HttpEntity resEntity = response.getEntity();
|
||||
if (resEntity != null) {
|
||||
result = EntityUtils.toString(resEntity, "utf-8");
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static String doPost(String url, String params) throws Exception {
|
||||
|
||||
CloseableHttpClient httpclient = HttpClients.createDefault();
|
||||
HttpPost httpPost = new HttpPost(url);// 创建httpPost
|
||||
httpPost.setHeader("Accept", "application/json");
|
||||
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
String charSet = "UTF-8";
|
||||
StringEntity entity = new StringEntity(params, charSet);
|
||||
httpPost.setEntity(entity);
|
||||
CloseableHttpResponse response = null;
|
||||
|
||||
try {
|
||||
|
||||
response = httpclient.execute(httpPost);
|
||||
StatusLine status = response.getStatusLine();
|
||||
int state = status.getStatusCode();
|
||||
if (state == HttpStatus.SC_OK) {
|
||||
HttpEntity responseEntity = response.getEntity();
|
||||
String jsonString = EntityUtils.toString(responseEntity);
|
||||
return jsonString;
|
||||
}
|
||||
} finally {
|
||||
if (response != null) {
|
||||
try {
|
||||
response.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
httpclient.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package com.renkang.im.util;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
|
||||
/**
|
||||
* <p>名称:IdWorker.java</p>
|
||||
* <p>描述:分布式自增长ID</p>
|
||||
* <pre>
|
||||
* Twitter的 Snowflake JAVA实现方案
|
||||
* </pre>
|
||||
* 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用:
|
||||
* 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
|
||||
* 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,
|
||||
* 然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),
|
||||
* 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
|
||||
* 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),
|
||||
* 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
|
||||
* <p>
|
||||
* 64位ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加))
|
||||
*
|
||||
* @author Polim
|
||||
*/
|
||||
public class IdWorker {
|
||||
// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)
|
||||
private final static long twepoch = 1288834974657L;
|
||||
// 机器标识位数
|
||||
private final static long workerIdBits = 5L;
|
||||
// 数据中心标识位数
|
||||
private final static long datacenterIdBits = 5L;
|
||||
// 机器ID最大值
|
||||
private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);
|
||||
// 数据中心ID最大值
|
||||
private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
|
||||
// 毫秒内自增位
|
||||
private final static long sequenceBits = 12L;
|
||||
// 机器ID偏左移12位
|
||||
private final static long workerIdShift = sequenceBits;
|
||||
// 数据中心ID左移17位
|
||||
private final static long datacenterIdShift = sequenceBits + workerIdBits;
|
||||
// 时间毫秒左移22位
|
||||
private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
|
||||
|
||||
private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
|
||||
/* 上次生产id时间戳 */
|
||||
private static long lastTimestamp = -1L;
|
||||
private final long workerId;
|
||||
// 数据标识id部分
|
||||
private final long datacenterId;
|
||||
// 0,并发控制
|
||||
private long sequence = 0L;
|
||||
|
||||
public IdWorker() {
|
||||
this.datacenterId = getDatacenterId(maxDatacenterId);
|
||||
this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param workerId 工作机器ID
|
||||
* @param datacenterId 序列号
|
||||
*/
|
||||
public IdWorker(long workerId, long datacenterId) {
|
||||
if (workerId > maxWorkerId || workerId < 0) {
|
||||
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
|
||||
}
|
||||
if (datacenterId > maxDatacenterId || datacenterId < 0) {
|
||||
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
|
||||
}
|
||||
this.workerId = workerId;
|
||||
this.datacenterId = datacenterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 获取 maxWorkerId
|
||||
* </p>
|
||||
*/
|
||||
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
|
||||
StringBuffer mpid = new StringBuffer();
|
||||
mpid.append(datacenterId);
|
||||
String name = ManagementFactory.getRuntimeMXBean().getName();
|
||||
if (!name.isEmpty()) {
|
||||
/*
|
||||
* GET jvmPid
|
||||
*/
|
||||
mpid.append(name.split("@")[0]);
|
||||
}
|
||||
/*
|
||||
* MAC + PID 的 hashcode 获取16个低位
|
||||
*/
|
||||
return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 数据标识id部分
|
||||
* </p>
|
||||
*/
|
||||
protected static long getDatacenterId(long maxDatacenterId) {
|
||||
long id = 0L;
|
||||
try {
|
||||
InetAddress ip = InetAddress.getLocalHost();
|
||||
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
|
||||
if (network == null) {
|
||||
id = 1L;
|
||||
} else {
|
||||
byte[] mac = network.getHardwareAddress();
|
||||
id = ((0x000000FF & (long) mac[mac.length - 1])
|
||||
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
|
||||
id = id % (maxDatacenterId + 1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println(" getDatacenterId: " + e.getMessage());
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
//推特 26万个不重复的ID
|
||||
//参数1 参数2 是在0 -31 之间
|
||||
IdWorker idWorker = new IdWorker(0, 1);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
System.out.println(idWorker.nextId());//用于生成唯一的ID
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public synchronized long nextId() {
|
||||
long timestamp = timeGen();
|
||||
if (timestamp < lastTimestamp) {
|
||||
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
|
||||
}
|
||||
|
||||
if (lastTimestamp == timestamp) {
|
||||
// 当前毫秒内,则+1
|
||||
sequence = (sequence + 1) & sequenceMask;
|
||||
if (sequence == 0) {
|
||||
// 当前毫秒内计数满了,则等待下一秒
|
||||
timestamp = tilNextMillis(lastTimestamp);
|
||||
}
|
||||
} else {
|
||||
sequence = 0L;
|
||||
}
|
||||
lastTimestamp = timestamp;
|
||||
// ID偏移组合生成最终的ID,并返回ID
|
||||
long nextId = ((timestamp - twepoch) << timestampLeftShift)
|
||||
| (datacenterId << datacenterIdShift)
|
||||
| (workerId << workerIdShift) | sequence;
|
||||
|
||||
return nextId;
|
||||
}
|
||||
|
||||
private long tilNextMillis(final long lastTimestamp) {
|
||||
long timestamp = this.timeGen();
|
||||
while (timestamp <= lastTimestamp) {
|
||||
timestamp = this.timeGen();
|
||||
}
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
private long timeGen() {
|
||||
return System.currentTimeMillis();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,824 @@
|
||||
package com.renkang.im.util;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.renkang.im.ImSendEnum;
|
||||
import com.renkang.im.common.TencentCloudImApiConstant;
|
||||
import com.renkang.im.common.TencentCloudImConstant;
|
||||
import com.renkang.im.entity.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.JsonUtil;
|
||||
import org.jeecg.common.util.MyUploadUtil;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.util.TencentCloudImUtil
|
||||
* @description: 腾讯im基础配置
|
||||
* @User jinbo
|
||||
* @create: 2023-04-21 15:41
|
||||
* @Version 1.0
|
||||
**/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TencentCloudImUtil {
|
||||
|
||||
@Value("${IMConfig.requestUrl}")
|
||||
private String HTTPS_URL_PREFIX;
|
||||
private static final String APP_MANAGER = "administrator";
|
||||
private static final String REDIS_IM_USER_SIG = "silence:im_user_sig:";
|
||||
|
||||
@Value("${IMConfig.sdkAppId}")
|
||||
private long sdkAppId;
|
||||
|
||||
@Autowired
|
||||
private TximUtil tximUtil;
|
||||
|
||||
@Autowired
|
||||
private RedisUtil redisServiceUtil;
|
||||
|
||||
|
||||
public static Integer getRandomNum(int length) {
|
||||
if (length - 1 <= 0) {
|
||||
length = 2;
|
||||
}
|
||||
return (int) ((Math.random() + 1) * Math.pow(10, length - 1));
|
||||
}
|
||||
|
||||
public String getRandom() {
|
||||
return System.currentTimeMillis() + "" + StrUtil.subSuf(Math.random() + "", 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取腾讯云用户签名
|
||||
*/
|
||||
public String getTxCloudUserSig() {
|
||||
String userSig = (String) redisServiceUtil.get(REDIS_IM_USER_SIG + APP_MANAGER);
|
||||
if (StringUtils.isEmpty(userSig)) {
|
||||
userSig = tximUtil.genUserSig(APP_MANAGER);
|
||||
redisServiceUtil.set(REDIS_IM_USER_SIG + APP_MANAGER, userSig, 86400L);
|
||||
}
|
||||
return userSig;
|
||||
}
|
||||
|
||||
public String userSigAndroid(String userId) {
|
||||
String userSig = (String) redisServiceUtil.get(REDIS_IM_USER_SIG + userId);
|
||||
if (StringUtils.isEmpty(userSig)) {
|
||||
userSig = tximUtil.genUserSig(userId);
|
||||
redisServiceUtil.set(REDIS_IM_USER_SIG + userId, userSig, 86400L);
|
||||
}
|
||||
return userSig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取腾讯im请求路径
|
||||
*/
|
||||
private String getHttpsUrl(String imServiceApi, Integer random) {
|
||||
return String.format("%s%s?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json",
|
||||
HTTPS_URL_PREFIX, imServiceApi, sdkAppId, APP_MANAGER, this.getTxCloudUserSig(), random);
|
||||
}
|
||||
|
||||
|
||||
private String buildRequestUrl(String url) {
|
||||
String userSig = this.getTxCloudUserSig();
|
||||
// 云通信URL请求参数
|
||||
StringBuffer requestUrl = new StringBuffer(url + "?");
|
||||
requestUrl.append("sdkAppID=" + sdkAppId + "&identifier=" + APP_MANAGER + "&usersig=" + userSig + "&random="
|
||||
+ this.getRandom()).append("&contenttype=json");
|
||||
return requestUrl.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 导入单个账号
|
||||
*
|
||||
* @param userId 用户id
|
||||
*/
|
||||
public void accountImport(String userId) {
|
||||
accountImport(userId, null);
|
||||
}
|
||||
|
||||
public void accountImport(String userId, String userName) {
|
||||
accountImport(userId, userName, null);
|
||||
}
|
||||
|
||||
public void accountImport(String userId, String userName, String faceUrl) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.ACCOUNT_IMPORT, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("Identifier", userId);
|
||||
if (StringUtils.isNotEmpty(userName)) {
|
||||
jsonObject.put("Nick", userName);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(faceUrl)) {
|
||||
jsonObject.put("FaceUrl", faceUrl);
|
||||
}
|
||||
log.info("腾讯云im导入单个账号,请求参数:{}", jsonObject.toString());
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im导入单个账号,返回结果:{}", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入多个账号
|
||||
*
|
||||
* @param userIds 用户id集合
|
||||
*/
|
||||
public String multiAccountImport(List<String> userIds) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.MULTI_ACCOUNT_IMPORT, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("Accounts", userIds);
|
||||
log.info("腾讯云im导入多个账号,请求参数:{}", jsonObject);
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im导入多个账户,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除账号
|
||||
*
|
||||
* @param userIds 用户id集合
|
||||
*/
|
||||
public void accountDelete(List<String> userIds) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.ACCOUNT_DELETE, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("DeleteItem", getUserIdJsonList(userIds));
|
||||
log.info("腾讯云im删除账号,请求参数:{}", jsonObject);
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im删除账户,返回结果:{}", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询账号是否已经导入im
|
||||
*
|
||||
* @param userIds 用户id集合
|
||||
*/
|
||||
public String accountCheck(List<String> userIds) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.AccountManage.ACCOUNT_CHECK, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("CheckItem", getUserIdJsonList(userIds));
|
||||
log.info("腾讯云im查询账号,请求参数:{}", jsonObject.toString());
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im查询账号,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<JSONObject> getUserIdJsonList(List<String> userIds) {
|
||||
return userIds.stream().map(v -> {
|
||||
JSONObject userIdJson = new JSONObject();
|
||||
userIdJson.put("UserID", v);
|
||||
return userIdJson;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 单发单聊消息
|
||||
*
|
||||
* @param syncOtherMachine 是否同步消息到发送方(1-同步,2-不同步)
|
||||
* @param fromUserId 发送方用户id
|
||||
* @param toUserId 接收方用户id
|
||||
* @param msgType 消息对象类型
|
||||
* @param msgContent 消息内容
|
||||
*/
|
||||
public String sendMsg(Integer syncOtherMachine, String fromUserId, String toUserId, String msgType, String msgContent) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.SingleChatManage.SEND_MSG, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("SyncOtherMachine", syncOtherMachine);
|
||||
if (StringUtils.isNotEmpty(fromUserId)) {
|
||||
// 发送方不为空表示指定发送用户,为空表示为管理员发送消息
|
||||
jsonObject.put("From_Account", fromUserId);
|
||||
}
|
||||
jsonObject.put("To_Account", toUserId);
|
||||
jsonObject.put("MsgRandom", random);
|
||||
List<JSONObject> msgBody = getMsgBody(msgType, msgContent);
|
||||
jsonObject.put("MsgBody", msgBody);
|
||||
log.info("腾讯云im单发单聊消息,请求参数:{}", jsonObject.toString());
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im单发单聊消息,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 默认单发发群文本消息
|
||||
*
|
||||
* @return IMGroupMsgResVO
|
||||
*/
|
||||
public IMGroupMsgResDO sendGroupMsgText(ImGroupMsgTextReqDO imGroupMsgTextReqVO) {
|
||||
IMGroupMsgResDO res = new IMGroupMsgResDO();
|
||||
String url = HTTPS_URL_PREFIX+"v4/group_open_http_svc/send_group_msg";
|
||||
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("GroupId", imGroupMsgTextReqVO.getGroupId());
|
||||
param.put("MsgPriority", "High");
|
||||
param.put("Random", this.getRandom());
|
||||
// param.put("From_Account", imGroupMsgTextReqVO.getFromUserId());
|
||||
param.put("MsgRandom", this.getRandomNum(8));
|
||||
param.put("MsgTimeStamp", DateUtils.dateToUnixLong(new Date()));
|
||||
param.put("CloudCustomData", new JSONObject().fluentPut("fromAdmin", true).toJSONString());
|
||||
|
||||
|
||||
JSONObject jj = JSONObject.parseObject(imGroupMsgTextReqVO.getContent());
|
||||
jj.put("businessID", "system");
|
||||
try {
|
||||
//赋值
|
||||
JSONObject item = new JSONObject();
|
||||
JSONObject msgContentData = new JSONObject();
|
||||
msgContentData.put("Data", jj.toString());
|
||||
item.put("MsgType", ImSendEnum.TIMCustomElem.getValue());
|
||||
item.put("MsgContent", msgContentData);
|
||||
JSONArray msgBody = new JSONArray();
|
||||
msgBody.add(item);
|
||||
param.put("MsgBody", msgBody);
|
||||
String jsonStr = HttpUtil.doPost(buildRequestUrl(url), param.toString());
|
||||
if (StringUtils.isNotEmpty(jsonStr)) {
|
||||
JSONObject jsonObj = JSONObject.parseObject(jsonStr);
|
||||
if (jsonObj.containsKey("ErrorCode") && jsonObj.getInteger("ErrorCode") == 0) {
|
||||
log.info("=========={}==========", "发送成功!");
|
||||
}
|
||||
res = JsonUtil.toObject(jsonStr, IMGroupMsgResDO.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 默认单发发群文本消息
|
||||
*
|
||||
* @return IMGroupMsgResVO
|
||||
*/
|
||||
public IMGroupMsgResDO sendGroupMsgTextNew(ImGroupMsgTextReqDO imGroupMsgTextReqVO) {
|
||||
IMGroupMsgResDO res = new IMGroupMsgResDO();
|
||||
String url = HTTPS_URL_PREFIX+"v4/group_open_http_svc/send_group_msg";
|
||||
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("GroupId", imGroupMsgTextReqVO.getGroupId());
|
||||
param.put("MsgPriority", "High");
|
||||
param.put("Random", IdUtil.getSnowflakeNextIdStr());
|
||||
param.put("From_Account", imGroupMsgTextReqVO.getFromUserId());
|
||||
param.put("MsgRandom", this.getRandomNum(8));
|
||||
param.put("MsgTimeStamp", DateUtils.dateToUnixLong(new Date()));
|
||||
param.put("CloudCustomData", new JSONObject().fluentPut("fromAdmin", true).toJSONString());
|
||||
try {
|
||||
//赋值
|
||||
JSONObject item = new JSONObject();
|
||||
JSONObject msgContentData = new JSONObject();
|
||||
msgContentData.put("Text", imGroupMsgTextReqVO.getContent());
|
||||
item.put("MsgType", ImSendEnum.TIMTextElem.getValue());
|
||||
item.put("MsgContent", msgContentData);
|
||||
JSONArray msgBody = new JSONArray();
|
||||
msgBody.add(item);
|
||||
param.put("MsgBody", msgBody);
|
||||
String jsonStr = HttpUtil.doPost(buildRequestUrl(url), param.toString());
|
||||
if (StringUtils.isNotEmpty(jsonStr)) {
|
||||
JSONObject jsonObj = JSONObject.parseObject(jsonStr);
|
||||
if (jsonObj.containsKey("ErrorCode") && jsonObj.getInteger("ErrorCode") == 0) {
|
||||
log.info("=========={}==========", "发送成功!");
|
||||
}
|
||||
res = JsonUtil.toObject(jsonStr, IMGroupMsgResDO.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送群消息
|
||||
*
|
||||
* @param groupId
|
||||
* @param content
|
||||
* @return
|
||||
* @author
|
||||
*/
|
||||
public IMBaseDO sendGroupNotify(String groupId, String content) {
|
||||
|
||||
String url = HTTPS_URL_PREFIX+"v4/group_open_http_svc/send_group_system_notification";
|
||||
|
||||
// 云通信包参数
|
||||
JSONObject obj1 = new JSONObject();
|
||||
obj1.put("GroupId", groupId);
|
||||
obj1.put("Content", content);
|
||||
String tbu = obj1.toString();
|
||||
String result = cn.hutool.http.HttpUtil.post(buildRequestUrl(url), tbu);
|
||||
return JsonUtil.toObject(result, IMBaseDO.class);
|
||||
}
|
||||
|
||||
|
||||
public IMBaseDO sendGroupNotifyToUser(String groupId, List<String> userIds, String content) {
|
||||
|
||||
String url = HTTPS_URL_PREFIX+"v4/group_open_http_svc/send_group_system_notification";
|
||||
|
||||
// 云通信包参数
|
||||
JSONObject obj1 = new JSONObject();
|
||||
obj1.put("GroupId", groupId);
|
||||
obj1.put("Content", content);
|
||||
obj1.put("ToMembers_Account", userIds);
|
||||
String tbu = obj1.toString();
|
||||
String result = cn.hutool.http.HttpUtil.post(buildRequestUrl(url), tbu);
|
||||
return JsonUtil.toObject(result, IMBaseDO.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量发单聊消息
|
||||
*
|
||||
* @param syncOtherMachine 是否同步消息到发送方(1-同步,2-不同步)
|
||||
* @param fromUserId 发送方用户id
|
||||
* @param toUserIds 接收方用户id集合
|
||||
* @param msgType 消息对象类型
|
||||
* @param msgContent 消息内容
|
||||
*/
|
||||
public String batchSendMsg(Integer syncOtherMachine, String fromUserId, List<String> toUserIds, String msgType, String msgContent) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.SingleChatManage.BATCH_SEND_MSG, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("SyncOtherMachine", syncOtherMachine);
|
||||
if (StringUtils.isNotEmpty(fromUserId)) {
|
||||
// 发送方不为空表示指定发送用户,为空表示为管理员发送消息
|
||||
jsonObject.put("From_Account", fromUserId);
|
||||
}
|
||||
jsonObject.put("To_Account", toUserIds);
|
||||
jsonObject.put("MsgRandom", random);
|
||||
List<JSONObject> msgBody = getMsgBody(msgType, msgContent);
|
||||
jsonObject.put("MsgBody", msgBody);
|
||||
log.info("腾讯云im批量发单聊消息,请求参数:{}", jsonObject.toString());
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im批量发单聊消息,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拼接发送消息内容
|
||||
*
|
||||
* @param msgType 消息类型
|
||||
* @param msgContent 发送消息内容
|
||||
* @return 消息内容
|
||||
*/
|
||||
private List<JSONObject> getMsgBody(String msgType, String msgContent) {
|
||||
List<JSONObject> msgBody = new ArrayList<>();
|
||||
if (msgType.equals(TencentCloudImConstant.TIM_TEXT_ELEM)) {
|
||||
// 文本类型
|
||||
JSONObject msgBodyJson = new JSONObject();
|
||||
msgBodyJson.put("MsgType", msgType);
|
||||
JSONObject msgContentObj = new JSONObject();
|
||||
msgContentObj.put("Text", msgContent);
|
||||
msgBodyJson.put("MsgContent", msgContentObj);
|
||||
msgBody.add(msgBodyJson);
|
||||
}
|
||||
return msgBody;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询单聊消息
|
||||
*
|
||||
* @param fromUserId 发送方用户id
|
||||
* @param toUserId 接收方用户id
|
||||
* @param maxCnt 查询条数
|
||||
* @param startTime 起始时间(单位:秒)
|
||||
* @param endTime 结束时间(单位:秒)
|
||||
* @param lastMsgKey 最后一条消息的 MsgKey
|
||||
* @return 单聊消息列表
|
||||
*/
|
||||
public String adminGetRoamMsg(String fromUserId, String toUserId, Integer maxCnt, Long startTime, Long endTime, String lastMsgKey) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.SingleChatManage.ADMIN_GET_ROAM_MSG, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("From_Account", fromUserId);
|
||||
jsonObject.put("To_Account", toUserId);
|
||||
jsonObject.put("MaxCnt", maxCnt);
|
||||
jsonObject.put("MinTime", startTime);
|
||||
jsonObject.put("MaxTime", endTime);
|
||||
if (StringUtils.isNotEmpty(lastMsgKey)) {
|
||||
jsonObject.put("LastMsgKey", lastMsgKey);
|
||||
}
|
||||
log.info("腾讯云im查询单聊消息,请求参数:{}", jsonObject.toString());
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im查询单聊消息,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建群聊
|
||||
*
|
||||
* @param Owner_Account
|
||||
* @param Type
|
||||
* @param GroupId
|
||||
* @param Name
|
||||
* @param MemberList
|
||||
* @return
|
||||
*/
|
||||
public String creatGroup(String Owner_Account, String Type, String GroupId, String Name, List MemberList) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.CREATE_GROUP, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("Owner_Account", Owner_Account);
|
||||
jsonObject.put("Type", Type);
|
||||
jsonObject.put("Name", Name);
|
||||
jsonObject.put("GroupId", GroupId);
|
||||
jsonObject.put("MemberList", MemberList);
|
||||
log.info("腾讯云im创建群聊,请求参数:{}", jsonObject);
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im创建群聊,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加群成员
|
||||
*
|
||||
* @param GroupId
|
||||
* @param MemberList
|
||||
* @return
|
||||
*/
|
||||
public String addGroupMember(String GroupId, List MemberList) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.ADD_GROUP_MEMBER, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("GroupId", GroupId);
|
||||
jsonObject.put("MemberList", MemberList);
|
||||
log.info("腾讯云im创建群聊,请求参数:{}", jsonObject);
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im创建群聊,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拉取群聊历史消息
|
||||
*
|
||||
* @param groupId 要拉取历史消息的群组 ID
|
||||
* @param reqMsgNumber 拉取的历史消息的条数,目前一次请求最多返回20条历史消息,所以这里最好小于等于20
|
||||
* @param withRecalledMsg 是否带撤回的消息,填1表明需要拉取撤回后的消息;默认不拉取撤回后的消息
|
||||
* @return
|
||||
*/
|
||||
public String groupMessage(String groupId, Integer reqMsgNumber, Integer reqMsgSeq, Integer withRecalledMsg) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.GroupManage.GROUP_MSG_GET_SIMPLE, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("GroupId", groupId);
|
||||
jsonObject.put("ReqMsgNumber", reqMsgNumber);
|
||||
jsonObject.put("WithRecalledMsg", withRecalledMsg);
|
||||
jsonObject.put("ReqMsgSeq", reqMsgSeq);
|
||||
log.info("查询群聊历史消息,请求参数:{}", jsonObject);
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("查询群聊历史消息,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤回单聊消息
|
||||
*
|
||||
* @param fromUserId 发送方用户id
|
||||
* @param toUserId 接收方用户id
|
||||
* @param msgKey MsgKey
|
||||
*/
|
||||
public void adminMsgWithDraw(String fromUserId, String toUserId, String msgKey) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.SingleChatManage.ADMIN_MSG_WITH_DRAW, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("From_Account", fromUserId);
|
||||
jsonObject.put("To_Account", toUserId);
|
||||
jsonObject.put("MsgKey", msgKey);
|
||||
log.info("腾讯云im撤回单聊消息,请求参数:{}", jsonObject);
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im撤回单聊消息,返回结果:{}", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置单聊消息已读
|
||||
*
|
||||
* @param reportUserId 读取消息的用户
|
||||
* @param peerUserId 发送消息的用户
|
||||
*/
|
||||
public void adminSetMsgRead(String reportUserId, String peerUserId) {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.SingleChatManage.ADMIN_SET_MSG_READ, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("Report_Account", reportUserId);
|
||||
jsonObject.put("Peer_Account", peerUserId);
|
||||
log.info("腾讯云im设置单聊消息已读,请求参数:{}", jsonObject);
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im设置单聊消息已读,返回结果:{}", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉取群历史全量消息
|
||||
*
|
||||
* @param groupId 拉取消息的群 ID
|
||||
* @return 群历史全量消息
|
||||
*/
|
||||
public JSONObject groupMsgGetSimple(String groupId) {
|
||||
try {
|
||||
JSONObject groupMsgJsonData = groupMsgGetSimplePage(groupId, null);
|
||||
if (groupMsgJsonData == null) {
|
||||
return null;
|
||||
}
|
||||
Integer code = (Integer) groupMsgJsonData.get("ErrorCode");
|
||||
if (code != 0) {
|
||||
return null;
|
||||
}
|
||||
JSONArray rspMsgList = groupMsgJsonData.getJSONArray("RspMsgList");
|
||||
groupMsgRecursive(rspMsgList, groupId);
|
||||
groupMsgJsonData.put("RspMsgList", rspMsgList);
|
||||
return groupMsgJsonData;
|
||||
} catch (Exception e) {
|
||||
log.error("拉取群历史消息异常", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归算法,查询所有消息记录
|
||||
*
|
||||
* @param rspMsgList 消息记录集合
|
||||
* @param groupId 群ID
|
||||
*/
|
||||
public void groupMsgRecursive(JSONArray rspMsgList, String groupId) {
|
||||
JSONObject leastMsgSeq = (JSONObject) rspMsgList.get(rspMsgList.size() - 1);
|
||||
Integer msgSeq = leastMsgSeq.getInteger("MsgSeq");
|
||||
if (msgSeq > 1) {
|
||||
JSONObject groupMsgJsonData = groupMsgGetSimplePage(groupId, msgSeq - 1);
|
||||
if (groupMsgJsonData == null) {
|
||||
return;
|
||||
}
|
||||
Integer code = (Integer) groupMsgJsonData.get("ErrorCode");
|
||||
if (code != 0) {
|
||||
return;
|
||||
}
|
||||
rspMsgList.addAll(groupMsgJsonData.getJSONArray("RspMsgList"));
|
||||
groupMsgRecursive(rspMsgList, groupId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉取群历史消息
|
||||
*
|
||||
* @param groupId 拉取消息的群 ID
|
||||
* @param reqMsgSeq 请求的消息最大 seq,返回 <=ReqMsgSeq 的消息
|
||||
* @return 群历史消息
|
||||
*/
|
||||
public JSONObject groupMsgGetSimplePage(String groupId, Integer reqMsgSeq) {
|
||||
try {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String url = getHttpsUrl(TencentCloudImApiConstant.GroupManage.GROUP_MSG_GET_SIMPLE, random);
|
||||
JSONObject requestPackage = new JSONObject();
|
||||
requestPackage.put("GroupId", groupId); //拉取消息的群 ID
|
||||
if (reqMsgSeq != null) {
|
||||
requestPackage.put("ReqMsgSeq", reqMsgSeq); //请求的消息最大 seq,返回 <=ReqMsgSeq 的消息
|
||||
}
|
||||
requestPackage.put("ReqMsgNumber", 20); //需要拉取的消息条数
|
||||
String body = HttpUtil.doPost(url, requestPackage);
|
||||
log.info("拉取群历史消息应答包体报文:{}", body);
|
||||
if (StrUtil.isEmpty(body)) {
|
||||
return null;
|
||||
}
|
||||
return JSONObject.parseObject(body);
|
||||
} catch (Exception e) {
|
||||
log.error("拉取群历史消息异常", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MsgBody changeUrel(MsgBody msgBody, String msgType) {
|
||||
if (msgBody != null) {
|
||||
if (msgType != null) {
|
||||
String flieName = UUID.randomUUID().toString();
|
||||
String bizPath = "IM";
|
||||
if ("TIMImageElem".equalsIgnoreCase(msgType)) {
|
||||
log.info("存图片");
|
||||
ImgMsgContent img = JSON.parseObject(JSON.toJSONBytes(msgBody.getMsgContent()), ImgMsgContent.class);
|
||||
List<ImgMsg> img1 = img.getImageInfoArray();
|
||||
img1.forEach(imgMsg -> {
|
||||
|
||||
String newImgMsg = changeOldUrlToNew(imgMsg.getURL());
|
||||
imgMsg.setURL(newImgMsg);
|
||||
|
||||
FileInputStream fileInputStream = null;
|
||||
File fileByUrl = null;
|
||||
try {
|
||||
// 根据url下载图片
|
||||
fileByUrl = FileUtil.getFileByUrl(imgMsg.getURL());
|
||||
fileInputStream = new FileInputStream(fileByUrl);
|
||||
String url = MyUploadUtil.upload(fileInputStream, bizPath, flieName + fileByUrl.getName());
|
||||
// 更新图片地址
|
||||
imgMsg.setURL(url);
|
||||
} catch (Exception ignored) {
|
||||
// 如果出异常了,就不更新聊天记录的图片了
|
||||
} finally {
|
||||
if (fileInputStream != null) {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (fileByUrl != null) {
|
||||
fileByUrl.delete();
|
||||
}
|
||||
}
|
||||
});
|
||||
img.setImageInfoArray(img1);
|
||||
msgBody.setMsgContent(img);
|
||||
} else if ("TIMVideoFileElem".equalsIgnoreCase(msgType)) {
|
||||
log.info("存视频");
|
||||
VedioMsgContent img = JSON.parseObject(JSON.toJSONBytes(msgBody.getMsgContent()), VedioMsgContent.class);
|
||||
FileInputStream fileInputStream = null;
|
||||
File fileByUrl = null;
|
||||
try {
|
||||
|
||||
|
||||
String newImgMsg = changeOldUrlToNew(img.getThumbUrl());
|
||||
img.setThumbUrl(newImgMsg);
|
||||
|
||||
String newBideo = changeOldUrlToNew(img.getVideoUrl());
|
||||
img.setVideoUrl(newBideo);
|
||||
|
||||
// 根据url下载图片
|
||||
fileByUrl = FileUtil.getFileByUrl(img.getThumbUrl());
|
||||
fileInputStream = new FileInputStream(fileByUrl);
|
||||
String url = MyUploadUtil.upload(fileInputStream, bizPath, flieName + fileByUrl.getName());
|
||||
img.setThumbUrl(url);
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
fileByUrl.delete();
|
||||
// 根据url下载图片
|
||||
fileByUrl = FileUtil.getFileByUrl(img.getVideoUrl());
|
||||
fileInputStream = new FileInputStream(fileByUrl);
|
||||
String urlMp4 = MyUploadUtil.upload(fileInputStream, bizPath, flieName + fileByUrl.getName());
|
||||
img.setVideoUrl(urlMp4);
|
||||
} catch (Exception ignored) {
|
||||
// 如果出异常了,就不更新聊天记录的文件
|
||||
} finally {
|
||||
if (fileInputStream != null) {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (fileByUrl != null) {
|
||||
fileByUrl.delete();
|
||||
}
|
||||
}
|
||||
msgBody.setMsgContent(img);
|
||||
} else if ("TIMFileElem".equalsIgnoreCase(msgType)) {
|
||||
log.info("存文件");
|
||||
FileMsgContent file = JSON.parseObject(JSON.toJSONBytes(msgBody.getMsgContent()), FileMsgContent.class);
|
||||
FileInputStream fileInputStream = null;
|
||||
File fileByUrl = null;
|
||||
try {
|
||||
|
||||
String newImgMsg = changeOldUrlToNew(file.getUrl());
|
||||
file.setUrl(newImgMsg);
|
||||
|
||||
// 根据url下载文件
|
||||
fileByUrl = FileUtil.getFileByUrl(file.getUrl());
|
||||
fileInputStream = new FileInputStream(fileByUrl);
|
||||
String url = MyUploadUtil.upload(fileInputStream, bizPath, flieName + fileByUrl.getName());
|
||||
file.setUrl(url);
|
||||
} catch (Exception ignored) {
|
||||
// 如果出异常了,就不更新聊天记录的文件
|
||||
} finally {
|
||||
if (fileInputStream != null) {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (fileByUrl != null) {
|
||||
fileByUrl.delete();
|
||||
}
|
||||
}
|
||||
msgBody.setMsgContent(file);
|
||||
} else if ("TIMSoundElem".equalsIgnoreCase(msgType)) {
|
||||
log.info("语言文件");
|
||||
SoundMsgContent file = JSON.parseObject(JSON.toJSONBytes(msgBody.getMsgContent()), SoundMsgContent.class);
|
||||
FileInputStream fileInputStream = null;
|
||||
File fileByUrl = null;
|
||||
try {
|
||||
|
||||
String newImgMsg = changeOldUrlToNew(file.getUrl());
|
||||
file.setUrl(newImgMsg);
|
||||
|
||||
// 根据url下载文件
|
||||
fileByUrl = FileUtil.getFileByUrl(file.getUrl());
|
||||
fileInputStream = new FileInputStream(fileByUrl);
|
||||
String url = MyUploadUtil.upload(fileInputStream, bizPath, flieName + fileByUrl.getName());
|
||||
file.setUrl(url);
|
||||
} catch (Exception ignored) {
|
||||
// 如果出异常了,就不更新聊天记录的文件
|
||||
} finally {
|
||||
if (fileInputStream != null) {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (fileByUrl != null) {
|
||||
fileByUrl.delete();
|
||||
}
|
||||
}
|
||||
msgBody.setMsgContent(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return msgBody;
|
||||
}
|
||||
|
||||
public String changeOldUrlToNew(String url){
|
||||
String newUrl = "";
|
||||
if(url.contains("https://cn.imrich.qcloud.com")){
|
||||
newUrl = url.replace("https://cn.imrich.qcloud.com", "http://101.201.149.156:8609/qc");
|
||||
}
|
||||
if(url.contains("https://cos.ap-guangzhou.myqcloud.com")){
|
||||
newUrl = url.replace("https://cos.ap-guangzhou.myqcloud.com", "http://101.201.149.156:8609/gmc");
|
||||
}
|
||||
if(url.contains("https://cn.rich.my-imcloud.com")){
|
||||
newUrl = url.replace("https://cn.rich.my-imcloud.com", "http://101.201.149.156:8609/ic");
|
||||
}
|
||||
if(url.contains("https://cos.ap-shanghai.myqcloud.com")){
|
||||
newUrl = url.replace("https://cos.ap-shanghai.myqcloud.com", "http://101.201.149.156:8609/smc");
|
||||
}
|
||||
if(url.contains("https://cos.ap-shanghai.tencentcos.cn")){
|
||||
newUrl = url.replace("https://cos.ap-shanghai.tencentcos.cn", " http://101.201.149.156:8609/tc");
|
||||
}
|
||||
return newUrl;
|
||||
}
|
||||
|
||||
|
||||
public String getIpList() {
|
||||
Integer random = RandomUtils.nextInt(0, 999999999);
|
||||
String httpsUrl = getHttpsUrl(TencentCloudImApiConstant.OperationManage.GET_IP_LIST, random);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
log.info("腾讯云im获取服务器IP,请求参数:{}", jsonObject);
|
||||
String result = HttpUtil.doPost(httpsUrl, jsonObject);
|
||||
log.info("腾讯云im获取服务器IP,返回结果:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public Map<String,String> changeUrelArray(List<String> urlArray, String msgType) {
|
||||
Map<String,String> map = new HashMap<>();
|
||||
if (CollectionUtil.isNotEmpty(urlArray)) {
|
||||
if (msgType != null) {
|
||||
String flieName = UUID.randomUUID().toString();
|
||||
String bizPath = "IM";
|
||||
if ("TIMImageElem".equalsIgnoreCase(msgType)) {
|
||||
log.info("存图片");
|
||||
|
||||
urlArray.forEach(imgMsg -> {
|
||||
FileInputStream fileInputStream = null;
|
||||
File fileByUrl = null;
|
||||
try {
|
||||
// 根据url下载图片
|
||||
fileByUrl = FileUtil.getFileByUrl(imgMsg);
|
||||
fileInputStream = new FileInputStream(fileByUrl);
|
||||
String url = MyUploadUtil.upload(fileInputStream, bizPath, flieName + fileByUrl.getName());
|
||||
// 更新图片地址
|
||||
map.put(imgMsg,url);
|
||||
} catch (Exception ignored) {
|
||||
// 如果出异常了,就不更新聊天记录的图片了
|
||||
} finally {
|
||||
if (fileInputStream != null) {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
if (fileByUrl != null) {
|
||||
fileByUrl.delete();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
package com.renkang.im.util;
|
||||
|
||||
/**
|
||||
* @program: cqyt-platform
|
||||
* @ClassName com.renkang.im.util.TximUtil
|
||||
* @description: TODO
|
||||
* @User jinbo
|
||||
* @create: 2023-05-11 17:52
|
||||
* @Version 1.0
|
||||
**/
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TximUtil {
|
||||
|
||||
@Value("${IMConfig.sdkAppId}")
|
||||
private long sdkAppId;
|
||||
@Value("${IMConfig.secretKey}")
|
||||
private String secretKey;
|
||||
|
||||
private static byte[] base64EncodeUrl(byte[] input) {
|
||||
byte[] base64 = Base64.getEncoder().encode(input);
|
||||
for (int i = 0; i < base64.length; ++i)
|
||||
switch (base64[i]) {
|
||||
case '+':
|
||||
base64[i] = '*';
|
||||
break;
|
||||
case '/':
|
||||
base64[i] = '-';
|
||||
break;
|
||||
case '=':
|
||||
base64[i] = '_';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return base64;
|
||||
}
|
||||
|
||||
/**
|
||||
* 【功能说明】用于签发 TRTC 和 IM 服务中必须要使用的 UserSig 鉴权票据
|
||||
* <p>
|
||||
* 【参数说明】
|
||||
*
|
||||
* @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
|
||||
* @return usersig -生成的签名
|
||||
*/
|
||||
public String genUserSig(String userid) {
|
||||
return genUserSig(userid, 259200, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【功能说明】用于签发 TRTC 和 IM 服务中必须要使用的 UserSig 鉴权票据
|
||||
* <p>
|
||||
* 【参数说明】
|
||||
*
|
||||
* @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
|
||||
* @param expire - UserSig 票据的过期时间,单位是秒,比如 86400 代表生成的 UserSig 票据在一天后就无法再使用了。
|
||||
* @return usersig -生成的签名
|
||||
*/
|
||||
public String genUserSig(String userid, long expire) {
|
||||
return genUserSig(userid, expire, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【功能说明】
|
||||
* 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。
|
||||
* PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力:
|
||||
* - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。
|
||||
* - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。
|
||||
* 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】/【应用管理】/【应用信息】中打开“启动权限密钥”开关。
|
||||
* <p>
|
||||
* 【参数说明】
|
||||
*
|
||||
* @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
|
||||
* @param expire - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。
|
||||
* @param roomid - 房间号,用于指定该 userid 可以进入的房间号
|
||||
* @param privilegeMap - 权限位,使用了一个字节中的 8 个比特位,分别代表八个具体的功能权限开关:
|
||||
* - 第 1 位:0000 0001 = 1,创建房间的权限
|
||||
* - 第 2 位:0000 0010 = 2,加入房间的权限
|
||||
* - 第 3 位:0000 0100 = 4,发送语音的权限
|
||||
* - 第 4 位:0000 1000 = 8,接收语音的权限
|
||||
* - 第 5 位:0001 0000 = 16,发送视频的权限
|
||||
* - 第 6 位:0010 0000 = 32,接收视频的权限
|
||||
* - 第 7 位:0100 0000 = 64,发送辅路(也就是屏幕分享)视频的权限
|
||||
* - 第 8 位:1000 0000 = 200,接收辅路(也就是屏幕分享)视频的权限
|
||||
* - privilegeMap == 1111 1111 == 255 代表该 userid 在该 roomid 房间内的所有功能权限。
|
||||
* - privilegeMap == 0010 1010 == 42 代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。
|
||||
* @return usersig - 生成带userbuf的签名
|
||||
*/
|
||||
public String genPrivateMapKey(String userid, long expire, long roomid, long privilegeMap) {
|
||||
byte[] userbuf = genUserBuf(userid, roomid, expire, privilegeMap, 0, ""); //生成userbuf
|
||||
return genUserSig(userid, expire, userbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【功能说明】
|
||||
* 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。
|
||||
* PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力:
|
||||
* - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。
|
||||
* - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。
|
||||
* 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】/【应用管理】/【应用信息】中打开“启动权限密钥”开关。
|
||||
* <p>
|
||||
* 【参数说明】
|
||||
*
|
||||
* @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
|
||||
* @param expire - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。
|
||||
* @param roomstr - 字符串房间号,用于指定该 userid 可以进入的房间号
|
||||
* @param privilegeMap - 权限位,使用了一个字节中的 8 个比特位,分别代表八个具体的功能权限开关:
|
||||
* - 第 1 位:0000 0001 = 1,创建房间的权限
|
||||
* - 第 2 位:0000 0010 = 2,加入房间的权限
|
||||
* - 第 3 位:0000 0100 = 4,发送语音的权限
|
||||
* - 第 4 位:0000 1000 = 8,接收语音的权限
|
||||
* - 第 5 位:0001 0000 = 16,发送视频的权限
|
||||
* - 第 6 位:0010 0000 = 32,接收视频的权限
|
||||
* - 第 7 位:0100 0000 = 64,发送辅路(也就是屏幕分享)视频的权限
|
||||
* - 第 8 位:1000 0000 = 200,接收辅路(也就是屏幕分享)视频的权限
|
||||
* - privilegeMap == 1111 1111 == 255 代表该 userid 在该 roomid 房间内的所有功能权限。
|
||||
* - privilegeMap == 0010 1010 == 42 代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。
|
||||
* @return usersig - 生成带userbuf的签名
|
||||
*/
|
||||
public String genPrivateMapKeyWithStringRoomID(String userid, long expire, String roomstr, long privilegeMap) {
|
||||
byte[] userbuf = genUserBuf(userid, 0, expire, privilegeMap, 0, roomstr); //生成userbuf
|
||||
return genUserSig(userid, expire, userbuf);
|
||||
}
|
||||
|
||||
private String hmacsha256(String identifier, long currTime, long expire, String base64Userbuf) {
|
||||
String contentToBeSigned = "TLS.identifier:" + identifier + "\n"
|
||||
+ "TLS.sdkappid:" + sdkAppId + "\n"
|
||||
+ "TLS.time:" + currTime + "\n"
|
||||
+ "TLS.expire:" + expire + "\n";
|
||||
if (null != base64Userbuf) {
|
||||
contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
|
||||
}
|
||||
try {
|
||||
byte[] byteKey = secretKey.getBytes(StandardCharsets.UTF_8);
|
||||
Mac hmac = Mac.getInstance("HmacSHA256");
|
||||
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
|
||||
hmac.init(keySpec);
|
||||
byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8));
|
||||
return (Base64.getEncoder().encodeToString(byteSig)).replaceAll("\\s*", "");
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String genUserSig(String userid, long expire, byte[] userbuf) {
|
||||
|
||||
long currTime = System.currentTimeMillis() / 1000;
|
||||
|
||||
JSONObject sigDoc = new JSONObject();
|
||||
sigDoc.put("TLS.ver", "2.0");
|
||||
sigDoc.put("TLS.identifier", userid);
|
||||
sigDoc.put("TLS.sdkappid", sdkAppId);
|
||||
sigDoc.put("TLS.expire", expire);
|
||||
sigDoc.put("TLS.time", currTime);
|
||||
|
||||
String base64UserBuf = null;
|
||||
if (null != userbuf) {
|
||||
base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
|
||||
sigDoc.put("TLS.userbuf", base64UserBuf);
|
||||
}
|
||||
String sig = hmacsha256(userid, currTime, expire, base64UserBuf);
|
||||
if (sig.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
sigDoc.put("TLS.sig", sig);
|
||||
Deflater compressor = new Deflater();
|
||||
compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
|
||||
compressor.finish();
|
||||
byte[] compressedBytes = new byte[2048];
|
||||
int compressedBytesLength = compressor.deflate(compressedBytes);
|
||||
compressor.end();
|
||||
return (new String(base64EncodeUrl(Arrays.copyOfRange(compressedBytes,
|
||||
0, compressedBytesLength)))).replaceAll("\\s*", "");
|
||||
}
|
||||
|
||||
public byte[] genUserBuf(String account, long dwAuthID, long dwExpTime,
|
||||
long dwPrivilegeMap, long dwAccountType, String RoomStr) {
|
||||
//视频校验位需要用到的字段,按照网络字节序放入buf中
|
||||
/*
|
||||
cVer unsigned char/1 版本号,填0
|
||||
wAccountLen unsigned short /2 第三方自己的帐号长度
|
||||
account wAccountLen 第三方自己的帐号字符
|
||||
dwSdkAppid unsigned int/4 sdkappid
|
||||
dwAuthID unsigned int/4 群组号码
|
||||
dwExpTime unsigned int/4 过期时间 ,直接使用填入的值
|
||||
dwPrivilegeMap unsigned int/4 权限位,主播0xff,观众0xab
|
||||
dwAccountType unsigned int/4 第三方帐号类型
|
||||
*/
|
||||
int accountLength = account.length();
|
||||
int roomStrLength = RoomStr.length();
|
||||
int offset = 0;
|
||||
int bufLength = 1 + 2 + accountLength + 20;
|
||||
if (roomStrLength > 0) {
|
||||
bufLength = bufLength + 2 + roomStrLength;
|
||||
}
|
||||
byte[] userbuf = new byte[bufLength];
|
||||
|
||||
//cVer
|
||||
if (roomStrLength > 0) {
|
||||
userbuf[offset++] = 1;
|
||||
} else {
|
||||
userbuf[offset++] = 0;
|
||||
}
|
||||
|
||||
//wAccountLen
|
||||
userbuf[offset++] = (byte) ((accountLength & 0xFF00) >> 8);
|
||||
userbuf[offset++] = (byte) (accountLength & 0x00FF);
|
||||
|
||||
//account
|
||||
for (; offset < 3 + accountLength; ++offset) {
|
||||
userbuf[offset] = (byte) account.charAt(offset - 3);
|
||||
}
|
||||
|
||||
//dwSdkAppid
|
||||
userbuf[offset++] = (byte) ((sdkAppId & 0xFF000000) >> 24);
|
||||
userbuf[offset++] = (byte) ((sdkAppId & 0x00FF0000) >> 16);
|
||||
userbuf[offset++] = (byte) ((sdkAppId & 0x0000FF00) >> 8);
|
||||
userbuf[offset++] = (byte) (sdkAppId & 0x000000FF);
|
||||
|
||||
//dwAuthId,房间号
|
||||
userbuf[offset++] = (byte) ((dwAuthID & 0xFF000000) >> 24);
|
||||
userbuf[offset++] = (byte) ((dwAuthID & 0x00FF0000) >> 16);
|
||||
userbuf[offset++] = (byte) ((dwAuthID & 0x0000FF00) >> 8);
|
||||
userbuf[offset++] = (byte) (dwAuthID & 0x000000FF);
|
||||
|
||||
//expire,过期时间,当前时间 + 有效期(单位:秒)
|
||||
long currTime = System.currentTimeMillis() / 1000;
|
||||
long expire = currTime + dwExpTime;
|
||||
userbuf[offset++] = (byte) ((expire & 0xFF000000) >> 24);
|
||||
userbuf[offset++] = (byte) ((expire & 0x00FF0000) >> 16);
|
||||
userbuf[offset++] = (byte) ((expire & 0x0000FF00) >> 8);
|
||||
userbuf[offset++] = (byte) (expire & 0x000000FF);
|
||||
|
||||
//dwPrivilegeMap,权限位
|
||||
userbuf[offset++] = (byte) ((dwPrivilegeMap & 0xFF000000) >> 24);
|
||||
userbuf[offset++] = (byte) ((dwPrivilegeMap & 0x00FF0000) >> 16);
|
||||
userbuf[offset++] = (byte) ((dwPrivilegeMap & 0x0000FF00) >> 8);
|
||||
userbuf[offset++] = (byte) (dwPrivilegeMap & 0x000000FF);
|
||||
|
||||
//dwAccountType,账户类型
|
||||
userbuf[offset++] = (byte) ((dwAccountType & 0xFF000000) >> 24);
|
||||
userbuf[offset++] = (byte) ((dwAccountType & 0x00FF0000) >> 16);
|
||||
userbuf[offset++] = (byte) ((dwAccountType & 0x0000FF00) >> 8);
|
||||
userbuf[offset++] = (byte) (dwAccountType & 0x000000FF);
|
||||
|
||||
|
||||
if (roomStrLength > 0) {
|
||||
//roomStrLen
|
||||
userbuf[offset++] = (byte) ((roomStrLength & 0xFF00) >> 8);
|
||||
userbuf[offset++] = (byte) (roomStrLength & 0x00FF);
|
||||
|
||||
//roomStr
|
||||
for (; offset < bufLength; ++offset) {
|
||||
userbuf[offset] = (byte) RoomStr.charAt(offset - (bufLength - roomStrLength));
|
||||
}
|
||||
}
|
||||
return userbuf;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package com.renkang.im.util;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.security.SecureRandom;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* @ClassName: UniqId
|
||||
* @Description: 生成32位全局唯一id
|
||||
*/
|
||||
public class UniqId {
|
||||
|
||||
private static UniqId me = new UniqId();
|
||||
private final Random random = new SecureRandom();
|
||||
private final UniqTimer timer = new UniqTimer();
|
||||
private String hostAddr;
|
||||
private boolean isOutputInfo = false;
|
||||
|
||||
private UniqId() {
|
||||
try {
|
||||
final InetAddress addr = InetAddress.getLocalHost();
|
||||
|
||||
hostAddr = addr.getHostAddress();
|
||||
} catch (final IOException e) {
|
||||
System.err.println("[UniqID] Get HostAddr Error" + e);
|
||||
hostAddr = String.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
if (null == hostAddr || hostAddr.trim().length() == 0 || "127.0.0.1".equals(hostAddr)) {
|
||||
hostAddr = String.valueOf(System.currentTimeMillis());
|
||||
|
||||
}
|
||||
hostAddr = hostAddr.substring(hostAddr.length() - 2).replace(".", "0");
|
||||
|
||||
if (isOutputInfo) {
|
||||
System.out.println("[UniqID]hostAddr is:" + hostAddr + "----length:" + hostAddr.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取UniqID实例
|
||||
*
|
||||
* @return UniqId
|
||||
*/
|
||||
public static UniqId getInstance() {
|
||||
me.isOutputInfo = false;
|
||||
return me;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取UniqID实例
|
||||
*
|
||||
* @return UniqId
|
||||
*/
|
||||
public static UniqId getInstanceWithLog() {
|
||||
me.isOutputInfo = true;
|
||||
return me;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化日期,规范成yyyy-MM-dd
|
||||
*
|
||||
* @param timestamp
|
||||
* @return
|
||||
*/
|
||||
public static String timestamp2Date(long timestamp) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
return dateFormat.format(new Date(timestamp * 1000));
|
||||
}
|
||||
|
||||
private static String timestamp2Datetimes(long timestamp) {
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
return dateFormat.format(new Date(timestamp));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
//打印生成过程
|
||||
UniqId.getInstanceWithLog().getUniqID();
|
||||
|
||||
//建议如下使用
|
||||
// String uid = UniqId.getInstance().getUniqID();
|
||||
// System.out.println(uid);
|
||||
// System.out.println(uid.length());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得不会重复的毫秒数
|
||||
*
|
||||
* @return 不会重复的时间
|
||||
*/
|
||||
public String getUniqTime() {
|
||||
String time = timer.getCurrentTime();
|
||||
if (isOutputInfo) {
|
||||
System.out.println("[UniqID.getUniqTime]" + time + "----length:" + time.length());
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得UniqId
|
||||
*
|
||||
* @return uniqTime-randomNum-hostAddr-threadId
|
||||
*/
|
||||
public String getUniqID() {
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
final String t = getUniqTime();
|
||||
int randomNumber = random.nextInt(8999999) + 1000000;
|
||||
sb.append(t);
|
||||
sb.append(hostAddr);
|
||||
sb.append(getUniqThreadCode());
|
||||
sb.append(randomNumber);
|
||||
if (isOutputInfo) {
|
||||
System.out.println("[UniqID.randomNumber]" + randomNumber + "----length:" + String.valueOf(randomNumber).length());
|
||||
System.out.println("[UniqID.getUniqID]" + sb.toString() + "----length:" + String.valueOf(sb).length());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getUniqThreadCode() {
|
||||
String threadCode = StringUtils.left(String.valueOf(Thread.currentThread().hashCode()), 9);
|
||||
if (isOutputInfo) {
|
||||
System.out.println("[UniqID.getUniqThreadCode]" + threadCode + "----length:" + threadCode.length());
|
||||
}
|
||||
return StringUtils.leftPad(threadCode, 9, "0");
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现不重复的时间
|
||||
*/
|
||||
private class UniqTimer {
|
||||
private final AtomicLong lastTime = new AtomicLong(System.currentTimeMillis());
|
||||
|
||||
public String getCurrentTime() {
|
||||
if (!timestamp2Date(this.lastTime.incrementAndGet()).equals(timestamp2Date(System.currentTimeMillis()))) {
|
||||
lastTime.set(System.currentTimeMillis() + random.nextInt(10000));
|
||||
}
|
||||
return timestamp2Datetimes(this.lastTime.incrementAndGet());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>health-im</artifactId>
|
||||
<groupId>com.renkang</groupId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>health-im-start</artifactId>
|
||||
<dependencies>
|
||||
<!--微服务启动 starter-->
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<artifactId>jeecg-boot-starter-cloud</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--引入业务模块-->
|
||||
<dependency>
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>health-im-biz</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<!-- 打包名称 -->
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>divide-package</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<start-class>com.renkang.HealthIMCloudApplication</start-class>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.renkang;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = {"com.renkang", "org.jeecg"})
|
||||
@EnableFeignClients(basePackages = {"org.jeecg", "com.renkang"})
|
||||
public class HealthIMCloudApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(HealthIMCloudApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
PROFILE_NAME=dev
|
||||
SERVER_PORT=7012
|
||||
NACOS_SERVER_ADDR=localhost:8848
|
||||
NACOS_USERNAME=nacos
|
||||
NACOS_PASSWORD=nacos
|
||||
NACOS_NAMESPACE=f3f65fb2-303b-4bf7-bccb-4755886503c1
|
||||
NACOS_GROUP=dev
|
||||
FILE_SERVER_URL=http://fileserver.yg.dt.io
|
||||
@@ -0,0 +1,28 @@
|
||||
server:
|
||||
port: ${SERVER_PORT:7012}
|
||||
spring:
|
||||
application:
|
||||
name: health-im
|
||||
config:
|
||||
import:
|
||||
- optional:nacos:jeecg.yaml
|
||||
- optional:nacos:${spring.application.name}-${PROFILE_NAME}.yaml
|
||||
cloud:
|
||||
nacos:
|
||||
server-addr: ${NACOS_SERVER_ADDR}
|
||||
username: ${NACOS_USERNAME:nacos}
|
||||
password: ${NACOS_PASSWORD:nacos}
|
||||
config:
|
||||
enabled: true
|
||||
namespace: ${NACOS_NAMESPACE:}
|
||||
group: ${NACOS_GROUP:DEFAULT_GROUP}
|
||||
server-addr: ${spring.cloud.nacos.server-addr}
|
||||
username: ${spring.cloud.nacos.username}
|
||||
password: ${spring.cloud.nacos.password}
|
||||
discovery:
|
||||
enabled: true
|
||||
namespace: ${NACOS_NAMESPACE:}
|
||||
group: ${NACOS_GROUP:DEFAULT_GROUP}
|
||||
server-addr: ${spring.cloud.nacos.server-addr}
|
||||
username: ${spring.cloud.nacos.username}
|
||||
password: ${spring.cloud.nacos.password}
|
||||
@@ -0,0 +1,17 @@
|
||||
-- ceishi.im_msg_record_all definition
|
||||
|
||||
CREATE TABLE `im_msg_record_all`
|
||||
(
|
||||
`id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`groupId` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '群组ID',
|
||||
`from_account` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '发送者账号',
|
||||
`to_account` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '接受者账号',
|
||||
`sendtime` datetime DEFAULT NULL COMMENT '发送时间',
|
||||
`msgtype` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '消息类型 1单聊 2群聊',
|
||||
`msgcontent` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '消息内容',
|
||||
`contenttype` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '消息元素类别;目前支持的消息对象包括:TIMTextElem(文本消息),TIMLocationElem(位置消息),TIMFaceElem(表情消息),TIMCustomElem(自定义消息),TIMSoundElem(语音消息),TIMImageElem(图像消息),TIMFileElem(文件消息),TIMVideoFileElem(视频消息)',
|
||||
`msgseq` bigint NOT NULL COMMENT '消息序列',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_0900_ai_ci COMMENT ='IM消息表';
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>jeecg-boot-parent</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>4.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>health-im</artifactId>
|
||||
<groupId>com.renkang</groupId>
|
||||
<version>2.0.0</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.install.skip>true</maven.install.skip>
|
||||
</properties>
|
||||
|
||||
<!--项目子模块-->
|
||||
<modules>
|
||||
<module>health-im-api</module>
|
||||
<module>health-im-biz</module>
|
||||
<module>health-im-start</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
||||
Reference in New Issue
Block a user