diff --git a/modules/.DS_Store b/modules/.DS_Store index 99b5b4c9e0..628b54f058 100644 Binary files a/modules/.DS_Store and b/modules/.DS_Store differ diff --git a/modules/ai/.DS_Store b/modules/ai/.DS_Store index 5c39d0b665..eac92ca9eb 100644 Binary files a/modules/ai/.DS_Store and b/modules/ai/.DS_Store differ diff --git a/modules/ai/src/.DS_Store b/modules/ai/src/.DS_Store index 6231c8db00..81e1029edf 100644 Binary files a/modules/ai/src/.DS_Store and b/modules/ai/src/.DS_Store differ diff --git a/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaConfig.java b/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaConfig.java index f96892a958..58993a2b76 100644 --- a/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaConfig.java +++ b/modules/ai/src/main/java/com/bytedesk/ai/ollama/OllamaConfig.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-05-31 10:24:39 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-26 11:18:10 + * @LastEditTime: 2024-09-17 22:24:02 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -76,14 +76,14 @@ public class OllamaConfig { @Bean OllamaChatModel ollamaChatModel() { return new OllamaChatModel(ollamaApi(), OllamaOptions.create().withModel( - ollamaChatModel).withTemperature(0.9f)); + ollamaChatModel).withTemperature(0.9)); } // https://docs.spring.io/spring-ai/reference/api/embeddings/ollama-embeddings.html @Bean OllamaEmbeddingModel ollamaEmbeddingModel() { return new OllamaEmbeddingModel(ollamaApi(), OllamaOptions.create().withModel( - ollamaEmbeddingModel).withTemperature(0.9f)); + ollamaEmbeddingModel).withTemperature(0.9)); } } diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEmbedingEnum.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEmbedingEnum.java deleted file mode 100644 index 22d5e0fab4..0000000000 --- a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEmbedingEnum.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-06-06 13:08:36 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-21 23:25:21 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.ai.robot; - -// embedings无法枚举,只能使用字符串 -// public enum RobotEmbedingEnum { -// M3E_BASE("m3e-base"); - -// private final String value; - -// RobotEmbedingEnum(String value) { -// this.value = value; -// } - -// // 获取枚举常量的整型值 -// public String getValue() { -// return value; -// } - -// // 根据整型值查找对应的枚举常量 -// public static RobotEmbedingEnum fromValue(String value) { -// for (RobotEmbedingEnum type : RobotEmbedingEnum.values()) { -// if (type.getValue().equalsIgnoreCase(value)) { -// return type; -// } -// } -// throw new IllegalArgumentException("No RobotEmbedingEnum constant with value " + value); -// } -// } diff --git a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEventListener.java b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEventListener.java index 041c9d2eb8..92fa383fc8 100644 --- a/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEventListener.java +++ b/modules/ai/src/main/java/com/bytedesk/ai/robot/RobotEventListener.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-12 07:17:13 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 18:49:09 + * @LastEditTime: 2024-09-18 06:56:09 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -66,8 +66,6 @@ public class RobotEventListener { private final ZhipuaiService zhipuaiService; - // private final BytedeskEventPublisher bytedeskEventPublisher; - private final UidUtils uidUtils; private final ThreadService threadService; @@ -194,6 +192,7 @@ public class RobotEventListener { } else if (threadProtobuf.getType().equals(ThreadTypeEnum.AGENT) || threadProtobuf.getType().equals(ThreadTypeEnum.WORKGROUP)) { log.info("robot threadTopic {}, thread.type {}", threadTopic, threadProtobuf.getType()); + // TODO: 取消查库 Thread thread = threadService.findByTopic(threadTopic) .orElseThrow(() -> new RuntimeException("thread with topic " + threadTopic + " not found")); UserProtobuf agent = JSON.parseObject(thread.getAgent(), UserProtobuf.class); diff --git a/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiConfig.java b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiConfig.java index 9bc2c10e7d..089c36b5d3 100644 --- a/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiConfig.java +++ b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiConfig.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-05-31 10:53:11 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-30 14:40:31 + * @LastEditTime: 2024-09-17 22:24:11 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -70,7 +70,7 @@ public class ZhipuaiConfig { return new ZhiPuAiChatModel(zhipuaiApi(), ZhiPuAiChatOptions.builder() // .withModel(ZhiPuAiApi.ChatModel.GLM_3_Turbo.getValue()) .withModel(zhiPuAiApiModel) - .withTemperature(0.4f) + .withTemperature(0.4) .withMaxTokens(200) .build()); } diff --git a/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiController.java b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiController.java index 32d11ebf7e..4c21bedb94 100644 --- a/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiController.java +++ b/modules/ai/src/main/java/com/bytedesk/ai/zhipuai/ZhipuAiController.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-05-31 11:00:20 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-02 10:03:06 + * @LastEditTime: 2024-09-17 22:24:17 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -69,7 +69,7 @@ public class ZhipuaiController { "Generate the names of 5 famous pirates.", ZhiPuAiChatOptions.builder() .withModel(ZhiPuAiApi.ChatModel.GLM_3_Turbo.getValue()) - .withTemperature(0.5f) + .withTemperature(0.5) .build())); return ResponseEntity.ok(JsonResult.success(response)); } diff --git a/modules/core/.DS_Store b/modules/core/.DS_Store index 025dee0334..8377be861e 100644 Binary files a/modules/core/.DS_Store and b/modules/core/.DS_Store differ diff --git a/modules/core/src/.DS_Store b/modules/core/src/.DS_Store index a5494bdf07..d9e2ec0d2f 100644 Binary files a/modules/core/src/.DS_Store and b/modules/core/src/.DS_Store differ diff --git a/modules/core/src/main/java/com/bytedesk/core/black/Black.java b/modules/core/src/main/java/com/bytedesk/core/black/Black.java index 0bcbf67eb0..032baa06e1 100644 --- a/modules/core/src/main/java/com/bytedesk/core/black/Black.java +++ b/modules/core/src/main/java/com/bytedesk/core/black/Black.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-03-28 22:02:34 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-01 07:01:34 + * @LastEditTime: 2024-09-23 22:21:54 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,12 +14,15 @@ */ package com.bytedesk.core.black; -import com.bytedesk.core.base.BaseEntity; -import com.bytedesk.core.rbac.user.User; -import com.fasterxml.jackson.annotation.JsonIgnore; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; +import com.bytedesk.core.base.BaseEntity; +import com.bytedesk.core.constant.BdConstants; +import com.bytedesk.core.constant.TypeConsts; + +import jakarta.persistence.Column; import jakarta.persistence.Entity; -import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Builder; @@ -31,6 +34,7 @@ import lombok.experimental.Accessors; /** * black list * 黑名单 + * TODO: 拉黑ip、添加时间段限制 */ @Entity @Data @@ -42,11 +46,13 @@ import lombok.experimental.Accessors; @Table(name = "core_black") public class Black extends BaseEntity { - // private String reason; - @JsonIgnore - @ManyToOne - private User user; - + // 访客 or 用户,json,类型在json中定义 + @Builder.Default + @Column(name = "black_user", columnDefinition = TypeConsts.COLUMN_TYPE_JSON) + @JdbcTypeCode(SqlTypes.JSON) + private String blackUser = BdConstants.EMPTY_JSON_STRING; + + private String userUid; } diff --git a/modules/core/src/main/java/com/bytedesk/core/black/BlackController.java b/modules/core/src/main/java/com/bytedesk/core/black/BlackController.java index 020c706d08..a077ce6a05 100644 --- a/modules/core/src/main/java/com/bytedesk/core/black/BlackController.java +++ b/modules/core/src/main/java/com/bytedesk/core/black/BlackController.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-27 12:20:45 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-01 19:43:10 + * @LastEditTime: 2024-09-23 21:47:16 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,20 +14,29 @@ */ package com.bytedesk.core.black; +import org.springframework.data.domain.Page; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.bytedesk.core.base.BaseController; +import com.bytedesk.core.utils.JsonResult; + +import lombok.AllArgsConstructor; @RestController @RequestMapping("/api/v1/black") +@AllArgsConstructor public class BlackController extends BaseController { + private final BlackService blackService; + @Override public ResponseEntity queryByOrg(BlackRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'"); + + Page page = blackService.queryByOrg(request); + + return ResponseEntity.ok(JsonResult.success(page)); } @Override @@ -38,20 +47,22 @@ public class BlackController extends BaseController { @Override public ResponseEntity create(BlackRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'create'"); + + return ResponseEntity.ok(JsonResult.success(blackService.create(request))); } @Override public ResponseEntity update(BlackRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'update'"); + + return ResponseEntity.ok(JsonResult.success(blackService.update(request))); } @Override public ResponseEntity delete(BlackRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'delete'"); + + blackService.deleteByUid(request.getUid()); + + return ResponseEntity.ok(JsonResult.success()); } } diff --git a/modules/core/src/main/java/com/bytedesk/core/black/BlackEntityListener.java b/modules/core/src/main/java/com/bytedesk/core/black/BlackEntityListener.java index 1f232937e6..e1cd14d0b8 100644 --- a/modules/core/src/main/java/com/bytedesk/core/black/BlackEntityListener.java +++ b/modules/core/src/main/java/com/bytedesk/core/black/BlackEntityListener.java @@ -14,9 +14,9 @@ */ package com.bytedesk.core.black; -import org.springframework.stereotype.Component; +// import org.springframework.stereotype.Component; -@Component +// @Component public class BlackEntityListener { } diff --git a/modules/core/src/main/java/com/bytedesk/core/black/BlackRepository.java b/modules/core/src/main/java/com/bytedesk/core/black/BlackRepository.java index 2c34d6fa81..d084d84c2e 100644 --- a/modules/core/src/main/java/com/bytedesk/core/black/BlackRepository.java +++ b/modules/core/src/main/java/com/bytedesk/core/black/BlackRepository.java @@ -14,9 +14,12 @@ */ package com.bytedesk.core.black; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; public interface BlackRepository extends JpaRepository, JpaSpecificationExecutor { + Optional findByUid(String uid); } diff --git a/modules/core/src/main/java/com/bytedesk/core/black/BlackRequest.java b/modules/core/src/main/java/com/bytedesk/core/black/BlackRequest.java index 38c68da49d..2682b30827 100644 --- a/modules/core/src/main/java/com/bytedesk/core/black/BlackRequest.java +++ b/modules/core/src/main/java/com/bytedesk/core/black/BlackRequest.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-27 12:21:18 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-27 12:23:24 + * @LastEditTime: 2024-09-23 22:22:05 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -16,6 +16,22 @@ package com.bytedesk.core.black; import com.bytedesk.core.base.BaseRequest; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@Builder +@EqualsAndHashCode(callSuper = false) +@AllArgsConstructor +@NoArgsConstructor public class BlackRequest extends BaseRequest { + private String reason; + + private String blackUser; + + // private String userUid; } diff --git a/modules/core/src/main/java/com/bytedesk/core/black/BlackResponse.java b/modules/core/src/main/java/com/bytedesk/core/black/BlackResponse.java index 60075c0ec9..5de93ff6ed 100644 --- a/modules/core/src/main/java/com/bytedesk/core/black/BlackResponse.java +++ b/modules/core/src/main/java/com/bytedesk/core/black/BlackResponse.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-27 12:21:29 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-27 12:21:32 + * @LastEditTime: 2024-09-23 22:21:11 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -16,6 +16,22 @@ package com.bytedesk.core.black; import com.bytedesk.core.base.BaseResponse; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +@Data +@Builder +@EqualsAndHashCode(callSuper = false) +@AllArgsConstructor +@NoArgsConstructor public class BlackResponse extends BaseResponse { + private String reason; + + private String user; + + // private String userUid; } diff --git a/modules/core/src/main/java/com/bytedesk/core/black/BlackService.java b/modules/core/src/main/java/com/bytedesk/core/black/BlackService.java index 596cef8818..bdefe40d03 100644 --- a/modules/core/src/main/java/com/bytedesk/core/black/BlackService.java +++ b/modules/core/src/main/java/com/bytedesk/core/black/BlackService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-27 12:20:55 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-01 19:42:05 + * @LastEditTime: 2024-09-23 21:52:07 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -16,11 +16,20 @@ package com.bytedesk.core.black; import java.util.Optional; +import org.modelmapper.ModelMapper; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.ObjectOptimisticLockingFailureException; import org.springframework.stereotype.Service; import com.bytedesk.core.base.BaseService; +import com.bytedesk.core.rbac.auth.AuthService; +import com.bytedesk.core.rbac.user.User; +import com.bytedesk.core.uid.UidUtils; import lombok.AllArgsConstructor; @@ -28,10 +37,25 @@ import lombok.AllArgsConstructor; @AllArgsConstructor public class BlackService extends BaseService { + private final BlackRepository repository; + + private final ModelMapper modelMapper; + + private final UidUtils uidUtils; + + private final AuthService authService; + @Override public Page queryByOrg(BlackRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'"); + + Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.DESC, + "createdAt"); + + Specification specification = BlackSpecification.search(request); + + Page blacks = repository.findAll(specification, pageable); + + return blacks.map(this::convertToResponse); } @Override @@ -40,16 +64,25 @@ public class BlackService extends BaseService findByUid(String uid) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findByUid'"); + return repository.findByUid(uid); } @Override public BlackResponse create(BlackRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'create'"); + User user = authService.getCurrentUser(); + // + Black entity = modelMapper.map(request, Black.class); + entity.setUid(uidUtils.getUid()); + entity.setUserUid(user.getUid()); + // + Black savedBlack = save(entity); + if (savedBlack == null) { + throw new RuntimeException("Create black failed"); + } + return convertToResponse(savedBlack); } @Override @@ -60,8 +93,12 @@ public class BlackService extends BaseService search(BlackRequest request) { + return (root, query, criteriaBuilder) -> { + List predicates = new ArrayList<>(); + predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid())); + // + // + return criteriaBuilder.and(predicates.toArray(new Predicate[0])); + }; + } } diff --git a/modules/core/src/main/java/com/bytedesk/core/category/CategoryController.java b/modules/core/src/main/java/com/bytedesk/core/category/CategoryController.java index ca0305fd08..3b0e569355 100644 --- a/modules/core/src/main/java/com/bytedesk/core/category/CategoryController.java +++ b/modules/core/src/main/java/com/bytedesk/core/category/CategoryController.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-05-11 18:21:26 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-08 16:47:17 + * @LastEditTime: 2024-09-20 16:03:46 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -16,8 +16,6 @@ package com.bytedesk.core.category; import org.springframework.data.domain.Page; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -34,7 +32,6 @@ public class CategoryController extends BaseController { private final CategoryService categoryService; - @GetMapping("/query/org") @Override public ResponseEntity queryByOrg(CategoryRequest request) { @@ -49,7 +46,6 @@ public class CategoryController extends BaseController { throw new UnsupportedOperationException("Unimplemented method 'query'"); } - @PostMapping("/create") @Override public ResponseEntity create(@RequestBody CategoryRequest request) { @@ -58,7 +54,6 @@ public class CategoryController extends BaseController { return ResponseEntity.ok(JsonResult.success(response)); } - @PostMapping("/update") @Override public ResponseEntity update(@RequestBody CategoryRequest request) { @@ -67,7 +62,6 @@ public class CategoryController extends BaseController { return ResponseEntity.ok(JsonResult.success(response)); } - @PostMapping("/delete") @Override public ResponseEntity delete(@RequestBody CategoryRequest request) { diff --git a/modules/core/src/main/java/com/bytedesk/core/config/BytedeskConfig.java b/modules/core/src/main/java/com/bytedesk/core/config/BytedeskConfig.java index 747655a428..5faf33b8e2 100644 --- a/modules/core/src/main/java/com/bytedesk/core/config/BytedeskConfig.java +++ b/modules/core/src/main/java/com/bytedesk/core/config/BytedeskConfig.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-30 07:52:26 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-07-30 09:11:25 + * @LastEditTime: 2024-09-19 12:50:10 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -15,6 +15,7 @@ package com.bytedesk.core.config; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Value; @@ -62,6 +63,7 @@ public class BytedeskConfig { public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); // restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + restTemplate.setInterceptors(Arrays.asList(new TraceIdInterceptor())); return restTemplate; } @@ -71,16 +73,16 @@ public class BytedeskConfig { } @Bean - public OpenAPI apiInfo() { - return new OpenAPI().info(new Info().title("bytedesk apis").version(appVersion)); - } + public OpenAPI apiInfo() { + return new OpenAPI().info(new Info().title("bytedesk apis").version(appVersion)); + } - // @Bean - // public GroupedOpenApi httpApi() { - // return GroupedOpenApi.builder() - // .group("http") - // .pathsToMatch("/**") - // .build(); - // } + // @Bean + // public GroupedOpenApi httpApi() { + // return GroupedOpenApi.builder() + // .group("http") + // .pathsToMatch("/**") + // .build(); + // } } diff --git a/modules/core/src/main/java/com/bytedesk/core/config/BytedeskEventPublisher.java b/modules/core/src/main/java/com/bytedesk/core/config/BytedeskEventPublisher.java index 7dfe361585..ad3deed3c5 100644 --- a/modules/core/src/main/java/com/bytedesk/core/config/BytedeskEventPublisher.java +++ b/modules/core/src/main/java/com/bytedesk/core/config/BytedeskEventPublisher.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-02-23 14:42:58 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-09 16:26:19 + * @LastEditTime: 2024-09-20 10:29:14 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -46,6 +46,7 @@ import com.bytedesk.core.socket.stomp.StompUnsubscribeEvent; import com.bytedesk.core.thread.Thread; import com.bytedesk.core.thread.ThreadCreateEvent; import com.bytedesk.core.thread.ThreadUpdateEvent; +import com.bytedesk.core.thread.ThreadUpdateStatusEvent; import com.bytedesk.core.topic.TopicCreateEvent; import com.bytedesk.core.topic.TopicUpdateEvent; @@ -146,6 +147,10 @@ public class BytedeskEventPublisher { applicationEventPublisher.publishEvent(new ThreadUpdateEvent(this, thread)); } + public void publishThreadUpdateStatusEvent(Thread thread, String status) { + applicationEventPublisher.publishEvent(new ThreadUpdateStatusEvent(this, thread, status)); + } + public void publishActionCreateEvent(Action action) { applicationEventPublisher.publishEvent(new ActionCreateEvent(this, action)); } diff --git a/modules/core/src/main/java/com/bytedesk/core/config/CorsConfig.java b/modules/core/src/main/java/com/bytedesk/core/config/CorsConfig.java index a49c066b87..6ac8504e4c 100644 --- a/modules/core/src/main/java/com/bytedesk/core/config/CorsConfig.java +++ b/modules/core/src/main/java/com/bytedesk/core/config/CorsConfig.java @@ -29,9 +29,10 @@ public class CorsConfig { /** * 经测试:仅有此处起作用,corsFilter()和WebMvcConfig.addCorsMappings()不起作用 + * * @return */ - // https://docs.spring.io/spring-security/reference/reactive/integrations/cors.html + // https://docs.spring.io/spring-security/reference/reactive/channels/cors.html @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); @@ -40,31 +41,33 @@ public class CorsConfig { // configuration.setAllowedOriginPatterns(List.of("*")); // 不能启用 configuration.setAllowedMethods(List.of("*")); configuration.setAllowedHeaders(List.of("*")); - // configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); + // configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", + // "OPTIONS")); // configuration.setAllowedHeaders(List.of("Authorization", "Content-Type")); - // + // UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } - // @Bean - // public CorsFilter corsFilter() { - // log.info("CorsConfig.corsFilter()"); - // CorsConfiguration corsConfiguration = new CorsConfiguration(); - // //1,允许任何来源 - // corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*")); - // //2,允许任何请求头 - // corsConfiguration.addAllowedHeader(CorsConfiguration.ALL); - // //3,允许任何方法 - // corsConfiguration.addAllowedMethod(CorsConfiguration.ALL); - // //4,允许凭证 - // corsConfiguration.setAllowCredentials(true); - // // - // UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - // source.registerCorsConfiguration("/**", corsConfiguration); - // // - // return new CorsFilter(source); - // } + // @Bean + // public CorsFilter corsFilter() { + // log.info("CorsConfig.corsFilter()"); + // CorsConfiguration corsConfiguration = new CorsConfiguration(); + // //1,允许任何来源 + // corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*")); + // //2,允许任何请求头 + // corsConfiguration.addAllowedHeader(CorsConfiguration.ALL); + // //3,允许任何方法 + // corsConfiguration.addAllowedMethod(CorsConfiguration.ALL); + // //4,允许凭证 + // corsConfiguration.setAllowCredentials(true); + // // + // UrlBasedCorsConfigurationSource source = new + // UrlBasedCorsConfigurationSource(); + // source.registerCorsConfiguration("/**", corsConfiguration); + // // + // return new CorsFilter(source); + // } } \ No newline at end of file diff --git a/modules/core/src/main/java/com/bytedesk/core/config/SecurityConfig.java b/modules/core/src/main/java/com/bytedesk/core/config/SecurityConfig.java index 7178a82b64..799faa8dc2 100644 --- a/modules/core/src/main/java/com/bytedesk/core/config/SecurityConfig.java +++ b/modules/core/src/main/java/com/bytedesk/core/config/SecurityConfig.java @@ -62,7 +62,7 @@ public class SecurityConfig { .requestMatchers("/api/**").authenticated() // .requestMatchers("/actuator/**").authenticated() // monitor endpoints .anyRequest().permitAll()) - // https://docs.spring.io/spring-security/reference/servlet/integrations/websocket.html + // https://docs.spring.io/spring-security/reference/servlet/channels/websocket.html .headers(headers -> headers.frameOptions(frameOptions -> frameOptions.sameOrigin().disable())) .authenticationProvider(authenticationProvider()) // .oauth2ResourceServer((oauth2) -> oauth2.jwt(withDefaults())) diff --git a/modules/core/src/main/java/com/bytedesk/core/config/TraceIdFilter.java b/modules/core/src/main/java/com/bytedesk/core/config/TraceIdFilter.java new file mode 100644 index 0000000000..c7489bead5 --- /dev/null +++ b/modules/core/src/main/java/com/bytedesk/core/config/TraceIdFilter.java @@ -0,0 +1,70 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-09-19 11:36:33 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2024-09-19 12:47:23 + * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk + * Please be aware of the BSL license restrictions before installing Bytedesk IM – + * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. + * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.core.config; + +import java.io.IOException; +import java.util.UUID; + +import org.slf4j.MDC; +import org.springframework.stereotype.Component; + +import com.bytedesk.core.constant.BdConstants; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; + +/** + * 日志链路跟踪 + * https://developer.aliyun.com/article/1581355?spm=5176.26934562.main.1.67c12f7755gBG5 + */ +@Slf4j +@Component +public class TraceIdFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + HttpServletRequest httpRequest = (HttpServletRequest) request; + String traceId = httpRequest.getHeader(BdConstants.TRACE_ID); + if (traceId == null) { + traceId = UUID.randomUUID().toString(); + } + + // 设置到ThreadLocal,方便后续在业务代码中获取 + MDC.put(BdConstants.TRACE_ID, traceId); + + // 添加到响应头,便于下游服务获取 + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.setHeader(BdConstants.TRACE_ID, traceId); + + chain.doFilter(request, response); + } + + @Override + public void destroy() { + log.info("TraceIdFilter destroy"); + // 请求处理完成后,清理ThreadLocal中存储的traceId + // MDC.clear(); + MDC.remove(BdConstants.TRACE_ID); + } + +} diff --git a/modules/core/src/main/java/com/bytedesk/core/config/TraceIdInterceptor.java b/modules/core/src/main/java/com/bytedesk/core/config/TraceIdInterceptor.java new file mode 100644 index 0000000000..d04a78b180 --- /dev/null +++ b/modules/core/src/main/java/com/bytedesk/core/config/TraceIdInterceptor.java @@ -0,0 +1,38 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-09-19 12:45:53 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2024-09-19 12:50:40 + * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk + * Please be aware of the BSL license restrictions before installing Bytedesk IM – + * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. + * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.core.config; + +import java.io.IOException; + +import org.slf4j.MDC; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; + +import com.bytedesk.core.constant.BdConstants; + +public class TraceIdInterceptor implements ClientHttpRequestInterceptor { + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) + throws IOException { + String traceId = MDC.get(BdConstants.TRACE_ID); + if (traceId != null) { + request.getHeaders().add(BdConstants.TRACE_ID, traceId); + } + return execution.execute(request, body); + } +} \ No newline at end of file diff --git a/modules/core/src/main/java/com/bytedesk/core/constant/BdConstants.java b/modules/core/src/main/java/com/bytedesk/core/constant/BdConstants.java index a1a827d066..89d94ee6c0 100644 --- a/modules/core/src/main/java/com/bytedesk/core/constant/BdConstants.java +++ b/modules/core/src/main/java/com/bytedesk/core/constant/BdConstants.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-02-02 21:48:19 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-08 08:43:47 + * @LastEditTime: 2024-09-19 12:52:21 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -28,7 +28,7 @@ public class BdConstants { // bytedesk public static final String PLATFORM_BYTEDESK = "BYTEDESK"; - // public static final boolean IS_DEBUG = false; + public static final String TRACE_ID = "traceId"; // 空字符串 public static final String EMPTY_STRING = ""; public static final String EMPTY_JSON_STRING = "{}"; @@ -40,6 +40,7 @@ public class BdConstants { public static final String DEFAULT_FILE_ASISTANT_UID = "df_fa_uid"; public static final String DEFAULT_SYSTEM_UID = "df_sys_uid"; public static final String DEFAULT_KB_UID = "df_kb_uid"; + public static final String DEFAULT_DY_UID = "df_dy_uid"; // public static final String ACTION_LOGIN_USERNAME = "loginWithUsernamePassword"; public static final String ACTION_LOGIN_MOBILE = "loginWithMobileCode"; diff --git a/modules/core/src/main/java/com/bytedesk/core/exception/GlobalControllerAdvice.java b/modules/core/src/main/java/com/bytedesk/core/exception/GlobalControllerAdvice.java index b9586a47ac..6bed8a4d33 100644 --- a/modules/core/src/main/java/com/bytedesk/core/exception/GlobalControllerAdvice.java +++ b/modules/core/src/main/java/com/bytedesk/core/exception/GlobalControllerAdvice.java @@ -20,6 +20,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.server.ResponseStatusException; @@ -131,6 +132,12 @@ public class GlobalControllerAdvice { return ResponseEntity.badRequest().body(JsonResult.error("TODO: jetty Websocket Timeout Exception")); } + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ResponseEntity handleHttpRequestMethodNotSupportedException( + HttpRequestMethodNotSupportedException ex) { + return ResponseEntity.badRequest().body(JsonResult.error("Http Request Method Not Supported Exception", 400)); + } + @ExceptionHandler(Exception.class) // @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ResponseEntity handleException(Exception e) { diff --git a/modules/core/src/main/java/com/bytedesk/core/exception/UsernameExistsException.java b/modules/core/src/main/java/com/bytedesk/core/exception/UsernameExistsException.java index 32f6074705..bd9f5435a0 100644 --- a/modules/core/src/main/java/com/bytedesk/core/exception/UsernameExistsException.java +++ b/modules/core/src/main/java/com/bytedesk/core/exception/UsernameExistsException.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-26 09:28:30 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-12 19:06:55 + * @LastEditTime: 2024-09-12 11:58:16 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -22,7 +22,4 @@ public class UsernameExistsException extends BaseException { super(message); //TODO Auto-generated constructor stub } - - - } diff --git a/modules/core/src/main/java/com/bytedesk/core/ip/IpInterceptor.java b/modules/core/src/main/java/com/bytedesk/core/ip/IpInterceptor.java index f0c2a984d3..4002187e2d 100644 --- a/modules/core/src/main/java/com/bytedesk/core/ip/IpInterceptor.java +++ b/modules/core/src/main/java/com/bytedesk/core/ip/IpInterceptor.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-05-17 12:53:46 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-27 17:04:27 + * @LastEditTime: 2024-09-12 11:58:40 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -40,7 +40,7 @@ public class IpInterceptor implements HandlerInterceptor { private static final List BLACKLISTED_IPS = Arrays.asList( "175.27.32.31", "112.53.2.93" - // 可以根据需要动态配置这个列表,例如从数据库或配置文件中加载 + // TODO: 可以根据需要动态配置这个列表,例如从数据库或配置文件中加载 ); @Override diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessagePersistService.java b/modules/core/src/main/java/com/bytedesk/core/message/MessagePersistService.java index 07515dae48..18df5760d7 100644 --- a/modules/core/src/main/java/com/bytedesk/core/message/MessagePersistService.java +++ b/modules/core/src/main/java/com/bytedesk/core/message/MessagePersistService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-16 18:04:37 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 16:23:29 + * @LastEditTime: 2024-09-12 19:01:36 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -191,7 +191,8 @@ public class MessagePersistService { // 消息撤回,从数据库中删除消息 private void dealWithMessageRecall(MessageProtobuf message) { // log.info("dealWithMessageRecall"); - messageService.deleteByUid(message.getUid()); + // content为撤回消息的uid + messageService.deleteByUid(message.getContent()); } private void dealWithRateMessage(MessageTypeEnum type, MessageProtobuf message) { @@ -252,6 +253,7 @@ public class MessagePersistService { } } + // 处理转接消息 private void dealWithTransferMessage(MessageTypeEnum type, MessageProtobuf message) { // log.info("dealWithTransferMessage"); MessageTransferContent transferContentObject = JSONObject.parseObject(message.getContent(), @@ -269,4 +271,5 @@ public class MessagePersistService { } } + } diff --git a/modules/core/src/main/java/com/bytedesk/core/message_unread/MessageUnreadEventListener.java b/modules/core/src/main/java/com/bytedesk/core/message_unread/MessageUnreadEventListener.java index 6c4bb43830..0d720670e8 100644 --- a/modules/core/src/main/java/com/bytedesk/core/message_unread/MessageUnreadEventListener.java +++ b/modules/core/src/main/java/com/bytedesk/core/message_unread/MessageUnreadEventListener.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-07-01 12:37:41 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-10 17:06:01 + * @LastEditTime: 2024-09-12 22:23:34 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -194,14 +194,13 @@ public class MessageUnreadEventListener { @EventListener public void onQuartzFiveSecondEvent(QuartzFiveSecondEvent event) { // log.info("message quartz five second event: " + event); - } @EventListener public void onMqttConnectEvent(MqttConnectedEvent event) { // 用户clientId格式: uid/client/deviceUid - String clientId = event.getClientId(); - log.info("message unread mqtt connect event: {}", clientId); + // String clientId = event.getClientId(); + // log.info("message unread mqtt connect event: {}", clientId); // String[] clientIdArray = clientId.split("/"); // if (clientIdArray.length != 3) { // return; @@ -217,7 +216,7 @@ public class MessageUnreadEventListener { @EventListener public void onStompSessionConnectedEvent(StompConnectedEvent event) { // TODO: 将缓存消息推送给相应访客端 - log.info("message unread stomp session connect event: {}", event.getClientId()); + // log.info("message unread stomp session connect event: {}", event.getClientId()); } } diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthEventListener.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthEventListener.java index 94fe067c2f..77bd49bfa8 100644 --- a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthEventListener.java +++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthEventListener.java @@ -57,7 +57,6 @@ public class AuthEventListener { contentObject.put(I18Consts.I18N_NOTICE_IP, action.getIp()); contentObject.put(I18Consts.I18N_NOTICE_IPLOCATION, action.getIpLocation()); // - // MessageProtobuf messsage = messageService.createNoticeMessage(user, JSON.toJSONString(contentObject)); MessageProtobuf messsage = MessageUtils.createNoticeMessage(uidUtils.getCacheSerialUid(), user.getUid(), user.getOrgUid(), JSON.toJSONString(contentObject)); MessageUtils.notifyUser(messsage); diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthService.java b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthService.java index 97cbb85d55..1bd2bed515 100644 --- a/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthService.java +++ b/modules/core/src/main/java/com/bytedesk/core/rbac/auth/AuthService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-23 07:53:01 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-27 13:18:42 + * @LastEditTime: 2024-09-19 10:03:16 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -23,7 +23,6 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Service; -// import com.bytedesk.core.enums.PlatformEnum; import com.bytedesk.core.rbac.user.User; import com.bytedesk.core.rbac.user.UserDetailsImpl; import com.bytedesk.core.rbac.user.UserDetailsServiceImpl; diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/User.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/User.java index 4b39c145a7..09ebb7779a 100644 --- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/User.java +++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/User.java @@ -83,8 +83,6 @@ public class User extends BaseEntityNoOrg { private String description = I18Consts.I18N_USER_DESCRIPTION; @Builder.Default - // @Enumerated(EnumType.STRING) - // private Sex sex = Sex.UNKNOWN; private String sex = Sex.UNKNOWN.name(); @Builder.Default @@ -104,8 +102,6 @@ public class User extends BaseEntityNoOrg { private boolean mobileVerified = false; @Builder.Default - // @Enumerated(EnumType.STRING) - // private PlatformEnum platform = PlatformEnum.BYTEDESK; private String platform = PlatformEnum.BYTEDESK.name(); @JsonIgnore diff --git a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRepository.java b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRepository.java index 55d897286d..3a7fe7b024 100644 --- a/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRepository.java +++ b/modules/core/src/main/java/com/bytedesk/core/rbac/user/UserRepository.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-29 16:21:24 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-18 09:36:27 + * @LastEditTime: 2024-09-19 10:05:17 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -19,10 +19,6 @@ import java.util.Optional; // import org.springframework.cache.annotation.Cacheable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -// import org.springframework.data.rest.core.annotation.RepositoryRestResource; -// import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Repository; -// import com.bytedesk.core.enums.PlatformEnum; /** * https://spring.io/guides/tutorials/react-and-spring-data-rest/ @@ -31,7 +27,7 @@ import org.springframework.stereotype.Repository; */ // @RepositoryRestResource(exported = false) // @PreAuthorize("hasRole('ROLE_ADMIN')") -@Repository +// @Repository public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { Optional findByUid(String uid); diff --git a/modules/core/src/main/java/com/bytedesk/core/socket/stomp/StompConfig.java b/modules/core/src/main/java/com/bytedesk/core/socket/stomp/StompConfig.java index 499a821bf2..df448342e6 100644 --- a/modules/core/src/main/java/com/bytedesk/core/socket/stomp/StompConfig.java +++ b/modules/core/src/main/java/com/bytedesk/core/socket/stomp/StompConfig.java @@ -48,7 +48,7 @@ public class StompConfig implements WebSocketMessageBrokerConfigurer { stompEndpointRegistry.addEndpoint("/stomp") .setAllowedOriginPatterns("*") .setHandshakeHandler(handshakeHandler()); - // https://docs.spring.io/spring-security/reference/servlet/integrations/websocket.html + // https://docs.spring.io/spring-security/reference/servlet/channels/websocket.html // FIXME: Access to XMLHttpRequest at // 'http://127.0.0.1:9003/sockjs/info?t=1718785780963' from origin // 'http://127.0.0.1:9006' has been blocked by CORS policy: The value of the diff --git a/modules/core/src/main/java/com/bytedesk/core/tag/TagSpecification.java b/modules/core/src/main/java/com/bytedesk/core/tag/TagSpecification.java index 3045a31b41..2e996de2f0 100644 --- a/modules/core/src/main/java/com/bytedesk/core/tag/TagSpecification.java +++ b/modules/core/src/main/java/com/bytedesk/core/tag/TagSpecification.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-07-09 22:19:21 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-07-09 22:19:24 + * @LastEditTime: 2024-09-23 21:27:59 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,6 +14,8 @@ */ package com.bytedesk.core.tag; -public class TagSpecification { +import com.bytedesk.core.base.BaseSpecification; + +public class TagSpecification extends BaseSpecification { } diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/Thread.java b/modules/core/src/main/java/com/bytedesk/core/thread/Thread.java index 784e42d785..9def39b1a5 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/Thread.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/Thread.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-29 16:21:24 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-11 08:50:25 + * @LastEditTime: 2024-09-23 16:07:43 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -48,16 +48,16 @@ import lombok.experimental.Accessors; @AllArgsConstructor @NoArgsConstructor @EntityListeners({ ThreadEntityListener.class }) +// 表继承(Table Per Class +// Inheritance):在这种策略中,每一个类(父类和每个子类)都映射到一个独立的数据库表中。子类表将只包含子类特有的属性,以及与父类表相关联的主键。 +// @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Table(name = "core_thread") public class Thread extends BaseEntity { private static final long serialVersionUID = 1L; + /** - * used to push message - * topic format: - * workgroup_wid + '/' + visitor_vid - * agent_aid + '/' + visitor_vid - * such as: wid/vid or aid/vid + * @{TopicUtils} */ @NotBlank private String topic; @@ -69,16 +69,14 @@ public class Thread extends BaseEntity { * @{ThreadTypeConsts} */ @Builder.Default - // @Enumerated(EnumType.STRING) @Column(name = "thread_type", nullable = false) - // private ThreadTypeEnum type = ThreadTypeEnum.WORKGROUP; private String type = ThreadTypeEnum.WORKGROUP.name(); + // TODO: 标记问题是否解决 + /** closed/open, agent closed/auto closed */ @Builder.Default - // @Enumerated(EnumType.STRING) - // private ThreadStatusEnum status = ThreadStatusEnum.NORMAL; - private String status = ThreadStatusEnum.NORMAL.name(); + private String status = ThreadStatusEnum.START.name(); // 置顶 @Builder.Default @@ -151,31 +149,50 @@ public class Thread extends BaseEntity { @JdbcTypeCode(SqlTypes.JSON) private String agent = BdConstants.EMPTY_JSON_STRING; + + // 机器人和agent可以同时存在,人工接待的时候,机器人可以同时给出答案,客服可以选用 + // 存储机器人信息 + // @Builder.Default + // @Column(columnDefinition = TypeConsts.COLUMN_TYPE_JSON) + // @JdbcTypeCode(SqlTypes.JSON) + // private String robot = BdConstants.EMPTY_JSON_STRING; + // belongs to user @JsonIgnore @ManyToOne(fetch = FetchType.LAZY) private User owner; - // public Boolean isInit() { - // return this.status == ThreadStatusEnum.NORMAL.name(); - // } // public Boolean isClosed() { - return this.status == ThreadStatusEnum.AGENT_CLOSED.name() || this.status == ThreadStatusEnum.AUTO_CLOSED.name(); + return this.status.equals(ThreadStatusEnum.AGENT_CLOSED.name()) + || this.status.equals(ThreadStatusEnum.AUTO_CLOSED.name()); } public Boolean isCustomerService() { - return this.type == ThreadTypeEnum.AGENT.name() || this.type == ThreadTypeEnum.WORKGROUP.name(); + return this.type.equals(ThreadTypeEnum.AGENT.name()) + || this.type.equals(ThreadTypeEnum.WORKGROUP.name()); + } + + public Boolean isRobotType() { + return this.type.equals(ThreadTypeEnum.ROBOT.name()); + } + + public Boolean isWorkgroupType() { + return this.type.equals(ThreadTypeEnum.WORKGROUP.name()); + } + + public Boolean isAgentType() { + return this.type.equals(ThreadTypeEnum.AGENT.name()); } public ThreadProtobuf toProtobuf() { return ConvertUtils.convertToThreadProtobuf(this); } - public UserProtobuf getAgentProtobuf() { - return JSON.parseObject(this.agent, UserProtobuf.class); - } + // public UserProtobuf getAgentProtobuf() { + // return JSON.parseObject(this.agent, UserProtobuf.class); + // } public UserProtobuf getUserProtobuf() { return JSON.parseObject(this.user, UserProtobuf.class); diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadController.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadController.java index a61cad30ba..bfa701b7c1 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadController.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadController.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-29 16:21:24 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 16:41:04 + * @LastEditTime: 2024-09-20 09:51:27 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -92,7 +92,7 @@ public class ThreadController extends BaseController { @PostMapping("/close") public ResponseEntity close(@RequestBody ThreadRequest request) { - request.setStatus(ThreadStatusEnum.AGENT_CLOSED); + request.setStatus(ThreadStatusEnum.AGENT_CLOSED.name()); ThreadResponse threadResponse = threadService.close(request); diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEntityListener.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEntityListener.java index 9fb96592e7..1a79f74d7e 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEntityListener.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEntityListener.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-15 09:30:56 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-27 13:07:30 + * @LastEditTime: 2024-09-20 10:27:24 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -15,6 +15,7 @@ package com.bytedesk.core.thread; import org.springframework.util.SerializationUtils; + import org.springframework.stereotype.Component; import com.bytedesk.core.config.BytedeskEventPublisher; @@ -22,29 +23,39 @@ import com.bytedesk.core.utils.ApplicationContextHolder; import jakarta.persistence.PostPersist; import jakarta.persistence.PostUpdate; +// import jakarta.persistence.PostUpdate; import lombok.extern.slf4j.Slf4j; // @Async @Slf4j @Component public class ThreadEntityListener { + + // @Transient + // private transient Thread oldThread; @PostPersist public void postPersist(Thread thread) { log.info("thread postPersist {}", thread.getUid()); // send notifications Thread clonedThread = SerializationUtils.clone(thread); - + BytedeskEventPublisher bytedeskEventPublisher = ApplicationContextHolder.getBean(BytedeskEventPublisher.class); bytedeskEventPublisher.publishThreadCreateEvent(clonedThread); } + + // @PreUpdate + // public void preUpdate(Thread thread) { + // log.info("preUpdate {}", thread.getUid()); + // this.oldThread = SerializationUtils.clone(thread); + // } @PostUpdate public void postUpdate(Thread thread) { log.info("postUpdate {}", thread.getUid()); // send notifications Thread clonedThread = SerializationUtils.clone(thread); - // + BytedeskEventPublisher bytedeskEventPublisher = ApplicationContextHolder.getBean(BytedeskEventPublisher.class); bytedeskEventPublisher.publishThreadUpdateEvent(clonedThread); } diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEventListener.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEventListener.java index e96802055e..3448b04b1c 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEventListener.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadEventListener.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-28 13:32:23 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-11 11:19:50 + * @LastEditTime: 2024-09-19 14:44:32 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -56,6 +56,11 @@ public class ThreadEventListener { // return; // } + // 机器人接待的会话存在user == null的情况,不需要订阅topic + if (user == null) { + return; + } + // 创建客服会话之后,需要订阅topic if (thread.getType().equals(ThreadTypeEnum.AGENT.name()) || thread.getType().equals(ThreadTypeEnum.WORKGROUP.name())) { @@ -101,7 +106,7 @@ public class ThreadEventListener { .userUid(user.getUid()) .build(); topicCacheService.pushRequest(request); - } else if (thread.getOwner() != null) { + } else if (user != null) { TopicRequest request = TopicRequest.builder() .topic(thread.getTopic()) .userUid(user.getUid()) diff --git a/modules/core/src/main/java/com/bytedesk/core/message/MessageControllerVisitor.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadFlowNode.java similarity index 61% rename from modules/core/src/main/java/com/bytedesk/core/message/MessageControllerVisitor.java rename to modules/core/src/main/java/com/bytedesk/core/thread/ThreadFlowNode.java index 02ee8e157f..e80fb7e53f 100644 --- a/modules/core/src/main/java/com/bytedesk/core/message/MessageControllerVisitor.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadFlowNode.java @@ -1,8 +1,8 @@ /* * @Author: jackning 270580156@qq.com - * @Date: 2024-07-18 19:23:14 + * @Date: 2024-09-19 10:44:15 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-07-18 19:23:17 + * @LastEditTime: 2024-09-19 15:27:05 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -12,21 +12,28 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.core.message; +package com.bytedesk.core.thread; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import java.io.Serializable; import lombok.AllArgsConstructor; -// import lombok.extern.slf4j.Slf4j; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; -// 消息接口,可匿名访问 -// @Slf4j -@RestController +@Data +@Builder @AllArgsConstructor -@RequestMapping("/visitor/api/v1") -public class MessageControllerVisitor { +@NoArgsConstructor +public class ThreadFlowNode implements Serializable { - - + private final static long serialVersionUID = 1L; + + private ThreadStatusEnum status; + + private String content; + + private String createAt; + + private ThreadFlowNode children[]; } diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadRequest.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadRequest.java index c9d7391b3f..94a8bfd491 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadRequest.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadRequest.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-02-21 10:01:12 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-16 08:12:30 + * @LastEditTime: 2024-09-20 09:50:49 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -43,7 +43,7 @@ public class ThreadRequest extends BaseRequest { // private String topic; - private ThreadStatusEnum status; + private String status; private UserProtobuf user; diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadResponse.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadResponse.java index fc06580ab0..5829736e17 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadResponse.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadResponse.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-02-21 10:01:27 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-16 08:12:39 + * @LastEditTime: 2024-09-20 09:50:26 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -17,7 +17,6 @@ package com.bytedesk.core.thread; import java.util.Date; import com.bytedesk.core.base.BaseResponse; -import com.bytedesk.core.enums.ClientEnum; import com.bytedesk.core.rbac.user.UserProtobuf; import lombok.AllArgsConstructor; @@ -44,9 +43,9 @@ public class ThreadResponse extends BaseResponse { private String content; - private ThreadTypeEnum type; + private String type; - private ThreadStatusEnum status; + private String status; // private Boolean top; @@ -63,7 +62,7 @@ public class ThreadResponse extends BaseResponse { private Boolean folded; - private ClientEnum client; + private String client; private String extra; diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadService.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadService.java index b740acbd1e..feeda5cac9 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadService.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-29 16:21:24 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 19:00:26 + * @LastEditTime: 2024-09-20 10:27:49 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -35,6 +35,7 @@ import org.springframework.util.StringUtils; import com.alibaba.fastjson2.JSON; import com.bytedesk.core.base.BaseService; +// import com.bytedesk.core.config.BytedeskEventPublisher; import com.bytedesk.core.enums.ClientEnum; import com.bytedesk.core.message.MessageProtobuf; import com.bytedesk.core.message.MessageTypeEnum; @@ -57,13 +58,15 @@ import lombok.extern.slf4j.Slf4j; @AllArgsConstructor public class ThreadService extends BaseService { - private AuthService authService; + private final AuthService authService; - private ModelMapper modelMapper; + private final ModelMapper modelMapper; - private ThreadRepository threadRepository; + private final ThreadRepository threadRepository; - private UidUtils uidUtils; + private final UidUtils uidUtils; + + // private final BytedeskEventPublisher bytedeskEventPublisher; public Page queryByOrg(ThreadRequest request) { @@ -112,7 +115,7 @@ public class ThreadService extends BaseService threadOptional = findByUid(threadRequest.getUid()); Optional threadOptional = findByTopic(threadRequest.getTopic()); if (!threadOptional.isPresent()) { throw new RuntimeException("close thread " + threadRequest.getTopic() + " not found"); } // Thread thread = threadOptional.get(); - // if (ThreadStatusEnum.AGENT_CLOSED.name().equals(thread.getStatus()) || ThreadStatusEnum.AUTO_CLOSED.name().equals(thread.getStatus())) { // log.info("thread {} is already closed", uid); throw new RuntimeException("thread is already closed"); } - // thread.setStatus(ThreadStatusEnum.AGENT_CLOSED.name()); - thread.setStatus(threadRequest.getStatus().name()); + thread.setStatus(threadRequest.getStatus()); // Thread updateThread = save(thread); if (updateThread == null) { throw new RuntimeException("thread save failed"); } + // bytedeskEventPublisher.publishThreadUpdateEvent(updateThread); // 发布关闭消息, 通知用户 - String content = threadRequest.getStatus().equals(ThreadStatusEnum.AUTO_CLOSED) ? I18Consts.I18N_AUTO_CLOSED : I18Consts.I18N_AGENT_CLOSED; - MessageProtobuf messageProtobuf = MessageUtils.createThreadMessage(uidUtils.getCacheSerialUid(), updateThread, - MessageTypeEnum.fromValue(threadRequest.getStatus().name()), + String content = threadRequest.getStatus().equals(ThreadStatusEnum.AUTO_CLOSED.name()) ? I18Consts.I18N_AUTO_CLOSED + : I18Consts.I18N_AGENT_CLOSED; + MessageProtobuf messageProtobuf = MessageUtils.createThreadMessage(uidUtils.getCacheSerialUid(), updateThread, + MessageTypeEnum.fromValue(threadRequest.getStatus()), content); MessageUtils.notifyUser(messageProtobuf); // @@ -335,15 +335,14 @@ public class ThreadService extends BaseService findByTopicNotClosed(String topic, String status) { - return threadRepository.findFirstByTopicAndStatusNotContainingAndDeleted(topic, "CLOSED", false); - } - + // @Cacheable(value = "thread", key = "#topic", unless = "#result == null") + // public Optional findByTopicNotClosed(String topic, String status) { + // return threadRepository.findFirstByTopicAndStatusNotContainingAndDeleted(topic, "CLOSED", false); + // } // 找到某个访客当前对应某技能组未关闭会话 - @Cacheable(value = "thread", key = "#workgroupUid + '-' + #visitorUid", unless = "#result == null") - public Optional findByWgTopicNotClosed(String topic) { - // String likeTopic = TopicUtils.TOPIC_ORG_WORKGROUP_PREFIX + workgroupUid + "/%/" + visitorUid; + // @Cacheable(value = "thread", key = "#workgroupUid + '-' + #visitorUid", unless = "#result == null") + @Cacheable(value = "thread", key = "#topic", unless = "#result == null") + public Optional findByTopicNotClosed(String topic) { List statuses = Arrays .asList(new String[] { ThreadStatusEnum.AGENT_CLOSED.name(), ThreadStatusEnum.AUTO_CLOSED.name() }); return threadRepository.findFirstTopicAndStatusesNotInAndDeleted(topic, statuses, false); @@ -358,33 +357,13 @@ public class ThreadService extends BaseService findStatusOpen() { - List types = Arrays.asList(new String[] { ThreadTypeEnum.AGENT.name(), ThreadTypeEnum.WORKGROUP.name(), ThreadTypeEnum.ROBOT.name() }); + List types = Arrays.asList(new String[] { ThreadTypeEnum.AGENT.name(), ThreadTypeEnum.WORKGROUP.name(), + ThreadTypeEnum.ROBOT.name() }); List statuses = Arrays .asList(new String[] { ThreadStatusEnum.AUTO_CLOSED.name(), ThreadStatusEnum.AGENT_CLOSED.name() }); return threadRepository.findByTypesInAndStatusesNotInAndDeleted(types, statuses, false); } - public Boolean isClosed(Thread thread) { - return ThreadStatusEnum.AGENT_CLOSED.name().equals(thread.getStatus()) - || ThreadStatusEnum.AUTO_CLOSED.name().equals(thread.getStatus()); - } - - // public Thread reenter(Thread thread) { - // if (thread.getType().equals(ThreadTypeEnum.AGENT) - // || thread.getType().equals(ThreadTypeEnum.WORKGROUP)) { - // thread.setUnreadCount(1); - // } - // thread.setStatus(ThreadStatusEnum.REENTER); - // return save(thread); - // } - - - - // public Thread agentClose(Thread thread) { - // thread.setStatus(ThreadStatusEnum.AGENT_CLOSED); - // return save(thread); - // } - @Caching(put = { @CachePut(value = "thread", key = "#thread.uid"), @CachePut(value = "thread", key = "#thread.topic") @@ -394,7 +373,6 @@ public class ThreadService extends BaseService 0) { - return; - } - - } - @Override public Page queryByUser(ThreadRequest request) { // TODO Auto-generated method stub diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadStatusEnum.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadStatusEnum.java index 0395527748..1bc31b2bc2 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadStatusEnum.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadStatusEnum.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-05-25 10:43:58 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-04 17:52:52 + * @LastEditTime: 2024-09-18 17:36:41 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -15,10 +15,10 @@ package com.bytedesk.core.thread; public enum ThreadStatusEnum { + START, // 开始会话 QUEUING, // 排队中 - NORMAL, // 正常 CONTINUE, // 会话进行中,访客关闭会话页面之后,重新进入 - REOPEN, // 会话关闭之后,重新进入 + RESTART, // 会话关闭之后,重新进入 OFFLINE, // 客服不在线 RATED, // rated, prevent repeated rate AUTO_CLOSED, // 自动关闭 @@ -29,6 +29,7 @@ public enum ThreadStatusEnum { MONITORED, // 会话监控 TRANSFERED, // 会话转接 INVITED, // 会话邀请 + SOLVED, // 问题已解决 ; // 根据字符串查找对应的枚举常量 diff --git a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadUpdateEvent.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadUpdateEvent.java index f2418de896..cb45444840 100644 --- a/modules/core/src/main/java/com/bytedesk/core/thread/ThreadUpdateEvent.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadUpdateEvent.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-23 08:51:27 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-05-23 09:54:54 + * @LastEditTime: 2024-09-20 10:27:36 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -29,5 +29,4 @@ public class ThreadUpdateEvent extends ApplicationEvent { super(source); this.thread = thread; } - } diff --git a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogRequest.java b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadUpdateStatusEvent.java similarity index 64% rename from modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogRequest.java rename to modules/core/src/main/java/com/bytedesk/core/thread/ThreadUpdateStatusEvent.java index 314950d563..95c00d26a7 100644 --- a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogRequest.java +++ b/modules/core/src/main/java/com/bytedesk/core/thread/ThreadUpdateStatusEvent.java @@ -1,8 +1,8 @@ /* * @Author: jackning 270580156@qq.com - * @Date: 2024-04-18 10:48:52 + * @Date: 2024-04-23 08:51:27 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-23 10:09:21 + * @LastEditTime: 2024-09-20 10:28:38 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -12,22 +12,24 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.thread_log; +package com.bytedesk.core.thread; -import com.bytedesk.core.base.BaseRequest; +import org.springframework.context.ApplicationEvent; -import lombok.Builder; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; @Data -@Builder -@Accessors(chain = true) @EqualsAndHashCode(callSuper = false) -public class ThreadLogRequest extends BaseRequest { - +public class ThreadUpdateStatusEvent extends ApplicationEvent { - // organization oid - // private String orgUid; + private Thread thread; + + private String status; + + public ThreadUpdateStatusEvent(Object source, Thread thread, String status) { + super(source); + this.thread = thread; + this.status = status; + } } diff --git a/modules/core/src/main/java/com/bytedesk/core/topic/Topic.java b/modules/core/src/main/java/com/bytedesk/core/topic/Topic.java index 4a32acfe2a..451665e1ac 100644 --- a/modules/core/src/main/java/com/bytedesk/core/topic/Topic.java +++ b/modules/core/src/main/java/com/bytedesk/core/topic/Topic.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-13 16:03:44 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 12:51:48 + * @LastEditTime: 2024-09-20 09:30:14 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -45,14 +45,11 @@ public class Topic extends BaseEntityNoOrg { private static final long serialVersionUID = 1L; - // @Column(nullable = false) - // private String topic; /** 为防止后添加的记录,clientIds缺失,所以用数组代替,这样每个用户在topic中只有一条记录,cliendIds可共用 */ @Builder.Default @Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT) @Convert(converter = StringSetConverter.class) private Set topics = new HashSet<>(); - // private String topic; // 管理员监控的topic @Builder.Default @@ -62,6 +59,7 @@ public class Topic extends BaseEntityNoOrg { // 每个用户仅存在一条记录 // user, no need map, just uid + // 用户uid或者robotUid @NotBlank @Column(unique = true, nullable = false) private String userUid; diff --git a/modules/core/src/main/java/com/bytedesk/core/topic/TopicRequest.java b/modules/core/src/main/java/com/bytedesk/core/topic/TopicRequest.java index 259bc9934d..79c6528113 100644 --- a/modules/core/src/main/java/com/bytedesk/core/topic/TopicRequest.java +++ b/modules/core/src/main/java/com/bytedesk/core/topic/TopicRequest.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-13 16:15:11 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-05-04 10:37:19 + * @LastEditTime: 2024-09-20 09:29:45 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -35,8 +35,6 @@ import lombok.experimental.Accessors; @AllArgsConstructor public class TopicRequest extends BaseRequest { - // private String uid; - private String topic; @NotBlank @@ -55,7 +53,4 @@ public class TopicRequest extends BaseRequest { */ @Builder.Default private List clientIds = new ArrayList<>(); - - /** 描述 */ - // private String description; } diff --git a/modules/core/src/main/java/com/bytedesk/core/topic/TopicResponse.java b/modules/core/src/main/java/com/bytedesk/core/topic/TopicResponse.java index a00d3e2928..86ea03ee80 100644 --- a/modules/core/src/main/java/com/bytedesk/core/topic/TopicResponse.java +++ b/modules/core/src/main/java/com/bytedesk/core/topic/TopicResponse.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-13 16:15:22 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 12:52:48 + * @LastEditTime: 2024-09-20 09:30:00 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -36,9 +36,7 @@ import lombok.experimental.Accessors; @NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class TopicResponse extends BaseResponse { - - // private String uid; - + @Builder.Default private Set topics = new HashSet<>(); diff --git a/modules/core/src/main/java/com/bytedesk/core/topic/TopicUtils.java b/modules/core/src/main/java/com/bytedesk/core/topic/TopicUtils.java index c88fc301e3..cd456b71a9 100644 --- a/modules/core/src/main/java/com/bytedesk/core/topic/TopicUtils.java +++ b/modules/core/src/main/java/com/bytedesk/core/topic/TopicUtils.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-26 21:51:31 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-06 23:07:16 + * @LastEditTime: 2024-09-20 11:09:57 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -155,8 +155,6 @@ public class TopicUtils { ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - public static Boolean isOrgRobotTopic(String topic) { return topic.startsWith(TOPIC_ORG_ROBOT_PREFIX); } diff --git a/modules/core/src/main/java/com/bytedesk/core/uid/UidUtils.java b/modules/core/src/main/java/com/bytedesk/core/uid/UidUtils.java index 701a132c3e..6c7dbdb4d8 100644 --- a/modules/core/src/main/java/com/bytedesk/core/uid/UidUtils.java +++ b/modules/core/src/main/java/com/bytedesk/core/uid/UidUtils.java @@ -81,4 +81,8 @@ public class UidUtils { return String.valueOf(uid); } + public String getUid() { + return getDefaultSerialUid(); + } + } diff --git a/modules/core/src/main/java/com/bytedesk/core/utils/DateUtils.java b/modules/core/src/main/java/com/bytedesk/core/utils/DateUtils.java index 2959413e15..5232bae3b4 100644 --- a/modules/core/src/main/java/com/bytedesk/core/utils/DateUtils.java +++ b/modules/core/src/main/java/com/bytedesk/core/utils/DateUtils.java @@ -21,11 +21,11 @@ public class DateUtils { private static final String datetimeUidFormat = "yyyyMMddHHmmss"; - private static final String dtFormat = "yyyy-MM-dd"; + private static final String dateFormat = "yyyy-MM-dd"; - private static final String dtFormatSlash = "yyyy/MM/dd"; + private static final String dateFormatSlash = "yyyy/MM/dd"; - private static final String dtFormatSlashNoZero = "yyyy/M/d"; + private static final String dateFormatSlashNoZero = "yyyy/M/d"; private static final String timeFormat = "HH:mm:ss"; @@ -55,7 +55,7 @@ public class DateUtils { } public static String formatDateNow() { - SimpleDateFormat dateFormater = new SimpleDateFormat(dtFormat); + SimpleDateFormat dateFormater = new SimpleDateFormat(dateFormat); return dateFormater.format(new Date()); } @@ -78,27 +78,27 @@ public class DateUtils { } public static String formatDateSlashNow() { - SimpleDateFormat dateFormater = new SimpleDateFormat(dtFormatSlash); + SimpleDateFormat dateFormater = new SimpleDateFormat(dateFormatSlash); return dateFormater.format(new Date()); } public static String formatDateSlashNowNoZero() { - SimpleDateFormat dateFormater = new SimpleDateFormat(dtFormatSlashNoZero); + SimpleDateFormat dateFormater = new SimpleDateFormat(dateFormatSlashNoZero); return dateFormater.format(new Date()); } public static String formatDateToString(Date date) { - SimpleDateFormat formatter = new SimpleDateFormat(dtFormat); - return formatter.format(date); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); + return simpleDateFormat.format(date); } public static Date formatStringToDate(String date) { if (!StringUtils.hasText(date)) { return null; } - SimpleDateFormat dateFormat = new SimpleDateFormat(dtFormat); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat); try { - return dateFormat.parse(date); + return simpleDateFormat.parse(date); } catch (ParseException e) { e.printStackTrace(); } @@ -126,7 +126,7 @@ public class DateUtils { fromFormat = new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH); } // - SimpleDateFormat cnFormat = new SimpleDateFormat(dtFormat); + SimpleDateFormat cnFormat = new SimpleDateFormat(dateFormat); Date parse = null; try { parse = fromFormat.parse(enDate); diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/auto_reply/AutoReplySettings.java b/modules/kbase/src/main/java/com/bytedesk/kbase/auto_reply/AutoReplySettings.java index bd372c1ec1..1c2167add6 100644 --- a/modules/kbase/src/main/java/com/bytedesk/kbase/auto_reply/AutoReplySettings.java +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/auto_reply/AutoReplySettings.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-07-17 23:34:04 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-19 16:15:01 + * @LastEditTime: 2024-09-19 17:12:59 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -41,8 +41,6 @@ public class AutoReplySettings implements Serializable { // 自动回复类型 @Builder.Default - // @Enumerated(EnumType.STRING) - // private AutoReplyTypeEnum autoReplyType = AutoReplyTypeEnum.FIXED; private String autoReplyType = AutoReplyTypeEnum.FIXED.name(); // 固定回复类型所需要字段 @@ -51,8 +49,6 @@ public class AutoReplySettings implements Serializable { // 自动回复内容类型 @Builder.Default - // @Enumerated(EnumType.STRING) - // private MessageTypeEnum autoReplyContentType = MessageTypeEnum.TEXT; private String autoReplyContentType = MessageTypeEnum.TEXT.name(); // 自动回复内容 diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/knowledge_base/KnowledgebaseEventListener.java b/modules/kbase/src/main/java/com/bytedesk/kbase/knowledge_base/KnowledgebaseEventListener.java index e0d21cebee..6fccee8913 100644 --- a/modules/kbase/src/main/java/com/bytedesk/kbase/knowledge_base/KnowledgebaseEventListener.java +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/knowledge_base/KnowledgebaseEventListener.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-08-27 13:53:22 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 17:11:09 + * @LastEditTime: 2024-09-20 14:55:49 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -138,9 +138,6 @@ public class KnowledgebaseEventListener { kownledgebaseRequestTaboo.setType(KnowledgebaseTypeEnum.TABOO.name()); kownledgebaseRequestTaboo.setOrgUid(orgUid); knowledgebaseService.create(kownledgebaseRequestTaboo); - // - // - } @EventListener @@ -178,7 +175,7 @@ public class KnowledgebaseEventListener { return; } String query = messageProtobuf.getContent(); - log.info("kb processMessage {}", query); + // log.info("kb processMessage {}", query); // ThreadProtobuf thread = messageProtobuf.getThread(); if (thread == null) { diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/knowledge_base/KnowledgebaseService.java b/modules/kbase/src/main/java/com/bytedesk/kbase/knowledge_base/KnowledgebaseService.java index da636ee468..ca4d38cce0 100644 --- a/modules/kbase/src/main/java/com/bytedesk/kbase/knowledge_base/KnowledgebaseService.java +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/knowledge_base/KnowledgebaseService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-03-22 22:59:18 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-27 22:04:31 + * @LastEditTime: 2024-09-20 14:56:31 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -168,6 +168,7 @@ public class KnowledgebaseService extends BaseService download(@PathVariable String filename) throws UnsupportedEncodingException { + public ResponseEntity download( + @PathVariable(name = "yyyy") String year, + @PathVariable(name = "MM") String month, + @PathVariable(name = "dd") String day, + @PathVariable String filename) throws UnsupportedEncodingException { + log.info("year {}, month {}, day {}, filename: {}", year, month, day, filename); Resource fileResource = uploadService.loadAsResource(filename); - if (fileResource == null) { return ResponseEntity.notFound().build(); } - // 对文件名进行URL编码,以确保中文字符能够正确传输 String encodedFilename = URLEncoder.encode(fileResource.getFilename(), "UTF-8").replace("+", "%20"); - // 设置HTTP响应头,包含经过编码的文件名 HttpHeaders headers = new HttpHeaders(); headers.setContentDispositionFormData("attachment", encodedFilename); @@ -71,16 +76,21 @@ public class UploadFilePreview { /** * 浏览器预览文件,或放到 标签中在线展示 - * http://127.0.0.1:9003/file/20240319162820_img-service2.png + * http://127.0.0.1:9003/file/2024/09/16/20240916144702_身份证-背面.jpg * * @param filename * @return * @throws IOException */ - @GetMapping("/{filename:.+}") + @GetMapping("/{yyyy}/{MM}/{dd}/{filename:.+}") @ResponseBody - public void preview(@PathVariable String filename, HttpServletResponse response) throws IOException { - + public void preview( + @PathVariable(name = "yyyy") String year, + @PathVariable(name = "MM") String month, + @PathVariable(name = "dd") String day, + @PathVariable String filename, + HttpServletResponse response) throws IOException { + log.info("year {}, month {}, day {}, filename: {}", year, month, day, filename); Resource fileResource = uploadService.loadAsResource(filename); // 文件预览 @@ -102,4 +112,57 @@ public class UploadFilePreview { fileInputStream.close(); } + /////////////// 旧版本 + + // http://127.0.0.1:9003/file/download/20240319162820_img-service2.png + @Deprecated + @GetMapping("/download/{filename:.+}") + @ResponseBody + public ResponseEntity downloadOld(@PathVariable String filename) throws UnsupportedEncodingException { + Resource fileResource = uploadService.loadAsResource(filename); + + if (fileResource == null) { + return ResponseEntity.notFound().build(); + } + + // 对文件名进行URL编码,以确保中文字符能够正确传输 + String encodedFilename = URLEncoder.encode(fileResource.getFilename(), "UTF-8").replace("+", "%20"); + + // 设置HTTP响应头,包含经过编码的文件名 + HttpHeaders headers = new HttpHeaders(); + headers.setContentDispositionFormData("attachment", encodedFilename); + + return ResponseEntity.ok().headers(headers).body(fileResource); + } + + // http://127.0.0.1:9003/file/20240319162820_img-service2.png + @Deprecated + @GetMapping("/{filename:.+}") + @ResponseBody + public void previewOld( + @PathVariable String filename, + HttpServletResponse response) throws IOException { + log.info("filename: {}", filename); + + Resource fileResource = uploadService.loadAsResourceOld(filename); + + // 文件预览 + File file = fileResource.getFile(); + FileInputStream fileInputStream = new FileInputStream(file); + // 清空response + response.reset(); + // 2、设置文件下载方式 + response.setCharacterEncoding("utf-8"); + // response.setContentType("application/pdf"); + OutputStream outputStream = response.getOutputStream(); + int count = 0; + byte[] buffer = new byte[1024 * 1024]; + while ((count = fileInputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, count); + } + outputStream.flush(); + outputStream.close(); + fileInputStream.close(); + } + } diff --git a/modules/kbase/src/main/java/com/bytedesk/kbase/upload/UploadService.java b/modules/kbase/src/main/java/com/bytedesk/kbase/upload/UploadService.java index 2318eeb6cc..2e27b86c35 100755 --- a/modules/kbase/src/main/java/com/bytedesk/kbase/upload/UploadService.java +++ b/modules/kbase/src/main/java/com/bytedesk/kbase/upload/UploadService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-03-15 11:35:53 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-31 16:03:26 + * @LastEditTime: 2024-09-16 15:28:23 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -19,10 +19,12 @@ import java.io.InputStream; import java.net.MalformedURLException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; +// import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.Optional; import java.util.stream.Stream; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import org.modelmapper.ModelMapper; import org.springframework.core.io.Resource; @@ -42,8 +44,10 @@ import com.bytedesk.core.uid.UidUtils; import com.bytedesk.kbase.upload.storage.UploadStorageException; import com.bytedesk.kbase.upload.storage.UploadStorageFileNotFoundException; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; // https://spring.io/guides/gs/uploading-files +@Slf4j @Service @AllArgsConstructor public class UploadService extends BaseService { @@ -86,30 +90,62 @@ public class UploadService extends BaseService loadAll() { try { return Files.walk(this.uploadDir, 1) @@ -120,13 +156,51 @@ public class UploadService extends BaseService { return ResponseEntity.ok(JsonResult.success(agent)); } + @ActionAnnotation(title = "agent", action = "updateStatus", description = "update agent status") + @PostMapping("/update/status") + public ResponseEntity updateStatus(@RequestBody AgentRequest request) { + + AgentResponse agent = agentService.updateStatus(request); + // + return ResponseEntity.ok(JsonResult.success(agent)); + } + @ActionAnnotation(title = "agent", action = "updateAutoReply", description = "update agent autoreply") @PostMapping("/update/autoreply") public ResponseEntity updateAutoReply(@RequestBody AgentRequest request) { diff --git a/modules/service/src/main/java/com/bytedesk/service/agent/AgentCreateEvent.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentCreateEvent.java index fed7ec3da8..80cb9e3b1d 100644 --- a/modules/service/src/main/java/com/bytedesk/service/agent/AgentCreateEvent.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentCreateEvent.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-08-27 15:39:38 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-27 16:00:43 + * @LastEditTime: 2024-09-18 12:57:19 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -30,5 +30,4 @@ public class AgentCreateEvent extends ApplicationEvent { super(source); this.agent = agent; } - } diff --git a/modules/service/src/main/java/com/bytedesk/service/agent/AgentEntityListener.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentEntityListener.java index 0c53fba2fd..cf3eaf2799 100644 --- a/modules/service/src/main/java/com/bytedesk/service/agent/AgentEntityListener.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentEntityListener.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-15 09:30:30 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-27 15:42:58 + * @LastEditTime: 2024-09-18 15:07:51 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,6 +14,8 @@ */ package com.bytedesk.service.agent; +// import java.util.Objects; + import org.springframework.stereotype.Component; import org.springframework.util.SerializationUtils; @@ -24,20 +26,23 @@ import com.bytedesk.core.topic.TopicUtils; import com.bytedesk.core.utils.ApplicationContextHolder; import jakarta.persistence.PostPersist; +import jakarta.persistence.PostUpdate; +// import jakarta.persistence.PreUpdate; +// import jakarta.persistence.Transient; import lombok.extern.slf4j.Slf4j; @Slf4j @Component public class AgentEntityListener { - // 无法注入bean,否则报错 - // private final TopicService topicService; - - // @PrePersist - // public void prePersist(Agent agent) { - // log.info("prePersist {}", agent.getUid()); - // } - + /** + * @Transient 注解用于确保oldAgent字段不会被JPA持久化到数据库中。同时,使用transient关键字来防止该字段在序列化时被包含。 + * 缺点是它增加了内存消耗,因为你需要为每个更新的实体保存一个旧状态的副本。如果你的应用处理大量的更新操作,并且实体对象很大, + * 这可能会成为一个问题。在这种情况下,你可能需要考虑使用更高效的审计解决方案 + */ + // @Transient + // private transient Agent oldAgent; + @PostPersist public void postPersist(Agent agent) { // topicService.create(agent.getUid(), agent.getUser().getUid()); @@ -49,21 +54,34 @@ public class AgentEntityListener { BytedeskEventPublisher bytedeskEventPublisher = ApplicationContextHolder.getBean(BytedeskEventPublisher.class); // 默认订阅客服主题 bytedeskEventPublisher.publishTopicCreateEvent(TopicUtils.getOrgAgentTopic(cloneAgent.getUid()), user.getUid()); - // - bytedeskEventPublisher.publishGenericApplicationEvent(new GenericApplicationEvent(this, new AgentCreateEvent(this, cloneAgent))); + // + bytedeskEventPublisher.publishGenericApplicationEvent( + new GenericApplicationEvent(this, new AgentCreateEvent(this, cloneAgent))); } // @PreUpdate // public void preUpdate(Agent agent) { - // log.info("preUpdate {}", agent.getUid()); + // log.info("preUpdate {}", agent.getUid()); + // oldAgent = SerializationUtils.clone(agent); // 保存更新前的状态 // } - // @PostUpdate - // public void postUpdate(Agent agent) { - // log.info("postUpdate {}", agent.getUid()); - // // TODO: 切换agent对应的user时,需要更新topic:从原user缓存中删除,然后添加到新user缓存中 - // // topicService.update(agent.getUid(), agent.getUser().getUid()); - // } + @PostUpdate + public void postUpdate(Agent agent) { + log.info("postUpdate {}", agent.getUid()); + // if (oldAgent != null) { + // // 现在你可以比较oldAgent和agent来识别哪些字段发生了变化 + // // status before from OFFLINE to OFFLINE + // log.info("status before from {} to {}", oldAgent.getStatus(), agent.getStatus()); + // // 例如: + // if (!Objects.equals(oldAgent.getStatus(), agent.getStatus())) { + // // someField字段发生了变化 + // log.info("status changed from {} to {}", oldAgent.getStatus(), agent.getStatus()); + // } + // // ...处理其他字段的变化 + // } + // TODO: 切换agent对应的user时,需要更新topic:从原user缓存中删除,然后添加到新user缓存中 + // topicService.update(agent.getUid(), agent.getUser().getUid()); + } // @PreRemove // public void preRemove(Agent agent) { diff --git a/modules/service/src/main/java/com/bytedesk/service/agent/AgentEventListener.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentEventListener.java index 6fa8275560..6c0636cd31 100644 --- a/modules/service/src/main/java/com/bytedesk/service/agent/AgentEventListener.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentEventListener.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-12 17:58:50 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-27 16:28:02 + * @LastEditTime: 2024-09-20 14:33:27 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -33,8 +33,8 @@ import com.bytedesk.core.rbac.organization.OrganizationCreateEvent; import com.bytedesk.core.rbac.user.User; import com.bytedesk.core.socket.mqtt.MqttConnectedEvent; import com.bytedesk.core.socket.mqtt.MqttDisconnectedEvent; -import com.bytedesk.core.thread.ThreadCreateEvent; -import com.bytedesk.core.thread.ThreadUpdateEvent; +// import com.bytedesk.core.thread.ThreadCreateEvent; +// import com.bytedesk.core.thread.ThreadUpdateEvent; import com.bytedesk.core.uid.UidUtils; import com.bytedesk.kbase.knowledge_base.KnowledgebaseRequest; import com.bytedesk.kbase.knowledge_base.KnowledgebaseService; @@ -106,6 +106,7 @@ public class AgentEventListener { } + // 因为依赖关系的原因,无法将该方法放到kbase事件监听中,所以放在此处 @EventListener public void onAgentCreateEvent(GenericApplicationEvent event) { AgentCreateEvent agentCreateEvent = (AgentCreateEvent) event.getObject(); @@ -122,7 +123,6 @@ public class AgentEventListener { kownledgebaseRequeqstQuickReply.setOrgUid(agent.getOrgUid()); kownledgebaseRequeqstQuickReply.setAgentUid(agent.getUid()); knowledgebaseService.create(kownledgebaseRequeqstQuickReply); - // } @@ -132,24 +132,24 @@ public class AgentEventListener { // log.info("agent quartz five second event: " + event); } - // TODO: 新创建会话,更新客服当前接待数量 - @EventListener - public void onThreadCreateEvent(ThreadCreateEvent event) { - // log.info("agent onThreadCreateEvent: " + event); - } + // // TODO: 新创建会话,更新客服当前接待数量 + // @EventListener + // public void onThreadCreateEvent(ThreadCreateEvent event) { + // // log.info("agent onThreadCreateEvent: " + event); + // } - // TODO: 会话关闭,更新客服当前接待数量 - @EventListener - public void onThreadUpdateEvent(ThreadUpdateEvent event) { - // log.info("agent onThreadUpdateEvent: " + event); - } + // // TODO: 会话关闭,更新客服当前接待数量 + // @EventListener + // public void onThreadUpdateEvent(ThreadUpdateEvent event) { + // // log.info("agent onThreadUpdateEvent: " + event); + // } @EventListener public void onMqttConnectedEvent(MqttConnectedEvent event) { String clientId = event.getClientId(); // 用户clientId格式: uid/client/deviceUid final String uid = clientId.split("/")[0]; - log.info("agent onMqttConnectedEvent uid {}, clientId {}", uid, clientId); + // log.info("agent onMqttConnectedEvent uid {}, clientId {}", uid, clientId); // agentService.updateConnect(uid, true); } @@ -159,7 +159,7 @@ public class AgentEventListener { String clientId = event.getClientId(); // 用户clientId格式: uid/client/deviceUid final String uid = clientId.split("/")[0]; - log.info("agent onMqttDisconnectedEvent uid {}, clientId {}", uid, clientId); + // log.info("agent onMqttDisconnectedEvent uid {}, clientId {}", uid, clientId); // agentService.updateConnect(uid, false); } diff --git a/modules/service/src/main/java/com/bytedesk/service/agent/AgentRequest.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentRequest.java index 9509e1de47..d74e0e7574 100644 --- a/modules/service/src/main/java/com/bytedesk/service/agent/AgentRequest.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentRequest.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-02-06 10:16:30 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-04 15:47:52 + * @LastEditTime: 2024-09-18 13:59:36 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -55,7 +55,8 @@ public class AgentRequest extends BaseRequest { private String description = I18Consts.I18N_AGENT_DESCRIPTION; @Builder.Default - private AgentStatusEnum status = AgentStatusEnum.AVAILABLE; + // private AgentStatusEnum status = AgentStatusEnum.AVAILABLE; + private String status = AgentStatusEnum.AVAILABLE.name(); @Builder.Default private Integer maxThreadCount = 10; diff --git a/modules/service/src/main/java/com/bytedesk/service/agent/AgentResponse.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentResponse.java index 59b9cd3f0d..acd1b54758 100644 --- a/modules/service/src/main/java/com/bytedesk/service/agent/AgentResponse.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentResponse.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-02-06 10:17:01 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-05 11:00:08 + * @LastEditTime: 2024-09-18 14:03:43 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -15,7 +15,6 @@ package com.bytedesk.service.agent; import com.bytedesk.core.base.BaseResponse; -// import com.bytedesk.core.rbac.user.UserProtobuf; import com.bytedesk.kbase.auto_reply.AutoReplySettings; import com.bytedesk.service.settings.ServiceSettingsResponse; import com.bytedesk.team.member.MemberResponseSimple; @@ -48,8 +47,8 @@ public class AgentResponse extends BaseResponse { private String description; // private String acceptStatus; - private AgentStatusEnum status; - // private String status; + // private AgentStatusEnum status; + private String status; // private Boolean enabled; private Boolean connected; diff --git a/modules/service/src/main/java/com/bytedesk/service/agent/AgentService.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentService.java index 1cae9b1fce..f48dca8919 100644 --- a/modules/service/src/main/java/com/bytedesk/service/agent/AgentService.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-29 16:19:51 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-08-05 10:59:52 + * @LastEditTime: 2024-09-18 15:13:28 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -44,8 +44,10 @@ import com.bytedesk.ai.robot.RobotService; import com.bytedesk.core.action.ActionRequest; import com.bytedesk.core.action.ActionService; import com.bytedesk.core.action.ActionTypeEnum; +import com.bytedesk.core.config.BytedeskEventPublisher; import com.bytedesk.core.config.BytedeskProperties; import com.bytedesk.core.constant.I18Consts; +import com.bytedesk.core.event.GenericApplicationEvent; import com.bytedesk.core.rbac.auth.AuthService; import com.bytedesk.core.rbac.user.User; import com.bytedesk.core.constant.BdConstants; @@ -88,7 +90,8 @@ public class AgentService { private final BytedeskProperties bytedeskProperties; - // private final BytedeskEventPublisher bytedeskEventPublisher; + private final BytedeskEventPublisher bytedeskEventPublisher; + private final ActionService actionService; public Page queryByOrg(AgentRequest agentRequest) { @@ -382,6 +385,29 @@ public class AgentService { return ConvertServiceUtils.convertToAgentResponse(updatedAgent); } + public AgentResponse updateStatus(AgentRequest request) { + Optional agentOptional = findByUid(request.getUid()); + if (!agentOptional.isPresent()) { + // 如果找不到对应的Agent,则返回null + throw new RuntimeException("null agent found with uid: " + request.getUid()); + } + // + Agent agent = agentOptional.get(); + agent.setStatus(request.getStatus()); // 更新接待状态 + // 保存Agent并检查返回值 + Agent updatedAgent = save(agent); + if (updatedAgent == null) { + // 根据业务逻辑决定如何处理保存失败的情况 + // 例如,可以抛出一个异常或返回一个错误响应 + throw new RuntimeException("Failed to save agent."); + } + bytedeskEventPublisher.publishGenericApplicationEvent( + new GenericApplicationEvent(this, new AgentUpdateEvent(this, updatedAgent, + AgentUpdateTypeEnum.STATUS.name()))); + + return ConvertServiceUtils.convertToAgentResponse(updatedAgent); + } + @Transactional public AgentResponse updateAutoReply(AgentRequest request) { // User user = authService.getCurrentUser(); diff --git a/modules/service/src/main/java/com/bytedesk/service/agent/AgentStatusEnum.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentStatusEnum.java index 67f68eb004..437738eba6 100644 --- a/modules/service/src/main/java/com/bytedesk/service/agent/AgentStatusEnum.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentStatusEnum.java @@ -16,6 +16,7 @@ package com.bytedesk.service.agent; public enum AgentStatusEnum { AVAILABLE, // 接待状态 + REST, // 休息状态 BUSY, // 忙碌状态 OFFLINE, // 离线状态 DISABLED; // 禁用状态 diff --git a/modules/service/src/main/java/com/bytedesk/service/route/StrategyHandler.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentUpdateEvent.java similarity index 54% rename from modules/service/src/main/java/com/bytedesk/service/route/StrategyHandler.java rename to modules/service/src/main/java/com/bytedesk/service/agent/AgentUpdateEvent.java index 476ebdffc1..12d1553787 100644 --- a/modules/service/src/main/java/com/bytedesk/service/route/StrategyHandler.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentUpdateEvent.java @@ -1,8 +1,8 @@ /* * @Author: jackning 270580156@qq.com - * @Date: 2024-04-09 15:01:26 + * @Date: 2024-08-27 15:39:38 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-04-09 15:01:28 + * @LastEditTime: 2024-09-18 15:11:07 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -12,24 +12,25 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.route; +package com.bytedesk.service.agent; -/** - * https://mp.weixin.qq.com/s/Wib0Ly45te00HMUnIG-tbg - * - * @author - * @date - */ -public interface StrategyHandler { +import org.springframework.context.ApplicationEvent; +import lombok.Data; +import lombok.EqualsAndHashCode; - @SuppressWarnings("rawtypes") - StrategyHandler DEFAULT = t -> null; +@Data +@EqualsAndHashCode(callSuper = false) +public class AgentUpdateEvent extends ApplicationEvent { - /** - * apply strategy - * - * @param param - * @return - */ - R apply(T param); + private final static long serialVersionUID = 1L; + + private Agent agent; + + private String updateType; + + public AgentUpdateEvent(Object source, Agent agent, String updateType) { + super(source); + this.agent = agent; + this.updateType = updateType; + } } diff --git a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintRepository.java b/modules/service/src/main/java/com/bytedesk/service/agent/AgentUpdateTypeEnum.java similarity index 82% rename from modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintRepository.java rename to modules/service/src/main/java/com/bytedesk/service/agent/AgentUpdateTypeEnum.java index ae2013bb9f..37b759a841 100644 --- a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintRepository.java +++ b/modules/service/src/main/java/com/bytedesk/service/agent/AgentUpdateTypeEnum.java @@ -1,8 +1,8 @@ /* * @Author: jackning 270580156@qq.com - * @Date: 2024-09-03 09:51:46 + * @Date: 2024-09-18 15:13:03 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-03 09:51:49 + * @LastEditTime: 2024-09-18 15:13:05 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -12,8 +12,8 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.complaint; +package com.bytedesk.service.agent; -public class ComplaintRepository { - +public enum AgentUpdateTypeEnum { + STATUS } diff --git a/modules/service/src/main/java/com/bytedesk/service/complaint/Complaint.java b/modules/service/src/main/java/com/bytedesk/service/complaint/Complaint.java deleted file mode 100644 index e1953fc760..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/complaint/Complaint.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-09-03 09:50:20 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-03 09:50:23 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.complaint; - -// 投诉,如:对在线人工客服进行投诉 -public class Complaint { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintController.java b/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintController.java deleted file mode 100644 index 3d1c548a30..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintController.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-09-03 09:50:58 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-03 09:51:01 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.complaint; - -public class ComplaintController { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintRequest.java b/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintRequest.java deleted file mode 100644 index 42fb9a0340..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-09-03 09:51:19 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-03 09:51:22 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.complaint; - -public class ComplaintRequest { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintResponse.java b/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintResponse.java deleted file mode 100644 index 3d74d04154..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-09-03 09:51:28 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-03 09:51:31 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.complaint; - -public class ComplaintResponse { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintService.java b/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintService.java deleted file mode 100644 index a270abe856..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintService.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-09-03 09:51:08 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-03 09:51:11 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.complaint; - -public class ComplaintService { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintSpecification.java b/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintSpecification.java deleted file mode 100644 index 07a24c86c7..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/complaint/ComplaintSpecification.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-09-03 09:52:03 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-03 09:52:06 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.complaint; - -public class ComplaintSpecification { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/queue/Queue.java b/modules/service/src/main/java/com/bytedesk/service/queue/Queue.java index f4336be561..b98e3e2b3d 100644 --- a/modules/service/src/main/java/com/bytedesk/service/queue/Queue.java +++ b/modules/service/src/main/java/com/bytedesk/service/queue/Queue.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-02-22 16:12:53 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-23 11:12:41 + * @LastEditTime: 2024-09-19 20:35:37 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,17 +14,17 @@ */ package com.bytedesk.service.queue; +import java.util.ArrayList; +import java.util.List; import com.bytedesk.core.base.BaseEntity; -import com.bytedesk.service.agent.Agent; -import com.bytedesk.service.visitor.Visitor; -import com.bytedesk.service.workgroup.Workgroup; - +import com.bytedesk.core.constant.TypeConsts; +import com.bytedesk.core.utils.StringListConverter; import jakarta.persistence.Column; +import jakarta.persistence.Convert; import jakarta.persistence.Entity; import jakarta.persistence.EntityListeners; -import jakarta.persistence.FetchType; -import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -43,35 +43,17 @@ import lombok.experimental.Accessors; @AllArgsConstructor @NoArgsConstructor @EntityListeners({ QueueListener.class }) -@Table(name = "service_queue") +@Table(name = "service_queue", uniqueConstraints = { + @UniqueConstraint(columnNames = { "queueUid", "orgUid" }) +}) public class Queue extends BaseEntity { private static final long serialVersionUID = 1L; - @Column(name = "queue_type") - private String type; + private String queueUid; - private Integer orderInQueue; - - private QueueStatusEnum status; - - // 排队访客 - @ManyToOne(fetch = FetchType.LAZY) - private Visitor visitor; - - // 1. 被排队一对一客服 - // 2. 或技能组中待分配客服,通过type区分 - @ManyToOne(fetch = FetchType.LAZY) - private Agent agent; - - // 1. 被排队技能组 - // 2. 或待分配客服所属技能组 通过type区分 - @ManyToOne(fetch = FetchType.LAZY) - private Workgroup workgroup; - - /** belong to org */ - // @JsonIgnore - // @ManyToOne(fetch = FetchType.LAZY) - // private Organization organization; - // private String orgUid; + @Builder.Default + @Column(columnDefinition = TypeConsts.COLUMN_TYPE_TEXT) + @Convert(converter = StringListConverter.class) + private List threadTopics = new ArrayList<>(); } diff --git a/modules/service/src/main/java/com/bytedesk/service/queue/QueueRepository.java b/modules/service/src/main/java/com/bytedesk/service/queue/QueueRepository.java index b44083074d..d3270de1d6 100644 --- a/modules/service/src/main/java/com/bytedesk/service/queue/QueueRepository.java +++ b/modules/service/src/main/java/com/bytedesk/service/queue/QueueRepository.java @@ -22,4 +22,6 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; public interface QueueRepository extends JpaRepository, JpaSpecificationExecutor { Optional findByUid(String uid); + + Optional findByQueueUid(String queueUid); } diff --git a/modules/service/src/main/java/com/bytedesk/service/queue/QueueRequest.java b/modules/service/src/main/java/com/bytedesk/service/queue/QueueRequest.java index 54f9e927b7..a35afadb07 100644 --- a/modules/service/src/main/java/com/bytedesk/service/queue/QueueRequest.java +++ b/modules/service/src/main/java/com/bytedesk/service/queue/QueueRequest.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-03-22 23:04:03 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-05-29 23:20:24 + * @LastEditTime: 2024-09-19 17:44:10 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,6 +14,9 @@ */ package com.bytedesk.service.queue; +import java.util.LinkedList; +import java.util.List; + import com.bytedesk.core.base.BaseRequest; import lombok.AllArgsConstructor; @@ -29,9 +32,14 @@ import lombok.NoArgsConstructor; @NoArgsConstructor public class QueueRequest extends BaseRequest { - private Integer orderInQueue; + private String queueUid; - private QueueStatusEnum status; + @Builder.Default + private List threadTopics = new LinkedList<>(); - private String orgUid; + // private Integer orderInQueue; + + // private QueueStatusEnum status; + + // private String orgUid; } diff --git a/modules/service/src/main/java/com/bytedesk/service/queue/QueueResponse.java b/modules/service/src/main/java/com/bytedesk/service/queue/QueueResponse.java index 43c33cf913..a15fea5d19 100644 --- a/modules/service/src/main/java/com/bytedesk/service/queue/QueueResponse.java +++ b/modules/service/src/main/java/com/bytedesk/service/queue/QueueResponse.java @@ -14,6 +14,9 @@ */ package com.bytedesk.service.queue; +import java.util.LinkedList; +import java.util.List; + import com.bytedesk.core.base.BaseResponse; import lombok.AllArgsConstructor; @@ -29,7 +32,12 @@ import lombok.NoArgsConstructor; @NoArgsConstructor public class QueueResponse extends BaseResponse { - private Integer orderInQueue; + private String queueUid; - private QueueStatusEnum status; + @Builder.Default + private List threadTopics = new LinkedList<>(); + + // private Integer orderInQueue; + + // private QueueStatusEnum status; } diff --git a/modules/service/src/main/java/com/bytedesk/service/queue/QueueService.java b/modules/service/src/main/java/com/bytedesk/service/queue/QueueService.java index d6001adf7f..dee90e7538 100644 --- a/modules/service/src/main/java/com/bytedesk/service/queue/QueueService.java +++ b/modules/service/src/main/java/com/bytedesk/service/queue/QueueService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-03-22 23:03:55 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-17 14:53:31 + * @LastEditTime: 2024-09-19 20:34:45 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -17,6 +17,7 @@ package com.bytedesk.service.queue; import java.util.Optional; import org.modelmapper.ModelMapper; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -24,39 +25,42 @@ import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.ObjectOptimisticLockingFailureException; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; +// import org.springframework.transaction.annotation.Transactional; import com.bytedesk.core.base.BaseService; +import com.bytedesk.core.uid.UidUtils; import lombok.AllArgsConstructor; @Service @AllArgsConstructor public class QueueService extends BaseService { - + private final QueueRepository queueRepository; private final ModelMapper modelMapper; - @Transactional - public void enqueue(QueueRequest request) { - // QueueMessage message = new QueueMessage(); - // message.setContent(content); - // // 设置其他属性 - // queueMessageRepository.save(message); - } + private final UidUtils uidUtils; - @Transactional - public Optional dequeue() { - // 假设我们按ID升序处理消息,因此这里使用findFirst() - // return queueMessageRepository.findFirst(); + // @Transactional + // public void enqueue(QueueRequest request) { + // // QueueMessage message = new QueueMessage(); + // // message.setContent(content); + // // // 设置其他属性 + // // queueMessageRepository.save(message); + // } + + // @Transactional + // public Optional dequeue() { + // // 假设我们按ID升序处理消息,因此这里使用findFirst() + // // return queueMessageRepository.findFirst(); + + // return null; + // } - return null; - } - @Override public Page queryByOrg(QueueRequest request) { - + Pageable pageable = PageRequest.of(request.getPageNumber(), request.getPageSize(), Sort.Direction.DESC, "updatedAt"); Specification specification = QueueSpecification.search(request); @@ -71,21 +75,43 @@ public class QueueService extends BaseService findByUid(String uid) { return queueRepository.findByUid(uid); } + @Cacheable(value = "queue", key = "#queueUid", unless = "#result==null") + public Optional findByQueueUid(String queueUid) { + return queueRepository.findByQueueUid(queueUid); + } + @Override public QueueResponse create(QueueRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'create'"); + Queue entity = modelMapper.map(request, Queue.class); + entity.setUid(uidUtils.getUid()); + // + Queue savedQueue = save(entity); + if (savedQueue == null) { + throw new RuntimeException("Create queue failed"); + } + return convertToResponse(savedQueue); } @Override public QueueResponse update(QueueRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'update'"); + + Optional queueOptional = findByQueueUid(request.getQueueUid()); + if (queueOptional.isPresent()) { + Queue entity = queueOptional.get(); + // modelMapper.map(request, entity); + entity.setQueueUid(request.getQueueUid()); + entity.setThreadTopics(request.getThreadTopics()); + // + return convertToResponse(save(entity)); + } + // + return create(request); } @Override @@ -123,5 +149,4 @@ public class QueueService extends BaseService - * +---------+ - * | Root | ----------- 第 1 层策略入口 - * +---------+ - * / \ ------------- 根据入参 P1 进行策略分发 - * / \ - * +------+ +------+ - * | A | | B | ------- 第 2 层不同策略的实现 - * +------+ +------+ - * / \ / \ --------- 根据入参 P2 进行策略分发 - * / \ / \ - * +---+ +---+ +---+ +---+ - * |A1 | |A2 | |B1 | |B2 | ----- 第 3 层不同策略的实现 - * +---+ +---+ +---+ +---+ - * - * - * @author - * @date - * @see StrategyHandler - */ -@Component -public abstract class AbstractStrategyRouter { - - /** - * 策略映射器,根据指定的入参路由到对应的策略处理者。 - * - * @param 策略的入参类型 - * @param 策略的返回值类型 - */ - public interface StrategyMapper { - /** - * 根据入参获取到对应的策略处理者。可通过 if-else 实现,也可通过 Map 实现。 - * - * @param param 入参 - * @return 策略处理者 - */ - StrategyHandler get(T param); - } - - private StrategyMapper strategyMapper; - - /** - * 类初始化时注册分发策略 Mapper - */ - @PostConstruct - private void abstractInit() { - strategyMapper = registerStrategyMapper(); - Objects.requireNonNull(strategyMapper, "strategyMapper cannot be null"); - } - - @Getter - @Setter - @SuppressWarnings("unchecked") - private StrategyHandler defaultStrategyHandler = StrategyHandler.DEFAULT; - - /** - * 执行策略,框架会自动根据策略分发至下游的 Handler 进行处理 - * - * @param param 入参 - * @return 下游执行者给出的返回值 - */ - public R applyStrategy(T param) { - final StrategyHandler strategyHandler = strategyMapper.get(param); - if (strategyHandler != null) { - return strategyHandler.apply(param); - } - - return defaultStrategyHandler.apply(param); - } - - /** - * 抽象方法,需要子类实现策略的分发逻辑 - * - * @return 分发逻辑 Mapper 对象 - */ - protected abstract StrategyMapper registerStrategyMapper(); - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/route/IRouteService.java b/modules/service/src/main/java/com/bytedesk/service/route/IRouteService.java index eebdfba996..100aa6340c 100644 --- a/modules/service/src/main/java/com/bytedesk/service/route/IRouteService.java +++ b/modules/service/src/main/java/com/bytedesk/service/route/IRouteService.java @@ -1,8 +1,8 @@ /* * @Author: jackning 270580156@qq.com - * @Date: 2024-04-08 13:03:35 + * @Date: 2024-09-19 18:56:41 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-04-09 13:08:44 + * @LastEditTime: 2024-09-20 10:11:15 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,6 +14,20 @@ */ package com.bytedesk.service.route; +import com.bytedesk.ai.robot.Robot; +import com.bytedesk.core.message.MessageProtobuf; +import com.bytedesk.service.agent.Agent; +import com.bytedesk.core.thread.Thread; +import com.bytedesk.service.visitor.VisitorRequest; +import com.bytedesk.service.workgroup.Workgroup; + +import jakarta.annotation.Nonnull; + public interface IRouteService { - + + public MessageProtobuf routeRobot(VisitorRequest request, @Nonnull Thread thread, @Nonnull Robot robot); + + public MessageProtobuf routeAgent(VisitorRequest request, @Nonnull Thread thread, @Nonnull Agent agent); + + public MessageProtobuf routeWorkgroup(VisitorRequest request, @Nonnull Thread thread, @Nonnull Workgroup workgroup); } diff --git a/modules/service/src/main/java/com/bytedesk/service/route/Route.java b/modules/service/src/main/java/com/bytedesk/service/route/Route.java deleted file mode 100644 index 7f4126f1f2..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/route/Route.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-04-08 13:03:09 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-04-08 13:03:12 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.route; - -public class Route { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/route/RouteFactory.java b/modules/service/src/main/java/com/bytedesk/service/route/RouteFactory.java deleted file mode 100644 index 35d6051abb..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/route/RouteFactory.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-04-09 14:05:05 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-04-09 14:05:08 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.route; - -public class RouteFactory { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/route/RouteRepository.java b/modules/service/src/main/java/com/bytedesk/service/route/RouteRepository.java deleted file mode 100644 index 3d85fc3586..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/route/RouteRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-04-08 13:04:04 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-04-08 13:04:06 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.route; - -public interface RouteRepository { - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/route/RouteServiceImpl.java b/modules/service/src/main/java/com/bytedesk/service/route/RouteServiceImpl.java new file mode 100644 index 0000000000..1981e3e41d --- /dev/null +++ b/modules/service/src/main/java/com/bytedesk/service/route/RouteServiceImpl.java @@ -0,0 +1,166 @@ +/* + * @Author: jackning 270580156@qq.com + * @Date: 2024-09-19 18:56:55 + * @LastEditors: jackning 270580156@qq.com + * @LastEditTime: 2024-09-20 10:16:18 + * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk + * Please be aware of the BSL license restrictions before installing Bytedesk IM – + * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. + * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 + * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE + * contact: 270580156@qq.com + * 联系:270580156@qq.com + * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. + */ +package com.bytedesk.service.route; + +import org.springframework.stereotype.Service; + +import com.alibaba.fastjson2.JSON; +import com.bytedesk.ai.robot.Robot; +import com.bytedesk.ai.utils.ConvertAiUtils; +import com.bytedesk.core.message.MessageProtobuf; +import com.bytedesk.core.message.MessageUtils; +import com.bytedesk.core.rbac.user.UserProtobuf; +import com.bytedesk.service.agent.Agent; +import com.bytedesk.service.strategy.ThreadMessageUtil; +import com.bytedesk.service.utils.ConvertServiceUtils; +import com.bytedesk.core.thread.Thread; +import com.bytedesk.core.thread.ThreadService; +import com.bytedesk.core.thread.ThreadStatusEnum; +import com.bytedesk.service.visitor.VisitorRequest; +import com.bytedesk.service.workgroup.Workgroup; + +import jakarta.annotation.Nonnull; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +@AllArgsConstructor +public class RouteServiceImpl implements IRouteService { + + private final ThreadService threadService; + + @Override + public MessageProtobuf routeRobot(VisitorRequest request, @Nonnull Thread thread, @Nonnull Robot robot) { + if (robot != null) { + thread.setContent(robot.getServiceSettings().getWelcomeTip()); + // 使用agent的serviceSettings配置 + UserProtobuf agenProtobuf = ConvertAiUtils.convertToUserProtobuf(robot); + thread.setAgent(JSON.toJSONString(agenProtobuf)); + // 客服在线 且 接待状态 + thread.setUnreadCount(0); + thread.setStatus(ThreadStatusEnum.START.name()); + threadService.save(thread); + // log.info("getAgentProcessingMessage agent: {}", thread.getAgent()); + // + MessageProtobuf messageProtobuf = ThreadMessageUtil.getThreadMessage(agenProtobuf, thread, false); + // 广播消息,由消息通道统一处理 + // messageService.notifyUser(messageProtobuf); + return messageProtobuf; + } else { + throw new RuntimeException( + "please set robot in the admin panel first"); + } + } + + @Override + public MessageProtobuf routeAgent(VisitorRequest visitorRequest, @Nonnull Thread thread, @Nonnull Agent agent) { + log.info("RouteServiceImpl routeAgent: " + agent.getUid()); + // 排队在vip模块中处理 + boolean isReenter = true; + if (thread.getStatus() == ThreadStatusEnum.START.name()) { + // 访客首次进入会话 + isReenter = false; + } + // + if (!agent.isConnected() || !agent.isAvailable()) { + // 离线状态永远显示离线提示语,不显示“继续会话” + isReenter = false; + // 客服离线 或 非接待状态 + thread.setContent(agent.getServiceSettings().getLeavemsgTip()); + thread.setStatus(ThreadStatusEnum.OFFLINE.name()); + } else { + // 客服在线 且 接待状态 + thread.setUnreadCount(1); + thread.setContent(agent.getServiceSettings().getWelcomeTip()); + // if thread is closed, reopen it and then create a new message + if (visitorRequest.getForceAgent()) { + isReenter = false; + thread.setStatus(ThreadStatusEnum.START.name()); + } else if (thread.isClosed()) { + // 访客会话关闭之后,重新进入 + isReenter = false; + thread.setStatus(ThreadStatusEnum.RESTART.name()); + } else { + thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.START.name()); + } + } + threadService.save(thread); + // + UserProtobuf user = ConvertServiceUtils.convertToUserProtobuf(agent); + // + MessageProtobuf messageProtobuf = ThreadMessageUtil.getThreadMessage(user, thread, isReenter); + // 广播消息,由消息通道统一处理 + MessageUtils.notifyUser(messageProtobuf); + + return messageProtobuf; + } + + @Override + public MessageProtobuf routeWorkgroup(VisitorRequest visitorRequest, Thread thread, Workgroup workgroup) { + log.info("RouteServiceImpl routeWorkgroup: " + workgroup.getUid()); + // 排队在vip模块中处理 + // 高级路由逻辑在vip模块中处理 + if (workgroup.getAgents().isEmpty()) { + throw new RuntimeException("No agents found in workgroup with uid " + workgroup.getUid()); + } + // 下面人工接待 + Agent agent = workgroup.nextAgent(); + if (agent == null) { + throw new RuntimeException("No available agent found in workgroup with uid " + workgroup.getUid()); + } + // + boolean isReenter = true; + if (thread.getStatus() == ThreadStatusEnum.START.name()) { + // 访客首次进入会话 + isReenter = false; + } + if (!agent.isConnected() || !agent.isAvailable()) { + // 离线状态永远显示离线提示语,不显示“继续会话” + // 客服离线 或 非接待状态 + thread.setContent(workgroup.getServiceSettings().getLeavemsgTip()); + thread.setStatus(ThreadStatusEnum.OFFLINE.name()); + } else { + // 客服在线 且 接待状态 + thread.setUnreadCount(1); + thread.setContent(workgroup.getServiceSettings().getWelcomeTip()); + if (visitorRequest.getForceAgent()) { + isReenter = false; + thread.setStatus(ThreadStatusEnum.START.name()); + } else if (thread.isClosed()) { + // 访客会话关闭之后,重新进入 + isReenter = false; + thread.setStatus(ThreadStatusEnum.RESTART.name()); + } else { + thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.START.name()); + } + } + // + thread.setOwner(agent.getMember().getUser()); + UserProtobuf agentProtobuf = ConvertServiceUtils.convertToUserProtobuf(agent); + thread.setAgent(JSON.toJSONString(agentProtobuf)); + // return getWorkgroupMessage(visitorRequest, thread, agent, workgroup); + threadService.save(thread); + // + UserProtobuf user = ConvertServiceUtils.convertToUserProtobuf(agent); + // + MessageProtobuf messageProtobuf = ThreadMessageUtil.getThreadMessage(user, thread, isReenter); + // 广播消息,由消息通道统一处理 + MessageUtils.notifyUser(messageProtobuf); + + return messageProtobuf; + } + +} diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/AgentCsThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/AgentCsThreadCreationStrategy.java similarity index 52% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/AgentCsThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/AgentCsThreadCreationStrategy.java index 8feac4c316..4326912c8e 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/AgentCsThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/AgentCsThreadCreationStrategy.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-07-15 15:58:11 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-11 08:50:53 + * @LastEditTime: 2024-09-23 17:47:31 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import java.util.Optional; @@ -20,7 +20,6 @@ import org.springframework.stereotype.Component; import com.alibaba.fastjson2.JSON; import com.bytedesk.ai.robot.Robot; -import com.bytedesk.ai.utils.ConvertAiUtils; import com.bytedesk.core.enums.ClientEnum; import com.bytedesk.core.message.MessageProtobuf; import com.bytedesk.core.message.MessageUtils; @@ -32,11 +31,10 @@ import com.bytedesk.core.topic.TopicUtils; import com.bytedesk.core.uid.UidUtils; import com.bytedesk.service.agent.Agent; import com.bytedesk.service.agent.AgentService; +import com.bytedesk.service.route.IRouteService; import com.bytedesk.service.utils.ConvertServiceUtils; import com.bytedesk.service.visitor.VisitorRequest; -import jakarta.annotation.Nonnull; - import com.bytedesk.core.thread.Thread; import lombok.AllArgsConstructor; @@ -52,12 +50,10 @@ public class AgentCsThreadCreationStrategy implements CsThreadCreationStrategy { private final ThreadService threadService; - // private final MessageService messageService; + private final IRouteService routeService; private final UidUtils uidUtils; - // private final ModelMapper modelMapper; - @Override public MessageProtobuf createCsThread(VisitorRequest visitorRequest) { return createAgentCsThread(visitorRequest); @@ -87,137 +83,26 @@ public class AgentCsThreadCreationStrategy implements CsThreadCreationStrategy { Boolean transferToRobot = agent.getServiceSettings().shouldTransferToRobot(isOffline); if (transferToRobot) { // 转机器人 - // TODO: 将robot设置为agent Robot robot = agent.getServiceSettings().getRobot(); - if (robot != null) { - // visitorRequest.setSid(robot.getUid()); - // return robotCsThreadCreationStrategy.createCsThread(visitorRequest); - // - thread.setContent(robot.getServiceSettings().getWelcomeTip()); - // 使用agent的serviceSettings配置 - // thread.setExtra(JSON.toJSONString(ConvertAiUtils.convertToServiceSettingsResponseVisitor( - // robot.getServiceSettings()))); - UserProtobuf agenProtobuf = ConvertAiUtils.convertToUserProtobuf(robot); - // thread.setAgentProtobuf(agenProtobuf); - thread.setAgent(JSON.toJSONString(agenProtobuf)); - // - return getRobotMessage(visitorRequest, thread, agenProtobuf); - // - } else { - throw new RuntimeException("please set robot for " + agent.getNickname() + " in the admin panel first"); - } + // + return routeService.routeRobot(visitorRequest, thread, robot); } } - // TODO: 判断是否达到最大接待人数,如果达到则进入排队 - - return getAgentMessage(visitorRequest, thread, agent); + // + return routeService.routeAgent(visitorRequest, thread, agent); } // 是否存在未关闭的会话 private Thread getProcessingThread(String topic) { // TODO: 到visitor thread表中拉取 // 拉取未关闭会话 - Optional threadOptional = threadService.findByTopicNotClosed(topic, "CLOSED"); + Optional threadOptional = threadService.findByTopicNotClosed(topic); if (threadOptional.isPresent()) { return threadOptional.get(); } return null; } - private Thread getAgentThread(VisitorRequest visitorRequest, Agent agent, String topic) { - // TODO: 到visitor thread表中拉取 - Thread thread = Thread.builder().build(); - Optional threadOptional = threadService.findByTopic(topic); - if (threadOptional.isPresent()) { - // return threadOptional.get(); - thread = threadOptional.get(); - } else { - // - thread = Thread.builder().build(); - thread.setUid(uidUtils.getCacheSerialUid()); - thread.setTopic(topic); - thread.setType(ThreadTypeEnum.AGENT.name()); - thread.setClient(ClientEnum.fromValue(visitorRequest.getClient()).name()); - // - UserProtobuf visitor = ConvertServiceUtils.convertToUserProtobuf(visitorRequest); - thread.setUser(JSON.toJSONString(visitor)); - // - thread.setOwner(agent.getMember().getUser()); - thread.setOrgUid(agent.getOrgUid()); - } - // 考虑到配置可能变化,更新配置 - thread.setExtra(JSON - .toJSONString( - ConvertServiceUtils.convertToServiceSettingsResponseVisitor(agent.getServiceSettings()))); - // 考虑到客服信息发生变化,更新客服信息 - UserProtobuf agentProtobuf = ConvertServiceUtils.convertToUserProtobuf(agent); - thread.setAgent(JSON.toJSONString(agentProtobuf)); - // - return thread; - } - - private MessageProtobuf getAgentMessage(VisitorRequest visitorRequest, @Nonnull Thread thread, @Nonnull Agent agent) { - // - boolean isReenter = true; - if (thread.getStatus() == ThreadStatusEnum.NORMAL.name()) { - // 访客首次进入会话 - isReenter = false; - } - // - if (!agent.isConnected() || !agent.isAvailable()) { - // 离线状态永远显示离线提示语,不显示“继续会话” - isReenter = false; - // 客服离线 或 非接待状态 - thread.setContent(agent.getServiceSettings().getLeavemsgTip()); - thread.setStatus(ThreadStatusEnum.OFFLINE.name()); - } else { - // 客服在线 且 接待状态 - thread.setUnreadCount(1); - thread.setContent(agent.getServiceSettings().getWelcomeTip()); - // thread.setExtra(JSON.toJSONString( - // ConvertServiceUtils.convertToServiceSettingsResponseVisitor(agent.getServiceSettings()))); - // thread.setAgent(JSON.toJSONString(ConvertServiceUtils.convertToAgentResponseSimple(agent))); - // if thread is closed, reopen it and then create a new message - if (visitorRequest.getForceAgent()) { - isReenter = false; - thread.setStatus(ThreadStatusEnum.NORMAL.name()); - } else if (thread.isClosed()) { - // 访客会话关闭之后,重新进入 - isReenter = false; - thread.setStatus(ThreadStatusEnum.REOPEN.name()); - } else { - thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.NORMAL.name()); - } - } - threadService.save(thread); - // - // UserProtobuf user = modelMapper.map(agent, UserProtobuf.class); - UserProtobuf user = ConvertServiceUtils.convertToUserProtobuf(agent); - // - MessageProtobuf messageProtobuf = ThreadMessageUtil.getThreadMessage(user, thread, isReenter); - // 广播消息,由消息通道统一处理 - MessageUtils.notifyUser(messageProtobuf); - - return messageProtobuf; - } - - private MessageProtobuf getRobotMessage(VisitorRequest visitorRequest, Thread thread, UserProtobuf user) { - if (thread == null) { - throw new RuntimeException("Thread cannot be null"); - } - // 客服在线 且 接待状态 - thread.setUnreadCount(0); - thread.setStatus(ThreadStatusEnum.NORMAL.name()); - threadService.save(thread); - // log.info("getAgentProcessingMessage agent: {}", thread.getAgent()); - // - MessageProtobuf messageProtobuf = ThreadMessageUtil.getThreadMessage(user, thread, false); - // 广播消息,由消息通道统一处理 - // messageService.notifyUser(messageProtobuf); - - return messageProtobuf; - } - private MessageProtobuf getAgentProcessingMessage(VisitorRequest visitorRequest, Thread thread) { if (thread == null) { throw new RuntimeException("Thread cannot be null"); @@ -236,24 +121,35 @@ public class AgentCsThreadCreationStrategy implements CsThreadCreationStrategy { return messageProtobuf; } - // private MessageProtobuf notifyAgent(MessageProtobuf message) { - // // - // MessageProtobuf messageProtobuf = getAgentMessage(visitorRequest, thread, - // agent); - // // 广播消息,由消息通道统一处理 - // messageService.notifyUser(messageProtobuf); - // // - // // if (agent.isConnected() && agent.isAvailable()) { - // // // notify agent - 通知客服 - // // notifyAgent(messageProtobuf); - // // } else { - // // // 离线状态 - // // } - // // else if (agent.isAvailable()) { - // // // TODO: 断开连接,但是接待状态,判断是否有客服移动端token,有则发送通知 - // // } - - // return messageProtobuf; - // } + private Thread getAgentThread(VisitorRequest visitorRequest, Agent agent, String topic) { + // TODO: 到visitor thread表中拉取 + Thread thread = Thread.builder().build(); + Optional threadOptional = threadService.findByTopic(topic); + if (threadOptional.isPresent()) { + thread = threadOptional.get(); + } else { + // thread.setUid(uidUtils.getCacheSerialUid()); + thread.setTopic(topic); + thread.setType(ThreadTypeEnum.AGENT.name()); + thread.setClient(ClientEnum.fromValue(visitorRequest.getClient()).name()); + // + UserProtobuf visitor = ConvertServiceUtils.convertToUserProtobuf(visitorRequest); + thread.setUser(JSON.toJSONString(visitor)); + // + thread.setOwner(agent.getMember().getUser()); + thread.setOrgUid(agent.getOrgUid()); + } + // 强制生成新会话uid,代表新会话。便于会话跟踪计数统计 + thread.setUid(uidUtils.getUid()); + // 考虑到配置可能变化,更新配置 + thread.setExtra(JSON + .toJSONString( + ConvertServiceUtils.convertToServiceSettingsResponseVisitor(agent.getServiceSettings()))); + // 考虑到客服信息发生变化,更新客服信息 + UserProtobuf agentProtobuf = ConvertServiceUtils.convertToUserProtobuf(agent); + thread.setAgent(JSON.toJSONString(agentProtobuf)); + // + return thread; + } } \ No newline at end of file diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/AgentasistantThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/AgentasistantThreadCreationStrategy.java similarity index 95% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/AgentasistantThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/AgentasistantThreadCreationStrategy.java index f9e30a0754..4d51d629be 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/AgentasistantThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/AgentasistantThreadCreationStrategy.java @@ -1,4 +1,4 @@ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import java.util.Optional; @@ -93,7 +93,7 @@ public class AgentasistantThreadCreationStrategy implements CsThreadCreationStra thread.setContent(robot.getServiceSettings().getWelcomeTip()); // boolean isReenter = true; - if (thread.getStatus() == ThreadStatusEnum.NORMAL.name()) { + if (thread.getStatus() == ThreadStatusEnum.START.name()) { isReenter = false; } // 更新机器人配置+大模型相关信息 @@ -104,9 +104,9 @@ public class AgentasistantThreadCreationStrategy implements CsThreadCreationStra // if thread is closed, reopen it and then create a new message if (thread.isClosed()) { isReenter = false; - thread.setStatus(ThreadStatusEnum.REOPEN.name()); + thread.setStatus(ThreadStatusEnum.RESTART.name()); } else { - thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.NORMAL.name()); + thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.START.name()); } threadService.save(thread); // diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/CsThreadCreationContext.java b/modules/service/src/main/java/com/bytedesk/service/strategy/CsThreadCreationContext.java similarity index 98% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/CsThreadCreationContext.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/CsThreadCreationContext.java index 168b428328..c84b51678b 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/CsThreadCreationContext.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/CsThreadCreationContext.java @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import java.util.EnumMap; import java.util.List; diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/CsThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/CsThreadCreationStrategy.java similarity index 95% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/CsThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/CsThreadCreationStrategy.java index c18a9fa743..2eebb4dcae 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/CsThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/CsThreadCreationStrategy.java @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import com.bytedesk.core.message.MessageProtobuf; import com.bytedesk.service.visitor.VisitorRequest; diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/FeedbackCsThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/FeedbackCsThreadCreationStrategy.java similarity index 96% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/FeedbackCsThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/FeedbackCsThreadCreationStrategy.java index 7c9f5d05eb..78e454e852 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/FeedbackCsThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/FeedbackCsThreadCreationStrategy.java @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import org.springframework.stereotype.Component; diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/KbCsThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/KbCsThreadCreationStrategy.java similarity index 95% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/KbCsThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/KbCsThreadCreationStrategy.java index 1dd3e9bebe..72f1bf1d8a 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/KbCsThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/KbCsThreadCreationStrategy.java @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import java.util.Optional; @@ -101,7 +101,7 @@ public class KbCsThreadCreationStrategy implements CsThreadCreationStrategy { thread.setContent(kb.getName()); // boolean isReenter = true; - if (thread.getStatus() == ThreadStatusEnum.NORMAL.name()) { + if (thread.getStatus() == ThreadStatusEnum.START.name()) { isReenter = false; } // 更新机器人配置+大模型相关信息 @@ -112,9 +112,9 @@ public class KbCsThreadCreationStrategy implements CsThreadCreationStrategy { // if thread is closed, reopen it and then create a new message if (thread.isClosed()) { isReenter = false; - thread.setStatus(ThreadStatusEnum.REOPEN.name()); + thread.setStatus(ThreadStatusEnum.RESTART.name()); } else { - thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.NORMAL.name()); + thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.START.name()); } threadService.save(thread); // diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/KbdocCsThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/KbdocCsThreadCreationStrategy.java similarity index 96% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/KbdocCsThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/KbdocCsThreadCreationStrategy.java index 11aa571987..ec5a17c084 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/KbdocCsThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/KbdocCsThreadCreationStrategy.java @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import java.util.Optional; @@ -101,7 +101,7 @@ public class KbdocCsThreadCreationStrategy implements CsThreadCreationStrategy { // thread.setContent(robot.getServiceSettings().getWelcomeTip()); // boolean isReenter = true; - if (thread.getStatus() == ThreadStatusEnum.NORMAL.name()) { + if (thread.getStatus() == ThreadStatusEnum.START.name()) { isReenter = false; } // 更新机器人配置+大模型相关信息 @@ -112,9 +112,9 @@ public class KbdocCsThreadCreationStrategy implements CsThreadCreationStrategy { // if thread is closed, reopen it and then create a new message if (thread.isClosed()) { isReenter = false; - thread.setStatus(ThreadStatusEnum.REOPEN.name()); + thread.setStatus(ThreadStatusEnum.RESTART.name()); } else { - thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.NORMAL.name()); + thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.START.name()); } threadService.save(thread); // diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/RobotCsThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/RobotCsThreadCreationStrategy.java similarity index 95% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/RobotCsThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/RobotCsThreadCreationStrategy.java index b8f3b91752..3cc2ed9b35 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/RobotCsThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/RobotCsThreadCreationStrategy.java @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import java.util.Optional; @@ -85,7 +85,7 @@ public class RobotCsThreadCreationStrategy implements CsThreadCreationStrategy { UserProtobuf visitor = ConvertServiceUtils.convertToUserProtobuf(visitorRequest); thread.setUser(JSON.toJSONString(visitor)); } - // + // thread.setExtra(JSON.toJSONString(ConvertAiUtils.convertToServiceSettingsResponseVisitor( robot.getServiceSettings()))); // @@ -96,19 +96,19 @@ public class RobotCsThreadCreationStrategy implements CsThreadCreationStrategy { } private MessageProtobuf getRobotMessage(VisitorRequest visitorRequest, Thread thread, Robot robot) { - // + // thread.setContent(robot.getServiceSettings().getWelcomeTip()); // boolean isReenter = true; - if (thread.getStatus() == ThreadStatusEnum.NORMAL.name()) { + if (thread.getStatus() == ThreadStatusEnum.START.name()) { isReenter = false; } // if thread is closed, reopen it and then create a new message if (thread.isClosed()) { isReenter = false; - thread.setStatus(ThreadStatusEnum.REOPEN.name()); + thread.setStatus(ThreadStatusEnum.RESTART.name()); } else { - thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.NORMAL.name()); + thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.START.name()); } threadService.save(thread); // diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/ThreadMessageUtil.java b/modules/service/src/main/java/com/bytedesk/service/strategy/ThreadMessageUtil.java similarity index 96% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/ThreadMessageUtil.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/ThreadMessageUtil.java index f9cbf975ee..50bb128ede 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/ThreadMessageUtil.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/ThreadMessageUtil.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-08-29 22:22:38 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 22:35:25 + * @LastEditTime: 2024-09-21 09:38:45 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import com.alibaba.fastjson2.JSON; import com.bytedesk.core.constant.I18Consts; @@ -49,7 +49,6 @@ public class ThreadMessageUtil { .user(JSON.toJSONString(user)) .build(); // message.setUid(uidUtils.getCacheSerialUid()); - // message.setUid(Utils.getUid()); message.setUid(UidUtils.getInstance().getDefaultSerialUid()); message.setOrgUid(thread.getOrgUid()); message.setCreatedAt(new Date()); diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/TicketCsThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/TicketCsThreadCreationStrategy.java similarity index 95% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/TicketCsThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/TicketCsThreadCreationStrategy.java index 9cdd518ee9..061af89a5c 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/TicketCsThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/TicketCsThreadCreationStrategy.java @@ -1,4 +1,4 @@ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import java.util.Optional; @@ -92,7 +92,7 @@ public class TicketCsThreadCreationStrategy implements CsThreadCreationStrategy thread.setContent(robot.getServiceSettings().getWelcomeTip()); // boolean isReenter = true; - if (thread.getStatus() == ThreadStatusEnum.NORMAL.name()) { + if (thread.getStatus() == ThreadStatusEnum.START.name()) { isReenter = false; } // 更新机器人配置+大模型相关信息 @@ -103,9 +103,9 @@ public class TicketCsThreadCreationStrategy implements CsThreadCreationStrategy // if thread is closed, reopen it and then create a new message if (thread.isClosed()) { isReenter = false; - thread.setStatus(ThreadStatusEnum.REOPEN.name()); + thread.setStatus(ThreadStatusEnum.RESTART.name()); } else { - thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.NORMAL.name()); + thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.START.name()); } threadService.save(thread); // diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/WorkgroupCsThreadCreationStrategy.java b/modules/service/src/main/java/com/bytedesk/service/strategy/WorkgroupCsThreadCreationStrategy.java similarity index 50% rename from modules/service/src/main/java/com/bytedesk/service/visitor/strategy/WorkgroupCsThreadCreationStrategy.java rename to modules/service/src/main/java/com/bytedesk/service/strategy/WorkgroupCsThreadCreationStrategy.java index 6767299da6..13407ab5db 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/strategy/WorkgroupCsThreadCreationStrategy.java +++ b/modules/service/src/main/java/com/bytedesk/service/strategy/WorkgroupCsThreadCreationStrategy.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-07-15 15:58:23 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-11 08:50:05 + * @LastEditTime: 2024-09-23 14:07:41 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -12,7 +12,7 @@ * 联系:270580156@qq.com * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. */ -package com.bytedesk.service.visitor.strategy; +package com.bytedesk.service.strategy; import java.util.Optional; @@ -20,7 +20,6 @@ import org.springframework.stereotype.Component; import com.alibaba.fastjson2.JSON; import com.bytedesk.ai.robot.Robot; -import com.bytedesk.ai.utils.ConvertAiUtils; import com.bytedesk.core.enums.ClientEnum; import com.bytedesk.core.message.MessageProtobuf; import com.bytedesk.core.message.MessageUtils; @@ -30,7 +29,7 @@ import com.bytedesk.core.thread.ThreadStatusEnum; import com.bytedesk.core.thread.ThreadTypeEnum; import com.bytedesk.core.topic.TopicUtils; import com.bytedesk.core.uid.UidUtils; -import com.bytedesk.service.agent.Agent; +import com.bytedesk.service.route.IRouteService; import com.bytedesk.service.utils.ConvertServiceUtils; import com.bytedesk.service.visitor.VisitorRequest; import com.bytedesk.service.workgroup.Workgroup; @@ -50,6 +49,8 @@ public class WorkgroupCsThreadCreationStrategy implements CsThreadCreationStrate private final ThreadService threadService; + private final IRouteService routeService; + private final UidUtils uidUtils; @Override @@ -80,47 +81,20 @@ public class WorkgroupCsThreadCreationStrategy implements CsThreadCreationStrate Boolean transferToRobot = workgroup.getServiceSettings().shouldTransferToRobot(isOffline); if (transferToRobot) { // 转机器人 - // TODO: 将robot设置为agent + // 将robot设置为agent Robot robot = workgroup.getServiceSettings().getRobot(); - if (robot != null) { - // - thread.setContent(robot.getServiceSettings().getWelcomeTip()); - // - UserProtobuf agenProtobuf = ConvertAiUtils.convertToUserProtobuf(robot); - thread.setAgent(JSON.toJSONString(agenProtobuf)); - // - return getRobotMessage(visitorRequest, thread, agenProtobuf); - } else { - throw new RuntimeException("route " + workgroupUid + " to a robot"); - } + + return routeService.routeRobot(visitorRequest, thread, robot); } } - // 下面人工接待 - // TODO: 所有客服都达到最大接待人数,则进入排队 - // TODO: 排队人数动态变化,随时通知访客端 - - if (workgroup.getAgents().isEmpty()) { - throw new RuntimeException("No agents found in workgroup with uid " + workgroupUid); - } - - // TODO: 首先完善各个agent的统计数据,比如接待量、等待时长等 - Agent agent = workgroup.nextAgent(); - if (agent == null) { - throw new RuntimeException("No available agent found in workgroup with uid " + workgroupUid); - } // - thread.setOwner(agent.getMember().getUser()); - UserProtobuf agentProtobuf = ConvertServiceUtils.convertToUserProtobuf(agent); - thread.setAgent(JSON.toJSONString(agentProtobuf)); - // - return getWorkgroupMessage(visitorRequest, thread, agent, workgroup); + return routeService.routeWorkgroup(visitorRequest, thread, workgroup); } // 是否存在未关闭的会话 private Thread getProcessingThread(String topic) { - // TODO: 到visitor thread表中拉取 // 拉取未关闭会话 - Optional threadOptional = threadService.findByWgTopicNotClosed(topic); + Optional threadOptional = threadService.findByTopicNotClosed(topic); if (threadOptional.isPresent()) { return threadOptional.get(); } @@ -130,87 +104,27 @@ public class WorkgroupCsThreadCreationStrategy implements CsThreadCreationStrate private Thread getWorkgroupThread(VisitorRequest visitorRequest, Workgroup workgroup, String topic) { // Thread thread = Thread.builder().build(); - // TODO: 到visitor thread表中拉取 Optional threadOptional = threadService.findByTopic(topic); if (threadOptional.isPresent()) { thread = threadOptional.get(); } else { - thread.setUid(uidUtils.getCacheSerialUid()); + // thread.setUid(uidUtils.getCacheSerialUid()); thread.setTopic(topic); thread.setType(ThreadTypeEnum.WORKGROUP.name()); thread.setClient(ClientEnum.fromValue(visitorRequest.getClient()).name()); thread.setOrgUid(workgroup.getOrgUid()); } + // 强制生成新会话uid,代表新会话。便于会话跟踪计数统计 + thread.setUid(uidUtils.getUid()); // UserProtobuf visitor = ConvertServiceUtils.convertToUserProtobuf(visitorRequest); thread.setUser(JSON.toJSONString(visitor)); - // thread.setExtra(JSON.toJSONString( ConvertServiceUtils.convertToServiceSettingsResponseVisitor(workgroup.getServiceSettings()))); // return thread; } - private MessageProtobuf getWorkgroupMessage(VisitorRequest visitorRequest, Thread thread, Agent agent, Workgroup workgroup) { - // - boolean isReenter = true; - if (thread.getStatus() == ThreadStatusEnum.NORMAL.name()) { - // 访客首次进入会话 - isReenter = false; - } - // - if (!agent.isConnected() || !agent.isAvailable()) { - // 离线状态永远显示离线提示语,不显示“继续会话” - isReenter = false; - // 客服离线 或 非接待状态 - thread.setContent(workgroup.getServiceSettings().getLeavemsgTip()); - thread.setStatus(ThreadStatusEnum.OFFLINE.name()); - } else { - // 客服在线 且 接待状态 - thread.setUnreadCount(1); - thread.setContent(workgroup.getServiceSettings().getWelcomeTip()); - // thread.setAgent(JSON.toJSONString(ConvertServiceUtils.convertToWorkgroupResponseSimple(workgroup))); - // if thread is closed, reopen it and then create a new message - if (visitorRequest.getForceAgent()) { - isReenter = false; - thread.setStatus(ThreadStatusEnum.NORMAL.name()); - } else if (thread.isClosed()) { - // 访客会话关闭之后,重新进入 - isReenter = false; - thread.setStatus(ThreadStatusEnum.REOPEN.name()); - } else { - thread.setStatus(isReenter ? ThreadStatusEnum.CONTINUE.name() : ThreadStatusEnum.NORMAL.name()); - } - } - threadService.save(thread); - // - // UserProtobuf user = modelMapper.map(agent, UserProtobuf.class); - UserProtobuf user = ConvertServiceUtils.convertToUserProtobuf(agent); - // - MessageProtobuf messageProtobuf = ThreadMessageUtil.getThreadMessage(user, thread, isReenter); - // 广播消息,由消息通道统一处理 - MessageUtils.notifyUser(messageProtobuf); - - return messageProtobuf; - } - - private MessageProtobuf getRobotMessage(VisitorRequest visitorRequest, Thread thread, UserProtobuf user) { - if (thread == null) { - throw new RuntimeException("Thread cannot be null"); - } - // 客服在线 且 接待状态 - thread.setUnreadCount(0); - thread.setStatus(ThreadStatusEnum.NORMAL.name()); - threadService.save(thread); - // log.info("getAgentProcessingMessage agent: {}", thread.getAgent()); - // - MessageProtobuf messageProtobuf = ThreadMessageUtil.getThreadMessage(user, thread, false); - // 广播消息,由消息通道统一处理 - // messageService.notifyUser(messageProtobuf); - - return messageProtobuf; - } - private MessageProtobuf getWorkgroupProcessingMessage(VisitorRequest visitorRequest, Thread thread) { if (thread == null) { throw new RuntimeException("Thread cannot be null"); @@ -230,22 +144,4 @@ public class WorkgroupCsThreadCreationStrategy implements CsThreadCreationStrate return messageProtobuf; } - // // 广播消息,由消息通道统一处理 - // messageService.notifyUser(messageProtobuf); - // - // if (agent.isConnected() && agent.isAvailable()) { - // log.info("agent is connected and available"); - // // notify agent - 通知客服 - // notifyAgent(messageProtobuf); - // } - // else if (agent.isAvailable()) { - // // TODO: 断开连接,但是接待状态,判断是否有客服移动端token,有则发送通知 - // log.info("agent is available"); - // cacheService.pushForPersist(JSON.toJSONString(messageProtobuf)); - // } else { - // cacheService.pushForPersist(JSON.toJSONString(messageProtobuf)); - // } - // - // return messageProtobuf; - } diff --git a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLog.java b/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLog.java deleted file mode 100644 index 136e76979f..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLog.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-04-09 16:34:13 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-06 16:41:59 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.thread_log; - -import org.hibernate.annotations.JdbcTypeCode; -import org.hibernate.type.SqlTypes; - -import com.bytedesk.core.base.BaseEntity; -import com.bytedesk.core.constant.BdConstants; -import com.bytedesk.core.constant.TypeConsts; -import com.bytedesk.core.enums.ClientEnum; -import com.bytedesk.core.rbac.user.User; -import com.bytedesk.core.thread.ThreadStatusEnum; -import com.bytedesk.core.thread.ThreadTypeEnum; -import com.fasterxml.jackson.annotation.JsonIgnore; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import jakarta.validation.constraints.NotBlank; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; - -/** - * 记录thread的创建、更新、删除等操作 - * thread主表对于一个访客和客服之间的对话仅存放一条,当存在访客多次请求会话的情况时,在主表中仅修改主表thread状态status, - * 在此表记录多次会话情况,便于统计,减少thread表数据量,提高查询效率。 - */ -@Entity -@Data -@Builder -@Accessors(chain = true) -@EqualsAndHashCode(callSuper = true) -@AllArgsConstructor -@NoArgsConstructor -@Table(name = "service_thread_log") -public class ThreadLog extends BaseEntity { - - private static final long serialVersionUID = 1L; - - /** - * @{TopicConsts} - */ - @NotBlank - private String topic; - - @Builder.Default - private String content = BdConstants.EMPTY_STRING; - - @Builder.Default - private Integer unreadCount = 0; - - /** - * @{ThreadTypeConsts} - */ - @Builder.Default - // @Enumerated(EnumType.STRING) - @Column(name = "thread_type", nullable = false) - // private String type = ThreadTypeConsts.WORKGROUP; - // private ThreadTypeEnum type = ThreadTypeEnum.WORKGROUP; - private String type = ThreadTypeEnum.WORKGROUP.name(); - - // closed/open - @Builder.Default - // @Enumerated(EnumType.STRING) - // private String status = StatusConsts.THREAD_STATUS_OPEN; - // private ThreadStatusEnum status = ThreadStatusEnum.NORMAL; - private String status = ThreadStatusEnum.NORMAL.name(); - - @Builder.Default - // @Enumerated(EnumType.STRING) - // private ClientEnum client; - private String client = ClientEnum.WEB.name(); - - @Builder.Default - @Column(columnDefinition = TypeConsts.COLUMN_TYPE_JSON) - // 用于兼容postgreSQL,否则会报错,[ERROR: column "extra" is of type json but expression is - // of type character varying - @JdbcTypeCode(SqlTypes.JSON) - private String extra = BdConstants.EMPTY_JSON_STRING; - - // h2 db 不能使用 user, 所以重定义为 _user - @Builder.Default - @Column(name = "thread_user", columnDefinition = TypeConsts.COLUMN_TYPE_JSON) - @JdbcTypeCode(SqlTypes.JSON) - private String user = BdConstants.EMPTY_JSON_STRING; - - /** belongs to user */ - @JsonIgnore - @ManyToOne(fetch = FetchType.LAZY) - private User owner; - - /** belong to org */ - // private String orgUid; - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogController.java b/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogController.java deleted file mode 100644 index 94bac1773c..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogController.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-04-18 10:48:52 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-04-18 10:48:54 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.thread_log; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.bytedesk.core.base.BaseController; - -import lombok.AllArgsConstructor; - -@RestController -@RequestMapping("/api/v1/thread_log") -@AllArgsConstructor -public class ThreadLogController extends BaseController { - - @Override - public ResponseEntity queryByOrg(ThreadLogRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'queryByOrg'"); - } - - @Override - public ResponseEntity query(ThreadLogRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'query'"); - } - - @Override - public ResponseEntity create(ThreadLogRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'create'"); - } - - @Override - public ResponseEntity update(ThreadLogRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'update'"); - } - - @Override - public ResponseEntity delete(ThreadLogRequest request) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'delete'"); - } - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogEventListener.java b/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogEventListener.java deleted file mode 100644 index dee9067521..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogEventListener.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-05-29 15:09:26 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-10 23:21:44 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.thread_log; - -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; - -import com.bytedesk.core.thread.ThreadCreateEvent; -import com.bytedesk.core.thread.ThreadUpdateEvent; -import com.bytedesk.core.quartz.event.QuartzOneMinEvent; -import com.bytedesk.core.thread.Thread; - -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -@Component -@AllArgsConstructor -public class ThreadLogEventListener { - - private ThreadLogService threadLogService; - - @EventListener - public void onThreadCreateEvent(ThreadCreateEvent event) { - Thread thread = event.getThread(); - // log.info("thread log ThreadCreateEvent: {}", thread.getUid()); - // - threadLogService.create(thread); - } - - @EventListener - public void onThreadUpdateEvent(ThreadUpdateEvent event) { - Thread thread = event.getThread(); - log.info("thread log onThreadUpdateEvent: {}", thread.getUid()); - // - // 访客之前会话已经关闭,重新请求会话,则重新创建一条threadlog - // if (thread.getStatus().equals(ThreadStatusEnum.REENTER)) { - // threadLogService.create(thread); - // } - // TODO: 更新threadlog - - } - - @EventListener - public void onQuartzOneMinEvent(QuartzOneMinEvent event) { - // log.info("threadlog quartz five second event: " + event); - // auto close thread - threadLogService.autoCloseThread(); - } - - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogRepository.java b/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogRepository.java deleted file mode 100644 index 24cc82bf15..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogRepository.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-04-18 10:48:16 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-29 13:32:34 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.thread_log; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -public interface ThreadLogRepository extends JpaRepository, JpaSpecificationExecutor { - - // Page findByOrgUid(String orgUid, Pageable pageable); - - Boolean existsByUid(String uid); -} diff --git a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogResponse.java b/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogResponse.java deleted file mode 100644 index cb6eac7962..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogResponse.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-04-18 10:49:12 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-29 13:40:47 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.thread_log; - -import java.util.Date; - -import com.bytedesk.core.base.BaseResponse; -import com.bytedesk.core.rbac.user.UserProtobuf; -import com.bytedesk.core.thread.ThreadTypeEnum; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; - - -@Data -@Builder -@Accessors(chain = true) -@AllArgsConstructor -@NoArgsConstructor -@EqualsAndHashCode(callSuper = true) -public class ThreadLogResponse extends BaseResponse { - - private static final long serialVersionUID = 1L; - - // private String title; - - // private String avatar; - - private String topic; - - private String content; - - private Integer unreadCount; - - private ThreadTypeEnum type; - - private String extra; - - private Date createdAt; - - private UserProtobuf user; -} diff --git a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogService.java b/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogService.java deleted file mode 100644 index 81a25b7081..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogService.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-04-18 10:47:38 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-06 16:42:43 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.thread_log; - -import java.util.Date; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.modelmapper.ModelMapper; -import org.springframework.data.domain.Sort; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.scheduling.annotation.Async; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; - -import com.alibaba.fastjson2.JSON; -import com.bytedesk.core.thread.Thread; -import com.bytedesk.core.thread.ThreadService; -import com.bytedesk.core.thread.ThreadTypeEnum; -import com.bytedesk.kbase.service_settings.ServiceSettingsResponseVisitor; - -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -@Service -@AllArgsConstructor -public class ThreadLogService { - - private final ThreadLogRepository threadLogRepository; - - private final ModelMapper modelMapper; - - private final ThreadService threadService; - - public Page queryByOrg(ThreadLogRequest threadLogRequest) { - - Pageable pageable = PageRequest.of(threadLogRequest.getPageNumber(), - threadLogRequest.getPageSize(), Sort.Direction.DESC, - "updatedAt"); - - Specification spec = ThreadLogSpecification.search(threadLogRequest); - - Page threadLogPage = threadLogRepository.findAll(spec, pageable); - - return threadLogPage.map(this::convertThreadLogResponse); - } - - public ThreadLog create(Thread thread) { - - if (threadLogRepository.existsByUid(thread.getUid())) { - return null; - } - - ThreadLog threadLog = modelMapper.map(thread, ThreadLog.class); - - return save(threadLog); - } - - /** - * - * TODO: 座席端25分钟不回复则自动断开,推送满意度 - * TODO: 客户端2分钟没有回复坐席则自动推送1分钟计时提醒: - * 温馨提示:您已经有2分钟未有操作了,如再有1分钟未有操作,系统将自动结束本次对话,感谢您的支持与谅解 - * 如果1分钟之内无回复,则推送满意度: - */ - // TODO: 频繁查库,待优化 - @Async - public void autoCloseThread() { - List threads = threadService.findStatusOpen(); - // log.info("autoCloseThread size {}", threads.size()); - threads.forEach(thread -> { - // 计算两个日期之间的毫秒差 - long diffInMilliseconds = Math.abs(new Date().getTime() - thread.getUpdatedAt().getTime()); - // 转换为分钟 - long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diffInMilliseconds); - // log.info("1.autoCloseThread threadUid {} threadType {} threadId {} diffInMinutes {}", thread.getUid(), thread.getType(), - // thread.getUid(), diffInMinutes); - // - // log.info("{}, {}, {} ", ThreadTypeEnum.WORKGROUP.name(), ThreadTypeEnum.AGENT.name(), ThreadTypeEnum.ROBOT.name()); - if (thread.getType().equals(ThreadTypeEnum.WORKGROUP.name()) - || thread.getType().equals(ThreadTypeEnum.AGENT.name()) - || thread.getType().equals(ThreadTypeEnum.ROBOT.name())) { - ServiceSettingsResponseVisitor settings = JSON.parseObject(thread.getExtra(), - ServiceSettingsResponseVisitor.class); - Double autoCloseMinites = settings.getAutoCloseMin(); - // log.info("2. autoCloseThread threadUid {} threadType {} autoCloseMinites {}, diffInMinutes {}", - // thread.getUid(), thread.getType(), autoCloseMinites, diffInMinutes); - if (diffInMinutes > autoCloseMinites) { - threadService.autoClose(thread); - } - } - // else if (thread.getType() == ThreadTypeEnum.ROBOT.name()) { - // ServiceSettingsResponseVisitor settings = JSON.parseObject(thread.getExtra(), - // ServiceSettingsResponseVisitor.class); - // Double autoCloseMinites = settings.getAutoCloseMin(); - // if (diffInMinutes > autoCloseMinites) { - // threadService.autoClose(thread); - // } - // } - }); - } - - public ThreadLog save(ThreadLog threadLog) { - return threadLogRepository.save(threadLog); - } - - public ThreadLogResponse convertThreadLogResponse(ThreadLog threadLog) { - return modelMapper.map(threadLog, ThreadLogResponse.class); - } - -} diff --git a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogSpecification.java b/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogSpecification.java deleted file mode 100644 index 1bc1319e65..0000000000 --- a/modules/service/src/main/java/com/bytedesk/service/thread_log/ThreadLogSpecification.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * @Author: jackning 270580156@qq.com - * @Date: 2024-06-29 13:18:49 - * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-29 13:20:12 - * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk - * Please be aware of the BSL license restrictions before installing Bytedesk IM – - * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. - * 仅支持企业内部员工自用,严禁私自用于销售、二次销售或者部署SaaS方式销售 - * Business Source License 1.1: https://github.com/Bytedesk/bytedesk/blob/main/LICENSE - * contact: 270580156@qq.com - * 联系:270580156@qq.com - * Copyright (c) 2024 by bytedesk.com, All Rights Reserved. - */ -package com.bytedesk.service.thread_log; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.data.jpa.domain.Specification; - -import com.bytedesk.core.base.BaseSpecification; - -import jakarta.persistence.criteria.Predicate; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public class ThreadLogSpecification extends BaseSpecification { - - public static Specification search(ThreadLogRequest request) { - log.info("request: {}", request); - return (root, query, criteriaBuilder) -> { - List predicates = new ArrayList<>(); - predicates.addAll(getBasicPredicates(root, criteriaBuilder, request.getOrgUid())); - // - return criteriaBuilder.and(predicates.toArray(new Predicate[0])); - }; - } -} diff --git a/modules/service/src/main/java/com/bytedesk/service/utils/ConvertServiceUtils.java b/modules/service/src/main/java/com/bytedesk/service/utils/ConvertServiceUtils.java index c6240f81a1..84bc41129e 100644 --- a/modules/service/src/main/java/com/bytedesk/service/utils/ConvertServiceUtils.java +++ b/modules/service/src/main/java/com/bytedesk/service/utils/ConvertServiceUtils.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-04 11:25:45 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 10:24:56 + * @LastEditTime: 2024-09-20 09:38:17 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -106,12 +106,7 @@ public class ConvertServiceUtils { public static WorkgroupResponse convertToWorkgroupResponse(Workgroup workgroup) { return new ModelMapper().map(workgroup, WorkgroupResponse.class); } - - // public static WorkgroupResponseSimple - // convertToWorkgroupResponseSimple(Workgroup workgroup) { - // return new ModelMapper().map(workgroup, WorkgroupResponseSimple.class); - // } - + // public static ServiceSettingsResponseVisitor convertToServiceSettingsResponseVisitor( ServiceSettings serviceSettings) { diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorAspect.java b/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorAspect.java index af87cb2b69..c37dd3ed3a 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorAspect.java +++ b/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorAspect.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-05 14:51:45 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-29 11:41:47 + * @LastEditTime: 2024-09-18 17:12:20 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -45,7 +45,7 @@ public class VisitorAspect { */ @Before(value = "@annotation(visitorAnnotation)") public void doBefore(JoinPoint joinPoint, VisitorAnnotation visitorAnnotation) { - log.debug("VisitorFilterAspect before: model {}, ", visitorAnnotation.title()); + log.debug("VisitorAspect before: model {}, ", visitorAnnotation.title()); // // 获取方法签名 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorRequest.java b/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorRequest.java index 20b6299acb..7860f1a9d9 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorRequest.java +++ b/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorRequest.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-04-04 17:05:48 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 13:02:59 + * @LastEditTime: 2024-09-13 17:03:09 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -15,7 +15,6 @@ package com.bytedesk.service.visitor; import com.bytedesk.core.base.BaseRequest; -import com.bytedesk.core.constant.AvatarConsts; import com.bytedesk.core.thread.ThreadTypeEnum; import lombok.Data; @@ -34,7 +33,7 @@ public class VisitorRequest extends BaseRequest { */ private String nickname; - private String avatar = AvatarConsts.DEFAULT_VISITOR_AVATAR_URL; + private String avatar; // location info private String ip; @@ -79,4 +78,5 @@ public class VisitorRequest extends BaseRequest { } + } diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorService.java b/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorService.java index c979394b8f..9bf160297d 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorService.java +++ b/modules/service/src/main/java/com/bytedesk/service/visitor/VisitorService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-29 16:21:24 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 14:53:50 + * @LastEditTime: 2024-09-13 17:02:54 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -36,8 +36,9 @@ import com.bytedesk.core.ip.IpService; import com.bytedesk.core.message.MessageProtobuf; import com.bytedesk.core.rbac.user.UserProtobuf; import com.bytedesk.core.uid.UidUtils; +import com.bytedesk.service.strategy.CsThreadCreationContext; import com.bytedesk.service.utils.ConvertServiceUtils; -import com.bytedesk.service.visitor.strategy.CsThreadCreationContext; + import jakarta.servlet.http.HttpServletRequest; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -97,7 +98,7 @@ public class VisitorService extends BaseService findByUid(String uid); Boolean existsByUid(String uid); + + Optional findByTopic(String topic); + + Boolean existsByTopic(String topic); } diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadRequest.java b/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadRequest.java index 0c41e49ac5..002d8539fc 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadRequest.java +++ b/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadRequest.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-29 13:09:44 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-29 13:41:04 + * @LastEditTime: 2024-09-19 09:49:41 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -27,4 +27,6 @@ import lombok.experimental.Accessors; @EqualsAndHashCode(callSuper = false) public class VisitorThreadRequest extends BaseRequest { + + private String visitorUid; } diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadResponse.java b/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadResponse.java index 53f6e4b40d..615c0a56d4 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadResponse.java +++ b/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadResponse.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-29 13:09:55 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-06-29 13:40:53 + * @LastEditTime: 2024-09-19 10:41:17 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,12 +14,7 @@ */ package com.bytedesk.service.visitor_thread; -import java.util.Date; - import com.bytedesk.core.base.BaseResponse; -import com.bytedesk.core.rbac.user.UserProtobuf; -import com.bytedesk.core.thread.ThreadTypeEnum; - import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -35,17 +30,19 @@ import lombok.experimental.Accessors; @EqualsAndHashCode(callSuper = true) public class VisitorThreadResponse extends BaseResponse { - private String topic; + // private String topic; - private String content; + // private String content; - private Integer unreadCount; + // private Integer unreadCount; - private ThreadTypeEnum type; + // private ThreadTypeEnum type; - private String extra; + // private String extra; - private Date createdAt; + // private Date createdAt; - private UserProtobuf user; + // private UserProtobuf user; + + private String visitorUid; } diff --git a/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadService.java b/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadService.java index e86af151b8..ade86e2894 100644 --- a/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadService.java +++ b/modules/service/src/main/java/com/bytedesk/service/visitor_thread/VisitorThreadService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-06-29 13:08:52 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-09-07 09:45:59 + * @LastEditTime: 2024-09-20 06:32:18 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -14,7 +14,10 @@ */ package com.bytedesk.service.visitor_thread; +import java.util.Date; +import java.util.List; import java.util.Optional; +import java.util.concurrent.TimeUnit; import org.modelmapper.ModelMapper; import org.springframework.cache.annotation.Cacheable; @@ -24,14 +27,16 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.Specification; import org.springframework.orm.ObjectOptimisticLockingFailureException; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import com.alibaba.fastjson2.JSON; import com.bytedesk.core.base.BaseService; import com.bytedesk.core.rbac.user.UserProtobuf; import com.bytedesk.core.thread.Thread; -import com.bytedesk.service.visitor.Visitor; -import com.bytedesk.service.visitor.VisitorService; +import com.bytedesk.core.thread.ThreadService; +import com.bytedesk.core.thread.ThreadTypeEnum; +import com.bytedesk.kbase.service_settings.ServiceSettingsResponseVisitor; import lombok.AllArgsConstructor; @@ -41,7 +46,7 @@ public class VisitorThreadService extends BaseService findByTopic(String topic) { + return visitorThreadRepository.findByTopic(topic); + } - if (existsByUid(thread.getUid())) { - return null; - } + public VisitorThread create(Thread thread) { // VisitorThread visitorThread = modelMapper.map(thread, VisitorThread.class); // String visitorString = thread.getUser(); UserProtobuf visitor = JSON.parseObject(visitorString, UserProtobuf.class); + visitorThread.setVisitorUid(visitor.getUid()); // - Optional visitorOpt = visitorService.findByUid(visitor.getUid()); - if (visitorOpt.isPresent()) { - visitorThread.setVisitor(visitorOpt.get()); - } else { - throw new RuntimeException("Visitor " + visitor.getUid() + " not found"); + VisitorThread savedThread = save(visitorThread); + if (savedThread == null) { + throw new RuntimeException("Could not save visitor thread"); } - // - return save(visitorThread); + return savedThread; } public VisitorThread update(Thread thread) { @@ -99,7 +103,6 @@ public class VisitorThreadService extends BaseService threads = threadService.findStatusOpen(); + // log.info("autoCloseThread size {}", threads.size()); + threads.forEach(thread -> { + // 计算两个日期之间的毫秒差 + long diffInMilliseconds = Math.abs(new Date().getTime() - thread.getUpdatedAt().getTime()); + // 转换为分钟 + long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(diffInMilliseconds); + // log.info("1.autoCloseThread threadUid {} threadType {} threadId {} + // diffInMinutes {}", thread.getUid(), thread.getType(), + // thread.getUid(), diffInMinutes); + if (thread.getType().equals(ThreadTypeEnum.WORKGROUP.name()) + || thread.getType().equals(ThreadTypeEnum.AGENT.name()) + || thread.getType().equals(ThreadTypeEnum.ROBOT.name())) { + ServiceSettingsResponseVisitor settings = JSON.parseObject(thread.getExtra(), + ServiceSettingsResponseVisitor.class); + Double autoCloseMinites = settings.getAutoCloseMin(); + // log.info("2. autoCloseThread threadUid {} threadType {} autoCloseMinites {}, + // diffInMinutes {}", + // thread.getUid(), thread.getType(), autoCloseMinites, diffInMinutes); + if (diffInMinutes > autoCloseMinites) { + threadService.autoClose(thread); + } + } + }); + } + @Override public VisitorThread save(VisitorThread entity) { try { return visitorThreadRepository.save(entity); } catch (Exception e) { // TODO: handle exception + e.printStackTrace(); } return null; } diff --git a/modules/service/src/main/java/com/bytedesk/service/workgroup/Workgroup.java b/modules/service/src/main/java/com/bytedesk/service/workgroup/Workgroup.java index 96f993f1e6..295bb3a793 100644 --- a/modules/service/src/main/java/com/bytedesk/service/workgroup/Workgroup.java +++ b/modules/service/src/main/java/com/bytedesk/service/workgroup/Workgroup.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-29 16:19:51 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-07-11 18:35:00 + * @LastEditTime: 2024-09-18 15:34:34 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -89,7 +89,6 @@ public class Workgroup extends BaseEntity { @JsonIgnore @Builder.Default @ManyToMany(fetch = FetchType.LAZY) - // private Set agents = new HashSet<>(); // 为方便路由分配客服,特修改成list private List agents = new ArrayList<>(); diff --git a/modules/service/src/main/java/com/bytedesk/service/workgroup/WorkgroupService.java b/modules/service/src/main/java/com/bytedesk/service/workgroup/WorkgroupService.java index 9ac4f2bc1d..957bbe00d8 100644 --- a/modules/service/src/main/java/com/bytedesk/service/workgroup/WorkgroupService.java +++ b/modules/service/src/main/java/com/bytedesk/service/workgroup/WorkgroupService.java @@ -2,7 +2,7 @@ * @Author: jackning 270580156@qq.com * @Date: 2024-01-29 16:19:51 * @LastEditors: jackning 270580156@qq.com - * @LastEditTime: 2024-07-12 17:51:40 + * @LastEditTime: 2024-09-20 11:22:28 * @Description: bytedesk.com https://github.com/Bytedesk/bytedesk * Please be aware of the BSL license restrictions before installing Bytedesk IM – * selling, reselling, or hosting Bytedesk IM as a service is a breach of the terms and automatically terminates your rights under the license. @@ -81,6 +81,7 @@ public class WorkgroupService { "id"); Specification specs = WorkgroupSpecification.search(workgroupRequest); + Page workgroupPage = workgroupRepository.findAll(specs, pageable); return workgroupPage.map(ConvertServiceUtils::convertToWorkgroupResponse); diff --git a/modules/social/.DS_Store b/modules/social/.DS_Store index 287781d97b..709e435ec1 100644 Binary files a/modules/social/.DS_Store and b/modules/social/.DS_Store differ diff --git a/modules/team/.DS_Store b/modules/team/.DS_Store index 6715dcdfd1..ee04501f76 100644 Binary files a/modules/team/.DS_Store and b/modules/team/.DS_Store differ diff --git a/modules/team/src/.DS_Store b/modules/team/src/.DS_Store index c2b599c405..3d84642282 100644 Binary files a/modules/team/src/.DS_Store and b/modules/team/src/.DS_Store differ