diff --git a/pom.xml b/pom.xml
index c178eb9..8bb0832 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,6 +41,12 @@
spring-ai-starter-model-openai
+
+ com.larksuite.oapi
+ oapi-sdk
+ 2.4.24
+
+
com.github.xiaoymin
knife4j-openapi3-jakarta-spring-boot-starter
@@ -52,6 +58,12 @@
lombok
+
+ cn.hutool
+ hutool-all
+ 5.8.9
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/src/main/java/com/wonderland/stardewvalley/constant/GuideConstant.java b/src/main/java/com/wonderland/stardewvalley/constant/GuideConstant.java
new file mode 100644
index 0000000..b8ad9ff
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/constant/GuideConstant.java
@@ -0,0 +1,13 @@
+package com.wonderland.stardewvalley.constant;
+
+public class GuideConstant {
+
+ final public static String GUIDE = "\uD83C\uDF31 在这个名为“如果人生是星露谷”的世界中,玩家扮演的是一位现实世界中的普通人 ,在某种“精神投射”或“虚拟现实”中,进入了一个与《星露谷物语》相似的模拟世界。这个世界并非简单的幻想乡,而是对现实生活的重构与映射 ,玩家通过在现实世界中“种田、打工、探索、运动”等行为,影响游戏中的生活节奏与心理状态。\n" +
+ "\n" +
+ "\uD83C\uDFAE 游戏说明:\n" +
+ "\uD83C\uDF06 车水马龙的街道,拥挤的人潮,在这充满快节奏的水泥森林里,人们被巨大的压力裹挟着,疲惫不堪,宛若行尸走肉。改不完的稿子,数不完的ddl,望不到头的前路,许久没体会过的放松....生活什么时变得这么累了\n" +
+ "\n" +
+ "\uD83C\uDFD9 你被困在水泥森林里多久了?你又有多久没给自己好好地放个假了?你童年的星星依然在天上等着你,但你还能找到回家的路吗?\u200B \n" +
+ "\n" +
+ "\uD83C\uDF3E 放下城市的喧嚣,放下心里的压力,拿起一杆锄头,和我们一起,去往一个叫“星露谷”的地方吧。";
+}
diff --git a/src/main/java/com/wonderland/stardewvalley/constant/LarkConstant.java b/src/main/java/com/wonderland/stardewvalley/constant/LarkConstant.java
new file mode 100644
index 0000000..17692e4
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/constant/LarkConstant.java
@@ -0,0 +1,8 @@
+package com.wonderland.stardewvalley.constant;
+
+public class LarkConstant {
+
+ final public static String APP_ID = "cli_a876d25014e9100e";
+ final public static String APP_SECRET = "8rSGfa6nLgB8vQmQRFSzodK4AozlFP3U";
+ final public static String USER_OPEN_ID = "ou_857c58ee28b89f44c4ecc939a83b2476";
+}
diff --git a/src/main/java/com/wonderland/stardewvalley/controller/ChatController.java b/src/main/java/com/wonderland/stardewvalley/controller/ChatController.java
index e35c333..cb2ea63 100644
--- a/src/main/java/com/wonderland/stardewvalley/controller/ChatController.java
+++ b/src/main/java/com/wonderland/stardewvalley/controller/ChatController.java
@@ -2,6 +2,8 @@ package com.wonderland.stardewvalley.controller;
import com.wonderland.stardewvalley.ai.ChatUtil;
import com.wonderland.stardewvalley.entity.AIChatRequest;
+import com.wonderland.stardewvalley.entity.BaseResponse;
+import com.wonderland.stardewvalley.util.ResultUtil;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -16,7 +18,7 @@ public class ChatController {
private ChatUtil chatUtil;
@PostMapping
- public String chat(@RequestBody AIChatRequest aiChatRequest) {
- return chatUtil.doChat(aiChatRequest.getBackGround(), aiChatRequest.getContent());
+ public BaseResponse chat(@RequestBody AIChatRequest aiChatRequest) {
+ return ResultUtil.success(chatUtil.doChat(aiChatRequest.getBackGround(), aiChatRequest.getContent()));
}
}
diff --git a/src/main/java/com/wonderland/stardewvalley/controller/HealthController.java b/src/main/java/com/wonderland/stardewvalley/controller/HealthController.java
index 570ae83..d162a5c 100644
--- a/src/main/java/com/wonderland/stardewvalley/controller/HealthController.java
+++ b/src/main/java/com/wonderland/stardewvalley/controller/HealthController.java
@@ -1,5 +1,7 @@
package com.wonderland.stardewvalley.controller;
+import com.wonderland.stardewvalley.entity.BaseResponse;
+import com.wonderland.stardewvalley.util.ResultUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -9,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController;
public class HealthController {
@GetMapping("/ping")
- public String healthTest() {
- return "Welcome to Stardew Valley!";
+ public BaseResponse healthTest() {
+ return ResultUtil.success("Welcome to Stardew Valley!");
}
}
diff --git a/src/main/java/com/wonderland/stardewvalley/controller/LarkController.java b/src/main/java/com/wonderland/stardewvalley/controller/LarkController.java
new file mode 100644
index 0000000..cacf2c7
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/controller/LarkController.java
@@ -0,0 +1,20 @@
+package com.wonderland.stardewvalley.controller;
+
+import com.wonderland.stardewvalley.constant.GuideConstant;
+import com.wonderland.stardewvalley.entity.BaseResponse;
+import com.wonderland.stardewvalley.lark.LarkUtil;
+import com.wonderland.stardewvalley.util.ResultUtil;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("lark")
+public class LarkController {
+
+ @GetMapping("welcome")
+ public BaseResponse welcome() throws Exception {
+ LarkUtil.sendText(GuideConstant.GUIDE);
+ return ResultUtil.success("发送成功");
+ }
+}
diff --git a/src/main/java/com/wonderland/stardewvalley/entity/BaseResponse.java b/src/main/java/com/wonderland/stardewvalley/entity/BaseResponse.java
new file mode 100644
index 0000000..60ababe
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/entity/BaseResponse.java
@@ -0,0 +1,33 @@
+package com.wonderland.stardewvalley.entity;
+
+
+import com.wonderland.stardewvalley.exception.ErrorCode;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class BaseResponse implements Serializable {
+
+ private int code;
+
+ private T data;
+
+ private String message;
+
+
+ public BaseResponse(int code, T data, String message) {
+ this.code = code;
+ this.data = data;
+ this.message = message;
+ }
+
+
+ public BaseResponse(int code, T data) {
+ this(code, data, "");
+ }
+
+ public BaseResponse(ErrorCode errorCode) {
+ this(errorCode.getCode(), null, errorCode.getMessage());
+ }
+}
diff --git a/src/main/java/com/wonderland/stardewvalley/exception/BusinessException.java b/src/main/java/com/wonderland/stardewvalley/exception/BusinessException.java
new file mode 100644
index 0000000..2e7e308
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/exception/BusinessException.java
@@ -0,0 +1,22 @@
+package com.wonderland.stardewvalley.exception;
+
+
+public class BusinessException extends RuntimeException{
+
+ private final int code;
+
+ public BusinessException(int code, String message) {
+ super(message);
+ this.code = code;
+ }
+
+ public BusinessException(ErrorCode errorCode) {
+ super(errorCode.getMessage());
+ this.code = errorCode.getCode();
+ }
+
+ public BusinessException(ErrorCode errorCode, String message) {
+ super(message);
+ this.code = errorCode.getCode();
+ }
+}
diff --git a/src/main/java/com/wonderland/stardewvalley/exception/ErrorCode.java b/src/main/java/com/wonderland/stardewvalley/exception/ErrorCode.java
new file mode 100644
index 0000000..49f401f
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/exception/ErrorCode.java
@@ -0,0 +1,33 @@
+package com.wonderland.stardewvalley.exception;
+
+
+import lombok.Getter;
+
+@Getter
+public enum ErrorCode {
+
+ SUCCESS(0, "ok"),
+ PARAMS_ERROR(40000, "请求参数错误"),
+ NOT_LOGIN_ERROR(40100, "未登录"),
+ NO_AUTH_ERROR(40101, "无权限"),
+ NOT_FOUND_ERROR(40400, "请求数据不存在"),
+ FORBIDDEN_ERROR(40300, "禁止访问"),
+ SYSTEM_ERROR(50000, "系统内部异常"),
+ OPERATION_ERROR(50001, "操作失败");
+
+ /**
+ * 状态码
+ */
+ private final int code;
+
+ /**
+ * 信息
+ */
+ private final String message;
+
+ ErrorCode(int code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+
+}
diff --git a/src/main/java/com/wonderland/stardewvalley/exception/ThrowUtils.java b/src/main/java/com/wonderland/stardewvalley/exception/ThrowUtils.java
new file mode 100644
index 0000000..9958897
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/exception/ThrowUtils.java
@@ -0,0 +1,19 @@
+package com.wonderland.stardewvalley.exception;
+
+
+public class ThrowUtils {
+
+ public static void throwIf(boolean condition, RuntimeException runtimeException) {
+ if (condition) {
+ throw runtimeException;
+ }
+ }
+
+ public static void throwIf(boolean condition, ErrorCode errorCode) {
+ throwIf(condition, new BusinessException(errorCode));
+ }
+
+ public static void throwIf(boolean condition, ErrorCode errorCode, String message) {
+ throwIf(condition, new BusinessException(errorCode, message));
+ }
+}
diff --git a/src/main/java/com/wonderland/stardewvalley/lark/LarkUtil.java b/src/main/java/com/wonderland/stardewvalley/lark/LarkUtil.java
new file mode 100644
index 0000000..eb70681
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/lark/LarkUtil.java
@@ -0,0 +1,60 @@
+package com.wonderland.stardewvalley.lark;
+
+
+import cn.hutool.core.util.IdUtil;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.gson.JsonParser;
+import com.lark.oapi.Client;
+import com.lark.oapi.core.utils.Jsons;
+import com.lark.oapi.service.im.v1.model.CreateMessageReq;
+import com.lark.oapi.service.im.v1.model.CreateMessageReqBody;
+import com.lark.oapi.service.im.v1.model.CreateMessageResp;
+import com.wonderland.stardewvalley.constant.LarkConstant;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.nio.charset.StandardCharsets;
+
+@Slf4j
+@Service
+public class LarkUtil {
+// SDK 使用文档:https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/server-side-sdk/java-sdk-guide/preparations
+// 复制该 Demo 后, 需要将 "YOUR_APP_ID", "YOUR_APP_SECRET" 替换为自己应用的 APP_ID, APP_SECRET.
+// 以下示例代码默认根据文档示例值填充,如果存在代码问题,请在 API 调试台填上相关必要参数后再复制代码使用
+
+ public static void sendText(String content) throws Exception {
+ // 构建client
+ Client client = Client.newBuilder(LarkConstant.APP_ID, LarkConstant.APP_SECRET).build();
+
+ // 组装文本 JSON
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode node = mapper.createObjectNode();
+ node.put("text", content);
+ log.info("[Lark] 发送消息:{}", node.toString());
+
+ // 创建请求对象
+ CreateMessageReq req = CreateMessageReq.newBuilder()
+ .receiveIdType("open_id")
+ .createMessageReqBody(CreateMessageReqBody.newBuilder()
+ .receiveId(LarkConstant.USER_OPEN_ID)
+ .msgType("text")
+ .content(node.toString())
+ .uuid(IdUtil.randomUUID())
+ .build())
+ .build();
+
+ // 发起请求
+ CreateMessageResp resp = client.im().v1().message().create(req);
+
+ // 处理服务端错误
+ if(!resp.success()) {
+ System.out.println(String.format("code:%s,msg:%s,reqId:%s, resp:%s",
+ resp.getCode(), resp.getMsg(), resp.getRequestId(), Jsons.createGSON(true, false).toJson(JsonParser.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8)))));
+ return;
+ }
+
+ // 业务数据处理
+ System.out.println(Jsons.DEFAULT.toJson(resp.getData()));
+ }
+}
diff --git a/src/main/java/com/wonderland/stardewvalley/util/ResultUtil.java b/src/main/java/com/wonderland/stardewvalley/util/ResultUtil.java
new file mode 100644
index 0000000..7c73fcc
--- /dev/null
+++ b/src/main/java/com/wonderland/stardewvalley/util/ResultUtil.java
@@ -0,0 +1,24 @@
+package com.wonderland.stardewvalley.util;
+
+
+import com.wonderland.stardewvalley.entity.BaseResponse;
+import com.wonderland.stardewvalley.exception.ErrorCode;
+
+public class ResultUtil {
+
+ public static BaseResponse success(T data) {
+ return new BaseResponse<>(ErrorCode.SUCCESS.getCode(), data, ErrorCode.SUCCESS.getMessage());
+ }
+
+ public static BaseResponse> error(ErrorCode errorCode) {
+ return new BaseResponse<>(errorCode);
+ }
+
+ public static BaseResponse> error(int code, String message) {
+ return new BaseResponse<>(code, null, message);
+ }
+
+ public static BaseResponse> error(ErrorCode errorCode, String message) {
+ return new BaseResponse<>(errorCode.getCode(), null, message);
+ }
+}
diff --git a/src/test/java/com/wonderland/stardewvalley/lark/LarkUtilTest.java b/src/test/java/com/wonderland/stardewvalley/lark/LarkUtilTest.java
new file mode 100644
index 0000000..f6028c8
--- /dev/null
+++ b/src/test/java/com/wonderland/stardewvalley/lark/LarkUtilTest.java
@@ -0,0 +1,18 @@
+package com.wonderland.stardewvalley.lark;
+
+import org.junit.jupiter.api.Test;
+
+class LarkUtilTest {
+
+ @Test
+ void sendText() throws Exception {
+ LarkUtil.sendText("\uD83C\uDF31 在这个名为“如果人生是星露谷”的世界中,玩家扮演的是一位现实世界中的普通人 ,在某种“精神投射”或“虚拟现实”中,进入了一个与《星露谷物语》相似的模拟世界。这个世界并非简单的幻想乡,而是对现实生活的重构与映射 ,玩家通过在现实世界中“种田、打工、探索、运动”等行为,影响游戏中的生活节奏与心理状态。\n" +
+ "\n" +
+ "\uD83C\uDFAE 游戏说明:\n" +
+ "\uD83C\uDF06 车水马龙的街道,拥挤的人潮,在这充满快节奏的水泥森林里,人们被巨大的压力裹挟着,疲惫不堪,宛若行尸走肉。改不完的稿子,数不完的ddl,望不到头的前路,许久没体会过的放松....生活什么时变得这么累了\n" +
+ "\n" +
+ "\uD83C\uDFD9 你被困在水泥森林里多久了?你又有多久没给自己好好地放个假了?你童年的星星依然在天上等着你,但你还能找到回家的路吗?\u200B \n" +
+ "\n" +
+ "\uD83C\uDF3E 放下城市的喧嚣,放下心里的压力,拿起一杆锄头,和我们一起,去往一个叫“星露谷”的地方吧。");
+ }
+}
\ No newline at end of file