diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
index a4e1deae2..6e3f2b2f1 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
@@ -120,6 +120,35 @@
4.5.14
compile
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+ com.squareup.okhttp3
+ okhttp
+
+
+ com.google.guava
+ guava
+
+
+ net.dv8tion
+ JDA
+ 5.0.0-beta.21
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java
index dd8a599c6..8f749baf4 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyConfig.java
@@ -42,14 +42,20 @@ public class MidjourneyConfig {
* 发送命令
*/
private String apiInteractions = "api/v9/interactions";
-
+ /**
+ * 附件
+ */
+ private String apiAttachments = "/api/v9/channels/%s/attachments";
+ /**
+ * 文件上传
+ */
+ private String apiAttachmentsUpload = "https://discord-attachments-uploads-prd.storage.googleapis.com/";
//
// 浏览器配置
private String userAage = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36";
-
//
// 请求 json 文件
@@ -65,9 +71,6 @@ public class MidjourneyConfig {
this.token = token;
this.guildId = guildId;
this.channelId = channelId;
- this.serverUrl = serverUrl;
- this.apiInteractions = apiInteractions;
- this.userAage = userAage;
this.requestTemplates = requestTemplates;
// 生成 session id
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java
index 884f2626c..751652b08 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java
@@ -34,4 +34,8 @@ public final class MjConstants {
public static final String MSG_ATTACHMENTS = "attachments";
+ //
+ //
+
+ public static final String HTTP_COOKIE = "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0";
}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java
deleted file mode 100644
index 67ce684f2..000000000
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjClient.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package cn.iocoder.yudao.framework.ai.midjourney.interactions;
-
-import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.web.client.RestTemplate;
-
-import java.util.Map;
-
-/**
- * mj client
- *
- * author: fansili
- * time: 2024/4/3 17:37
- */
-public class MjClient {
-
- private static RestTemplate restTemplate = new RestTemplate();
- private static HttpHeaders headers = new HttpHeaders();
-
- private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s";
-
- static {
- headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON
- headers.set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36");
- headers.set("Cookie", "__dcfduid=6ca536c0e3fa11eeb7cbe34c31b49caf; __sdcfduid=6ca536c1e3fa11eeb7cbe34c31b49caf52cce5ffd8983d2a052cf6aba75fe5fe566f2c265902e283ce30dbf98b8c9c93; _gcl_au=1.1.245923998.1710853617; _ga=GA1.1.111061823.1710853617; __cfruid=6385bb3f48345a006b25992db7dcf984e395736d-1712124666; _cfuvid=O09la5ms0ypNptiG0iD8A6BKWlTxz1LG0WR7qRStD7o-1712124666575-0.0.1.1-604800000; locale=zh-CN; cf_clearance=l_YGod1_SUtYxpDVeZXiX7DLLPl1DYrquZe8WVltvYs-1712124668-1.0.1.1-Hl2.fToel23EpF2HCu9J20rB4D7OhhCzoajPSdo.9Up.wPxhvq22DP9RHzEBKuIUlKyH.kJLxXJfAt2N.LD5WQ; OptanonConsent=isIABGlobal=false&datestamp=Wed+Apr+03+2024+14%3A11%3A15+GMT%2B0800+(%E4%B8%AD%E5%9B%BD%E6%A0%87%E5%87%86%E6%97%B6%E9%97%B4)&version=6.33.0&hosts=&landingPath=https%3A%2F%2Fdiscord.com%2F&groups=C0001%3A1%2CC0002%3A1%2CC0003%3A1; _ga_Q149DFWHT7=GS1.1.1712124668.4.1.1712124679.0.0.0");
- }
-
- public static String post(String url, MidjourneyConfig config, String body) {
- // 设置 header
- headers.set("Referer", String.format(HEADER_REFERER, config.getGuildId(), config.getChannelId()));
- headers.set("Authorization", config.getToken());
- // 封装请求体和头部信息
- HttpEntity requestEntity = new HttpEntity<>(body, headers);
- // 发送请求
- return restTemplate.postForObject(url, requestEntity, String.class);
- }
-
-
- public static String setParams(String requestTemplate, Map requestParams) {
- for (Map.Entry entry : requestParams.entrySet()) {
- requestTemplate = requestTemplate.replace("$".concat(entry.getKey()), entry.getValue());
- }
- return requestTemplate;
- }
-}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java
index 1a4d0d817..07827e978 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java
@@ -3,10 +3,25 @@ package cn.iocoder.yudao.framework.ai.midjourney.interactions;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig;
+import cn.iocoder.yudao.framework.ai.midjourney.constants.MjConstants;
+import cn.iocoder.yudao.framework.ai.midjourney.util.MjUtil;
+import cn.iocoder.yudao.framework.ai.midjourney.vo.Attachments;
+import cn.iocoder.yudao.framework.ai.midjourney.vo.Describe;
import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll;
+import cn.iocoder.yudao.framework.ai.midjourney.vo.UploadAttachmentsRes;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.http.*;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+import java.io.IOException;
import java.util.HashMap;
/**
@@ -18,9 +33,12 @@ import java.util.HashMap;
@Slf4j
public class MjInteractions {
- private MidjourneyConfig midjourneyConfig;
- private String url;
+ private final String url;
+ private final MidjourneyConfig midjourneyConfig;
+ private final RestTemplate restTemplate = new RestTemplate();
+ private static final String HEADER_REFERER = "https://discord.com/channels/%s/%s";
+
public MjInteractions(MidjourneyConfig midjourneyConfig) {
this.midjourneyConfig = midjourneyConfig;
@@ -37,10 +55,13 @@ public class MjInteractions {
requestParams.put("session_id", midjourneyConfig.getSessionId());
requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId()));
requestParams.put("prompt", prompt);
- // 设置参数
- String requestBody = MjClient.setParams(requestTemplate, requestParams);
+ // 解析 template 参数占位符
+ String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams);
+ // 获取 header
+ HttpHeaders httpHeaders = getHttpHeaders();
// 发送请求
- String res = MjClient.post(url, midjourneyConfig, requestBody);
+ HttpEntity requestEntity = new HttpEntity<>(requestBody, httpHeaders);
+ String res = restTemplate.postForObject(url, requestEntity, String.class);
// 这个 res 只要不返回值,就是成功!
boolean isSuccess = StrUtil.isBlank(res);
if (isSuccess) {
@@ -50,6 +71,8 @@ public class MjInteractions {
return isSuccess;
}
+
+
public Boolean reRoll(ReRoll reRoll) {
// 获取请求模板
String requestTemplate = midjourneyConfig.getRequestTemplates().get("reroll");
@@ -61,10 +84,13 @@ public class MjInteractions {
requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId()));
requestParams.put("custom_id", reRoll.getCustomId());
requestParams.put("message_id", reRoll.getMessageId());
+ // 获取 header
+ HttpHeaders httpHeaders = getHttpHeaders();
// 设置参数
- String requestBody = MjClient.setParams(requestTemplate, requestParams);
+ String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams);
// 发送请求
- String res = MjClient.post(url, midjourneyConfig, requestBody);
+ HttpEntity requestEntity = new HttpEntity<>(requestBody, httpHeaders);
+ String res = restTemplate.postForObject(url, requestEntity, String.class);
// 这个 res 只要不返回值,就是成功!
boolean isSuccess = StrUtil.isBlank(res);
if (isSuccess) {
@@ -73,4 +99,90 @@ public class MjInteractions {
log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res);
return isSuccess;
}
+
+
+ public UploadAttachmentsRes uploadAttachments(Attachments attachments) {
+ // file
+ JSONObject fileObj = new JSONObject();
+ fileObj.put("id", "0");
+ fileObj.put("filename", attachments.getFileSystemResource().getFilename());
+ try {
+ fileObj.put("file_size", attachments.getFileSystemResource().contentLength());
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ // 创建用于存放表单数据的MultiValueMap
+ MultiValueMap multipartRequest = new LinkedMultiValueMap<>();
+ multipartRequest.put("files", Lists.newArrayList(fileObj));
+ // 设置header值
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.setContentType(MediaType.APPLICATION_JSON);
+ httpHeaders.set("Authorization", midjourneyConfig.getToken());
+ httpHeaders.set("User-Agent", midjourneyConfig.getUserAage());
+ httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE);
+ httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId()));
+ // 创建HttpEntity对象,包含表单数据和头部信息
+ HttpEntity> multiValueMapHttpEntity = new HttpEntity<>(multipartRequest, httpHeaders);
+ // 发送POST请求并接收响应
+ String uri = String.format(midjourneyConfig.getApiAttachments(), midjourneyConfig.getChannelId());
+ String response = restTemplate.postForObject(midjourneyConfig.getServerUrl().concat(uri), multiValueMapHttpEntity, String.class);
+ UploadAttachmentsRes uploadAttachmentsRes = JSON.parseObject(response, UploadAttachmentsRes.class);
+
+
+ //
+ // 上传文件
+ String uploadUrl = uploadAttachmentsRes.getAttachments().getFirst().getUploadUrl();
+ String uploadAttachmentsUrl = midjourneyConfig.getApiAttachmentsUpload().concat(uploadUrl);
+ httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
+ HttpEntity fileSystemResourceHttpEntity = new HttpEntity<>(attachments.getFileSystemResource(), httpHeaders);
+ ResponseEntity exchange = restTemplate.exchange(uploadUrl, HttpMethod.PUT, fileSystemResourceHttpEntity, String.class);
+ String uploadRes = exchange.getBody();
+
+ return uploadAttachmentsRes;
+ }
+
+ public Boolean describe(Describe describe) {
+ // 获取请求模板
+ String requestTemplate = midjourneyConfig.getRequestTemplates().get("describe");
+ // 设置参数
+ HashMap requestParams = Maps.newHashMap();
+ requestParams.put("guild_id", midjourneyConfig.getGuildId());
+ requestParams.put("channel_id", midjourneyConfig.getChannelId());
+ requestParams.put("session_id", midjourneyConfig.getSessionId());
+ requestParams.put("nonce", String.valueOf(IdUtil.getSnowflakeNextId()));
+ requestParams.put("file_name", describe.getFileName());
+ requestParams.put("final_file_name", describe.getFinalFileName());
+ // 设置 header
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); // 设置内容类型为JSON
+ httpHeaders.set("Authorization", midjourneyConfig.getToken());
+ httpHeaders.set("User-Agent", midjourneyConfig.getUserAage());
+ httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE);
+ httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId()));
+ String requestBody = MjUtil.parseTemplate(requestTemplate, requestParams);
+ // 创建表单数据
+ MultiValueMap formData = new LinkedMultiValueMap<>();
+ formData.add("payload_json", requestBody);
+ // 发送请求
+ HttpEntity> multiValueMapHttpEntity = new HttpEntity<>(formData, httpHeaders);
+ String res = restTemplate.postForObject(url, multiValueMapHttpEntity, String.class);
+ // 这个 res 只要不返回值,就是成功!
+ boolean isSuccess = StrUtil.isBlank(res);
+ if (isSuccess) {
+ return true;
+ }
+ log.error("请求失败! 请求参数:{} 返回结果! {}", requestBody, res);
+ return isSuccess;
+ }
+
+ @NotNull
+ private HttpHeaders getHttpHeaders() {
+ HttpHeaders httpHeaders = new HttpHeaders();
+ httpHeaders.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON
+ httpHeaders.set("Authorization", midjourneyConfig.getToken());
+ httpHeaders.set("User-Agent", midjourneyConfig.getUserAage());
+ httpHeaders.set("Cookie", MjConstants.HTTP_COOKIE);
+ httpHeaders.set("Referer", String.format(HEADER_REFERER, midjourneyConfig.getGuildId(), midjourneyConfig.getChannelId()));
+ return httpHeaders;
+ }
}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java
index 4e04e69dc..751a79b04 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/util/MjUtil.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.util;
import cn.hutool.core.text.CharSequenceUtil;
import cn.iocoder.yudao.framework.ai.midjourney.MjMessage;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -19,7 +20,12 @@ public class MjUtil {
public static final String CONTENT_REGEX = ".*?\\*\\*(.*?)\\*\\*.+<@\\d+> \\((.*?)\\)";
public static final String CONTENT_PROGRESS_REGEX = "\\(([^)]*)\\)";
-
+ /**
+ * 解析 content 参数
+ *
+ * @param content
+ * @return
+ */
public static MjMessage.Content parseContent(String content) {
// 有三种格式。
// 南极应该是什么样子?
@@ -61,4 +67,17 @@ public class MjUtil {
return mjContent;
}
+ /**
+ * 设置 params
+ *
+ * @param requestTemplate
+ * @param requestParams
+ * @return
+ */
+ public static String parseTemplate(String requestTemplate, Map requestParams) {
+ for (Map.Entry entry : requestParams.entrySet()) {
+ requestTemplate = requestTemplate.replace("$".concat(entry.getKey()), entry.getValue());
+ }
+ return requestTemplate;
+ }
}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java
new file mode 100644
index 000000000..133a7031f
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Attachments.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.framework.ai.midjourney.vo;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+import org.springframework.core.io.FileSystemResource;
+
+/**
+ * 附件
+ *
+ * author: fansili
+ * time: 2024/4/7 17:18
+ */
+@Data
+@Accessors(chain = true)
+public class Attachments {
+
+ /**
+ * 创建文件系统资源对象
+ */
+ private FileSystemResource fileSystemResource;
+
+}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java
new file mode 100644
index 000000000..6517f7b86
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/Describe.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.framework.ai.midjourney.vo;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.io.File;
+
+/**
+ * describe
+ *
+ * author: fansili
+ * time: 2024/4/7 12:30
+ */
+@Data
+@Accessors(chain = true)
+public class Describe {
+
+ /**
+ * 文件名字
+ */
+ private String fileName;
+ /**
+ * UploadAttachmentsRes 里面的 finalFileName
+ */
+ private String finalFileName;
+}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java
index 2d39ba1df..a28517419 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/ReRoll.java
@@ -11,6 +11,12 @@ import lombok.experimental.Accessors;
@Accessors(chain = true)
public class ReRoll {
+ /**
+ * socket 消息里面收到的 messageId
+ */
private String messageId;
+ /**
+ * socket 消息里面的,操作按钮id(MJ::JOB::upsample::3::2aeefbef-43e2-4057-bcf1-43b5f39ab6f7)
+ */
private String customId;
}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java
new file mode 100644
index 000000000..b06c1c318
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/vo/UploadAttachmentsRes.java
@@ -0,0 +1,36 @@
+package cn.iocoder.yudao.framework.ai.midjourney.vo;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ * 上传附件 - res
+ *
+ * author: fansili
+ * time: 2024/4/8 13:32
+ */
+@Data
+@Accessors(chain = true)
+public class UploadAttachmentsRes {
+
+ private List attachments;
+
+ @Data
+ @Accessors(chain = true)
+ public static class Attachment {
+ /**
+ * 附件的ID。
+ */
+ private int id;
+ /**
+ * 附件的上传URL。
+ */
+ private String uploadUrl;
+ /**
+ * 上传到服务器的文件名。
+ */
+ private String uploadFilename;
+ }
+}
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/describe.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/describe.json
new file mode 100644
index 000000000..6d1f534ab
--- /dev/null
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/describe.json
@@ -0,0 +1,28 @@
+{
+ "type": 2,
+ "guild_id": "$guild_id",
+ "channel_id": "$channel_id",
+ "application_id": "936929561302675456",
+ "session_id": "$session_id",
+ "nonce": "$nonce",
+ "data": {
+ "version": "1204231436023111690",
+ "id": "1092492867185950852",
+ "name": "describe",
+ "type": 1,
+ "options": [
+ {
+ "type": 11,
+ "name": "image",
+ "value": 0
+ }
+ ],
+ "attachments": [
+ {
+ "id": "0",
+ "filename": "$file_name",
+ "uploaded_filename": "$final_file_name"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/1.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/1.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/1.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/1.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/10.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/10.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/10.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/10.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/11.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/11.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/11.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/11.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/12.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/12.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/12.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/12.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/2.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/2.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/2.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/3.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/3.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/3.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/4.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/4.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/4.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/4.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/5.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/5.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/5.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/5.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/6.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/6.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/6.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/6.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/7.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/7.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/7.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/7.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/8.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/8.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/8.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/8.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/9.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/9.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/图片消息过程/9.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/imageGenerationProcess/9.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type2.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/interactions_type2.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type2.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/interactions_type2.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type3.json b/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/interactions_type3.json
similarity index 100%
rename from yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type3.json
rename to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/requestTestJson/interactions_type3.json
diff --git a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java
index 3108b31be..636e9d2d4 100644
--- a/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java
+++ b/yudao-module-ai/yudao-spring-boot-starter-ai/src/test/java/cn/iocoder/yudao/framework/ai/mj/MjInteractionsTests.java
@@ -3,9 +3,14 @@ package cn.iocoder.yudao.framework.ai.mj;
import cn.hutool.core.io.FileUtil;
import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig;
import cn.iocoder.yudao.framework.ai.midjourney.interactions.MjInteractions;
+import cn.iocoder.yudao.framework.ai.midjourney.vo.Attachments;
+import cn.iocoder.yudao.framework.ai.midjourney.vo.Describe;
import cn.iocoder.yudao.framework.ai.midjourney.vo.ReRoll;
+import cn.iocoder.yudao.framework.ai.midjourney.vo.UploadAttachmentsRes;
+import com.alibaba.fastjson.JSON;
import org.junit.Before;
import org.junit.Test;
+import org.springframework.core.io.FileSystemResource;
import java.io.File;
import java.util.HashMap;
@@ -46,4 +51,23 @@ public class MjInteractionsTests {
.setMessageId("1226165117448753243")
.setCustomId("MJ::JOB::upsample::3::2aeefbef-43e2-4057-bcf1-43b5f39ab6f7"));
}
+
+ @Test
+ public void uploadAttachmentsTest() {
+ MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig);
+ UploadAttachmentsRes res = mjImagineInteractions.uploadAttachments(
+ new Attachments().setFileSystemResource(
+ new FileSystemResource(new File("/Users/fansili/Downloads/DSC01402.JPG")))
+ );
+ System.err.println(JSON.toJSONString(res));
+ }
+
+ @Test
+ public void describeTest() {
+ MjInteractions mjImagineInteractions = new MjInteractions(midjourneyConfig);
+ mjImagineInteractions.describe(new Describe()
+ .setFileName("DSC01402.JPG")
+ .setFinalFileName("16826931-2873-45ec-8cfb-0ad81f1a075f/DSC01402.JPG")
+ );
+ }
}