├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── YeIM-Uni-Server.postman_collection.json ├── database.sql ├── pom.xml └── src ├── main ├── java │ └── cn │ │ └── wzjun1 │ │ └── yeimServer │ │ ├── .DS_Store │ │ ├── YeimServerApplication.java │ │ ├── annotation │ │ └── UserAuthorization.java │ │ ├── config │ │ ├── PrefixRedisSerializer.java │ │ ├── RedisConfig.java │ │ ├── WebConfig.java │ │ └── WebSocketConfig.java │ │ ├── constant │ │ ├── AddFriendType.java │ │ ├── ConversationType.java │ │ ├── FriendApplyStatus.java │ │ ├── GroupApplyStatus.java │ │ ├── JoinGroupMode.java │ │ ├── MessageStatus.java │ │ ├── MessageType.java │ │ └── StatusCode.java │ │ ├── controller │ │ ├── ConversatioController.java │ │ ├── FriendController.java │ │ ├── GroupController.java │ │ ├── GroupUserController.java │ │ ├── MessageController.java │ │ ├── UploadController.java │ │ └── UserController.java │ │ ├── domain │ │ ├── Conversation.java │ │ ├── ConversationV0.java │ │ ├── Friend.java │ │ ├── FriendApply.java │ │ ├── FriendApplyV0.java │ │ ├── FriendV0.java │ │ ├── Group.java │ │ ├── GroupApply.java │ │ ├── GroupMessage.java │ │ ├── GroupUser.java │ │ ├── Message.java │ │ ├── User.java │ │ ├── UserBlackList.java │ │ └── UserBlackListV0.java │ │ ├── dto │ │ ├── friend │ │ │ ├── AddFriendDTO.java │ │ │ ├── DeleteFriendDTO.java │ │ │ └── UpdateFriendDTO.java │ │ ├── group │ │ │ ├── GroupCreateDTO.java │ │ │ ├── GroupEditDTO.java │ │ │ └── GroupUserAddDTO.java │ │ ├── message │ │ │ └── MessageSaveDTO.java │ │ └── user │ │ │ ├── UserBlackListAddDTO.java │ │ │ ├── UserRegisterDTO.java │ │ │ ├── UserTokenDTO.java │ │ │ └── UserUpdateDTO.java │ │ ├── exception │ │ ├── FileUploadException.java │ │ ├── FrequencyLimitException.java │ │ ├── LoginExpireException.java │ │ ├── ParamsException.java │ │ ├── conversation │ │ │ └── ConversationNotFoundException.java │ │ ├── friend │ │ │ ├── ApplyNeedException.java │ │ │ ├── DuplicateException.java │ │ │ ├── FriendApplyNotFoundException.java │ │ │ └── FriendNotFoundException.java │ │ ├── group │ │ │ ├── GroupAllMuteException.java │ │ │ ├── GroupDuplicateException.java │ │ │ ├── GroupMuteException.java │ │ │ ├── GroupNoEntryException.java │ │ │ ├── GroupNotFoundException.java │ │ │ ├── GroupOnlyDissolveException.java │ │ │ ├── GroupPermissionDeniedException.java │ │ │ ├── GroupUserInsertLimitException.java │ │ │ └── NoGroupUserException.java │ │ ├── message │ │ │ ├── IdException.java │ │ │ ├── MessageRejectedException.java │ │ │ └── ToUserIdNotFoundException.java │ │ └── user │ │ │ ├── ExpireException.java │ │ │ ├── SignException.java │ │ │ ├── UserDuplicateException.java │ │ │ ├── UserFriendDenyException.java │ │ │ ├── UserFriendDuplicateException.java │ │ │ └── UserNotFoundException.java │ │ ├── handler │ │ └── GlobalExceptionHandler.java │ │ ├── interceptor │ │ ├── LoginUserContext.java │ │ └── UserAuthorizationInterceptor.java │ │ ├── mapper │ │ ├── ConversationMapper.java │ │ ├── FriendApplyMapper.java │ │ ├── FriendMapper.java │ │ ├── GroupApplyMapper.java │ │ ├── GroupMapper.java │ │ ├── GroupMessageMapper.java │ │ ├── GroupUserMapper.java │ │ ├── MessageMapper.java │ │ ├── UserBlackListMapper.java │ │ └── UserMapper.java │ │ ├── pojo │ │ ├── YeIMPushConfig.java │ │ └── push │ │ │ └── GtConfig.java │ │ ├── result │ │ ├── Result.java │ │ └── vo │ │ │ └── AddUserToGroupResultVO.java │ │ ├── service │ │ ├── AsyncService.java │ │ ├── ConversationService.java │ │ ├── FriendApplyService.java │ │ ├── FriendService.java │ │ ├── GroupApplyService.java │ │ ├── GroupMessageService.java │ │ ├── GroupService.java │ │ ├── GroupUserService.java │ │ ├── MessageService.java │ │ ├── OnlineChannel.java │ │ ├── PushService.java │ │ ├── UploadService.java │ │ ├── UserBlackListService.java │ │ ├── UserService.java │ │ └── impl │ │ │ ├── AsyncServiceImpl.java │ │ │ ├── ConversationServiceImpl.java │ │ │ ├── FriendApplyServiceImpl.java │ │ │ ├── FriendServiceImpl.java │ │ │ ├── GroupApplyServiceImpl.java │ │ │ ├── GroupMessageServiceImpl.java │ │ │ ├── GroupServiceImpl.java │ │ │ ├── GroupUserServiceImpl.java │ │ │ ├── MessageServiceImpl.java │ │ │ ├── OnlineChannelimpl.java │ │ │ ├── PushServiceImpl.java │ │ │ ├── UploadServiceImpl.java │ │ │ ├── UserBlackListServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ ├── socket │ │ └── WebSocket.java │ │ └── utils │ │ ├── Common.java │ │ ├── JavaCvUtil.java │ │ ├── MD5Util.java │ │ ├── RedisUtil.java │ │ └── SpringUtils.java └── resources │ ├── application-dev.properties │ ├── application-prod.properties │ ├── application.properties │ ├── config │ ├── dev │ │ ├── database.properties │ │ ├── redis.properties │ │ ├── yeim.properties │ │ └── yeim │ │ │ ├── push.properties │ │ │ └── storage.properties │ └── prod │ │ ├── database.properties │ │ ├── redis.properties │ │ ├── yeim.properties │ │ └── yeim │ │ ├── push.properties │ │ └── storage.properties │ ├── mapper │ ├── ConversationMapper.xml │ ├── FriendApplyMapper.xml │ ├── FriendMapper.xml │ ├── GroupApplyMapper.xml │ ├── GroupMapper.xml │ ├── GroupMessageMapper.xml │ ├── GroupUserMapper.xml │ ├── MessageMapper.xml │ ├── UserBlackListMapper.xml │ └── UserMapper.xml │ └── spy.properties └── test └── java └── cn └── wzjun1 └── yeimServer └── YeimServerApplicationTests.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore 2 | *.idea 3 | target 4 | .DS_Store 5 | .gitattributes 6 | src/main/java/cn/wzjun1/yeimServer/.DS_Store 7 | *.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![微信公众号.png](https://s2.loli.net/2024/03/31/MHE1CD3WtP2nUOQ.jpg) 2 |

3 | YeIM-Uni-Server 4 |
5 |
6 | YeIM-Uni-SDK服务端 7 |
8 |
9 | 查看文档 10 | | 备用文档 11 |
12 | 13 |

14 | 15 | `此为社区开源项目,用于学习交流使用,禁止用于非法途径。如作他用所造成的一切法律责任均不由作者承担。` 16 | 17 | - 注:不是聊天项目!不是聊天项目!不是聊天项目!只是SDK,通过使用SDK里的一系列接口可实现聊天,跟环信、融云、腾讯云即时通信等等类似的一种可实现聊天的IMSDK。 18 | 19 | [YeIM-Uni-SDK](https://github.com/wzJun1/YeIM-Uni-SDK)是可以`私有化部署`的`全开源`即时通讯`js-sdk`,仅需集成 SDK 即可轻松实现聊天能力,支持Web、[uni-app](https://uniapp.dcloud.net.cn/)接入使用,满足通信需要。 20 | 21 | 支持私聊和群聊,支持发送的消息类型:文字消息、图片消息、语音消息、视频消息、位置消息、自定义消息。 22 | 23 | [YeIM-Uni-Server](https://github.com/wzJun1/YeIM-Uni-Server)是[YeIM-Uni-SDK](https://github.com/wzJun1/YeIM-Uni-SDK)的配套服务端。 24 | 25 | 因此[YeIM-Uni-SDK](https://github.com/wzJun1/YeIM-Uni-SDK)必须搭配[YeIM-Uni-Server](https://github.com/wzJun1/YeIM-Uni-Server)服务端,开箱即用。 26 | 27 | ## 支持哪些端? 28 | 29 | `YeIM-Uni-SDK`由`JavaScript`构建,支持Web端、uni-app端的项目接入使用。 30 | 31 | 当项目在uni环境打包,SDK将使用`uni-app API`,否则使用JS相关API,详情可查看源码。 32 | 33 | 作为通用JSSDK,`YeIM-Uni-SDK`支持包括不限于H5(uni和非uni环境均可)、Android APP、iOS APP、微信小程序、字节小程序、支付宝小程序、百度小程序(仅限uni环境)等平台项目。 34 | 35 | ## 使用文档 36 | 37 | 查看文档 38 | | 备用文档 39 | 40 | ## 反馈与共建 41 | 42 | - 普通交流QQ群:[391276294](https://qm.qq.com/cgi-bin/qm/qr?k=hEQnVRj3c1B0gDpD2QJrD7UIfWMzCUuM&jump_from=webapi&authKey=kbrD7NHXGIPaiVb2puw+vJeRCIQSXVhIci7eFvFLBH/UjGt+hrdOk4upK731S+1+) 43 | 44 | ## 基于YeIM-Uni-SDK的演示案例 45 | 46 | ### 代码 47 | 48 | [下载基于YeIM-Uni-SDK的演示案例源码](https://ext.dcloud.net.cn/plugin?id=10266) 49 | 50 | ### Android App Demo 51 | 52 | 53 | 54 | ### Electron 桌面端 Demo 55 | 56 | [https://github.com/wzJun1/YeIM-Uni-SDK-Electron-Demo](https://github.com/wzJun1/YeIM-Uni-SDK-Electron-Demo) 57 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | cn.wzjun1 6 | yeimServer 7 | 1.2.3 8 | yeimServer 9 | YeIM for Spring Boot 10 | 11 | 12 | 1.8 13 | UTF-8 14 | UTF-8 15 | 2.7.6 16 | 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | com.alibaba 27 | fastjson 28 | 1.2.83 29 | 30 | 31 | 32 | mysql 33 | mysql-connector-java 34 | runtime 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-test 40 | test 41 | 42 | 43 | org.junit.vintage 44 | junit-vintage-engine 45 | 46 | 47 | 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-websocket 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-configuration-processor 57 | 58 | 59 | 60 | org.projectlombok 61 | lombok 62 | true 63 | 64 | 65 | 66 | org.slf4j 67 | slf4j-api 68 | 1.7.25 69 | 70 | 71 | 72 | 73 | org.springframework.boot 74 | spring-boot-starter-data-redis 75 | 76 | 77 | 78 | org.apache.commons 79 | commons-pool2 80 | 81 | 82 | 83 | 84 | 85 | org.hibernate 86 | hibernate-validator 87 | 6.0.1.Final 88 | 89 | 90 | 91 | 92 | com.baomidou 93 | mybatis-plus-boot-starter 94 | 3.5.2 95 | 96 | 97 | 98 | p6spy 99 | p6spy 100 | 3.9.1 101 | 102 | 103 | 104 | commons-codec 105 | commons-codec 106 | 1.10 107 | 108 | 109 | 110 | 111 | com.github.yitter 112 | yitter-idgenerator 113 | 1.0.6 114 | 115 | 116 | 117 | 118 | net.coobird 119 | thumbnailator 120 | 0.4.18 121 | 122 | 123 | 124 | 125 | com.twelvemonkeys.imageio 126 | imageio-tiff 127 | 3.9.3 128 | 129 | 130 | 131 | 132 | com.twelvemonkeys.imageio 133 | imageio-webp 134 | 3.9.3 135 | 136 | 137 | 138 | 139 | org.bytedeco 140 | javacv 141 | 1.5.8 142 | 143 | 144 | org.bytedeco 145 | ffmpeg 146 | 5.1.2-1.5.8 147 | 148 | 149 | 150 | 151 | 152 | macosx-x86_64 153 | 154 | 155 | 156 | 157 | 158 | com.getui.push 159 | restful-sdk 160 | 1.0.0.10 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | org.springframework.boot 169 | spring-boot-dependencies 170 | ${spring-boot.version} 171 | pom 172 | import 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | org.apache.maven.plugins 181 | maven-compiler-plugin 182 | 3.8.1 183 | 184 | 1.8 185 | 1.8 186 | UTF-8 187 | 188 | 189 | 190 | org.springframework.boot 191 | spring-boot-maven-plugin 192 | 2.7.6 193 | 194 | cn.wzjun1.yeimServer.YeimServerApplication 195 | 196 | 197 | 198 | repackage 199 | 200 | repackage 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wzJun1/YeIM-Uni-Server/dda702b1cc829ed67dd99292fef256d8a6eaa2b8/src/main/java/cn/wzjun1/yeimServer/.DS_Store -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/YeimServerApplication.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.scheduling.annotation.EnableAsync; 8 | import org.springframework.transaction.annotation.EnableTransactionManagement; 9 | 10 | @MapperScan("cn.wzjun1.yeimServer.mapper") 11 | @EnableTransactionManagement 12 | @SpringBootApplication 13 | @EnableAsync 14 | @Slf4j 15 | public class YeimServerApplication { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(YeimServerApplication.class, args); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/annotation/UserAuthorization.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target({ElementType.TYPE, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface UserAuthorization { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/config/PrefixRedisSerializer.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.config; 2 | 3 | 4 | import com.baomidou.mybatisplus.core.toolkit.StringUtils; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.annotation.Order; 9 | import org.springframework.data.redis.serializer.StringRedisSerializer; 10 | 11 | @Slf4j 12 | @Order 13 | @Configuration 14 | public class PrefixRedisSerializer extends StringRedisSerializer { 15 | 16 | @Value("${yeim.redis.prefix}") 17 | private String prefix; 18 | 19 | /** 20 | * 序列化 21 | * 22 | * @param s key 23 | * @return 结果 24 | */ 25 | @Override 26 | public byte[] serialize(String s) { 27 | if (s == null) { 28 | return new byte[0]; 29 | } 30 | String realKey = prefix + s; 31 | return super.serialize(realKey); 32 | } 33 | 34 | /** 35 | * 反序列化 36 | * 37 | * @param bytes 数据 38 | * @return 结果 39 | */ 40 | @Override 41 | public String deserialize(byte[] bytes) { 42 | String s = bytes == null ? null : new String(bytes); 43 | if (StringUtils.isBlank(s)) { 44 | return s; 45 | } 46 | int index = s.indexOf(prefix); 47 | if (index != -1) { 48 | return s.substring(index + 2); 49 | } 50 | return s; 51 | } 52 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.config; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.PropertyAccessor; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import com.fasterxml.jackson.databind.SerializationFeature; 7 | import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; 8 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.data.redis.connection.RedisConnectionFactory; 12 | import org.springframework.data.redis.core.RedisTemplate; 13 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 14 | import org.springframework.data.redis.serializer.StringRedisSerializer; 15 | 16 | @Configuration 17 | public class RedisConfig { 18 | /** 19 | * SpringBoot自动帮我们在容器中生成了一个RedisTemplate和一个StringRedisTemplate。 20 | * 但是,这个RedisTemplate的泛型是,写代码不方便,需要写好多类型转换的代码;我们需要一个泛型为形式的RedisTemplate 21 | * 同时,设置key-value的序列化方式 22 | */ 23 | @Bean 24 | public RedisTemplate redisTemplate(RedisConnectionFactory factory) { 25 | RedisTemplate template = new RedisTemplate(); 26 | template.setConnectionFactory(factory); 27 | /* 28 | * 设置序列化参数 29 | */ 30 | // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值 31 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); 32 | ObjectMapper om = new ObjectMapper(); 33 | // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public 34 | om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 35 | // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 36 | om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); 37 | //解决jackson2无法序列化LocalDateTime的问题,这里扩展一个LocalDateTime类型,它是日期类型对象 jdk1.8出的(并且这个类是不可变的和线程安全的,可以研究一下它的API),当然还需要对这个对象进行json格式的转换,如下图: 38 | om.disable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS); 39 | om.registerModule(new JavaTimeModule()); 40 | jackson2JsonRedisSerializer.setObjectMapper(om); 41 | 42 | StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 43 | // key采用String的序列化方式 44 | template.setKeySerializer(stringRedisSerializer); 45 | // hash的key也采用String的序列化方式 46 | template.setHashKeySerializer(stringRedisSerializer); 47 | // value序列化方式采用jackson 48 | template.setValueSerializer(jackson2JsonRedisSerializer); 49 | // hash的value序列化方式采用jackson 50 | template.setHashValueSerializer(jackson2JsonRedisSerializer); 51 | 52 | template.afterPropertiesSet(); 53 | return template; 54 | } 55 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.config; 2 | 3 | import cn.wzjun1.yeimServer.interceptor.UserAuthorizationInterceptor; 4 | import cn.wzjun1.yeimServer.utils.RedisUtil; 5 | import com.baomidou.mybatisplus.annotation.DbType; 6 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; 7 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; 8 | import com.github.yitter.contract.IdGeneratorOptions; 9 | import com.github.yitter.idgen.YitIdHelper; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.web.cors.CorsConfiguration; 15 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 16 | import org.springframework.web.filter.CorsFilter; 17 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 18 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 19 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 20 | 21 | import java.io.File; 22 | 23 | 24 | @Configuration 25 | public class WebConfig implements WebMvcConfigurer { 26 | 27 | @Value("${yeim.generator.workId}") 28 | short idGenWorkId; 29 | 30 | @Value("${yeim.file.storage.baseDir}") 31 | String baseDir; 32 | 33 | @Autowired 34 | RedisUtil redisUtil; 35 | 36 | @Override 37 | public void addInterceptors(InterceptorRegistry registry) { 38 | /** 39 | * 添加用户权限拦截器 40 | */ 41 | registry.addInterceptor(new UserAuthorizationInterceptor(redisUtil)) 42 | .addPathPatterns("/**"); 43 | } 44 | 45 | @Override 46 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 47 | registry.addResourceHandler("/**").addResourceLocations("file:" + baseDir + File.separator); 48 | } 49 | 50 | /** 51 | * 跨域 52 | */ 53 | @Bean 54 | public CorsFilter corsFilter() { 55 | CorsConfiguration config = new CorsConfiguration(); 56 | config.addAllowedOriginPattern("*"); 57 | config.setAllowCredentials(true); 58 | config.addAllowedMethod("*"); 59 | config.addAllowedHeader("*"); 60 | UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource(); 61 | configSource.registerCorsConfiguration("/**", config); 62 | return new CorsFilter(configSource); 63 | } 64 | 65 | @Bean 66 | public MybatisPlusInterceptor mybatisPlusInterceptor() { 67 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); 68 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); 69 | return interceptor; 70 | } 71 | 72 | /** 73 | * 初始化ID生成器 74 | */ 75 | @Bean 76 | public void yitIdHelper() { 77 | // 创建 IdGeneratorOptions 对象,可在构造函数中输入 WorkerId: 78 | IdGeneratorOptions options = new IdGeneratorOptions(idGenWorkId); 79 | options.SeqBitLength = 6; // 默认值6,限制每毫秒生成的ID个数。若生成速度超过5万个/秒,建议加大 SeqBitLength 到 10。 80 | // options.WorkerIdBitLength = 10; // 默认值6,限定 WorkerId 最大值为2^6-1,即默认最多支持64个节点。 81 | // options.BaseTime = Your_Base_Time; // 如果要兼容老系统的雪花算法,此处应设置为老系统的BaseTime。 82 | // ...... 其它参数参考 IdGeneratorOptions 定义。 83 | // 保存参数(务必调用,否则参数设置不生效): 84 | YitIdHelper.setIdGenerator(options); 85 | // 以上过程只需全局一次,且应在生成ID之前完成。 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/config/WebSocketConfig.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.config; 2 | 3 | import cn.wzjun1.yeimServer.domain.User; 4 | import cn.wzjun1.yeimServer.pojo.YeIMPushConfig; 5 | import cn.wzjun1.yeimServer.socket.WebSocket; 6 | import cn.wzjun1.yeimServer.utils.RedisUtil; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.http.server.ServerHttpRequest; 12 | import org.springframework.http.server.ServerHttpResponse; 13 | import org.springframework.web.socket.CloseStatus; 14 | import org.springframework.web.socket.WebSocketHandler; 15 | import org.springframework.web.socket.config.annotation.EnableWebSocket; 16 | import org.springframework.web.socket.config.annotation.WebSocketConfigurer; 17 | import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; 18 | import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; 19 | 20 | import java.util.Map; 21 | 22 | @Configuration 23 | @EnableWebSocket 24 | @Slf4j 25 | public class WebSocketConfig implements WebSocketConfigurer { 26 | 27 | @Autowired 28 | YeIMPushConfig yeIMPushConfig; 29 | 30 | @Autowired 31 | RedisUtil redisUtil; 32 | 33 | @Override 34 | public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { 35 | registry 36 | .addHandler(new WebSocket(yeIMPushConfig), "/im/*/*") 37 | .addInterceptors(new HttpSessionHandshakeInterceptor() { 38 | @Override 39 | public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map attributes) throws Exception { 40 | String path = request.getURI().getPath().substring(request.getURI().getPath().lastIndexOf("im/")); 41 | String[] pathArr = path.split("/"); 42 | if (pathArr.length != 3) { 43 | response.setStatusCode(HttpStatus.FORBIDDEN); 44 | return false; 45 | } 46 | String userId = pathArr[1]; 47 | String token = pathArr[2]; 48 | token = "token:" + token; 49 | if (!redisUtil.hasKey(token)) { 50 | //token不存在,验证失败 51 | response.setStatusCode(HttpStatus.UNAUTHORIZED); 52 | return false; 53 | } else { 54 | User user = (User) redisUtil.get(token); 55 | if (!userId.equals(user.getUserId())) { 56 | //token不属于此user,验证失败 57 | response.setStatusCode(HttpStatus.UNAUTHORIZED); 58 | return false; 59 | } else { 60 | //验证成功 61 | attributes.put("user", user); 62 | } 63 | } 64 | return super.beforeHandshake(request, response, wsHandler, attributes); 65 | } 66 | 67 | @Override 68 | public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) { 69 | super.afterHandshake(serverHttpRequest, serverHttpResponse, webSocketHandler, e); 70 | } 71 | }) 72 | .setAllowedOrigins("*") 73 | .setAllowedOriginPatterns("*"); 74 | } 75 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/constant/AddFriendType.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.constant; 2 | 3 | /** 4 | * 好友添加的方式 5 | */ 6 | public class AddFriendType { 7 | 8 | /** 9 | * 允许任何人添加自己为好友 10 | */ 11 | public static final Integer ALLOW = 1; 12 | /** 13 | * 需要经过自己确认才能添加自己为好友 14 | */ 15 | public static final Integer CONFIRM = 2; 16 | /** 17 | * 拒绝加好友 18 | */ 19 | public static final Integer DENY = 3; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/constant/ConversationType.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.constant; 2 | 3 | /** 4 | * 会话类型 5 | */ 6 | public class ConversationType { 7 | //私聊 8 | public static final String PRIVATE = "private"; 9 | //群聊 10 | public static final String GROUP = "group"; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/constant/FriendApplyStatus.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.constant; 2 | 3 | /** 4 | * 好友申请处理状态 5 | */ 6 | public class FriendApplyStatus { 7 | 8 | /** 9 | * 待处理 10 | */ 11 | public static final Integer PENDING = 1; 12 | /** 13 | * 同意申请 14 | */ 15 | public static final Integer AGREE = 2; 16 | /** 17 | * 拒绝 18 | */ 19 | public static final Integer REFUSE = 3; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/constant/GroupApplyStatus.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.constant; 2 | 3 | /** 4 | * 入群申请状态 5 | */ 6 | public class GroupApplyStatus { 7 | 8 | /** 9 | * 待处理 10 | */ 11 | public static final Integer PENDING = 1; 12 | /** 13 | * 同意申请 14 | */ 15 | public static final Integer AGREE = 2; 16 | /** 17 | * 拒绝 18 | */ 19 | public static final Integer REFUSE = 3; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/constant/JoinGroupMode.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.constant; 2 | 3 | /** 4 | * 群组的加群处理方式 5 | */ 6 | public class JoinGroupMode { 7 | 8 | //自有加入,不需要申请和审核,不需要被邀请人允许。 9 | public static final Integer FREE = 1; 10 | //验证加入,需要申请,以及群主或管理员的同意才能入群 11 | public static final Integer CHECK = 2; 12 | //禁止加入 13 | public static final Integer FORBIDDEN = 3; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/constant/MessageStatus.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.constant; 2 | 3 | public class MessageStatus { 4 | public static final String UNSEND = "unSend"; 5 | public static final String SUCCESS = "success"; 6 | public static final String FAIL = "fail"; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/constant/MessageType.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.constant; 2 | 3 | /** 4 | * 消息类型 5 | */ 6 | public class MessageType { 7 | 8 | //文本消息 9 | public static final String TEXT = "text"; 10 | //图片消息 11 | public static final String IMAGE = "image"; 12 | //语音消息 13 | public static final String AUDIO = "audio"; 14 | //小视频消息 15 | public static final String VIDEO = "video"; 16 | //位置消息 17 | public static final String LOCATION = "location"; 18 | //自定义消息 19 | public static final String CUSTOM = "custom"; 20 | //合并消息 21 | public static final String MERGER = "merger"; 22 | //转发消息 23 | public static final String FORWARD = "forward"; 24 | //私聊系统消息 25 | public static final String SYS_NOTICE = "sys_notice"; 26 | 27 | //群聊系统通知 28 | public static final String GROUP_SYS_NOTICE = "group_sys_notice"; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/constant/StatusCode.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.constant; 2 | 3 | public enum StatusCode { 4 | 5 | //签名错误 6 | SIGN_ERROR(10000, "签名校验错误"), 7 | 8 | //网络连接错误 9 | CONNECT_ERROR(10001, "聊天服务网络连接错误"), 10 | //用户验权 11 | TOKEN_ERROR(10002, "用户验证失败,请检查userId、token"), 12 | 13 | //用户未登录 14 | LOGIN_EXPIRE(10003, "用户登录状态过期,请重新登录"), 15 | 16 | //会话不存在 17 | CONVERSATION_NOT_FOUND(10004, "会话不存在"), 18 | 19 | //接收者ID错误 20 | TOUSER_ID_NOT_FOUND(10005, "接收者ID错误"), 21 | 22 | //ID错误 23 | ID_ERROR(10006, "ID错误"), 24 | 25 | //您已被当前用户拉黑,无法向他发送消息 26 | MESSAGE_REJECTED(10007, "您已被当前用户拉黑,无法向他发送消息"), 27 | 28 | //参数错误 29 | PARAMS_ERROR(10008, "参数错误"), 30 | 31 | //多端挤下线 32 | KICKED_OUT(10009, "有新连接踢掉了当前连接"), 33 | 34 | //上传错误 35 | UPLOAD_ERROR(10010, "上传错误"), 36 | 37 | //群组全体禁言 38 | GROUP_ALL_MUTE(10011, "当前群组全体禁言"), 39 | 40 | //被禁言 41 | GROUP_MUTE(10012, "您在当前群组内已被禁言"), 42 | 43 | //非群成员,无法执行此操作 44 | NO_GROUP_USER(10013, "非群成员,无法执行此操作"), 45 | 46 | //群ID重复 47 | GROUP_DUPLICATE(10015, "群ID重复"), 48 | 49 | //无权限操作群相关修改 50 | GROUP_PERMISSION_DENIED(10016, "无权限操作"), 51 | 52 | //用户不存在 53 | USER_NOT_FOUND(10017, "用户不存在"), 54 | 55 | //群主只能解散,群主不能退出 56 | GROUP_ONLY_DISSOLVE(10018, "群主只能解散,不能退出"), 57 | 58 | //用户重复 59 | USER_DUPLICATE(10019, "用户重复"), 60 | 61 | //过期时间设置错误 62 | EXPIRE_ERROR(10020, "过期时间设置错误"), 63 | 64 | //对方拒绝添加好友 65 | USER_FRIEND_DENY_FOUND(10021, "对方拒绝添加好友"), 66 | 67 | //好友重复 68 | USER_FRIEND_DUPLICATE(10022, "好友重复"), 69 | 70 | //频率限制 71 | FREQUENCY_LIMIT(10023, "频率限制"), 72 | 73 | 74 | //未找到此好友 75 | FRIEND_NOT_FOUND(10025, "未找到此好友"), 76 | 77 | //未找到此好友申请 78 | FRIEND_APPLY_NOT_FOUND(10026, "未找到此好友申请"), 79 | 80 | //重复操作 81 | DUPLICATE_ERROR(10027, "重复操作"), 82 | 83 | //好友申请:已发送申请,请等待对方处理 84 | APPLY_NEED(20020, "已发送申请,请等待对方处理"), 85 | 86 | //当前群组不存在或已解散 87 | GROUP_NOT_FOUND(10201, "当前群组不存在或已解散"), 88 | 89 | //当前群组设置禁止加群 90 | GROUP_NO_ENTRY(10202, "当前群组设置禁止加群"), 91 | 92 | //群用户单次添加数量超过限制 93 | GROUP_USER_INSERT_LIMIT(10203, "群用户单次添加数量不能超过500"), 94 | 95 | //登陆成功 96 | LOGIN_SUCCESS(201, "登陆成功"), 97 | 98 | //心跳 99 | HEART(202, ""), 100 | 101 | //会话更新 102 | CONVERSATION_CHANGED(203, "会话更新"), 103 | 104 | //会话列表更新 105 | CONVERSATION_LIST_CHANGED(204, "会话列表更新"), 106 | 107 | //私聊会话已读回执 108 | PRIVATE_READ_RECEIPT(205, "会话已读回执"), 109 | 110 | //入群申请事件 111 | GROUP_APPLY_RECEIVE(206, "入群申请"), 112 | 113 | //消息撤回事件 114 | MESSAGE_REVOKED(207, "消息撤回"), 115 | 116 | //好友列表更新事件 117 | FRIEND_LIST_CHANGED(208, "好友列表更新"), 118 | 119 | //好友申请列表更新事件 120 | FRIEND_APPLY_LIST_CHANGED(209, "好友申请列表更新"), 121 | 122 | //好友申请被拒绝 123 | FRIEND_APPLY_REFUSE(210, "好友申请被拒绝"), 124 | 125 | //推送新消息 126 | MESSAGE_RECEIVE(200, ""); 127 | 128 | private Integer code; 129 | private String desc; 130 | 131 | private StatusCode(Integer code, String desc) { 132 | this.code = code; 133 | this.desc = desc; 134 | } 135 | 136 | private StatusCode() { 137 | } 138 | 139 | public Integer getCode() { 140 | return code; 141 | } 142 | 143 | public String getDesc() { 144 | return desc; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/controller/ConversatioController.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.controller; 2 | 3 | import cn.wzjun1.yeimServer.annotation.UserAuthorization; 4 | import cn.wzjun1.yeimServer.constant.StatusCode; 5 | import cn.wzjun1.yeimServer.domain.Conversation; 6 | import cn.wzjun1.yeimServer.domain.ConversationV0; 7 | import cn.wzjun1.yeimServer.domain.Message; 8 | import cn.wzjun1.yeimServer.exception.conversation.ConversationNotFoundException; 9 | import cn.wzjun1.yeimServer.interceptor.LoginUserContext; 10 | import cn.wzjun1.yeimServer.mapper.ConversationMapper; 11 | import cn.wzjun1.yeimServer.mapper.MessageMapper; 12 | import cn.wzjun1.yeimServer.pojo.YeIMPushConfig; 13 | import cn.wzjun1.yeimServer.service.ConversationService; 14 | import cn.wzjun1.yeimServer.result.Result; 15 | import com.alibaba.fastjson.JSONObject; 16 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 17 | import com.baomidou.mybatisplus.core.metadata.IPage; 18 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 19 | import lombok.extern.slf4j.Slf4j; 20 | import netscape.javascript.JSObject; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.validation.annotation.Validated; 23 | import org.springframework.web.bind.annotation.GetMapping; 24 | import org.springframework.web.bind.annotation.RequestParam; 25 | import org.springframework.web.bind.annotation.RestController; 26 | 27 | import javax.validation.constraints.NotEmpty; 28 | import javax.validation.constraints.NotNull; 29 | 30 | @Slf4j 31 | @Validated 32 | @RestController 33 | public class ConversatioController { 34 | 35 | @Autowired 36 | MessageMapper messageMapper; 37 | @Autowired 38 | ConversationMapper conversationMapper; 39 | 40 | @Autowired 41 | ConversationService conversationService; 42 | 43 | /** 44 | * 获取会话列表 45 | * 46 | * @param page 页码 47 | * @param limit 每页数量 48 | * @return IPage 49 | */ 50 | @UserAuthorization 51 | @GetMapping(path = "/conversation/list") 52 | public Result list(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "20") Integer limit) { 53 | try { 54 | IPage conversationV0s = conversationMapper.listConversationV0(Page.of(page, limit), LoginUserContext.getUser().getUserId()); 55 | return Result.success(conversationV0s); 56 | } catch (Exception e) { 57 | return Result.error(e.getMessage()); 58 | } 59 | } 60 | 61 | /** 62 | * 删除会话及聊天记录 63 | * 64 | * @param conversationId 会话ID 65 | * @return Result 66 | */ 67 | @UserAuthorization 68 | @GetMapping(path = "/conversation/delete") 69 | public Result delete(@RequestParam @NotEmpty String conversationId) { 70 | try { 71 | boolean exist = conversationMapper.exists(new QueryWrapper().eq("conversation_id", conversationId).eq("user_id", LoginUserContext.getUser().getUserId())); 72 | if (!exist) { 73 | throw new ConversationNotFoundException("会话不存在"); 74 | } 75 | //删除会话 76 | conversationMapper.delete(new QueryWrapper().eq("conversation_id", conversationId)); 77 | //软删除会话内聊天记录 78 | Message update = new Message(); 79 | update.setIsDeleted(1); 80 | messageMapper.update(update, new QueryWrapper().eq("user_id", LoginUserContext.getUser().getUserId()).eq("conversation_id", conversationId)); 81 | return Result.success(); 82 | } catch (Exception e) { 83 | if (e instanceof ConversationNotFoundException){ 84 | return Result.error(StatusCode.CONVERSATION_NOT_FOUND); 85 | } 86 | return Result.error(e.getMessage()); 87 | } 88 | } 89 | 90 | /** 91 | * 清除会话未读数并设置会话内接收消息已读状态 92 | * 更新完成后发送事件 `PRIVATE_READ_RECEIPT` 93 | * 94 | * @param conversationId 会话ID 95 | * @return Result 96 | */ 97 | @UserAuthorization 98 | @GetMapping(path = "/conversation/update/unread") 99 | public Result clearConversationUnread(@RequestParam @NotEmpty String conversationId) { 100 | try { 101 | conversationService.clearConversationUnread(conversationId); 102 | return Result.success(); 103 | } catch (Exception e) { 104 | if (e instanceof ConversationNotFoundException){ 105 | return Result.error(StatusCode.CONVERSATION_NOT_FOUND); 106 | } 107 | return Result.error(e.getMessage()); 108 | } 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/controller/GroupController.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.controller; 2 | 3 | import cn.wzjun1.yeimServer.annotation.UserAuthorization; 4 | import cn.wzjun1.yeimServer.constant.StatusCode; 5 | import cn.wzjun1.yeimServer.dto.group.GroupCreateDTO; 6 | import cn.wzjun1.yeimServer.dto.group.GroupEditDTO; 7 | import cn.wzjun1.yeimServer.exception.group.GroupDuplicateException; 8 | import cn.wzjun1.yeimServer.exception.group.GroupNotFoundException; 9 | import cn.wzjun1.yeimServer.exception.group.GroupPermissionDeniedException; 10 | import cn.wzjun1.yeimServer.exception.group.NoGroupUserException; 11 | import cn.wzjun1.yeimServer.exception.user.UserNotFoundException; 12 | import cn.wzjun1.yeimServer.interceptor.LoginUserContext; 13 | import cn.wzjun1.yeimServer.mapper.GroupMapper; 14 | import cn.wzjun1.yeimServer.mapper.GroupUserMapper; 15 | import cn.wzjun1.yeimServer.service.GroupService; 16 | import cn.wzjun1.yeimServer.result.Result; 17 | import lombok.extern.slf4j.Slf4j; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.validation.annotation.Validated; 20 | import org.springframework.web.bind.annotation.*; 21 | 22 | import javax.validation.constraints.NotEmpty; 23 | import javax.validation.constraints.NotNull; 24 | 25 | @Slf4j 26 | @Validated 27 | @RestController 28 | public class GroupController { 29 | 30 | @Autowired 31 | GroupService groupService; 32 | 33 | @Autowired 34 | GroupMapper groupMapper; 35 | 36 | @Autowired 37 | GroupUserMapper groupUserMapper; 38 | 39 | /** 40 | * 创建群组 41 | * 42 | * @param params 43 | * @return 44 | */ 45 | @PostMapping(path = "/group/create") 46 | @UserAuthorization 47 | public Result create(@RequestBody @Validated GroupCreateDTO params) { 48 | try { 49 | groupService.createGroup(params); 50 | return Result.success(); 51 | } catch (Exception e) { 52 | if (e instanceof GroupDuplicateException){ 53 | return Result.error(StatusCode.GROUP_DUPLICATE); 54 | } 55 | return Result.error(e.getMessage()); 56 | } 57 | } 58 | 59 | /** 60 | * 解散群组,仅群主可解散 61 | * 62 | * @param groupId 63 | * @return 64 | */ 65 | @GetMapping(path = "/group/dissolve") 66 | @UserAuthorization 67 | public Result dissolve(@RequestParam @NotEmpty String groupId) { 68 | try { 69 | groupService.dissolveGroup(groupId); 70 | return Result.success(); 71 | } catch (Exception e) { 72 | if (e instanceof GroupNotFoundException){ 73 | return Result.error(StatusCode.GROUP_NOT_FOUND); 74 | } else if (e instanceof GroupPermissionDeniedException){ 75 | return Result.error(StatusCode.GROUP_PERMISSION_DENIED); 76 | } 77 | return Result.error(e.getMessage()); 78 | } 79 | } 80 | 81 | /** 82 | * 根据群ID获取群信息 83 | * 84 | * @return 85 | */ 86 | @GetMapping(path = "/group/get") 87 | @UserAuthorization 88 | public Result get(@RequestParam @NotEmpty String groupId) { 89 | try { 90 | return Result.success(groupMapper.findByGroupId(groupId)); 91 | } catch (Exception e) { 92 | return Result.error(e.getMessage()); 93 | } 94 | } 95 | 96 | /** 97 | * 修改群资料 98 | * 99 | * @return 100 | */ 101 | @PostMapping(path = "/group/edit") 102 | @UserAuthorization 103 | public Result edit(@RequestBody @Validated GroupEditDTO params) { 104 | try { 105 | groupService.updateGroup(params); 106 | return Result.success(); 107 | } catch (Exception e) { 108 | if (e instanceof GroupNotFoundException){ 109 | return Result.error(StatusCode.GROUP_NOT_FOUND); 110 | } else if (e instanceof GroupPermissionDeniedException){ 111 | return Result.error(StatusCode.GROUP_PERMISSION_DENIED); 112 | } else if (e instanceof NoGroupUserException){ 113 | return Result.error(StatusCode.NO_GROUP_USER); 114 | } 115 | return Result.error(e.getMessage()); 116 | } 117 | } 118 | 119 | /** 120 | * 转让群主 121 | * 122 | * @param groupId 123 | * @param userId 124 | * @return 125 | */ 126 | @GetMapping(path = "/group/transferLeader") 127 | @UserAuthorization 128 | public Result transferLeader(@RequestParam @NotEmpty String groupId, @NotEmpty String userId) { 129 | try { 130 | groupService.transferLeader(groupId, userId); 131 | return Result.success(); 132 | } catch (Exception e) { 133 | if (e instanceof GroupNotFoundException){ 134 | return Result.error(StatusCode.GROUP_NOT_FOUND); 135 | } else if (e instanceof GroupPermissionDeniedException){ 136 | return Result.error(StatusCode.GROUP_PERMISSION_DENIED); 137 | } else if (e instanceof NoGroupUserException){ 138 | return Result.error(StatusCode.NO_GROUP_USER); 139 | } else if (e instanceof UserNotFoundException){ 140 | return Result.error(StatusCode.USER_NOT_FOUND); 141 | } 142 | return Result.error(e.getMessage()); 143 | } 144 | } 145 | 146 | /** 147 | * 获取我加入的群组 148 | * 149 | * @return 150 | */ 151 | @GetMapping(path = "/group/list") 152 | @UserAuthorization 153 | public Result list() { 154 | try { 155 | return Result.success(groupMapper.selectGroupByUserId(LoginUserContext.getUser().getUserId())); 156 | } catch (Exception e) { 157 | return Result.error(e.getMessage()); 158 | } 159 | } 160 | 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/controller/UploadController.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.controller; 2 | 3 | import cn.wzjun1.yeimServer.annotation.UserAuthorization; 4 | import cn.wzjun1.yeimServer.constant.StatusCode; 5 | import cn.wzjun1.yeimServer.exception.FileUploadException; 6 | import cn.wzjun1.yeimServer.service.UploadService; 7 | import cn.wzjun1.yeimServer.result.Result; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.*; 11 | import org.springframework.web.multipart.MultipartFile; 12 | 13 | import javax.validation.constraints.NotEmpty; 14 | import javax.validation.constraints.NotNull; 15 | import java.util.Map; 16 | 17 | @Slf4j 18 | @RestController 19 | public class UploadController { 20 | 21 | 22 | @Autowired 23 | UploadService uploadService; 24 | 25 | /** 26 | * YeIMUniSDK 获取媒体上传参数 27 | * 28 | * @description YeIMUniSDK发送媒体消息需要使用到上传功能,此处获取相关上传参数,例如后端设置上传仓库为:腾讯云COS,则在此处获取上传签名等 29 | */ 30 | @UserAuthorization 31 | @GetMapping(path = "/upload/sign") 32 | public Result update() { 33 | try { 34 | Object params = uploadService.getStorageParams(); 35 | return Result.success(params); 36 | } catch (Exception e) { 37 | return Result.error(e.getMessage()); 38 | } 39 | } 40 | 41 | /** 42 | * 通用上传 43 | * 44 | * @param file 45 | * @param key 46 | * @return 47 | */ 48 | @UserAuthorization 49 | @PostMapping(path = "/upload") 50 | public Result> upload(@NotEmpty MultipartFile file, @RequestParam @NotEmpty String key) { 51 | try { 52 | return Result.success(uploadService.upload(key, file)); 53 | } catch (FileUploadException e) { 54 | return Result.error(StatusCode.UPLOAD_ERROR.getCode(), e.getMessage() != null ? e.getMessage() : StatusCode.UPLOAD_ERROR.getDesc()); 55 | } catch (Exception e) { 56 | e.printStackTrace(); 57 | return Result.error(StatusCode.UPLOAD_ERROR); 58 | } 59 | } 60 | 61 | /** 62 | * 上传图片 63 | * 64 | * @param file 文件 65 | * @param key 文件名称,带后缀 66 | * @return 67 | */ 68 | @UserAuthorization 69 | @PostMapping(path = "/upload/image") 70 | public Result> uploadImage(@NotEmpty MultipartFile file, @RequestParam @NotEmpty String key) { 71 | try { 72 | return Result.success(uploadService.uploadImage(key, file)); 73 | } catch (FileUploadException e) { 74 | return Result.error(StatusCode.UPLOAD_ERROR.getCode(), e.getMessage() != null ? e.getMessage() : StatusCode.UPLOAD_ERROR.getDesc()); 75 | } catch (Exception e) { 76 | e.printStackTrace(); 77 | return Result.error(StatusCode.UPLOAD_ERROR); 78 | } 79 | } 80 | 81 | /** 82 | * 上传视频 83 | * 84 | * @param file 文件 85 | * @param key 文件名称,带后缀 86 | * @return 87 | */ 88 | @UserAuthorization 89 | @PostMapping(path = "/upload/video") 90 | public Result> uploadVideo(@NotEmpty MultipartFile file, @RequestParam @NotEmpty String key) { 91 | try { 92 | return Result.success(uploadService.uploadVideo(key, file)); 93 | } catch (FileUploadException e) { 94 | return Result.error(StatusCode.UPLOAD_ERROR.getCode(), e.getMessage() != null ? e.getMessage() : StatusCode.UPLOAD_ERROR.getDesc()); 95 | } catch (Exception e) { 96 | e.printStackTrace(); 97 | return Result.error(StatusCode.UPLOAD_ERROR); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.controller; 2 | 3 | import cn.wzjun1.yeimServer.annotation.UserAuthorization; 4 | import cn.wzjun1.yeimServer.constant.StatusCode; 5 | import cn.wzjun1.yeimServer.domain.User; 6 | import cn.wzjun1.yeimServer.dto.group.GroupUserAddDTO; 7 | import cn.wzjun1.yeimServer.dto.user.UserBlackListAddDTO; 8 | import cn.wzjun1.yeimServer.exception.ParamsException; 9 | import cn.wzjun1.yeimServer.exception.message.MessageRejectedException; 10 | import cn.wzjun1.yeimServer.exception.message.ToUserIdNotFoundException; 11 | import cn.wzjun1.yeimServer.exception.user.ExpireException; 12 | import cn.wzjun1.yeimServer.exception.user.SignException; 13 | import cn.wzjun1.yeimServer.exception.user.UserDuplicateException; 14 | import cn.wzjun1.yeimServer.exception.user.UserNotFoundException; 15 | import cn.wzjun1.yeimServer.interceptor.LoginUserContext; 16 | import cn.wzjun1.yeimServer.dto.user.UserRegisterDTO; 17 | import cn.wzjun1.yeimServer.dto.user.UserTokenDTO; 18 | import cn.wzjun1.yeimServer.dto.user.UserUpdateDTO; 19 | import cn.wzjun1.yeimServer.service.UserBlackListService; 20 | import cn.wzjun1.yeimServer.service.UserService; 21 | import cn.wzjun1.yeimServer.utils.MD5Util; 22 | import cn.wzjun1.yeimServer.utils.RedisUtil; 23 | import cn.wzjun1.yeimServer.result.Result; 24 | import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; 25 | import lombok.extern.slf4j.Slf4j; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.beans.factory.annotation.Value; 28 | import org.springframework.validation.annotation.Validated; 29 | import org.springframework.web.bind.annotation.*; 30 | 31 | import javax.validation.constraints.NotEmpty; 32 | import javax.validation.constraints.NotNull; 33 | import java.util.HashMap; 34 | import java.util.Map; 35 | import java.util.Objects; 36 | 37 | @Slf4j 38 | @Validated 39 | @RestController 40 | public class UserController { 41 | 42 | @Value("${yeim.secret.key}") 43 | private String secretKey; 44 | 45 | @Autowired 46 | RedisUtil redisUtil; 47 | 48 | @Autowired 49 | UserService userService; 50 | 51 | @Autowired 52 | UserBlackListService userBlackListService; 53 | 54 | /** 55 | * 用户注册 56 | * 57 | * @param user 58 | * @description 使用YeIMUniSDK的用户必须注册才能使用(请使用自己的服务端请求此接口或者根据自身项目自行实现相关代码) 59 | */ 60 | @PostMapping(path = "/user/register") 61 | public Result register(@RequestBody @Validated UserRegisterDTO user) { 62 | try { 63 | userService.register(user); 64 | } catch (Exception e) { 65 | if (e instanceof UserDuplicateException) { 66 | return Result.error(StatusCode.USER_DUPLICATE); 67 | } 68 | return Result.error(e.getMessage()); 69 | } 70 | return Result.success(); 71 | } 72 | 73 | /** 74 | * 换取token 75 | * 76 | * @param params 77 | * @return 78 | * @description 用户使用YeIMUniSDK登陆YeImUniServer使用的token,在此换取。或者开发者可自行打通系统,推荐开发者自行打通生成token,避免安全问题。 79 | */ 80 | @PostMapping(path = "/user/token/get") 81 | public Result> getToken(@RequestBody @Validated UserTokenDTO params) { 82 | 83 | try { 84 | if (params.getTimestamp() < System.currentTimeMillis()) { 85 | throw new ExpireException("过期时间设置错误,必须大于当前时间"); 86 | } 87 | //sign = md5(userId+timestamp+secretKey) 88 | //secretKey(yeim.secret.key)在application.properties 可自行替换想要的字符串 89 | String str = params.getUserId() + params.getTimestamp() + secretKey; 90 | String secret = MD5Util.encode(str); 91 | if (!secret.equals(params.getSign())) { 92 | throw new SignException("签名校验错误"); 93 | } 94 | 95 | User user = userService.getUserById(params.getUserId()); 96 | if (Objects.isNull(user)) { 97 | throw new UserNotFoundException("用户不存在,请先注册"); 98 | } 99 | 100 | //过期时间 101 | int expire = (int) ((params.getTimestamp() - System.currentTimeMillis()) / 1000); 102 | //token 103 | String token = MD5Util.encode(params.getUserId() + System.currentTimeMillis() + secretKey); 104 | //用户数据放入缓存 105 | redisUtil.setWithExpire("token:" + token, user, expire); 106 | 107 | return Result.success(new HashMap() {{ 108 | put("token", token); 109 | }}); 110 | 111 | } catch (Exception e) { 112 | if (e instanceof ExpireException) { 113 | return Result.error(StatusCode.EXPIRE_ERROR.getCode(), e.getMessage()); 114 | } else if (e instanceof SignException) { 115 | return Result.error(StatusCode.SIGN_ERROR); 116 | } else if (e instanceof UserNotFoundException) { 117 | return Result.error(StatusCode.USER_NOT_FOUND.getCode(), e.getMessage()); 118 | } 119 | return Result.error(e.getMessage()); 120 | } 121 | } 122 | 123 | /** 124 | * 用户更新资料 125 | * 126 | * @param user 127 | * @description 更新用户昵称和头像地址 128 | */ 129 | @UserAuthorization 130 | @PostMapping(path = "/user/update") 131 | public Result update(@RequestBody @Validated UserUpdateDTO user) { 132 | try { 133 | userService.updateUser(LoginUserContext.getUser().getUserId(), user); 134 | } catch (Exception e) { 135 | if (e instanceof ParamsException) { 136 | return Result.error(StatusCode.PARAMS_ERROR.getCode(), e.getMessage()); 137 | } 138 | return Result.error(e.getMessage()); 139 | } 140 | return Result.success(); 141 | } 142 | 143 | /** 144 | * 根据userId获取用户资料 145 | * 146 | * @param userId 147 | * @return 148 | */ 149 | @UserAuthorization 150 | @GetMapping(path = "/user/info") 151 | public Result getUserInfo(@RequestParam @NotEmpty String userId) { 152 | return Result.success(userService.getUserById(userId)); 153 | } 154 | 155 | /** 156 | * 绑定个推移动端推送clientId 157 | * 158 | * @param clientId 推送标识符 159 | * @return 160 | */ 161 | @UserAuthorization 162 | @GetMapping(path = "/user/bind/push/id") 163 | public Result bindClientId(@RequestParam @NotEmpty String clientId) { 164 | try { 165 | User update = new User(); 166 | update.setMobileDeviceId(clientId); 167 | userService.update(update, new UpdateWrapper().eq("user_id", LoginUserContext.getUser().getUserId())); 168 | } catch (Exception e) { 169 | return Result.error(e.getMessage()); 170 | } 171 | return Result.success(); 172 | } 173 | 174 | /** 175 | * 获取黑名单列表 176 | * 177 | * @return 178 | */ 179 | @UserAuthorization 180 | @GetMapping(path = "/user/black/list") 181 | public Result getBlackUserList() { 182 | try { 183 | return Result.success(userBlackListService.getBlackUserList()); 184 | } catch (Exception e) { 185 | return Result.error(e.getMessage()); 186 | } 187 | } 188 | 189 | /** 190 | * 将用户加入黑名单 191 | * 192 | * @param params UserBlackListAddDTO 193 | * @return 194 | */ 195 | @UserAuthorization 196 | @PostMapping(path = "/user/black/add") 197 | public Result addToBlackUserList(@RequestBody @Validated UserBlackListAddDTO params) { 198 | try { 199 | userBlackListService.addToBlackUserList(params); 200 | } catch (Exception e) { 201 | return Result.error(e.getMessage()); 202 | } 203 | return Result.success(); 204 | } 205 | 206 | /** 207 | * 将用户移除黑名单 208 | * 209 | * @param params UserBlackListAddDTO 210 | * @return 211 | */ 212 | @UserAuthorization 213 | @PostMapping(path = "/user/black/remove") 214 | public Result removeFromBlacklist(@RequestBody @Validated UserBlackListAddDTO params) { 215 | try { 216 | userBlackListService.removeFromBlacklist(params); 217 | } catch (Exception e) { 218 | return Result.error(e.getMessage()); 219 | } 220 | return Result.success(); 221 | } 222 | 223 | } 224 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/Conversation.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * 13 | * @TableName conversation 14 | */ 15 | @TableName(value ="conversation") 16 | @Data 17 | public class Conversation implements Serializable { 18 | /** 19 | * 20 | */ 21 | @TableId(type = IdType.AUTO) 22 | private Long id; 23 | 24 | /** 25 | * 会话ID 26 | */ 27 | private String conversationId; 28 | 29 | /** 30 | * 所属用户 31 | 32 | */ 33 | private String userId; 34 | 35 | /** 36 | * 会话类型 37 | 私聊:private 38 | 群聊:group 39 | */ 40 | @TableField(value = "`type`") 41 | private String type; 42 | 43 | /** 44 | * 未读数 45 | */ 46 | private Integer unread; 47 | 48 | /** 49 | * 最新消息ID 50 | */ 51 | private String lastMessageId; 52 | 53 | /** 54 | * 更新时间 55 | */ 56 | private Long updatedAt; 57 | 58 | /** 59 | * 创建时间 60 | */ 61 | private Long createdAt; 62 | 63 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/ConversationV0.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | @Data 9 | public class ConversationV0 implements Serializable { 10 | 11 | /** 12 | * 会话ID 13 | */ 14 | private String conversationId; 15 | 16 | /** 17 | * 用户信息 18 | 19 | */ 20 | private User userInfo; 21 | 22 | /** 23 | * 群组信息 24 | */ 25 | private Group groupInfo; 26 | 27 | 28 | /** 29 | * 会话类型 30 | 私聊:private 31 | 群聊:group 32 | */ 33 | @TableField(value = "`type`") 34 | private String type; 35 | 36 | /** 37 | * 未读数 38 | */ 39 | private Integer unread; 40 | 41 | /** 42 | * 最新消息ID 43 | */ 44 | 45 | private Message lastMessage; 46 | 47 | /** 48 | * 创建时间 49 | */ 50 | private Long createdAt; 51 | 52 | /** 53 | * 更新时间 54 | */ 55 | private Long updatedAt; 56 | 57 | 58 | 59 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/Friend.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName friend 13 | */ 14 | @TableName(value ="friend") 15 | @Data 16 | public class Friend implements Serializable { 17 | 18 | @TableId(type = IdType.AUTO) 19 | private Long id; 20 | 21 | private String userId; 22 | 23 | private String friendUserId; 24 | 25 | @JsonInclude(JsonInclude.Include.NON_NULL) 26 | private String remark; 27 | 28 | @JsonInclude(JsonInclude.Include.NON_NULL) 29 | private String extend; 30 | 31 | private Long createdAt; 32 | 33 | private static final long serialVersionUID = 1L; 34 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/FriendApply.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @TableName friend_apply 12 | */ 13 | @TableName(value ="friend_apply") 14 | @Data 15 | public class FriendApply implements Serializable { 16 | 17 | @TableId(type = IdType.AUTO) 18 | private Long id; 19 | 20 | private String applyUserId; 21 | 22 | private String userId; 23 | 24 | private String remark; 25 | 26 | private String extraMessage; 27 | 28 | private Integer status; 29 | 30 | private Long transformTime; 31 | 32 | private Integer isRead; 33 | 34 | private Long createdAt; 35 | 36 | private static final long serialVersionUID = 1L; 37 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/FriendApplyV0.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName friend_apply 13 | */ 14 | @TableName(value ="friend_apply") 15 | @Data 16 | public class FriendApplyV0 implements Serializable { 17 | 18 | @TableId(type = IdType.AUTO) 19 | private Long id; 20 | 21 | private String applyUserId; 22 | 23 | private String userId; 24 | 25 | @JsonInclude(JsonInclude.Include.NON_NULL) 26 | private String remark; 27 | 28 | @JsonInclude(JsonInclude.Include.NON_NULL) 29 | private String extraMessage; 30 | 31 | @JsonInclude(JsonInclude.Include.NON_NULL) 32 | private Integer status; 33 | 34 | @JsonInclude(JsonInclude.Include.NON_NULL) 35 | private Long transformTime; 36 | 37 | @JsonInclude(JsonInclude.Include.NON_NULL) 38 | private Integer isRead; 39 | 40 | @JsonInclude(JsonInclude.Include.NON_NULL) 41 | private Long createdAt; 42 | 43 | /** 44 | * 用户信息 45 | */ 46 | @JsonInclude(JsonInclude.Include.NON_NULL) 47 | private User userInfo; 48 | 49 | private static final long serialVersionUID = 1L; 50 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/FriendV0.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * @TableName friend 13 | */ 14 | @TableName(value ="friend") 15 | @Data 16 | public class FriendV0 implements Serializable { 17 | 18 | @TableId(type = IdType.AUTO) 19 | private Long id; 20 | 21 | private String userId; 22 | 23 | private String friendUserId; 24 | 25 | @JsonInclude(JsonInclude.Include.NON_NULL) 26 | private String remark; 27 | 28 | @JsonInclude(JsonInclude.Include.NON_NULL) 29 | private String extend; 30 | 31 | private Long createdAt; 32 | 33 | @JsonInclude(JsonInclude.Include.NON_NULL) 34 | private User friendInfo; 35 | 36 | private static final long serialVersionUID = 1L; 37 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/Group.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import java.io.Serializable; 7 | 8 | import com.fasterxml.jackson.annotation.JsonInclude; 9 | import lombok.Data; 10 | 11 | /** 12 | * @TableName group 13 | */ 14 | @TableName(value ="`group`") 15 | @Data 16 | public class Group implements Serializable { 17 | 18 | @TableId(type = IdType.AUTO) 19 | @JsonInclude(JsonInclude.Include.NON_NULL) 20 | private Long id; 21 | 22 | /** 23 | * 群组ID 24 | */ 25 | @JsonInclude(JsonInclude.Include.NON_NULL) 26 | private String groupId; 27 | 28 | /** 29 | * 群组名称 30 | */ 31 | @JsonInclude(JsonInclude.Include.NON_NULL) 32 | private String name; 33 | 34 | /** 35 | * 群组头像 36 | */ 37 | @JsonInclude(JsonInclude.Include.NON_NULL) 38 | private String avatarUrl; 39 | 40 | /** 41 | * 群主用户ID 42 | */ 43 | @JsonInclude(JsonInclude.Include.NON_NULL) 44 | private String leaderUserId; 45 | 46 | /** 47 | * 加群方式 48 | */ 49 | @JsonInclude(JsonInclude.Include.NON_NULL) 50 | private Integer joinMode; 51 | 52 | /** 53 | * 群介绍 54 | */ 55 | @JsonInclude(JsonInclude.Include.NON_NULL) 56 | private String introduction; 57 | 58 | /** 59 | * 群公告 60 | */ 61 | @JsonInclude(JsonInclude.Include.NON_NULL) 62 | private String notification; 63 | 64 | /** 65 | * 全体禁言 66 | * 1=是 67 | * 0=否 68 | */ 69 | private Integer isMute; 70 | 71 | /** 72 | * 是否已解散群组,1=已解散 0 = 未解散 73 | */ 74 | @JsonInclude(JsonInclude.Include.NON_NULL) 75 | private Integer isDissolve; 76 | 77 | /** 78 | * 创建时间 79 | */ 80 | @JsonInclude(JsonInclude.Include.NON_NULL) 81 | private Long createdAt; 82 | 83 | private static final long serialVersionUID = 1L; 84 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/GroupApply.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | import lombok.Data; 9 | 10 | /** 11 | * @TableName group_apply 12 | */ 13 | @TableName(value ="group_apply") 14 | @Data 15 | public class GroupApply implements Serializable { 16 | 17 | @TableId(type = IdType.AUTO) 18 | private Long id; 19 | 20 | /** 21 | * 群ID 22 | */ 23 | private String groupId; 24 | 25 | @TableField(exist = false) 26 | private Group groupInfo; 27 | 28 | /** 29 | * 申请用户ID 30 | */ 31 | private String userId; 32 | @TableField(exist = false) 33 | private User userInfo; 34 | 35 | /** 36 | * 邀请人id 37 | * 如果是别人代拉userid入群,此字段为操作者ID 38 | */ 39 | private String inviterId; 40 | 41 | /** 42 | * 申请附言 43 | */ 44 | private String extraMessage; 45 | 46 | /** 47 | * 申请状态 48 | */ 49 | private Integer status; 50 | 51 | /** 52 | * 处理申请的管理员ID 53 | */ 54 | private String adminId; 55 | 56 | /** 57 | * 处理时间 58 | */ 59 | private Long transformTime; 60 | 61 | /** 62 | * 处理附言 63 | */ 64 | private String transformMessage; 65 | 66 | /** 67 | * 申请的时间 68 | */ 69 | private Long createdAt; 70 | 71 | private static final long serialVersionUID = 1L; 72 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/GroupMessage.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | 9 | import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler; 10 | import lombok.Data; 11 | 12 | /** 13 | * @TableName group_message 14 | */ 15 | @TableName(value ="group_message") 16 | @Data 17 | public class GroupMessage implements Serializable { 18 | @TableId(type = IdType.AUTO) 19 | private Long sequence; 20 | 21 | /** 22 | * 消息ID 23 | * 私聊消息ID组成:分布式唯一ID-毫秒级时间戳-发送端1(接收端2) 24 | */ 25 | private String messageId; 26 | 27 | /** 28 | * 消息所属用户 29 | */ 30 | private String userId; 31 | 32 | 33 | /** 34 | * 消息所属会话ID 35 | */ 36 | private String conversationId; 37 | 38 | /** 39 | * 会话类型 40 | */ 41 | private String conversationType; 42 | 43 | /** 44 | * 消息方向:in=接收 out等于发出 45 | */ 46 | private String direction; 47 | 48 | /** 49 | * 消息发送方 50 | */ 51 | @TableField(value = "`from`") 52 | private String from; 53 | 54 | 55 | private User fromUserInfo; 56 | 57 | /** 58 | * 消息接收方 59 | */ 60 | @TableField(value = "`to`") 61 | private String to; 62 | 63 | /** 64 | * 消息类型 65 | */ 66 | @TableField(value = "`type`") 67 | private String type; 68 | 69 | /** 70 | * 消息内容 71 | */ 72 | @TableField(value = "`body`", typeHandler = FastjsonTypeHandler.class) 73 | private Object body; 74 | 75 | /** 76 | * 扩展的自定义数据(字符串类型) 77 | */ 78 | private String extra; 79 | 80 | /** 81 | * 对方是否已读 82 | */ 83 | private Integer isRead; 84 | 85 | /** 86 | * 是否被撤回的消息 87 | */ 88 | private Integer isRevoke; 89 | 90 | /** 91 | * 是否被删除的消息 92 | */ 93 | private Integer isDeleted; 94 | 95 | /** 96 | * 消息状态: 97 | * unSend(未发送) 98 | * success(发送成功) 99 | * fail(发送失败) 100 | */ 101 | @TableField(value = "`status`") 102 | private String status; 103 | 104 | /** 105 | * 对方接收状态 106 | * 0 = 未接收 107 | * 1 = 已接收 108 | */ 109 | @TableField(value = "`receive`") 110 | private Integer receive; 111 | 112 | /** 113 | * 消息时间,毫秒级时间戳 114 | */ 115 | @TableField(value = "`time`") 116 | private Long time; 117 | 118 | 119 | private static final long serialVersionUID = 1L; 120 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/GroupUser.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | import lombok.Data; 9 | 10 | /** 11 | * 群用户关联 12 | * @TableName group_user 13 | */ 14 | @TableName(value ="group_user") 15 | @Data 16 | public class GroupUser implements Serializable { 17 | 18 | @TableId(type = IdType.AUTO) 19 | private Integer id; 20 | 21 | /** 22 | * 群ID 23 | */ 24 | private String groupId; 25 | 26 | /** 27 | * 用户ID 28 | */ 29 | private String userId; 30 | 31 | @TableField(exist = false) 32 | private User userInfo; 33 | 34 | /** 35 | * 是否是管理员 36 | */ 37 | private Integer isAdmin; 38 | 39 | /** 40 | * 禁言到期时间 41 | * 0表示不禁言 42 | */ 43 | private Long muteEndTime; 44 | 45 | /** 46 | * 加入群的时间 47 | */ 48 | private Long joinAt; 49 | 50 | private Long createdAt; 51 | 52 | private static final long serialVersionUID = 1L; 53 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/Message.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler; 8 | import lombok.Data; 9 | 10 | import java.io.Serializable; 11 | 12 | /** 13 | * @TableName message 14 | */ 15 | @Data 16 | @TableName(value = "message") 17 | public class Message implements Serializable { 18 | 19 | @TableId(type = IdType.AUTO) 20 | private Long sequence; 21 | 22 | /** 23 | * 消息ID 24 | * 私聊消息ID组成:分布式唯一ID-毫秒级时间戳-发送端1(接收端2) 25 | */ 26 | private String messageId; 27 | 28 | /** 29 | * 消息所属用户 30 | */ 31 | private String userId; 32 | 33 | 34 | /** 35 | * 消息所属会话ID 36 | */ 37 | private String conversationId; 38 | 39 | /** 40 | * 会话类型 41 | */ 42 | private String conversationType; 43 | 44 | /** 45 | * 消息方向:in=接收 out等于发出 46 | */ 47 | private String direction; 48 | 49 | /** 50 | * 消息发送方 51 | */ 52 | @TableField(value = "`from`") 53 | private String from; 54 | 55 | 56 | private User fromUserInfo; 57 | 58 | /** 59 | * 消息接收方 60 | */ 61 | @TableField(value = "`to`") 62 | private String to; 63 | 64 | /** 65 | * 消息类型 66 | */ 67 | @TableField(value = "`type`") 68 | private String type; 69 | 70 | /** 71 | * 消息内容 72 | */ 73 | @TableField(value = "`body`", typeHandler = FastjsonTypeHandler.class) 74 | private Object body; 75 | 76 | /** 77 | * 扩展的自定义数据(字符串类型) 78 | */ 79 | private String extra; 80 | 81 | /** 82 | * 对方是否已读 83 | */ 84 | private Integer isRead; 85 | 86 | /** 87 | * 是否被撤回的消息 88 | */ 89 | private Integer isRevoke; 90 | 91 | /** 92 | * 是否被删除的消息 93 | */ 94 | private Integer isDeleted; 95 | 96 | /** 97 | * 消息状态: 98 | * unSend(未发送) 99 | * success(发送成功) 100 | * fail(发送失败) 101 | */ 102 | @TableField(value = "`status`") 103 | private String status; 104 | 105 | /** 106 | * 对方接收状态 107 | * 0 = 未接收 108 | * 1 = 已接收 109 | */ 110 | @TableField(value = "`receive`") 111 | private Integer receive; 112 | 113 | /** 114 | * 消息时间,毫秒级时间戳 115 | */ 116 | @TableField(value = "`time`") 117 | private Long time; 118 | 119 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/User.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import com.fasterxml.jackson.annotation.JsonInclude; 8 | import lombok.Data; 9 | 10 | import java.io.Serializable; 11 | 12 | /** 13 | * 14 | * @TableName user 15 | */ 16 | @TableName(value ="`user`") 17 | @Data 18 | public class User implements Serializable { 19 | /** 20 | * 21 | */ 22 | @JsonInclude(JsonInclude.Include.NON_NULL) 23 | @TableId(type = IdType.AUTO) 24 | private Long id; 25 | 26 | /** 27 | * 用户ID 28 | */ 29 | @JsonInclude(JsonInclude.Include.NON_NULL) 30 | private String userId; 31 | 32 | /** 33 | * 昵称 34 | */ 35 | private String nickname; 36 | 37 | /** 38 | * 头像地址 39 | */ 40 | private String avatarUrl; 41 | 42 | /** 43 | * 性别 44 | */ 45 | @JsonInclude(JsonInclude.Include.NON_NULL) 46 | private Integer gender; 47 | 48 | /** 49 | * 电话 50 | */ 51 | @TableField(value = "`mobile`") 52 | @JsonInclude(JsonInclude.Include.NON_NULL) 53 | private Long mobile; 54 | 55 | /** 56 | * 邮箱 57 | */ 58 | @JsonInclude(JsonInclude.Include.NON_NULL) 59 | private String email; 60 | 61 | /** 62 | * 生日 63 | */ 64 | @JsonInclude(JsonInclude.Include.NON_NULL) 65 | private String birthday; 66 | 67 | /** 68 | * 个性签名 69 | */ 70 | @JsonInclude(JsonInclude.Include.NON_NULL) 71 | private String motto; 72 | 73 | /** 74 | * 自定义扩展字段 75 | */ 76 | @JsonInclude(JsonInclude.Include.NON_NULL) 77 | private String extend; 78 | 79 | /** 80 | * 移动端推送标识符 81 | */ 82 | @JsonInclude(JsonInclude.Include.NON_NULL) 83 | private String mobileDeviceId; 84 | 85 | /** 86 | * 添加好友的方式 87 | * 88 | * 1:允许自由添加 89 | * 2:需要本人确认 90 | * 3:拒绝添加好友 91 | */ 92 | @JsonInclude(JsonInclude.Include.NON_NULL) 93 | private Integer addFriendType; 94 | 95 | /** 96 | * 创建时间 97 | */ 98 | @JsonInclude(JsonInclude.Include.NON_NULL) 99 | private Long createdAt; 100 | 101 | @TableField(exist = false) 102 | private static final long serialVersionUID = 1L; 103 | 104 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/UserBlackList.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import java.io.Serializable; 8 | import lombok.Data; 9 | 10 | /** 11 | * @TableName user_black_list 12 | */ 13 | @TableName(value ="user_black_list") 14 | @Data 15 | public class UserBlackList implements Serializable { 16 | private Long blackId; 17 | 18 | private String userId; 19 | 20 | private String coverUserId; 21 | 22 | private Long createdAt; 23 | 24 | private static final long serialVersionUID = 1L; 25 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/domain/UserBlackListV0.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.domain; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableName; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * @TableName user_black_list 10 | */ 11 | @Data 12 | public class UserBlackListV0 implements Serializable { 13 | private Long blackId; 14 | 15 | private String userId; 16 | 17 | private String coverUserId; 18 | 19 | private User coverUser; 20 | 21 | private Long createdAt; 22 | 23 | private static final long serialVersionUID = 1L; 24 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/friend/AddFriendDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.friend; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.NotNull; 9 | 10 | @Data 11 | public class AddFriendDTO { 12 | 13 | /** 14 | * 好友ID 15 | */ 16 | @NotNull(message = "好友用户ID不能为空") 17 | @Length(message = "好友用户ID的字节长度应在1-32位之间", min = 1, max = 32) 18 | @JsonProperty("userId") 19 | private String userId; 20 | 21 | /** 22 | * 好友备注 23 | */ 24 | @JsonProperty("remark") 25 | private String remark; 26 | 27 | /** 28 | * 附言 29 | */ 30 | @JsonProperty("extraMessage") 31 | private String extraMessage; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/friend/DeleteFriendDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.friend; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import javax.validation.constraints.NotEmpty; 7 | import javax.validation.constraints.NotNull; 8 | import java.util.List; 9 | 10 | @Data 11 | public class DeleteFriendDTO { 12 | 13 | /** 14 | * 用户ID数组 15 | */ 16 | @NotNull(message = "请传入用户ID列表") 17 | @NotEmpty(message = "请传入用户ID列表") 18 | @JsonProperty("members") 19 | private List members; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/friend/UpdateFriendDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.friend; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.NotNull; 9 | 10 | @Data 11 | public class UpdateFriendDTO { 12 | 13 | /** 14 | * 好友ID 15 | */ 16 | @NotNull(message = "好友用户ID不能为空") 17 | @Length(message = "好友用户ID的字节长度应在1-32位之间", min = 1, max = 32) 18 | @JsonProperty("userId") 19 | private String userId; 20 | 21 | /** 22 | * 好友备注 23 | */ 24 | @JsonProperty("remark") 25 | private String remark; 26 | 27 | /** 28 | * 自定义扩展字段 29 | */ 30 | @JsonProperty("extend") 31 | private String extend; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/group/GroupCreateDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.group; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import lombok.Data; 7 | import org.hibernate.validator.constraints.Length; 8 | 9 | import javax.validation.constraints.Max; 10 | import javax.validation.constraints.Min; 11 | import javax.validation.constraints.NotNull; 12 | import java.util.List; 13 | 14 | @Data 15 | public class GroupCreateDTO { 16 | 17 | /** 18 | * 群ID 19 | */ 20 | @JsonProperty("groupId") 21 | private String groupId; 22 | 23 | /** 24 | * 群名称 25 | */ 26 | @NotNull(message = "群名称不能为空") 27 | @Length(message = "群名称的字节长度应在1-255位之间", min = 1, max = 255) 28 | @JsonProperty("name") 29 | private String name; 30 | 31 | /** 32 | * 群头像地址 33 | */ 34 | @NotNull(message = "群头像不能为空") 35 | @Length(message = "群头像的字节长度应在1-300位之间", min = 1, max = 300) 36 | @JsonProperty("avatarUrl") 37 | private String avatarUrl; 38 | 39 | /** 40 | * 加群方式 41 | * JoinGroupMode 42 | */ 43 | @JsonProperty("joinMode") 44 | private Integer joinMode; 45 | 46 | /** 47 | * 群介绍 48 | */ 49 | @JsonProperty("introduction") 50 | private String introduction; 51 | 52 | /** 53 | * 群公告 54 | */ 55 | @JsonProperty("notification") 56 | private String notification; 57 | 58 | /** 59 | * 群聊成员用户ID数组 60 | */ 61 | @JsonProperty("members") 62 | private List members; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/group/GroupEditDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.group; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.NonNull; 7 | import org.hibernate.validator.constraints.Length; 8 | 9 | import javax.validation.constraints.NotEmpty; 10 | import javax.validation.constraints.NotNull; 11 | import java.util.List; 12 | 13 | @Data 14 | public class GroupEditDTO { 15 | 16 | /** 17 | * 群ID 18 | */ 19 | @NotEmpty(message = "群ID不能为空") 20 | @JsonProperty("groupId") 21 | private String groupId; 22 | 23 | /** 24 | * 群名称 25 | */ 26 | @JsonProperty("name") 27 | private String name; 28 | 29 | /** 30 | * 群头像地址 31 | */ 32 | @JsonProperty("avatarUrl") 33 | private String avatarUrl; 34 | 35 | /** 36 | * 加群方式 37 | * JoinGroupMode 38 | */ 39 | @JsonProperty("joinMode") 40 | private Integer joinMode; 41 | 42 | /** 43 | * 群介绍 44 | */ 45 | @JsonProperty("introduction") 46 | private String introduction; 47 | 48 | /** 49 | * 群公告 50 | */ 51 | @JsonProperty("notification") 52 | private String notification; 53 | 54 | /** 55 | * 全体禁言 56 | * 1=是 57 | * 0=否 58 | */ 59 | @JsonProperty("isMute") 60 | private Integer isMute; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/group/GroupUserAddDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.group; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.NonNull; 7 | import org.hibernate.validator.constraints.Length; 8 | 9 | import javax.validation.constraints.NotEmpty; 10 | import javax.validation.constraints.NotNull; 11 | import java.util.List; 12 | 13 | @Data 14 | public class GroupUserAddDTO { 15 | 16 | /** 17 | * 群ID 18 | */ 19 | @NotNull(message = "群ID不能为空") 20 | @Length(message = "群ID的字节长度应在1-255位之间", min = 1, max = 255) 21 | @JsonProperty("groupId") 22 | private String groupId; 23 | 24 | 25 | /** 26 | * 群聊成员用户ID数组 27 | */ 28 | @NotNull(message = "请传入用户ID列表") 29 | @NotEmpty(message = "请传入用户ID列表") 30 | @JsonProperty("members") 31 | private List members; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/message/MessageSaveDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.message; 2 | 3 | 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import lombok.Data; 7 | 8 | import javax.validation.constraints.NotBlank; 9 | import javax.validation.constraints.NotEmpty; 10 | import javax.validation.constraints.NotNull; 11 | 12 | @Data 13 | public class MessageSaveDTO { 14 | 15 | // 消息ID 16 | // @NotNull(message = "messageId 不能为空") 17 | // @JsonProperty("messageId") 18 | // private String messageId; 19 | 20 | //会话ID 21 | @NotEmpty(message = "conversationId 不能为空") 22 | @JsonProperty("conversationId") 23 | private String conversationId; 24 | 25 | //会话类型 26 | @NotEmpty(message = "conversationType 不能为空") 27 | @JsonProperty("conversationType") 28 | private String conversationType; 29 | 30 | //消息发送方ID 31 | @NotEmpty(message = "from 不能为空") 32 | @JsonProperty("from") 33 | private String from; 34 | 35 | //消息接收方ID 36 | @NotEmpty(message = "to 不能为空") 37 | @JsonProperty("to") 38 | private String to; 39 | 40 | //消息类型 41 | @NotEmpty(message = "type 不能为空") 42 | @JsonProperty("type") 43 | private String type; 44 | 45 | //消息体 46 | @NotNull(message = "body 不能为空") 47 | @JsonProperty("body") 48 | private Object body; 49 | 50 | //消息体 51 | @JsonProperty("extra") 52 | private String extra; 53 | 54 | //发送方发送时间 55 | @NotNull(message = "time 不能为空") 56 | @JsonProperty("time") 57 | private Long time; 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/user/UserBlackListAddDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.user; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.NotEmpty; 9 | import javax.validation.constraints.NotNull; 10 | import java.util.List; 11 | 12 | @Data 13 | public class UserBlackListAddDTO { 14 | 15 | /** 16 | * 黑名单用户ID数组 17 | */ 18 | @NotNull(message = "请传入用户ID列表") 19 | @NotEmpty(message = "请传入用户ID列表") 20 | @JsonProperty("members") 21 | private List members; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/user/UserRegisterDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.user; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import lombok.Data; 7 | import org.hibernate.validator.constraints.Length; 8 | 9 | import javax.validation.constraints.NotNull; 10 | 11 | @Data 12 | public class UserRegisterDTO { 13 | 14 | //用户ID 15 | @NotNull(message = "用户ID不能为空") 16 | @Length(message = "用户ID的字节长度应在1-32位之间", min = 1, max = 32) 17 | @JsonProperty("userId") 18 | private String userId; 19 | 20 | /** 21 | * 用户昵称 22 | */ 23 | @NotNull(message = "用户昵称不能为空") 24 | @Length(message = "用户昵称的字节长度应在1-32位之间", min = 1, max = 32) 25 | @JsonProperty("nickname") 26 | private String nickname; 27 | 28 | /** 29 | * 用户头像地址 30 | */ 31 | @NotNull(message = "用户头像不能为空") 32 | @Length(message = "用户头像的字节长度应在1-300位之间", min = 1, max = 300) 33 | @JsonProperty("avatarUrl") 34 | private String avatarUrl; 35 | 36 | /** 37 | * 性别 38 | */ 39 | @JsonProperty("gender") 40 | private Integer gender; 41 | 42 | /** 43 | * 电话 44 | */ 45 | @JsonProperty("mobile") 46 | private Long mobile; 47 | 48 | /** 49 | * 邮箱 50 | */ 51 | @JsonProperty("email") 52 | private String email; 53 | 54 | /** 55 | * 生日 56 | */ 57 | @JsonProperty("birthday") 58 | private String birthday; 59 | 60 | /** 61 | * 个性签名 62 | */ 63 | @JsonProperty("motto") 64 | private String motto; 65 | 66 | /** 67 | * 自定义扩展字段 68 | */ 69 | @JsonProperty("extend") 70 | private String extend; 71 | 72 | /** 73 | * 添加好友的方式 74 | * 75 | * 1:允许自由添加 76 | * 2:需要本人确认 77 | * 3:拒绝添加好友 78 | */ 79 | @JsonProperty("addFriendType") 80 | private Integer addFriendType; 81 | 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/user/UserTokenDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.user; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import org.hibernate.validator.constraints.Length; 7 | 8 | import javax.validation.constraints.Min; 9 | import javax.validation.constraints.NotNull; 10 | 11 | @Data 12 | public class UserTokenDTO { 13 | 14 | /** 15 | * 用户ID 16 | */ 17 | @NotNull(message = "用户ID不能为空") 18 | @Length(message = "用户ID的长度应在1-32位之间", min = 1, max = 32) 19 | @JsonProperty("userId") 20 | private String userId; 21 | 22 | /** 23 | * 过期时间 24 | */ 25 | @NotNull(message = "过期时间不能为空") 26 | @Min(message = "过期时间应为毫秒级时间戳",value = 1000000000000L) 27 | @JsonProperty("timestamp") 28 | private Long timestamp; 29 | 30 | /** 31 | * sign 32 | * 33 | */ 34 | @NotNull(message = "签名不能为空") 35 | @Length(message = "签名长度应为32字节", min = 32, max = 32) 36 | @JsonProperty("sign") 37 | private String sign; 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/dto/user/UserUpdateDTO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.dto.user; 2 | 3 | 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | 7 | @Data 8 | public class UserUpdateDTO { 9 | 10 | /** 11 | * 用户昵称 12 | */ 13 | @JsonProperty("nickname") 14 | private String nickname; 15 | 16 | /** 17 | * 用户头像地址 18 | */ 19 | @JsonProperty("avatarUrl") 20 | private String avatarUrl; 21 | 22 | /** 23 | * 性别 24 | */ 25 | @JsonProperty("gender") 26 | private Integer gender; 27 | 28 | /** 29 | * 电话 30 | */ 31 | @JsonProperty("mobile") 32 | private Long mobile; 33 | 34 | /** 35 | * 邮箱 36 | */ 37 | @JsonProperty("email") 38 | private String email; 39 | 40 | /** 41 | * 生日 42 | */ 43 | @JsonProperty("birthday") 44 | private String birthday; 45 | 46 | /** 47 | * 个性签名 48 | */ 49 | @JsonProperty("motto") 50 | private String motto; 51 | 52 | /** 53 | * 自定义扩展字段 54 | */ 55 | @JsonProperty("extend") 56 | private String extend; 57 | 58 | /** 59 | * 添加好友的方式 60 | * 61 | * 1:允许自由添加 62 | * 2:需要本人确认 63 | * 3:拒绝添加好友 64 | */ 65 | @JsonProperty("addFriendType") 66 | private Integer addFriendType; 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/FileUploadException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception; 2 | 3 | public class FileUploadException extends RuntimeException { 4 | public FileUploadException() { 5 | 6 | } 7 | 8 | public FileUploadException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/FrequencyLimitException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception; 2 | 3 | public class FrequencyLimitException extends RuntimeException { 4 | public FrequencyLimitException() { 5 | 6 | } 7 | 8 | public FrequencyLimitException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/LoginExpireException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception; 2 | 3 | public class LoginExpireException extends RuntimeException { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/ParamsException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception; 2 | 3 | public class ParamsException extends RuntimeException { 4 | public ParamsException() { 5 | 6 | } 7 | 8 | public ParamsException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/conversation/ConversationNotFoundException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.conversation; 2 | 3 | public class ConversationNotFoundException extends RuntimeException { 4 | public ConversationNotFoundException() { 5 | 6 | } 7 | 8 | public ConversationNotFoundException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/friend/ApplyNeedException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.friend; 2 | 3 | public class ApplyNeedException extends RuntimeException { 4 | public ApplyNeedException() { 5 | 6 | } 7 | 8 | public ApplyNeedException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/friend/DuplicateException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.friend; 2 | 3 | public class DuplicateException extends RuntimeException { 4 | public DuplicateException() { 5 | 6 | } 7 | 8 | public DuplicateException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/friend/FriendApplyNotFoundException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.friend; 2 | 3 | public class FriendApplyNotFoundException extends RuntimeException { 4 | public FriendApplyNotFoundException() { 5 | 6 | } 7 | 8 | public FriendApplyNotFoundException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/friend/FriendNotFoundException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.friend; 2 | 3 | public class FriendNotFoundException extends RuntimeException { 4 | public FriendNotFoundException() { 5 | 6 | } 7 | 8 | public FriendNotFoundException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/GroupAllMuteException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class GroupAllMuteException extends RuntimeException { 4 | public GroupAllMuteException() { 5 | 6 | } 7 | 8 | public GroupAllMuteException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/GroupDuplicateException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class GroupDuplicateException extends RuntimeException { 4 | public GroupDuplicateException() { 5 | 6 | } 7 | 8 | public GroupDuplicateException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/GroupMuteException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class GroupMuteException extends RuntimeException { 4 | public GroupMuteException() { 5 | 6 | } 7 | 8 | public GroupMuteException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/GroupNoEntryException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class GroupNoEntryException extends RuntimeException { 4 | public GroupNoEntryException() { 5 | 6 | } 7 | 8 | public GroupNoEntryException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/GroupNotFoundException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class GroupNotFoundException extends RuntimeException { 4 | public GroupNotFoundException() { 5 | 6 | } 7 | 8 | public GroupNotFoundException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/GroupOnlyDissolveException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class GroupOnlyDissolveException extends RuntimeException { 4 | public GroupOnlyDissolveException() { 5 | 6 | } 7 | 8 | public GroupOnlyDissolveException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/GroupPermissionDeniedException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class GroupPermissionDeniedException extends RuntimeException { 4 | public GroupPermissionDeniedException() { 5 | 6 | } 7 | 8 | public GroupPermissionDeniedException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/GroupUserInsertLimitException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class GroupUserInsertLimitException extends RuntimeException { 4 | public GroupUserInsertLimitException() { 5 | 6 | } 7 | 8 | public GroupUserInsertLimitException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/group/NoGroupUserException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.group; 2 | 3 | public class NoGroupUserException extends RuntimeException { 4 | public NoGroupUserException() { 5 | 6 | } 7 | 8 | public NoGroupUserException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/message/IdException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.message; 2 | 3 | public class IdException extends RuntimeException { 4 | public IdException() { 5 | 6 | } 7 | 8 | public IdException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/message/MessageRejectedException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.message; 2 | 3 | public class MessageRejectedException extends RuntimeException { 4 | public MessageRejectedException() { 5 | 6 | } 7 | 8 | public MessageRejectedException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/message/ToUserIdNotFoundException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.message; 2 | 3 | public class ToUserIdNotFoundException extends RuntimeException { 4 | public ToUserIdNotFoundException() { 5 | 6 | } 7 | 8 | public ToUserIdNotFoundException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/user/ExpireException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.user; 2 | 3 | public class ExpireException extends RuntimeException { 4 | public ExpireException() { 5 | 6 | } 7 | 8 | public ExpireException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/user/SignException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.user; 2 | 3 | public class SignException extends RuntimeException { 4 | public SignException() { 5 | 6 | } 7 | 8 | public SignException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/user/UserDuplicateException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.user; 2 | 3 | public class UserDuplicateException extends RuntimeException { 4 | public UserDuplicateException() { 5 | 6 | } 7 | 8 | public UserDuplicateException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/user/UserFriendDenyException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.user; 2 | 3 | public class UserFriendDenyException extends RuntimeException { 4 | public UserFriendDenyException() { 5 | 6 | } 7 | 8 | public UserFriendDenyException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/user/UserFriendDuplicateException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.user; 2 | 3 | public class UserFriendDuplicateException extends RuntimeException { 4 | public UserFriendDuplicateException() { 5 | 6 | } 7 | 8 | public UserFriendDuplicateException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/exception/user/UserNotFoundException.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.exception.user; 2 | 3 | public class UserNotFoundException extends RuntimeException { 4 | public UserNotFoundException() { 5 | 6 | } 7 | 8 | public UserNotFoundException(String message) { 9 | super(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/handler/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.handler; 2 | 3 | import cn.wzjun1.yeimServer.constant.StatusCode; 4 | import cn.wzjun1.yeimServer.exception.LoginExpireException; 5 | import cn.wzjun1.yeimServer.result.Result; 6 | import org.springframework.http.converter.HttpMessageNotReadableException; 7 | import org.springframework.web.HttpRequestMethodNotSupportedException; 8 | import org.springframework.web.bind.MethodArgumentNotValidException; 9 | import org.springframework.web.bind.MissingServletRequestParameterException; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | import org.springframework.web.bind.annotation.RestControllerAdvice; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | 17 | @ControllerAdvice 18 | @ResponseBody 19 | @RestControllerAdvice 20 | public class GlobalExceptionHandler { 21 | 22 | @ExceptionHandler(value = Exception.class) 23 | public Result allExceptionHandler(HttpServletRequest request, 24 | Exception exception) throws Exception { 25 | exception.printStackTrace(); 26 | if (exception instanceof MethodArgumentNotValidException) { 27 | MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) exception; 28 | return Result.error(methodArgumentNotValidException.getBindingResult().getFieldError().getDefaultMessage()); 29 | } else if (exception instanceof MissingServletRequestParameterException) { 30 | return Result.error(StatusCode.PARAMS_ERROR.getCode(), "请求缺少参数:" + ((MissingServletRequestParameterException) exception).getParameterName()); 31 | } else if (exception instanceof HttpRequestMethodNotSupportedException) { 32 | return Result.error(exception.getMessage()); 33 | } else if (exception instanceof ClassCastException || exception instanceof HttpMessageNotReadableException) { 34 | return Result.error(StatusCode.PARAMS_ERROR); 35 | } else if (exception instanceof LoginExpireException) { 36 | return Result.error(StatusCode.LOGIN_EXPIRE); 37 | } else { 38 | return Result.error(exception.getMessage()); 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/interceptor/LoginUserContext.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.interceptor; 2 | 3 | import cn.wzjun1.yeimServer.domain.User; 4 | 5 | public class LoginUserContext { 6 | 7 | private static ThreadLocal userInfo = new ThreadLocal(); 8 | 9 | private static ThreadLocal token = new ThreadLocal(); 10 | 11 | public LoginUserContext() { 12 | 13 | } 14 | 15 | public static User getUser() { 16 | User user = (User) userInfo.get(); 17 | return user; 18 | } 19 | 20 | public static void setUser(User user) { 21 | userInfo.set(user); 22 | } 23 | 24 | public static void removeUser() { 25 | userInfo.remove(); 26 | } 27 | 28 | public static String getToken() { 29 | return String.valueOf(userInfo.get()); 30 | } 31 | 32 | public static void setToken(String s) { 33 | token.set(s); 34 | } 35 | 36 | public static void removeToken() { 37 | token.remove(); 38 | } 39 | 40 | 41 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/interceptor/UserAuthorizationInterceptor.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.interceptor; 2 | 3 | import cn.wzjun1.yeimServer.annotation.UserAuthorization; 4 | import cn.wzjun1.yeimServer.domain.User; 5 | import cn.wzjun1.yeimServer.exception.LoginExpireException; 6 | import cn.wzjun1.yeimServer.utils.RedisUtil; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.web.method.HandlerMethod; 9 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.lang.reflect.Method; 14 | 15 | @Slf4j 16 | public class UserAuthorizationInterceptor extends HandlerInterceptorAdapter { 17 | 18 | private RedisUtil redisUtil; 19 | 20 | public UserAuthorizationInterceptor(RedisUtil redisUtil) { 21 | this.redisUtil = redisUtil; 22 | } 23 | 24 | /** 25 | * 存放鉴权信息的Header名称 26 | */ 27 | private String httpHeaderName = "token"; 28 | 29 | @Override 30 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 31 | /** 32 | * 如果不是映射到方法直接通过 33 | */ 34 | if (!(handler instanceof HandlerMethod)) { 35 | return true; 36 | } 37 | HandlerMethod handlerMethod = (HandlerMethod) handler; 38 | Method method = handlerMethod.getMethod(); 39 | String token = request.getHeader(httpHeaderName); 40 | 41 | if (token != null && token.length() > 0) { 42 | String key = "token:" + token; 43 | if (redisUtil.hasKey(key)) { 44 | User user = (User) redisUtil.get(key); 45 | LoginUserContext.setUser(user); 46 | LoginUserContext.setToken(token); 47 | return true; 48 | } 49 | } 50 | /** 51 | * 如果验证token失败,并且方法或类注明了Authorization,返回错误 52 | */ 53 | if (method.getAnnotation(UserAuthorization.class) != null || handlerMethod.getBeanType().getAnnotation(UserAuthorization.class) != null) { 54 | throw new LoginExpireException(); 55 | } 56 | return true; 57 | } 58 | 59 | 60 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/ConversationMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.Conversation; 4 | import cn.wzjun1.yeimServer.domain.ConversationV0; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.baomidou.mybatisplus.core.metadata.IPage; 7 | import org.apache.ibatis.annotations.*; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author wzjun1 13 | * @description 针对表【conversation】的数据库操作Mapper 14 | * @createDate 2022-11-17 16:51:12 15 | * @Entity cn.wzjun1.yeimServer.domain.Conversation 16 | */ 17 | @Mapper 18 | public interface ConversationMapper extends BaseMapper { 19 | 20 | ConversationV0 getConversationV0(@Param("conversationId") String conversationId, @Param("userId") String userId); 21 | 22 | IPage listConversationV0(IPage page, @Param("userId") String userId); 23 | 24 | @Select("update `conversation` set `unread` = `unread` + 1, `last_message_id` = #{messageId},`updated_at` = #{time} where `conversation_id` = #{groupId} and user_id = #{userId} and type = 'group'") 25 | void updateGroupConversation(@Param("messageId") String messageId, @Param("time") long time, @Param("groupId") String groupId, @Param("userId") String userId); 26 | 27 | } 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/FriendApplyMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.ConversationV0; 4 | import cn.wzjun1.yeimServer.domain.FriendApply; 5 | import cn.wzjun1.yeimServer.domain.FriendApplyV0; 6 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 7 | import com.baomidou.mybatisplus.core.metadata.IPage; 8 | import org.apache.ibatis.annotations.Mapper; 9 | import org.apache.ibatis.annotations.Param; 10 | 11 | /** 12 | * @author wzjun1 13 | * @description 针对表【friend_apply(好友申请添加表)】的数据库操作Mapper 14 | * @createDate 2023-04-03 19:09:36 15 | * @Entity generator.domain.FriendApply 16 | */ 17 | 18 | @Mapper 19 | public interface FriendApplyMapper extends BaseMapper { 20 | IPage getApplyList(IPage page, @Param("userId") String userId); 21 | IPage getRequestList(IPage page, @Param("userId") String userId); 22 | FriendApplyV0 fetchApplyById(@Param("id") Long id); 23 | } 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/FriendMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.ConversationV0; 4 | import cn.wzjun1.yeimServer.domain.Friend; 5 | import cn.wzjun1.yeimServer.domain.FriendV0; 6 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 7 | import com.baomidou.mybatisplus.core.metadata.IPage; 8 | import org.apache.ibatis.annotations.Mapper; 9 | import org.apache.ibatis.annotations.Param; 10 | 11 | /** 12 | * @author wzjun1 13 | * @description 针对表【friend(好友表)】的数据库操作Mapper 14 | * @createDate 2023-04-04 10:48:49 15 | * @Entity generator.domain.Friend 16 | */ 17 | @Mapper 18 | public interface FriendMapper extends BaseMapper { 19 | IPage getFriendList(IPage page, @Param("userId") String userId); 20 | IPage getFriendProfileList(IPage page, @Param("userId") String userId); 21 | } 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/GroupApplyMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.GroupApply; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author Administrator 12 | * @description 针对表【group_apply(入群申请表)】的数据库操作Mapper 13 | * @createDate 2022-12-11 10:52:00 14 | * @Entity cn.wzjun1.yeimServer.domain.GroupApply 15 | */ 16 | @Mapper 17 | public interface GroupApplyMapper extends BaseMapper { 18 | 19 | GroupApply getApply(@Param("id") Integer id); 20 | 21 | List getApplyList(@Param("groupIds") List groupIds); 22 | 23 | } 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/GroupMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.Group; 4 | import cn.wzjun1.yeimServer.domain.User; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | import org.apache.ibatis.annotations.Select; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author Administrator 14 | * @description 针对表【group】的数据库操作Mapper 15 | * @createDate 2022-12-07 20:00:11 16 | * @Entity cn.wzjun1.yeimServer.domain.Group 17 | */ 18 | @Mapper 19 | public interface GroupMapper extends BaseMapper { 20 | @Select("select * from `group` where group_id = #{groupId}") 21 | Group findByGroupId(@Param("groupId") String groupId); 22 | 23 | @Select("SELECT * FROM `group` WHERE `group_id` in ( SELECT `group_id` from group_user WHERE user_id = #{userId} )") 24 | List selectGroupByUserId(@Param("userId") String userId); 25 | } 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/GroupMessageMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.GroupMessage; 4 | import cn.wzjun1.yeimServer.domain.Message; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import com.baomidou.mybatisplus.core.metadata.IPage; 7 | import org.apache.ibatis.annotations.Mapper; 8 | import org.apache.ibatis.annotations.Param; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author Administrator 14 | * @description 针对表【group_message】的数据库操作Mapper 15 | * @createDate 2022-12-08 21:18:05 16 | * @Entity cn.wzjun1.yeimServer.domain.GroupMessage 17 | */ 18 | @Mapper 19 | public interface GroupMessageMapper extends BaseMapper { 20 | GroupMessage getMessageById(@Param("messageId") String messageId, @Param("conversationId") String conversationId); 21 | 22 | IPage listMessage(IPage page, @Param("userId") String userId, @Param("conversationId") String conversationId); 23 | 24 | List listMessageByNextMessageId(@Param("userId") String userId, @Param("conversationId") String conversationId, @Param("nextMessageId") String nextMessageId, @Param("limit") Integer limit); 25 | 26 | void deleteGroupMessage(@Param("messageId") String messageId, @Param("groupId") String groupId, @Param("userId") String userId, @Param("createdAt") Long createdAt); 27 | 28 | } 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/GroupUserMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.GroupUser; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author Administrator 12 | * @description 针对表【group_user】的数据库操作Mapper 13 | * @createDate 2022-12-07 20:55:41 14 | * @Entity cn.wzjun1.yeimServer.domain.GroupUser 15 | */ 16 | @Mapper 17 | public interface GroupUserMapper extends BaseMapper { 18 | List getGroupUserList(@Param("groupId") String groupId); 19 | } 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/MessageMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.Message; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import com.baomidou.mybatisplus.core.metadata.IPage; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author wzjun1 13 | * @description 针对表【message】的数据库操作Mapper 14 | * @createDate 2022-11-16 23:29:12 15 | * @Entity cn.wzjun1.yeimServer.domain.Message 16 | */ 17 | @Mapper 18 | public interface MessageMapper extends BaseMapper { 19 | Message getMessageById(@Param("messageId") String messageId, @Param("userId") String userId); 20 | IPage listMessage(IPage page, @Param("userId") String userId, @Param("conversationId") String conversationId); 21 | List listMessageByNextMessageId(@Param("userId") String userId, @Param("conversationId") String conversationId, @Param("nextMessageId") String nextMessageId, @Param("limit") Integer limit); 22 | 23 | } 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/UserBlackListMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.UserBlackList; 4 | import cn.wzjun1.yeimServer.domain.UserBlackListV0; 5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 6 | import org.apache.ibatis.annotations.Mapper; 7 | import org.apache.ibatis.annotations.Param; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author wzjun1 13 | * @description 针对表【user_black_list(用户黑名单列表)】的数据库操作Mapper 14 | * @createDate 2023-02-19 11:19:57 15 | * @Entity cn.wzjun1.yeimServer.domain.UserBlackList 16 | */ 17 | @Mapper 18 | public interface UserBlackListMapper extends BaseMapper { 19 | List getBlackUserList(@Param("userId") String userId); 20 | } 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.mapper; 2 | 3 | import cn.wzjun1.yeimServer.domain.User; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Mapper; 6 | import org.apache.ibatis.annotations.Param; 7 | import org.apache.ibatis.annotations.Select; 8 | 9 | /** 10 | * @author wzjun1 11 | * @description 针对表【user】的数据库操作Mapper 12 | * @createDate 2022-11-15 20:23:25 13 | * @Entity cn.wzjun1.yeimServer.domain.User 14 | */ 15 | @Mapper 16 | public interface UserMapper extends BaseMapper { 17 | 18 | @Select("select * from user where user_id = #{userId}") 19 | User findByUserId(@Param("userId") String userId); 20 | } 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/pojo/YeIMPushConfig.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.pojo; 2 | 3 | import cn.wzjun1.yeimServer.pojo.push.GtConfig; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.PropertySource; 9 | 10 | @Configuration 11 | @ConfigurationProperties(prefix = "yeim.push") 12 | @Getter 13 | @Setter 14 | public class YeIMPushConfig { 15 | private boolean enable; 16 | private String type; 17 | private GtConfig gt; 18 | private String oppoChannelId; 19 | private String xiaomiChannelId; 20 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/pojo/push/GtConfig.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.pojo.push; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.boot.context.properties.ConfigurationProperties; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Getter 9 | @Setter 10 | public class GtConfig { 11 | private String appId; 12 | private String appKey; 13 | private String masterSecret; 14 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/result/Result.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.result; 2 | 3 | import cn.wzjun1.yeimServer.constant.StatusCode; 4 | import com.alibaba.fastjson.JSONObject; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | public class Result implements Serializable { 11 | 12 | private static final long serialVersionUID = -3960261604608758516L; 13 | 14 | //通用返回成功状态码 15 | private static final int SUCCESS_CODE = 200; 16 | 17 | //通用返回失败状态码 18 | private static final int ERROR_CODE = 500; 19 | private int code; 20 | private String message; 21 | private T data; 22 | 23 | /** 24 | * 构造器,自定义状态码,返回消息,返回数据 25 | * 26 | * @param code 状态码 27 | * @param message 返回消息 28 | * @param data 返回数据 29 | */ 30 | private Result(int code, String message, T data) { 31 | this.code = code; 32 | this.message = message; 33 | this.data = data; 34 | } 35 | 36 | /** 37 | * 成功,无返回消息,无返回数据 38 | * 39 | * @param 40 | */ 41 | public static Result success() { 42 | return new Result<>(SUCCESS_CODE, "success", null); 43 | } 44 | 45 | /** 46 | * 成功,无返回数据 47 | * 48 | * @param 49 | */ 50 | public static Result success(String message) { 51 | return new Result<>(SUCCESS_CODE, message, null); 52 | } 53 | 54 | /** 55 | * 成功,无返回消息,返回数据 56 | * 57 | * @param data 返回数据 58 | * @param 59 | */ 60 | public static Result success(T data) { 61 | return new Result<>(SUCCESS_CODE, "success", data); 62 | } 63 | 64 | /** 65 | * 失败,无返回消息,无返回数据 66 | * 67 | * @param 68 | */ 69 | public static Result error() { 70 | return new Result<>(ERROR_CODE, "", null); 71 | } 72 | 73 | /** 74 | * 失败,返回消息,无返回数据 75 | * 76 | * @param message 返回消息 77 | * @param 78 | */ 79 | public static Result error(String message) { 80 | return new Result<>(ERROR_CODE, message, null); 81 | } 82 | 83 | /** 84 | * 失败,返回消息,无返回数据 85 | * 86 | * @param statusCode 87 | * @param 88 | * @return 89 | */ 90 | public static Result error(StatusCode statusCode) { 91 | return new Result<>(statusCode.getCode(), statusCode.getDesc(), null); 92 | } 93 | 94 | /** 95 | * 失败,返回消息,返回数据 96 | * 97 | * @param message 返回消息 98 | * @param data 返回数据 99 | * @param 100 | */ 101 | public static Result error(String message, T data) { 102 | return new Result<>(ERROR_CODE, message, data); 103 | } 104 | 105 | /** 106 | * 失败,返回状态码,消息 107 | * 108 | * @param code 109 | * @param message 110 | * @param 111 | * @return 112 | */ 113 | public static Result error(int code, String message) { 114 | return new Result<>(code, message, null); 115 | } 116 | 117 | /** 118 | * 失败,返回状态码,消息,返回数据 119 | * 120 | * @param code 121 | * @param message 122 | * @param data 123 | * @param 124 | * @return 125 | */ 126 | public static Result error(int code, String message, T data) { 127 | return new Result<>(code, message, data); 128 | } 129 | 130 | /** 131 | * 信息,返回状态码,消息,返回数据 132 | * 133 | * @param code 134 | * @param message 135 | * @param data 136 | * @param 137 | * @return 138 | */ 139 | public static Result info(int code, String message, T data) { 140 | return new Result<>(code, message, data); 141 | } 142 | 143 | /** 144 | * 转化为json字符串 145 | * 146 | * @return 147 | */ 148 | public String toJSONString() { 149 | return JSONObject.toJSONString(this); 150 | } 151 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/result/vo/AddUserToGroupResultVO.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.result.vo; 2 | 3 | import cn.wzjun1.yeimServer.domain.Group; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | 8 | 9 | /** 10 | * addUserToGroup 方法返回值 11 | * 12 | * @List successList 操作成功的用户ID列表 13 | * @List failList 操作失败的用户ID列表 14 | * @List ignoreList 忽略了的用户ID列表 15 | * 16 | */ 17 | @Data 18 | public class AddUserToGroupResultVO { 19 | 20 | /** 21 | * 群组信息 22 | */ 23 | private Group group; 24 | 25 | /** 26 | * 操作成功的用户ID列表 27 | */ 28 | private List successList; 29 | 30 | /** 31 | * 操作失败的用户ID列表 32 | */ 33 | private List failList; 34 | 35 | /** 36 | * 忽略了的用户ID列表 37 | */ 38 | private List ignoreList; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/AsyncService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.GroupMessage; 4 | import cn.wzjun1.yeimServer.domain.Message; 5 | 6 | public interface AsyncService { 7 | void emitJSSDKMessageReceive(Message message); 8 | 9 | void updateGroupConversationSendEvent(String groupId, GroupMessage message); 10 | 11 | void groupMessageRevokedSendEvent(String groupId, GroupMessage message); 12 | 13 | void messageRevokedSendEvent(Message message); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/ConversationService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.Conversation; 4 | import cn.wzjun1.yeimServer.domain.ConversationV0; 5 | import com.baomidou.mybatisplus.extension.service.IService; 6 | 7 | /** 8 | * @author wzjun1 9 | * @description 针对表【conversation】的数据库操作Service 10 | * @createDate 2022-11-17 16:51:12 11 | */ 12 | public interface ConversationService extends IService { 13 | ConversationV0 getConversation(String conversationId, String userId); 14 | 15 | /** 16 | * 新增或更新会话 17 | * 18 | * @param userId 会话所属用户 19 | * @param conversationId 会话ID 20 | * @param conversationType 会话类型 21 | * @param lastMessageId 最新消息ID 22 | * @param unread 未读数 23 | * @param emit 是否给会话所属用户发送会话更新事件 24 | */ 25 | boolean updateConversation(String userId, String conversationId, String conversationType, String lastMessageId, Integer unread, boolean emit); 26 | 27 | void clearConversationUnread(String conversationId) throws Exception; 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/FriendApplyService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.FriendApply; 4 | import cn.wzjun1.yeimServer.dto.friend.AddFriendDTO; 5 | import cn.wzjun1.yeimServer.dto.friend.DeleteFriendDTO; 6 | import com.baomidou.mybatisplus.extension.service.IService; 7 | 8 | /** 9 | * @author wzjun1 10 | * @description 针对表【friend_apply(好友申请添加表)】的数据库操作Service 11 | * @createDate 2023-04-03 19:09:36 12 | */ 13 | public interface FriendApplyService extends IService { 14 | void addFriend(AddFriendDTO addFriendDTO); 15 | void acceptApply(Integer id, String remark); 16 | void refuseApply(Integer id); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/FriendService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.Friend; 4 | import cn.wzjun1.yeimServer.dto.friend.DeleteFriendDTO; 5 | import cn.wzjun1.yeimServer.dto.friend.UpdateFriendDTO; 6 | import com.baomidou.mybatisplus.extension.service.IService; 7 | 8 | /** 9 | * @author wzjun1 10 | * @description 针对表【friend(好友表)】的数据库操作Service 11 | * @createDate 2023-04-04 10:48:49 12 | */ 13 | public interface FriendService extends IService { 14 | void deleteFriend(DeleteFriendDTO deleteFriendDTO); 15 | void updateFriend(UpdateFriendDTO updateFriendDTO); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/GroupApplyService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.GroupApply; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | /** 7 | * @author Administrator 8 | * @description 针对表【group_apply(入群申请表)】的数据库操作Service 9 | * @createDate 2022-12-11 10:52:00 10 | */ 11 | public interface GroupApplyService extends IService { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/GroupMessageService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.GroupMessage; 4 | import cn.wzjun1.yeimServer.domain.Message; 5 | import cn.wzjun1.yeimServer.domain.User; 6 | import cn.wzjun1.yeimServer.dto.message.MessageSaveDTO; 7 | import com.baomidou.mybatisplus.core.metadata.IPage; 8 | import com.baomidou.mybatisplus.extension.service.IService; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author Administrator 14 | * @description 针对表【group_message】的数据库操作Service 15 | * @createDate 2022-12-08 21:18:05 16 | */ 17 | public interface GroupMessageService extends IService { 18 | GroupMessage insertGroupMessage(User user, MessageSaveDTO message) throws Exception; 19 | GroupMessage insertGroupMessageToOne(User user, MessageSaveDTO message, String receiveUserId) throws Exception; 20 | IPage listMessage(IPage page, String conversationId) throws Exception; 21 | List listMessage(String conversationId, String nextMessageId, Integer limit); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/GroupService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.Group; 4 | import cn.wzjun1.yeimServer.dto.group.GroupCreateDTO; 5 | import cn.wzjun1.yeimServer.dto.group.GroupEditDTO; 6 | import com.baomidou.mybatisplus.extension.service.IService; 7 | 8 | /** 9 | * @author Administrator 10 | * @description 针对表【group】的数据库操作Service 11 | * @createDate 2022-12-07 20:00:11 12 | */ 13 | public interface GroupService extends IService { 14 | void createGroup(GroupCreateDTO params) throws Exception; 15 | 16 | void dissolveGroup(String groupId) throws Exception; 17 | 18 | void updateGroup(GroupEditDTO params) throws Exception; 19 | 20 | void transferLeader(String groupId, String userId) throws Exception; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/GroupUserService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.GroupApply; 4 | import cn.wzjun1.yeimServer.domain.GroupUser; 5 | import cn.wzjun1.yeimServer.dto.group.GroupUserAddDTO; 6 | import cn.wzjun1.yeimServer.result.vo.AddUserToGroupResultVO; 7 | import com.baomidou.mybatisplus.extension.service.IService; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author Administrator 13 | * @description 针对表【group_user】的数据库操作Service 14 | * @createDate 2022-12-07 20:55:41 15 | */ 16 | public interface GroupUserService extends IService { 17 | AddUserToGroupResultVO addUserToGroup(GroupUserAddDTO groupUserAddDTO) throws Exception; 18 | 19 | void deleteUserFromGroup(GroupUserAddDTO groupUserAddDTO) throws Exception; 20 | 21 | void leaveGroup(String groupId) throws Exception; 22 | 23 | void setAdminstrator(String groupId, String userId, Integer isAdmin) throws Exception; 24 | 25 | void setMute(String groupId, String userId, Integer time) throws Exception; 26 | 27 | GroupApply applyHandle(Integer ApplyId, Integer status) throws Exception; 28 | 29 | List getGroupUserList(String groupId) throws Exception; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/MessageService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.GroupMessage; 4 | import cn.wzjun1.yeimServer.domain.Message; 5 | import cn.wzjun1.yeimServer.domain.User; 6 | import cn.wzjun1.yeimServer.dto.message.MessageSaveDTO; 7 | import com.baomidou.mybatisplus.core.metadata.IPage; 8 | import com.baomidou.mybatisplus.extension.service.IService; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author wzjun1 15 | * @description 针对表【message】的数据库操作Service 16 | * @createDate 2022-11-16 23:29:12 17 | */ 18 | public interface MessageService extends IService { 19 | 20 | Message insertMessage(User user, MessageSaveDTO params) throws Exception; 21 | 22 | @Deprecated 23 | void updatePrivateMessageById(Message update, String userId, String messageId) throws Exception; 24 | 25 | void deleteMessage(String userId, String messageId) throws Exception; 26 | 27 | void revokeMessage(String userId, String messageId) throws Exception; 28 | 29 | IPage listMessage(IPage page, String userId, String conversationId); 30 | 31 | List listMessage(String conversationId, String nextMessageId, Integer limit); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/OnlineChannel.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | public interface OnlineChannel { 4 | void send(String userId, String data); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/PushService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | public interface PushService { 4 | void pushSingleByDeviceId(String deviceId, String pushTitle, String pushContent); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/UploadService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import org.springframework.web.multipart.MultipartFile; 4 | 5 | import java.util.Map; 6 | 7 | public interface UploadService { 8 | Map getStorageParams() throws Exception; 9 | 10 | Map upload(String filename, MultipartFile file) throws Exception; 11 | 12 | Map uploadImage(String filename, MultipartFile file) throws Exception; 13 | 14 | Map uploadVideo(String filename, MultipartFile file) throws Exception; 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/UserBlackListService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.UserBlackList; 4 | import cn.wzjun1.yeimServer.domain.UserBlackListV0; 5 | import cn.wzjun1.yeimServer.dto.user.UserBlackListAddDTO; 6 | import com.baomidou.mybatisplus.extension.service.IService; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author wzjun1 12 | * @description 针对表【user_black_list(用户黑名单列表)】的数据库操作Service 13 | * @createDate 2023-02-19 11:19:57 14 | */ 15 | public interface UserBlackListService extends IService { 16 | 17 | List getBlackUserList(); 18 | void addToBlackUserList(UserBlackListAddDTO userBlackListAddDTO) throws Exception; 19 | void removeFromBlacklist(UserBlackListAddDTO userBlackListAddDTO) throws Exception; 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/UserService.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service; 2 | 3 | import cn.wzjun1.yeimServer.domain.User; 4 | import cn.wzjun1.yeimServer.dto.user.UserRegisterDTO; 5 | import cn.wzjun1.yeimServer.dto.user.UserUpdateDTO; 6 | import com.baomidou.mybatisplus.extension.service.IService; 7 | 8 | /** 9 | * @author wzjun1 10 | * @description 针对表【user】的数据库操作Service 11 | * @createDate 2022-11-15 20:23:25 12 | */ 13 | public interface UserService extends IService { 14 | 15 | User getUserById(String userId); 16 | void register(UserRegisterDTO user) throws Exception; 17 | 18 | void updateUser(String userId, UserUpdateDTO user) throws Exception; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/impl/ConversationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service.impl; 2 | 3 | import cn.wzjun1.yeimServer.domain.ConversationV0; 4 | import cn.wzjun1.yeimServer.domain.Message; 5 | import cn.wzjun1.yeimServer.exception.conversation.ConversationNotFoundException; 6 | import cn.wzjun1.yeimServer.interceptor.LoginUserContext; 7 | import cn.wzjun1.yeimServer.mapper.MessageMapper; 8 | import cn.wzjun1.yeimServer.service.OnlineChannel; 9 | import cn.wzjun1.yeimServer.socket.WebSocket; 10 | import cn.wzjun1.yeimServer.constant.ConversationType; 11 | import cn.wzjun1.yeimServer.constant.StatusCode; 12 | import cn.wzjun1.yeimServer.result.Result; 13 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 14 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 15 | import cn.wzjun1.yeimServer.domain.Conversation; 16 | import cn.wzjun1.yeimServer.service.ConversationService; 17 | import cn.wzjun1.yeimServer.mapper.ConversationMapper; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.springframework.stereotype.Service; 20 | 21 | import java.util.HashMap; 22 | 23 | /** 24 | * @author wzjun1 25 | * @description 针对表【conversation】的数据库操作Service实现 26 | * @createDate 2022-11-17 16:51:12 27 | */ 28 | @Service 29 | public class ConversationServiceImpl extends ServiceImpl 30 | implements ConversationService { 31 | 32 | @Autowired 33 | ConversationMapper conversationMapper; 34 | 35 | @Autowired 36 | MessageMapper messageMapper; 37 | 38 | @Autowired 39 | OnlineChannel onlineChannel; 40 | 41 | @Override 42 | public ConversationV0 getConversation(String conversationId, String userId) { 43 | return conversationMapper.getConversationV0(conversationId, userId); 44 | } 45 | 46 | /** 47 | * 新增或更新会话 48 | * 49 | * @param userId 会话所属用户 50 | * @param conversationId 会话ID 51 | * @param conversationType 会话类型 52 | * @param lastMessageId 最新消息ID 53 | * @param unread 未读数 54 | * @param emit 是否给会话所属用户发送会话更新事件 55 | */ 56 | @Override 57 | public boolean updateConversation(String userId, String conversationId, String conversationType, String lastMessageId, Integer unread, boolean emit) { 58 | Conversation conversation = this.getOne(new QueryWrapper().eq("user_id", userId).eq("conversation_id", conversationId)); 59 | if (conversation == null) { 60 | conversation = new Conversation(); 61 | conversation.setUnread(unread); 62 | } else { 63 | //TODO 存在并发问题 64 | conversation.setUnread(conversation.getUnread() + unread); 65 | } 66 | conversation.setConversationId(conversationId); 67 | conversation.setType(conversationType); 68 | conversation.setUserId(userId); 69 | if (lastMessageId != null && !lastMessageId.equals("")) { 70 | conversation.setLastMessageId(lastMessageId); 71 | } 72 | if (conversation.getCreatedAt() == null || conversation.getCreatedAt() == 0) { 73 | conversation.setCreatedAt(System.currentTimeMillis()); 74 | } else { 75 | conversation.setUpdatedAt(System.currentTimeMillis()); 76 | } 77 | //新增或更新 78 | boolean conversation1Result = this.saveOrUpdate(conversation); 79 | if (conversation1Result) { 80 | //推送给发送者会话更新消息 81 | this.emitJSSDKConversationUpdated(conversation); 82 | } 83 | return conversation1Result; 84 | } 85 | 86 | @Override 87 | public void clearConversationUnread(String conversationId) throws Exception { 88 | Conversation exist = conversationMapper.selectOne(new QueryWrapper().eq("conversation_id", conversationId).eq("user_id", LoginUserContext.getUser().getUserId())); 89 | if (exist == null || exist.getConversationId() == null) { 90 | throw new ConversationNotFoundException("会话不存在"); 91 | } 92 | Conversation update = new Conversation(); 93 | update.setUnread(0); 94 | //更新会话未读数 95 | conversationMapper.update(update, new QueryWrapper().eq("conversation_id", conversationId).eq("user_id", LoginUserContext.getUser().getUserId())); 96 | //私聊会话更新消息已读状态并发送已读消息事件 97 | if (exist.getType().equals(ConversationType.PRIVATE)) { 98 | //更新消息已读状态 99 | Message updateMessage = new Message(); 100 | updateMessage.setIsRead(1); 101 | //更新当前会话对方的发件箱消息已读状态 102 | messageMapper.update(updateMessage, new QueryWrapper().eq("user_id", conversationId).eq("conversation_id", LoginUserContext.getUser().getUserId()).eq("direction", "out")); 103 | //如果会话接收方在线,发送PRIVATE_READ_RECEIPT事件 104 | onlineChannel.send(conversationId, Result.info(StatusCode.PRIVATE_READ_RECEIPT.getCode(), StatusCode.PRIVATE_READ_RECEIPT.getDesc(), new HashMap() {{ 105 | put("conversationId", LoginUserContext.getUser().getUserId()); 106 | }}).toJSONString()); 107 | } 108 | } 109 | 110 | /** 111 | * 会话更新事件 112 | * 113 | * @param conversation 114 | */ 115 | private void emitJSSDKConversationUpdated(Conversation conversation) { 116 | onlineChannel.send(conversation.getUserId(), Result.info(StatusCode.CONVERSATION_CHANGED.getCode(), StatusCode.CONVERSATION_CHANGED.getDesc(), this.getConversation(conversation.getConversationId(), conversation.getUserId())).toJSONString()); 117 | } 118 | } 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/impl/FriendServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service.impl; 2 | 3 | import cn.wzjun1.yeimServer.constant.StatusCode; 4 | import cn.wzjun1.yeimServer.domain.Friend; 5 | import cn.wzjun1.yeimServer.dto.friend.DeleteFriendDTO; 6 | import cn.wzjun1.yeimServer.dto.friend.UpdateFriendDTO; 7 | import cn.wzjun1.yeimServer.exception.ParamsException; 8 | import cn.wzjun1.yeimServer.exception.friend.FriendNotFoundException; 9 | import cn.wzjun1.yeimServer.interceptor.LoginUserContext; 10 | import cn.wzjun1.yeimServer.mapper.FriendMapper; 11 | import cn.wzjun1.yeimServer.result.Result; 12 | import cn.wzjun1.yeimServer.service.FriendService; 13 | import cn.wzjun1.yeimServer.service.OnlineChannel; 14 | import cn.wzjun1.yeimServer.utils.Common; 15 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 16 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.stereotype.Service; 19 | 20 | /** 21 | * @author wzjun1 22 | * @description 针对表【friend(好友表)】的数据库操作Service实现 23 | * @createDate 2023-04-04 10:48:49 24 | */ 25 | @Service 26 | public class FriendServiceImpl extends ServiceImpl 27 | implements FriendService { 28 | 29 | @Autowired 30 | OnlineChannel onlineChannel; 31 | 32 | /** 33 | * 删除好友 34 | * 35 | * @param deleteFriendDTO 36 | */ 37 | @Override 38 | public void deleteFriend(DeleteFriendDTO deleteFriendDTO) { 39 | //双向删除 40 | deleteFriendDTO.getMembers().forEach(id -> { 41 | this.remove(new QueryWrapper().eq("user_id", LoginUserContext.getUser().getUserId()).eq("friend_user_id", id)); 42 | this.remove(new QueryWrapper().eq("friend_user_id", LoginUserContext.getUser().getUserId()).eq("user_id", id)); 43 | onlineChannel.send(LoginUserContext.getUser().getUserId(), Result.info(StatusCode.FRIEND_LIST_CHANGED.getCode(), StatusCode.FRIEND_LIST_CHANGED.getDesc(), null).toJSONString()); 44 | onlineChannel.send(id, Result.info(StatusCode.FRIEND_LIST_CHANGED.getCode(), StatusCode.FRIEND_LIST_CHANGED.getDesc(), null).toJSONString()); 45 | }); 46 | } 47 | 48 | @Override 49 | public void updateFriend(UpdateFriendDTO updateFriendDTO) { 50 | Friend exist = this.getOne(new QueryWrapper().eq("user_id", LoginUserContext.getUser().getUserId()).eq("friend_user_id", updateFriendDTO.getUserId())); 51 | if (exist == null || exist.getId() == 0) { 52 | throw new FriendNotFoundException("他不是您的好友,无法更新资料"); 53 | } 54 | Friend update = new Friend(); 55 | if (updateFriendDTO.getRemark() != null) { 56 | update.setRemark(updateFriendDTO.getRemark()); 57 | } 58 | if (updateFriendDTO.getExtend() != null) { 59 | update.setExtend(updateFriendDTO.getExtend()); 60 | } 61 | if (!Common.isNotEmptyBean(update)) { 62 | throw new ParamsException("请至少传入一个参数更新"); 63 | } 64 | this.update(update, new QueryWrapper().eq("id", exist.getId())); 65 | //触发好友列表更新事件 66 | onlineChannel.send(LoginUserContext.getUser().getUserId(), Result.info(StatusCode.FRIEND_LIST_CHANGED.getCode(), StatusCode.FRIEND_LIST_CHANGED.getDesc(), null).toJSONString()); 67 | } 68 | } 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/impl/GroupApplyServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import cn.wzjun1.yeimServer.domain.GroupApply; 5 | import cn.wzjun1.yeimServer.service.GroupApplyService; 6 | import cn.wzjun1.yeimServer.mapper.GroupApplyMapper; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author Administrator 11 | * @description 针对表【group_apply(入群申请表)】的数据库操作Service实现 12 | * @createDate 2022-12-11 10:52:00 13 | */ 14 | @Service 15 | public class GroupApplyServiceImpl extends ServiceImpl 16 | implements GroupApplyService{ 17 | 18 | } 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/impl/OnlineChannelimpl.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service.impl; 2 | 3 | import cn.wzjun1.yeimServer.service.OnlineChannel; 4 | import cn.wzjun1.yeimServer.socket.WebSocket; 5 | import org.springframework.stereotype.Service; 6 | 7 | /** 8 | * 实时消息通道实现类 9 | */ 10 | @Service 11 | public class OnlineChannelimpl implements OnlineChannel { 12 | 13 | /** 14 | * 通过WebSocket发送消息 15 | * 16 | * @param userId 17 | * @param data 18 | */ 19 | @Override 20 | public void send(String userId, String data) { 21 | WebSocket.sendMessage(userId, data); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/impl/PushServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service.impl; 2 | 3 | import cn.wzjun1.yeimServer.pojo.YeIMPushConfig; 4 | import cn.wzjun1.yeimServer.service.PushService; 5 | import com.alibaba.fastjson.JSONObject; 6 | import com.getui.push.v2.sdk.ApiHelper; 7 | import com.getui.push.v2.sdk.GtApiConfiguration; 8 | import com.getui.push.v2.sdk.api.PushApi; 9 | import com.getui.push.v2.sdk.common.ApiResult; 10 | import com.getui.push.v2.sdk.dto.req.Audience; 11 | import com.getui.push.v2.sdk.dto.req.Settings; 12 | import com.getui.push.v2.sdk.dto.req.message.PushChannel; 13 | import com.getui.push.v2.sdk.dto.req.message.PushDTO; 14 | import com.getui.push.v2.sdk.dto.req.message.PushMessage; 15 | import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO; 16 | import com.getui.push.v2.sdk.dto.req.message.android.GTNotification; 17 | import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification; 18 | import com.getui.push.v2.sdk.dto.req.message.android.Ups; 19 | import com.getui.push.v2.sdk.dto.req.message.ios.Alert; 20 | import com.getui.push.v2.sdk.dto.req.message.ios.Aps; 21 | import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO; 22 | import com.github.yitter.idgen.YitIdHelper; 23 | import lombok.extern.slf4j.Slf4j; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.stereotype.Service; 26 | 27 | import java.util.Map; 28 | 29 | /** 30 | * @author wzjun1 31 | */ 32 | @Service 33 | @Slf4j 34 | public class PushServiceImpl implements PushService { 35 | 36 | @Autowired 37 | YeIMPushConfig yeIMPushConfig; 38 | 39 | @Override 40 | public void pushSingleByDeviceId(String deviceId, String pushTitle, String pushContent) { 41 | if (yeIMPushConfig.getType().equals("getui")) { 42 | gtSinglePush(deviceId, pushTitle, pushContent); 43 | } 44 | } 45 | 46 | private void gtSinglePush(String deviceId, String pushTitle, String pushContent) { 47 | 48 | GtApiConfiguration apiConfiguration = new GtApiConfiguration(); 49 | //填写应用配置,参数在“Uni Push”下的“应用配置”页面中获取 50 | apiConfiguration.setAppId(yeIMPushConfig.getGt().getAppId()); 51 | apiConfiguration.setAppKey(yeIMPushConfig.getGt().getAppKey()); 52 | apiConfiguration.setMasterSecret(yeIMPushConfig.getGt().getMasterSecret()); 53 | apiConfiguration.setDomain("https://restapi.getui.com/v2/"); 54 | // 实例化ApiHelper对象,用于创建接口对象 55 | ApiHelper apiHelper = ApiHelper.build(apiConfiguration); 56 | // 创建对象,建议复用。目前有PushApi、StatisticApi、UserApi 57 | PushApi pushApi = apiHelper.creatApi(PushApi.class); 58 | //根据cid进行单推 59 | PushDTO pushDTO = new PushDTO(); 60 | // 设置推送参数,requestid需要每次变化唯一 61 | pushDTO.setRequestId(System.currentTimeMillis() + "-" + YitIdHelper.nextId()); 62 | Settings settings = new Settings(); 63 | pushDTO.setSettings(settings); 64 | //消息有效期,走厂商消息必须设置该值 65 | settings.setTtl(3600000); 66 | //在线走个推通道时推送的消息体 67 | PushMessage pushMessage = new PushMessage(); 68 | pushDTO.setPushMessage(pushMessage); 69 | 70 | //GTNotification和transmission二选一 71 | // GTNotification gtNotification = new GTNotification(); 72 | // gtNotification.setTitle(pushTitle); 73 | // gtNotification.setBody(pushContent); 74 | // gtNotification.setClickType("startapp"); 75 | // gtNotification.setChannelId(yeIMPushConfig.getOppoChannelId()); 76 | // gtNotification.setChannelName("聊天离线通知"); 77 | // gtNotification.setChannelLevel("4"); 78 | //pushMessage.setNotification(gtNotification); 79 | 80 | JSONObject transmission = new JSONObject(); 81 | transmission.put("title", pushTitle); 82 | transmission.put("content", pushContent); 83 | transmission.put("payload", "nothing"); 84 | pushMessage.setTransmission(transmission.toJSONString()); 85 | 86 | // 设置接收人信息 87 | Audience audience = new Audience(); 88 | pushDTO.setAudience(audience); 89 | audience.addCid(deviceId); 90 | //设置离线推送时的消息体 91 | PushChannel pushChannel = new PushChannel(); 92 | //安卓离线厂商通道推送的消息体 93 | AndroidDTO androidDTO = new AndroidDTO(); 94 | Ups ups = new Ups(); 95 | ups.addOption("HO", "/android/notification/importance", "NORMAL"); 96 | ups.addOption("HW", "/message/android/category", "IM"); 97 | ups.addOption("HW", "/message/android/notification/badge/add_num", 1); 98 | ups.addOption("HW", "/message/android/notification/importance", "HIGH"); 99 | ups.addOption("VV", "/classification", 1); 100 | ups.addOption("XM", "/extra.channel_id", "high_system"); 101 | ups.addOption("XM", "/extra.notify_foreground", "1"); 102 | ups.addOption("OP", "/channel_id", yeIMPushConfig.getOppoChannelId()); 103 | ups.addOption("OPG", "/channel_id", yeIMPushConfig.getOppoChannelId()); 104 | ThirdNotification thirdNotification = new ThirdNotification(); 105 | thirdNotification.setTitle(pushTitle); 106 | thirdNotification.setBody(pushContent); 107 | thirdNotification.setClickType("startapp"); 108 | ups.setNotification(thirdNotification); 109 | androidDTO.setUps(ups); 110 | pushChannel.setAndroid(androidDTO); 111 | //ios离线apn通道推送的消息体 112 | Alert alert = new Alert(); 113 | alert.setTitle(pushTitle); 114 | alert.setBody(pushContent); 115 | Aps aps = new Aps(); 116 | aps.setContentAvailable(0); 117 | aps.setSound("default"); 118 | aps.setAlert(alert); 119 | IosDTO iosDTO = new IosDTO(); 120 | iosDTO.setAps(aps); 121 | iosDTO.setType("notify"); 122 | pushChannel.setIos(iosDTO); 123 | pushDTO.setPushChannel(pushChannel); 124 | // 进行cid单推 125 | ApiResult>> apiResult = pushApi.pushToSingleByCid(pushDTO); 126 | //System.out.println(JSONObject.toJSONString(apiResult)); 127 | } 128 | 129 | } 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/impl/UserBlackListServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service.impl; 2 | 3 | import cn.wzjun1.yeimServer.domain.UserBlackListV0; 4 | import cn.wzjun1.yeimServer.dto.user.UserBlackListAddDTO; 5 | import cn.wzjun1.yeimServer.interceptor.LoginUserContext; 6 | import cn.wzjun1.yeimServer.interceptor.UserAuthorizationInterceptor; 7 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 8 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 9 | import cn.wzjun1.yeimServer.domain.UserBlackList; 10 | import cn.wzjun1.yeimServer.service.UserBlackListService; 11 | import cn.wzjun1.yeimServer.mapper.UserBlackListMapper; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.function.Consumer; 18 | 19 | /** 20 | * @author wzjun1 21 | * @description 针对表【user_black_list(用户黑名单列表)】的数据库操作Service实现 22 | * @createDate 2023-02-19 11:19:57 23 | */ 24 | @Service 25 | public class UserBlackListServiceImpl extends ServiceImpl 26 | implements UserBlackListService { 27 | 28 | @Autowired 29 | UserBlackListMapper userBlackListMapper; 30 | 31 | /** 32 | * 获取黑名单列表 33 | * 34 | * @return 35 | */ 36 | @Override 37 | public List getBlackUserList() { 38 | return userBlackListMapper.getBlackUserList(LoginUserContext.getUser().getUserId()); 39 | } 40 | 41 | /** 42 | * 黑名单入库 43 | * 44 | * @param userBlackListAddDTO 45 | * @throws Exception 46 | */ 47 | @Override 48 | public void addToBlackUserList(UserBlackListAddDTO userBlackListAddDTO) throws Exception { 49 | long createdAt = System.currentTimeMillis(); 50 | List userBlackList = new ArrayList<>(); 51 | userBlackListAddDTO.getMembers().forEach(id -> { 52 | UserBlackList userBlack = new UserBlackList(); 53 | userBlack.setUserId(LoginUserContext.getUser().getUserId()); 54 | userBlack.setCoverUserId(id); 55 | userBlack.setCreatedAt(createdAt); 56 | userBlackList.add(userBlack); 57 | }); 58 | this.saveBatch(userBlackList); 59 | } 60 | 61 | /** 62 | * 黑名单移除 63 | * 64 | * @param userBlackListAddDTO 65 | * @throws Exception 66 | */ 67 | @Override 68 | public void removeFromBlacklist(UserBlackListAddDTO userBlackListAddDTO) throws Exception { 69 | userBlackListAddDTO.getMembers().forEach(id -> { 70 | this.remove(new QueryWrapper().eq("cover_user_id", id)); 71 | }); 72 | } 73 | 74 | 75 | } 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.service.impl; 2 | 3 | import cn.wzjun1.yeimServer.domain.Group; 4 | import cn.wzjun1.yeimServer.domain.User; 5 | import cn.wzjun1.yeimServer.exception.ParamsException; 6 | import cn.wzjun1.yeimServer.exception.user.UserDuplicateException; 7 | import cn.wzjun1.yeimServer.interceptor.LoginUserContext; 8 | import cn.wzjun1.yeimServer.mapper.UserMapper; 9 | import cn.wzjun1.yeimServer.dto.user.UserRegisterDTO; 10 | import cn.wzjun1.yeimServer.dto.user.UserUpdateDTO; 11 | import cn.wzjun1.yeimServer.service.UserService; 12 | import cn.wzjun1.yeimServer.utils.Common; 13 | import cn.wzjun1.yeimServer.utils.RedisUtil; 14 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 15 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.stereotype.Service; 18 | 19 | import java.util.Objects; 20 | 21 | /** 22 | * @author wzjun1 23 | * @description 针对表【user】的数据库操作Service实现 24 | * @createDate 2022-11-15 20:23:25 25 | */ 26 | @Service 27 | public class UserServiceImpl extends ServiceImpl 28 | implements UserService { 29 | 30 | @Autowired 31 | UserMapper userMapper; 32 | 33 | @Autowired 34 | RedisUtil redisUtil; 35 | 36 | @Override 37 | public User getUserById(String userId) { 38 | return userMapper.selectOne(new QueryWrapper().eq("user_id", userId)); 39 | } 40 | 41 | @Override 42 | public void register(UserRegisterDTO user) throws Exception { 43 | User exist = userMapper.selectOne(new QueryWrapper().eq("user_id", user.getUserId())); 44 | if (!Objects.isNull(exist)) { 45 | throw new UserDuplicateException("用户已存在,请勿重复注册"); 46 | } 47 | User entity = new User(); 48 | entity.setUserId(user.getUserId()); 49 | entity.setNickname(user.getNickname()); 50 | entity.setAvatarUrl(user.getAvatarUrl()); 51 | entity.setCreatedAt(System.currentTimeMillis()); 52 | if (user.getGender() != null) { 53 | entity.setGender(user.getGender()); 54 | } 55 | if (user.getMobile() != null && user.getMobile() != 0) { 56 | entity.setMobile(user.getMobile()); 57 | } 58 | if (user.getEmail() != null) { 59 | entity.setEmail(user.getEmail()); 60 | } 61 | if (user.getBirthday() != null) { 62 | entity.setBirthday(user.getBirthday()); 63 | } 64 | if (user.getMotto() != null) { 65 | entity.setMotto(user.getMotto()); 66 | } 67 | if (user.getExtend() != null) { 68 | entity.setExtend(user.getExtend()); 69 | } 70 | if (user.getAddFriendType() != null && user.getAddFriendType() != 0) { 71 | entity.setAddFriendType(user.getAddFriendType()); 72 | } 73 | int result = userMapper.insert(entity); 74 | if (result <= 0) { 75 | throw new Exception("注册用户异常,请稍后重试"); 76 | } 77 | } 78 | 79 | @Override 80 | public void updateUser(String userId, UserUpdateDTO user) throws Exception { 81 | 82 | User entity = new User(); 83 | if (user.getNickname() != null) { 84 | if (user.getNickname().length() > 32) { 85 | throw new ParamsException("用户昵称的不能超过32位"); 86 | } 87 | entity.setNickname(user.getNickname()); 88 | } 89 | if (user.getAvatarUrl() != null) { 90 | entity.setAvatarUrl(user.getAvatarUrl()); 91 | } 92 | if (user.getGender() != null) { 93 | entity.setGender(user.getGender()); 94 | } 95 | if (user.getMobile() != null && user.getMobile() != 0) { 96 | entity.setMobile(user.getMobile()); 97 | } 98 | if (user.getEmail() != null) { 99 | entity.setEmail(user.getEmail()); 100 | } 101 | if (user.getBirthday() != null) { 102 | entity.setBirthday(user.getBirthday()); 103 | } 104 | if (user.getMotto() != null) { 105 | entity.setMotto(user.getMotto()); 106 | } 107 | if (user.getExtend() != null) { 108 | entity.setExtend(user.getExtend()); 109 | } 110 | if (user.getAddFriendType() != null && user.getAddFriendType() != 0) { 111 | entity.setAddFriendType(user.getAddFriendType()); 112 | } 113 | if (!Common.isNotEmptyBean(entity)) { 114 | throw new ParamsException("请至少选择一个属性进行更新"); 115 | } 116 | 117 | //更新数据库 118 | int result = userMapper.update(entity, new QueryWrapper().eq("user_id", userId)); 119 | if (result <= 0) { 120 | throw new Exception("更新用户资料异常,请稍后重试"); 121 | } 122 | 123 | //更新redis缓存中用户信息 124 | String tokenKey = "token:" + LoginUserContext.getToken(); 125 | if (redisUtil.hasKey(tokenKey)) { 126 | long expire = redisUtil.getExpire(tokenKey); 127 | User update = this.getUserById(userId); 128 | redisUtil.setWithExpire(tokenKey, update, expire); 129 | } 130 | 131 | } 132 | } 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/socket/WebSocket.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.socket; 2 | 3 | import cn.wzjun1.yeimServer.domain.User; 4 | import cn.wzjun1.yeimServer.pojo.YeIMPushConfig; 5 | import cn.wzjun1.yeimServer.constant.StatusCode; 6 | import cn.wzjun1.yeimServer.utils.Common; 7 | import cn.wzjun1.yeimServer.result.Result; 8 | import com.alibaba.fastjson.JSONObject; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.springframework.web.socket.*; 12 | 13 | import java.util.HashMap; 14 | import java.util.concurrent.ConcurrentHashMap; 15 | import java.util.concurrent.CopyOnWriteArraySet; 16 | 17 | @Slf4j 18 | public class WebSocket implements WebSocketHandler { 19 | 20 | private YeIMPushConfig yeIMPushConfig; 21 | 22 | private static CopyOnWriteArraySet webSockets = new CopyOnWriteArraySet<>(); 23 | 24 | private static ConcurrentHashMap userPool = new ConcurrentHashMap<>(); 25 | 26 | private static ConcurrentHashMap sessionPool = new ConcurrentHashMap<>(); 27 | 28 | public WebSocket(YeIMPushConfig yeIMPushConfig) { 29 | this.yeIMPushConfig = yeIMPushConfig; 30 | } 31 | 32 | /** 33 | * 连接打开 34 | * 35 | * @param session 36 | * @throws Exception 37 | */ 38 | @Override 39 | public void afterConnectionEstablished(@NotNull WebSocketSession session) throws Exception { 40 | User user = (User) session.getAttributes().get("user"); 41 | //检测是否在线,踢掉 42 | WebSocketSession online = sessionPool.get(user.getUserId()); 43 | if (online != null) { 44 | sendMessage(online, Result.error(StatusCode.KICKED_OUT.getCode(), StatusCode.KICKED_OUT.getDesc()).toJSONString()); 45 | online.close(); 46 | sessionPool.remove(user.getUserId()); 47 | } 48 | webSockets.add(this); 49 | setUserId(session.getId(), user.getUserId()); 50 | sessionPool.put(user.getUserId(), session); 51 | 52 | sendMessage(session, Result.info(StatusCode.LOGIN_SUCCESS.getCode(), StatusCode.LOGIN_SUCCESS.getDesc(), new HashMap() {{ 53 | put("user", user); 54 | put("pushConfig", yeIMPushConfig); 55 | }}).toJSONString()); 56 | log.info("【YeIMUniServer】有新用户:" + user.getNickname() + "(userId:" + user.getUserId() + ")" + "的连接,现存总数为:" + webSockets.size()); 57 | } 58 | 59 | /** 60 | * 消息处理 61 | * 62 | * @param session 63 | * @param message 64 | * @throws Exception 65 | */ 66 | @Override 67 | public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception { 68 | String msgStr = (String) message.getPayload(); 69 | //IM所有消息通过json发送,判断类型,不是就停止执行 70 | if (!Common.isJSONObject(msgStr)) { 71 | return; 72 | } 73 | 74 | JSONObject msgObj = JSONObject.parseObject(msgStr); 75 | 76 | /** 77 | * socket发消息格式: 78 | * { type:"", data: "" } 79 | */ 80 | 81 | if (!msgObj.containsKey("type")) { 82 | log.info("【YeIMUniServer】消息缺失:type"); 83 | return; 84 | } 85 | 86 | if (!msgObj.containsKey("data")) { 87 | log.info("【YeIMUniServer】消息缺失:data"); 88 | return; 89 | } 90 | String type = msgObj.getString("type"); 91 | String data = msgObj.getString("data"); 92 | 93 | //心跳 94 | if (type.equals("heart")) { 95 | sendMessage(session, Result.info(StatusCode.HEART.getCode(), StatusCode.HEART.getDesc(), "pong").toJSONString()); 96 | } 97 | } 98 | 99 | /** 100 | * 连接错误 101 | * 102 | * @param session 103 | * @param exception 104 | * @throws Exception 105 | */ 106 | @Override 107 | public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { 108 | log.info("【YeIMUniServer】发生错误:" + exception.getMessage()); 109 | exception.printStackTrace(); 110 | } 111 | 112 | /** 113 | * 连接关闭 114 | * 115 | * @param session 116 | * @param closeStatus 117 | * @throws Exception 118 | */ 119 | @Override 120 | public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { 121 | try { 122 | webSockets.remove(this); 123 | if (getUserId(session.getId()) != null) { 124 | sessionPool.remove(getUserId(session.getId())); 125 | log.info("【YeIMUniServer】用户:" + getUserId(session.getId()) + " 连接断开,总数为:" + webSockets.size()); 126 | } 127 | } catch (Exception e) { 128 | //e.printStackTrace(); 129 | } 130 | } 131 | 132 | @Override 133 | public boolean supportsPartialMessages() { 134 | return false; 135 | } 136 | 137 | 138 | /** 139 | * 通过userId发送消息 140 | * 141 | * @param userId 142 | * @param message 143 | * @return int 144 | */ 145 | public static int sendMessage(String userId, String message) { 146 | WebSocketSession session = sessionPool.get(userId); 147 | if (session != null && session.isOpen()) { 148 | try { 149 | log.info("【YeIMUniServer】向userId:" + userId + " 发送消息:" + message); 150 | session.sendMessage(new TextMessage(message)); 151 | return 1; 152 | } catch (Exception e) { 153 | //e.printStackTrace(); 154 | } 155 | } 156 | return 0; 157 | } 158 | 159 | /** 160 | * 通过session发送消息 161 | * 162 | * @param session 163 | * @param message 164 | */ 165 | public void sendMessage(WebSocketSession session, String message) { 166 | if (session != null && session.isOpen()) { 167 | try { 168 | log.info("【YeIMUniServer】向sessionId:" + session.getId() + "(userId: " + getUserId(session.getId()) + ") 发送消息:" + message); 169 | session.sendMessage(new TextMessage(message)); 170 | } catch (Exception e) { 171 | //e.printStackTrace(); 172 | } 173 | } 174 | } 175 | 176 | /** 177 | * 保存用户ID 178 | * 179 | * @param sessionId 180 | * @return 181 | */ 182 | private void setUserId(String sessionId, String userId) { 183 | String exist = userPool.get(sessionId); 184 | if (exist != null) { 185 | userPool.remove(sessionId); 186 | } 187 | userPool.put(sessionId, userId); 188 | } 189 | 190 | /** 191 | * 根据sessionID获取用户ID 192 | * 193 | * @param sessionId 194 | * @return 195 | */ 196 | private String getUserId(String sessionId) { 197 | if (userPool != null) { 198 | String userId = userPool.get(sessionId); 199 | if (userId != null) { 200 | return userId; 201 | } else { 202 | return null; 203 | } 204 | } else { 205 | return null; 206 | } 207 | } 208 | 209 | } 210 | 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/utils/Common.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.utils; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | 5 | import java.lang.reflect.Field; 6 | import java.lang.reflect.Method; 7 | import java.util.Objects; 8 | 9 | public class Common { 10 | 11 | /** 12 | * 检测字符串是否是json对象 13 | * 14 | * @param str 15 | * @return 16 | */ 17 | public static boolean isJSONObject(String str) { 18 | boolean result = false; 19 | try { 20 | Object obj = JSON.parse(str); 21 | result = true; 22 | } catch (Exception e) { 23 | result = false; 24 | } 25 | return result; 26 | } 27 | 28 | /** 29 | * 判断对象是否为空 30 | * 31 | * @param obj 32 | * @return 33 | */ 34 | public static Boolean isNotEmptyBean(Object obj) { 35 | Boolean flag = false; 36 | try { 37 | if (null != obj) { 38 | //得到类对象 39 | Class c = (Class) obj.getClass(); 40 | //得到属性集合 41 | Field[] fs = c.getDeclaredFields(); 42 | //得到方法体集合 43 | Method[] methods = c.getDeclaredMethods(); 44 | //遍历属性 45 | for (Field f : fs) { 46 | //设置属性是可以访问的(私有的也可以) 47 | f.setAccessible(true); 48 | String fieldGetName = parGetName(f.getName()); 49 | //判断属性是否存在get方法 50 | if (!checkGetMet(methods, fieldGetName)) { 51 | continue; 52 | } 53 | //得到此属性的值 54 | Object val = f.get(obj); 55 | //只要有1个属性不为空,那么就不是所有的属性值都为空 56 | if (!Objects.isNull(val)) { 57 | flag = true; 58 | break; 59 | } 60 | } 61 | } 62 | } catch (Exception e) { 63 | e.printStackTrace(); 64 | } 65 | return flag; 66 | } 67 | 68 | /** 69 | * 拼接某属性的 get方法 70 | * 71 | * @param fieldName 72 | * @return String 73 | */ 74 | public static String parGetName(String fieldName) { 75 | if (null == fieldName || "".equals(fieldName)) { 76 | return null; 77 | } 78 | int startIndex = 0; 79 | if (fieldName.charAt(0) == '_') 80 | startIndex = 1; 81 | return "get" 82 | + fieldName.substring(startIndex, startIndex + 1).toUpperCase() 83 | + fieldName.substring(startIndex + 1); 84 | } 85 | 86 | /** 87 | * 判断是否存在某属性的 get方法 88 | * 89 | * @param methods 90 | * @param fieldGetMet 91 | * @return boolean 92 | */ 93 | public static Boolean checkGetMet(Method[] methods, String fieldGetMet) { 94 | 95 | for (Method met : methods) { 96 | if (fieldGetMet.equals(met.getName())) { 97 | return true; 98 | } 99 | } 100 | return false; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/utils/JavaCvUtil.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.utils; 2 | 3 | import net.coobird.thumbnailator.Thumbnails; 4 | import org.bytedeco.javacv.FFmpegFrameGrabber; 5 | import org.bytedeco.javacv.Frame; 6 | import org.bytedeco.javacv.Java2DFrameConverter; 7 | 8 | import java.awt.*; 9 | import java.awt.image.BufferedImage; 10 | import java.io.File; 11 | 12 | public class JavaCvUtil { 13 | 14 | /** 15 | * 获取视频缩略图 16 | * 17 | * @param videoPath:视频路径 18 | * @param baseDir:保存目录 19 | * @throws Exception 20 | */ 21 | public static String getVideoCover(String videoPath, String baseDir) throws Exception { 22 | 23 | FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(videoPath); 24 | ff.start(); 25 | //判断是否是竖屏小视频 26 | String rotate = ff.getVideoMetadata("rotate"); 27 | int ffLength = ff.getLengthInFrames(); 28 | Frame f; 29 | int i = 0; 30 | int index = 3;//截取图片第几帧 31 | BufferedImage bufferedImage = null; 32 | while (i < ffLength) { 33 | f = ff.grabImage(); 34 | if (i == index) { 35 | Java2DFrameConverter converter = new Java2DFrameConverter(); 36 | bufferedImage = converter.getBufferedImage(f); 37 | if (null != rotate && rotate.length() > 1) { 38 | Image image = (Image) bufferedImage; 39 | bufferedImage = rotate(image, 90); 40 | } 41 | break; 42 | } 43 | i++; 44 | } 45 | ff.stop(); 46 | if (bufferedImage == null) { 47 | throw new Exception("截取视频封面异常"); 48 | } 49 | String thumbFileName = MD5Util.encode(videoPath) + "_video_thumb.jpg"; 50 | File thumb = new File(baseDir + File.separator + thumbFileName); 51 | Thumbnails.of(bufferedImage) 52 | .scale(1f) 53 | .outputQuality(0.8f) 54 | .toFile(thumb); 55 | return thumbFileName; 56 | } 57 | 58 | /** 59 | * 图片旋转角度 60 | * 61 | * @param src 源图片 62 | * @param angel 角度 63 | * @return 目标图片 64 | */ 65 | public static BufferedImage rotate(Image src, int angel) { 66 | int src_width = src.getWidth(null); 67 | int src_height = src.getHeight(null); 68 | // calculate the new image size 69 | Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension( 70 | src_width, src_height)), angel); 71 | 72 | BufferedImage res = null; 73 | res = new BufferedImage(rect_des.width, rect_des.height, 74 | BufferedImage.TYPE_INT_RGB); 75 | Graphics2D g2 = res.createGraphics(); 76 | // transform(这里先平移、再旋转比较方便处理;绘图时会采用这些变化,绘图默认从画布的左上顶点开始绘画,源图片的左上顶点与画布左上顶点对齐,然后开始绘画,修改坐标原点后,绘画对应的画布起始点改变,起到平移的效果;然后旋转图片即可) 77 | 78 | //平移(原理修改坐标系原点,绘图起点变了,起到了平移的效果,如果作用于旋转,则为旋转中心点) 79 | g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2); 80 | 81 | //旋转(原理transalte(dx,dy)->rotate(radians)->transalte(-dx,-dy);修改坐标系原点后,旋转90度,然后再还原坐标系原点为(0,0),但是整个坐标系已经旋转了相应的度数 ) 82 | g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2); 83 | 84 | g2.drawImage(src, null, null); 85 | return res; 86 | } 87 | 88 | /** 89 | * 计算转换后目标矩形的宽高 90 | * 91 | * @param src 源矩形 92 | * @param angel 角度 93 | * @return 目标矩形 94 | */ 95 | private static Rectangle CalcRotatedSize(Rectangle src, int angel) { 96 | double cos = Math.abs(Math.cos(Math.toRadians(angel))); 97 | double sin = Math.abs(Math.sin(Math.toRadians(angel))); 98 | int des_width = (int) (src.width * cos) + (int) (src.height * sin); 99 | int des_height = (int) (src.height * cos) + (int) (src.width * sin); 100 | return new java.awt.Rectangle(new Dimension(des_width, des_height)); 101 | } 102 | 103 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.utils; 2 | 3 | import java.security.MessageDigest; 4 | 5 | public class MD5Util { 6 | //加密为MD5-32位 7 | public static String encode(String str) { 8 | try { 9 | //确定计算方法 10 | MessageDigest md5 = MessageDigest.getInstance("MD5"); 11 | //加密字符串 12 | byte[] md5Bytes = md5.digest(str.getBytes()); 13 | StringBuilder stringBuilder = new StringBuilder(); 14 | for (byte md5Byte : md5Bytes) { 15 | int val = ((int) md5Byte) & 0xff; 16 | if (val < 16) 17 | stringBuilder.append("0"); 18 | stringBuilder.append(Integer.toHexString(val)); 19 | } 20 | return stringBuilder.toString(); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | return "null"; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/utils/RedisUtil.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.utils; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.redis.core.RedisTemplate; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.util.CollectionUtils; 8 | 9 | import java.util.Collection; 10 | import java.util.List; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | @Component 14 | public final class RedisUtil { 15 | 16 | @Autowired 17 | private RedisTemplate redisTemplate; 18 | 19 | /** 20 | * 指定失效时间 21 | * 22 | * @param time 时间(秒) 23 | */ 24 | public boolean expire(String key, long time) { 25 | try { 26 | if (time > 0) { 27 | redisTemplate.expire(key, time, TimeUnit.SECONDS); 28 | } 29 | return true; 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | return false; 33 | } 34 | } 35 | 36 | /** 37 | * 根据key获取过期时间 38 | * 39 | * @param key 键 不能为null 40 | * @return 时间(秒) 返回0代表为永久有效 41 | */ 42 | public long getExpire(String key) { 43 | return redisTemplate.getExpire(key, TimeUnit.SECONDS); 44 | } 45 | 46 | /** 47 | * 判断key是否存在 48 | */ 49 | public boolean hasKey(String key) { 50 | try { 51 | return redisTemplate.hasKey(key); 52 | } catch (Exception e) { 53 | e.printStackTrace(); 54 | return false; 55 | } 56 | } 57 | 58 | /** 59 | * 删除 60 | * 61 | * @param key 可以传一个值 或多个 62 | */ 63 | @SuppressWarnings("unchecked") 64 | public void remove(String... key) { 65 | if (key != null && key.length > 0) { 66 | if (key.length == 1) { 67 | redisTemplate.delete(key[0]); 68 | } else { 69 | redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * 获取 76 | */ 77 | public Object get(String key) { 78 | return key == null ? null : redisTemplate.opsForValue().get(key); 79 | } 80 | 81 | /** 82 | * 获取,泛型 83 | * 84 | * @param clazz 类型 85 | */ 86 | public T get(String key, Class clazz) { 87 | ObjectMapper mapper = new ObjectMapper(); 88 | Object v = get(key); 89 | if (v == null) return null; 90 | T val = mapper.convertValue(v, clazz); 91 | return val; 92 | } 93 | 94 | /** 95 | * 放入 96 | */ 97 | public boolean set(String key, Object value) { 98 | try { 99 | redisTemplate.opsForValue().set(key, value); 100 | return true; 101 | } catch (Exception e) { 102 | e.printStackTrace(); 103 | return false; 104 | } 105 | } 106 | 107 | /** 108 | * 放入并设置时间 109 | * 110 | * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 111 | * @return true成功 false 失败 112 | */ 113 | public boolean setWithExpire(String key, Object value, long time) { 114 | try { 115 | if (time > 0) { 116 | redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); 117 | } else { 118 | set(key, value); 119 | } 120 | return true; 121 | } catch (Exception e) { 122 | e.printStackTrace(); 123 | return false; 124 | } 125 | } 126 | 127 | /** 128 | * 将list放入 129 | * 130 | * @param key 键 131 | * @param value 值 132 | * @return 133 | */ 134 | public boolean listRightPush(String key, Object value) { 135 | try { 136 | redisTemplate.opsForList().rightPush(key, value); 137 | return true; 138 | } catch (Exception e) { 139 | e.printStackTrace(); 140 | return false; 141 | } 142 | } 143 | 144 | /** 145 | * 获取list缓存的内容 146 | * 147 | * @param key 键 148 | * @param start 开始 149 | * @param end 结束 0 到 -1代表所有值 150 | */ 151 | public List lGet(String key, long start, long end) { 152 | try { 153 | return redisTemplate.opsForList().range(key, start, end); 154 | } catch (Exception e) { 155 | e.printStackTrace(); 156 | return null; 157 | } 158 | } 159 | 160 | public Object listRightPop(String key) { 161 | try { 162 | return redisTemplate.opsForList().rightPop(key); 163 | } catch (Exception e) { 164 | e.printStackTrace(); 165 | return null; 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/cn/wzjun1/yeimServer/utils/SpringUtils.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer.utils; 2 | 3 | 4 | import org.springframework.beans.BeansException; 5 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 6 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor; 7 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * SpringUtils 12 | */ 13 | public final class SpringUtils implements BeanFactoryPostProcessor { 14 | 15 | private static ConfigurableListableBeanFactory beanFactory; 16 | 17 | @Override 18 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 19 | SpringUtils.beanFactory = beanFactory; 20 | } 21 | 22 | public static ConfigurableListableBeanFactory getBeanFactory() { 23 | return beanFactory; 24 | } 25 | 26 | /** 27 | * 获取对象 28 | * 29 | * @param name 30 | * @return Object 一个以所给名字注册的bean的实例 31 | * @throws org.springframework.beans.BeansException 32 | */ 33 | @SuppressWarnings("unchecked") 34 | public static T getBean(String name) throws BeansException { 35 | if (getBeanFactory() == null) { 36 | //zhengkai.blog.csdn.net 37 | System.out.println("本地调试Main模式,没有BeanFactory,忽略错误"); 38 | return null; 39 | } else { 40 | T result = (T) getBeanFactory().getBean(name); 41 | return result; 42 | } 43 | } 44 | 45 | /** 46 | * 获取类型为requiredType的对象 47 | * 48 | * @param name 49 | * @return 50 | * @throws org.springframework.beans.BeansException 51 | */ 52 | public static T getBean(Class name) throws BeansException { 53 | if (getBeanFactory() == null) { 54 | //zhengkai.blog.csdn.net 55 | System.out.println("本地调试Main模式,没有BeanFactory,忽略错误"); 56 | return null; 57 | } else { 58 | T result = (T) getBeanFactory().getBean(name); 59 | return result; 60 | } 61 | } 62 | 63 | /** 64 | * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true 65 | * 66 | * @param name 67 | * @return boolean 68 | */ 69 | public static boolean containsBean(String name) { 70 | return getBeanFactory().containsBean(name); 71 | } 72 | 73 | /** 74 | * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) 75 | * 76 | * @param name 77 | * @return boolean 78 | * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException 79 | */ 80 | public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { 81 | return getBeanFactory().isSingleton(name); 82 | } 83 | 84 | /** 85 | * @param name 86 | * @return Class 注册对象的类型 87 | * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException 88 | */ 89 | public static Class getType(String name) throws NoSuchBeanDefinitionException { 90 | return getBeanFactory().getType(name); 91 | } 92 | 93 | /** 94 | * 如果给定的bean名字在bean定义中有别名,则返回这些别名 95 | * 96 | * @param name 97 | * @return 98 | * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException 99 | */ 100 | public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { 101 | return getBeanFactory().getAliases(name); 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | #\u5F00\u53D1\u73AF\u5883\u914D\u7F6E 2 | 3 | spring.application.name=YeIMUniServer 4 | #http\u548Cwebsocket\u5171\u7528\u7AEF\u53E3 5 | server.port=10010 6 | #\u4E0A\u4F20\u5927\u5C0F\u9650\u5236 7 | spring.servlet.multipart.max-file-size=100MB 8 | spring.servlet.multipart.max-request-size=100MB 9 | #\u65E5\u5FD7\u914D\u7F6E 10 | logging.level.root=info 11 | #\u5176\u4ED6\u914D\u7F6E 12 | spring.config.import[0]=classpath:/config/dev/database.properties 13 | spring.config.import[1]=classpath:/config/dev/redis.properties 14 | spring.config.import[2]=classpath:/config/dev/yeim.properties 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | #\u751F\u4EA7\u73AF\u5883\u914D\u7F6E 2 | 3 | spring.application.name=YeIMUniServer 4 | #http\u548Cwebsocket\u5171\u7528\u7AEF\u53E3 5 | server.port=10010 6 | #\u4E0A\u4F20\u5927\u5C0F\u9650\u5236 7 | spring.servlet.multipart.max-file-size=100MB 8 | spring.servlet.multipart.max-request-size=100MB 9 | #\u65E5\u5FD7\u914D\u7F6E 10 | logging.level.root=info 11 | #\u5176\u4ED6\u914D\u7F6E 12 | spring.config.import[0]=classpath:/config/prod/database.properties 13 | spring.config.import[1]=classpath:/config/prod/redis.properties 14 | spring.config.import[2]=classpath:/config/prod/yeim.properties 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #\u9ED8\u8BA4\u5F00\u53D1\u73AF\u5883\u914D\u7F6E\uFF0C\u751F\u6210\u73AF\u5883\u8BF7\u914D\u7F6E\u4E3Aprod\u5E76\u4FEE\u6539config/prod\u4E2D\u7684\u76F8\u5173\u914D\u7F6E 2 | spring.profiles.active=dev -------------------------------------------------------------------------------- /src/main/resources/config/dev/database.properties: -------------------------------------------------------------------------------- 1 | #\u6570\u636E\u5E93\u914D\u7F6E 2 | #\u8C03\u8BD5\u65F6\u4F7F\u7528p6spy\u6765\u5B9E\u65F6\u6253\u5370SQL\u8BED\u53E5 3 | spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver 4 | #\u8C03\u8BD5\u65F6\u4F7F\u7528p6spy\u6765\u5B9E\u65F6\u6253\u5370SQL\u8BED\u53E5 5 | spring.datasource.url=jdbc:p6spy:mysql://192.168.110.185:3306/yeim_uni_server 6 | spring.datasource.username=yeim_uni_server 7 | spring.datasource.password=7w6xd8LHpxi57PN7 8 | spring.datasource.name=defaultDataSource 9 | #Hikari\u8FDE\u63A5\u6C60\u914D\u7F6E 10 | spring.datasource.type=com.zaxxer.hikari.HikariDataSource 11 | spring.datasource.hikari.minimum-idle=10 12 | spring.datasource.hikari.maximum-pool-size=20 13 | spring.datasource.hikari.idle-timeout=500000 14 | spring.datasource.hikari.max-lifetime=540000 15 | spring.datasource.hikari.connection-timeout=60000 16 | spring.datasource.hikari.connection-test-query=SELECT 1 -------------------------------------------------------------------------------- /src/main/resources/config/dev/redis.properties: -------------------------------------------------------------------------------- 1 | #Redis 2 | spring.redis.host=192.168.110.185 3 | spring.redis.port=6379 4 | spring.redis.password=123456 5 | spring.redis.database=6 6 | spring.redis.timeout=3000 7 | spring.redis.lettuce.pool.max-active=20 8 | spring.redis.lettuce.pool.max-idle=10 9 | spring.redis.lettuce.pool.min-idle=5 10 | spring.redis.lettuce.pool.max-wait=5000 11 | -------------------------------------------------------------------------------- /src/main/resources/config/dev/yeim.properties: -------------------------------------------------------------------------------- 1 | #YeIM\u7CFB\u7EDF\u914D\u7F6E 2 | #\u6587\u6863: https://wzjun1.netlify.app/ye_plugins/sdk/yeimunisdk 3 | #redis\u7F13\u5B58\u524D\u7F00 4 | yeim.redis.prefix=yeim: 5 | #\u7B7E\u540D\u76D0 6 | yeim.secret.key=50abd47112ebe8c5a73f4694c96a49ce 7 | #\u5206\u5E03\u5F0FID\u751F\u6210\u5668\u7684\u5DE5\u4F5C\u8282\u70B9 idgenerator workId https://github.com/yitter/IdGenerator 8 | yeim.generator.workId=1 9 | #\u4E0A\u4F20\u4ED3\u5E93\u914D\u7F6E 10 | spring.config.import[0]=classpath:/config/dev/yeim/storage.properties 11 | #\u79BB\u7EBF\u63A8\u9001\u914D\u7F6E 12 | spring.config.import[1]=classpath:/config/dev/yeim/push.properties 13 | #\u662F\u5426\u5F00\u542F\u597D\u53CB\u5173\u7CFB\u68C0\u67E5 14 | yeim.friend.enable=true 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/config/dev/yeim/push.properties: -------------------------------------------------------------------------------- 1 | #APP\u79BB\u7EBF\u63A8\u9001\u53C2\u6570 2 | 3 | #\u5F00\u542F\u79BB\u7EBF\u63A8\u9001 4 | yeim.push.enable=false 5 | 6 | #\u63A8\u9001SDK\u7C7B\u578B\uFF0C\u76EE\u524D\u4EC5\u652F\u6301\u4E2A\u63A8\uFF0C\u8BF7\u586B\u5199\uFF1Agetui 7 | yeim.push.type=getui 8 | 9 | #\u4E2A\u63A8\u53C2\u6570: https://ask.dcloud.net.cn/article/35622 10 | yeim.push.gt.appId= 11 | yeim.push.gt.appKey= 12 | yeim.push.gt.masterSecret= 13 | 14 | #OPPO\u79C1\u4FE1\u63A8\u9001\u6E20\u9053ID 15 | yeim.push.oppoChannelId=default 16 | 17 | #\u5C0F\u7C73\u91CD\u8981\u7C7B\u522B\u63A8\u9001\u6E20\u9053ID 18 | yeim.push.xiaomiChannelId=high_system -------------------------------------------------------------------------------- /src/main/resources/config/dev/yeim/storage.properties: -------------------------------------------------------------------------------- 1 | #\u4E0A\u4F20\u4ED3\u5E93\u7C7B\u578B\uFF0C\u76EE\u524D\u53EF\u9009\u9879\u4E3A\uFF1Acos\u3001oss\u3001local\u3002\u5206\u522B\u4EE3\u8868\uFF1A\u817E\u8BAF\u4E91\u5BF9\u8C61\u5B58\u50A8\u3001\u963F\u91CC\u4E91\u5BF9\u8C61\u5B58\u50A8\u3001\u672C\u5730\u5B58\u50A8 2 | #\u6CE8\u610F\uFF1A\u5982\u679C\u7C7B\u578B\u9009\u62E9\u672C\u5730\u4E0A\u4F20\uFF0C\u8BF7\u5728pom.xml\u4FEE\u6539\u591A\u5A92\u4F53\u4F9D\u8D56\uFF0C\u641C\u7D22org.bytedeco\uFF0C\u6839\u636E\u6CE8\u91CA\u9009\u62E9\u76F8\u5E94\u7684\u5305\uFF0C\u4FDD\u5B58\u540EReload Project 3 | yeim.file.storage.type=local 4 | #\u5B58\u50A8\u8D44\u6E90\u8BBF\u95EE\u7684\u81EA\u5B9A\u4E49\u57DF\u540D\uFF0C\u6CA1\u6709\u53EF\u4EE5\u4E0D\u586B 5 | yeim.file.storage.customDomain= 6 | #\u5BF9\u8C61\u5B58\u50A8\u6876\u540D\u79F0 7 | yeim.file.storage.bucket= 8 | #\u5BF9\u8C61\u5B58\u50A8\u5730\u57DF 9 | yeim.file.storage.region= 10 | #\u516C\u6709\u4E91\u5BF9\u8C61\u5B58\u50A8API\u5BC6\u94A5 11 | yeim.file.storage.secretId= 12 | yeim.file.storage.secretKey= 13 | #4. \u5B58\u50A8\u7684\u6839\u76EE\u5F55\uFF0C\u5982\u679C\u4E0A\u4F20\u4ED3\u5E93\u7C7B\u578B\u4E3A\u672C\u5730\uFF08local\uFF09\uFF0C\u8BF7\u586B\u5199\u4E0A\u4F20\u6587\u4EF6\u4FDD\u5B58\u7684\u6839\u76EE\u5F55\u3002\u5982\u679C\u975E\u672C\u5730\uFF0C\u8BF7\u586B\u5199\u5BF9\u8C61\u5B58\u50A8\u7684\u4FDD\u5B58\u76EE\u5F55\uFF0C\u4F8B\u5982\uFF1A/im/resource 14 | #yeim.file.storage.baseDir=/Users/wzjun1/Desktop/yeim_storage 15 | #yeim.file.storage.baseDir=C:\\Users\\Administrator\\Desktop\\yeim_storage 16 | #yeim.file.storage.baseDir=/Users/wzjun1/Desktop/yeim-uni-server/resource 17 | #yeim.file.storage.baseDir=/www/wwwroot/yeim-uni-server/resource 18 | yeim.file.storage.baseDir=/Users/wzjun1/Desktop/yeim-uni-server/resource -------------------------------------------------------------------------------- /src/main/resources/config/prod/database.properties: -------------------------------------------------------------------------------- 1 | #\u6570\u636E\u5E93\u914D\u7F6E 2 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver 3 | spring.datasource.url=jdbc:mysql://127.0.0.1:3306/yeim_uni_server 4 | spring.datasource.username=yeim_uni_server 5 | spring.datasource.password=7w6xd8LHpxi57PN7 6 | spring.datasource.name=defaultDataSource 7 | #Hikari\u8FDE\u63A5\u6C60\u914D\u7F6E 8 | spring.datasource.type=com.zaxxer.hikari.HikariDataSource 9 | spring.datasource.hikari.minimum-idle=10 10 | spring.datasource.hikari.maximum-pool-size=20 11 | spring.datasource.hikari.idle-timeout=500000 12 | spring.datasource.hikari.max-lifetime=540000 13 | spring.datasource.hikari.connection-timeout=60000 14 | spring.datasource.hikari.connection-test-query=SELECT 1 -------------------------------------------------------------------------------- /src/main/resources/config/prod/redis.properties: -------------------------------------------------------------------------------- 1 | #Redis 2 | spring.redis.host=127.0.0.1 3 | spring.redis.port=6379 4 | spring.redis.password= 5 | spring.redis.database=6 6 | spring.redis.timeout=3000 7 | spring.redis.lettuce.pool.max-active=20 8 | spring.redis.lettuce.pool.max-idle=10 9 | spring.redis.lettuce.pool.min-idle=5 10 | spring.redis.lettuce.pool.max-wait=5000 11 | -------------------------------------------------------------------------------- /src/main/resources/config/prod/yeim.properties: -------------------------------------------------------------------------------- 1 | #YeIM\u7CFB\u7EDF\u914D\u7F6E 2 | #\u6587\u6863: https://wzjun1.netlify.app/ye_plugins/sdk/yeimunisdk 3 | #redis\u7F13\u5B58\u524D\u7F00 4 | yeim.redis.prefix=yeim: 5 | #\u7B7E\u540D\u76D0 6 | yeim.secret.key=50abd47112ebe8c5a73f4694c96a49ce 7 | #\u5206\u5E03\u5F0FID\u751F\u6210\u5668\u7684\u5DE5\u4F5C\u8282\u70B9 idgenerator workId https://github.com/yitter/IdGenerator 8 | yeim.generator.workId=1 9 | #\u4E0A\u4F20\u4ED3\u5E93\u914D\u7F6E 10 | spring.config.import[0]=classpath:/config/prod/yeim/storage.properties 11 | #\u79BB\u7EBF\u63A8\u9001\u914D\u7F6E 12 | spring.config.import[1]=classpath:/config/prod/yeim/push.properties 13 | #\u662F\u5426\u5F00\u542F\u597D\u53CB\u5173\u7CFB\u68C0\u67E5 14 | yeim.friend.enable=false 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/config/prod/yeim/push.properties: -------------------------------------------------------------------------------- 1 | #APP\u79BB\u7EBF\u63A8\u9001\u53C2\u6570 2 | #\u5F00\u542F\u79BB\u7EBF\u63A8\u9001 3 | yeim.push.enable=false 4 | #\u63A8\u9001SDK\u7C7B\u578B\uFF0C\u76EE\u524D\u4EC5\u652F\u6301\u4E2A\u63A8\uFF0C\u8BF7\u586B\u5199\uFF1Agetui 5 | yeim.push.type=getui 6 | #\u4E2A\u63A8\u53C2\u6570: https://ask.dcloud.net.cn/article/35622 7 | yeim.push.gt.appId= 8 | yeim.push.gt.appKey= 9 | yeim.push.gt.masterSecret= 10 | #OPPO\u79C1\u4FE1\u63A8\u9001\u6E20\u9053ID 11 | yeim.push.oppoChannelId=default 12 | #\u5C0F\u7C73\u91CD\u8981\u7C7B\u522B\u63A8\u9001\u6E20\u9053ID 13 | yeim.push.xiaomiChannelId=high_system -------------------------------------------------------------------------------- /src/main/resources/config/prod/yeim/storage.properties: -------------------------------------------------------------------------------- 1 | #\u4E0A\u4F20\u4ED3\u5E93\u7C7B\u578B\uFF0C\u76EE\u524D\u53EF\u9009\u9879\u4E3A\uFF1Acos\u3001oss\u3001local\u3002\u5206\u522B\u4EE3\u8868\uFF1A\u817E\u8BAF\u4E91\u5BF9\u8C61\u5B58\u50A8\u3001\u963F\u91CC\u4E91\u5BF9\u8C61\u5B58\u50A8\u3001\u672C\u5730\u5B58\u50A8 2 | #\u6CE8\u610F\uFF1A\u5982\u679C\u7C7B\u578B\u9009\u62E9\u672C\u5730\u4E0A\u4F20\uFF0C\u8BF7\u5728pom.xml\u4FEE\u6539\u591A\u5A92\u4F53\u4F9D\u8D56\uFF0C\u641C\u7D22org.bytedeco\uFF0C\u6839\u636E\u6CE8\u91CA\u9009\u62E9\u76F8\u5E94\u7684\u5305\uFF0C\u4FDD\u5B58\u540EReload Project 3 | yeim.file.storage.type=local 4 | #\u5B58\u50A8\u8D44\u6E90\u8BBF\u95EE\u7684\u81EA\u5B9A\u4E49\u57DF\u540D\uFF0C\u6CA1\u6709\u53EF\u4EE5\u4E0D\u586B 5 | yeim.file.storage.customDomain= 6 | #\u5BF9\u8C61\u5B58\u50A8\u6876\u540D\u79F0 7 | yeim.file.storage.bucket= 8 | #\u5BF9\u8C61\u5B58\u50A8\u5730\u57DF 9 | yeim.file.storage.region= 10 | #\u516C\u6709\u4E91\u5BF9\u8C61\u5B58\u50A8API\u5BC6\u94A5 11 | yeim.file.storage.secretId= 12 | yeim.file.storage.secretKey= 13 | #4. \u5B58\u50A8\u7684\u6839\u76EE\u5F55\uFF0C\u5982\u679C\u4E0A\u4F20\u4ED3\u5E93\u7C7B\u578B\u4E3A\u672C\u5730\uFF08local\uFF09\uFF0C\u8BF7\u586B\u5199\u4E0A\u4F20\u6587\u4EF6\u4FDD\u5B58\u7684\u6839\u76EE\u5F55\u3002\u5982\u679C\u975E\u672C\u5730\uFF0C\u8BF7\u586B\u5199\u5BF9\u8C61\u5B58\u50A8\u7684\u4FDD\u5B58\u76EE\u5F55\uFF0C\u4F8B\u5982\uFF1A/im/resource 14 | #yeim.file.storage.baseDir=/Users/wzjun1/Desktop/yeim_storage 15 | #yeim.file.storage.baseDir=C:\\Users\\Administrator\\Desktop\\yeim_storage 16 | #yeim.file.storage.baseDir=/Users/wzjun1/Desktop/yeim-uni-server/resource 17 | #yeim.file.storage.baseDir=/www/wwwroot/yeim-uni-server/resource 18 | yeim.file.storage.baseDir=/Users/wzjun1/Desktop/yeim-uni-server/resource -------------------------------------------------------------------------------- /src/main/resources/mapper/FriendApplyMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 41 | 42 | 49 | 50 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/main/resources/mapper/FriendMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 53 | 54 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/main/resources/mapper/GroupApplyMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | id 43 | ,group_id,user_id, 44 | inviter_id,status,admin_id,transform_message,extra_message 45 | transform_time,created_at 46 | 47 | 54 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/main/resources/mapper/GroupMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | id 22 | ,group_id,name, 23 | avatar_url,leader_user_id,introduction,notification,created_at,is_mute,is_dissolve 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/mapper/GroupMessageMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 58 | 59 | 60 | 90 | 91 | 125 | 126 | 127 | INSERT INTO `group_message_deleted`(`message_id`, `group_id`, `user_id`, `created_at`) 128 | VALUES (#{messageId}, #{groupId}, #{userId}, #{createdAt}) 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /src/main/resources/mapper/GroupUserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | id 34 | ,group_id,user_id,is_admin,mute_end_time, 35 | join_at,created_at 36 | 37 | 38 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/resources/mapper/MessageMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 58 | 59 | 86 | 87 | 117 | 118 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserBlackListMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | black_id 27 | ,user_id,cover_user_id, 28 | created_at 29 | 30 | 31 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/spy.properties: -------------------------------------------------------------------------------- 1 | modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory 2 | logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger 3 | appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger 4 | deregisterdrivers=true 5 | useprefix=true 6 | excludecategories=info,debug,result,commit,resultset 7 | dateformat=yyyy-MM-dd HH:mm:ss 8 | outagedetection=true 9 | outagedetectioninterval=2 -------------------------------------------------------------------------------- /src/test/java/cn/wzjun1/yeimServer/YeimServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package cn.wzjun1.yeimServer; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class YeimServerApplicationTests { 8 | @Test 9 | void contextLoads() { 10 | } 11 | } 12 | --------------------------------------------------------------------------------