✨Feat: 完成 Lark 简单信息发送

This commit is contained in:
2025-10-25 19:23:47 +08:00
parent 27cb78112d
commit eb1bbe78a1
13 changed files with 270 additions and 4 deletions
@@ -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 放下城市的喧嚣,放下心里的压力,拿起一杆锄头,和我们一起,去往一个叫“星露谷”的地方吧。";
}
@@ -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";
}
@@ -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<String> chat(@RequestBody AIChatRequest aiChatRequest) {
return ResultUtil.success(chatUtil.doChat(aiChatRequest.getBackGround(), aiChatRequest.getContent()));
}
}
@@ -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<String> healthTest() {
return ResultUtil.success("Welcome to Stardew Valley!");
}
}
@@ -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<String> welcome() throws Exception {
LarkUtil.sendText(GuideConstant.GUIDE);
return ResultUtil.success("发送成功");
}
}
@@ -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<T> 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());
}
}
@@ -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();
}
}
@@ -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;
}
}
@@ -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));
}
}
@@ -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()));
}
}
@@ -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 <T> BaseResponse<T> 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);
}
}
@@ -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 放下城市的喧嚣,放下心里的压力,拿起一杆锄头,和我们一起,去往一个叫“星露谷”的地方吧。");
}
}