Commit 5044a58118408c98367c7d3eaed440abac4accd5

Authored by cherishsince
1 parent 28b2fad7

增加mj web socket

Showing 26 changed files with 110 additions and 591 deletions
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.midjourney.constants;
  2 +
  3 +public final class MjConstants {
  4 +
  5 + public static final String CHANNEL_ID = "channel_id";
  6 +
  7 +
  8 +}
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/MidjourneyInteractionsEnum.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjInteractionsEnum.java
1   -package cn.iocoder.yudao.framework.ai.midjourney;
  1 +package cn.iocoder.yudao.framework.ai.midjourney.constants;
2 2  
3 3 import lombok.Getter;
4 4  
... ... @@ -6,7 +6,7 @@ import lombok.Getter;
6 6 * MJ 命令
7 7 */
8 8 @Getter
9   -public enum MidjourneyInteractionsEnum {
  9 +public enum MjInteractionsEnum {
10 10  
11 11 IMAGINE("imagine", "生成图片"),
12 12 DESCRIBE("describe", "生成描述"),
... ... @@ -17,7 +17,7 @@ public enum MidjourneyInteractionsEnum {
17 17  
18 18 ;
19 19  
20   - MidjourneyInteractionsEnum(String value, String message) {
  20 + MjInteractionsEnum(String value, String message) {
21 21 this.value =value;
22 22 this.message =message;
23 23 }
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/MessageType.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjMessageTypeEnum.java
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss;
  1 +package cn.iocoder.yudao.framework.ai.midjourney.constants;
2 2  
3 3  
4   -public enum MessageType {
  4 +public enum MjMessageTypeEnum {
5 5 /**
6 6 * 创建.
7 7 */
... ... @@ -15,7 +15,7 @@ public enum MessageType {
15 15 */
16 16 DELETE;
17 17  
18   - public static MessageType of(String type) {
  18 + public static MjMessageTypeEnum of(String type) {
19 19 return switch (type) {
20 20 case "MESSAGE_CREATE" -> CREATE;
21 21 case "MESSAGE_UPDATE" -> UPDATE;
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/ReturnCode.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/constants/MjNotifyCode.java
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss;
  1 +package cn.iocoder.yudao.framework.ai.midjourney.constants;
2 2  
3 3 import lombok.experimental.UtilityClass;
4 4  
5 5 @UtilityClass
6   -public final class ReturnCode {
  6 +public final class MjNotifyCode {
7 7 /**
8 8 * 成功.
9 9 */
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordJadMain.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo;
2   -
3   -/**
4   - * author: fansili
5   - * time: 2024/4/3 15:54
6   - */
7   -public class DiscordJadMain {
8   -
9   -
10   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/DiscordWebSocketClient.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo;
2   -import cn.hutool.http.useragent.UserAgent;
3   -import cn.hutool.http.useragent.UserAgentUtil;
4   -import cn.hutool.json.JSONObject;
5   -import com.alibaba.fastjson.JSON;
6   -import org.springframework.web.socket.*;
7   -import org.springframework.web.socket.client.standard.StandardWebSocketClient;
8   -import org.springframework.web.socket.handler.TextWebSocketHandler;
9   -
10   -import java.io.IOException;
11   -import java.net.URI;
12   -import java.net.URISyntaxException;
13   -import java.nio.ByteBuffer;
14   -import java.nio.charset.StandardCharsets;
15   -import java.util.concurrent.ExecutionException;
16   -import java.util.concurrent.Future;
17   -
18   -/**
19   - * https://blog.csdn.net/qq_38490457/article/details/125250135
20   - */
21   -public class DiscordWebSocketClient {
22   -
23   - private static final String DISCORD_GATEWAY_URL = "wss://gateway.discord.gg/?v=9&encoding=json";
24   -
25   - public static void main(String[] args) throws InterruptedException, ExecutionException, IOException, URISyntaxException {
26   - StandardWebSocketClient client = new StandardWebSocketClient();
27   - DiscordWebSocketHandler handler = new DiscordWebSocketHandler();
28   -
29   -
30   - WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
31   - headers.add("Accept-Encoding", "gzip, deflate, br");
32   - headers.add("Accept-Language", "zh-CN,zh;q=0.9");
33   - headers.add("Cache-Control", "no-cache");
34   - headers.add("Pragma", "no-cache");
35   - headers.add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits");
36   - headers.add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36");
37   -
38   - Future<WebSocketSession> futureSession = client.doHandshake(handler, headers, new URI(DISCORD_GATEWAY_URL));
39   - WebSocketSession session = futureSession.get(); // 这会阻塞直到连接建立
40   -
41   - // 登录过程(你需要替换 TOKEN 为你的 Discord Bot Token)
42   -// String token = "YOUR_DISCORD_BOT_TOKEN"; // 请替换为你的 Bot Token
43   -// String identifyPayload = "{\"op\":2,\"d\":{\"token\":\"" + token + "\",\"properties\":{\"$os\":\"java\",\"$browser\":\"spring-websocket\",\"$device\":\"spring-websocket\"},\"compress\":false,\"large_threshold\":256,\"shard\":[0,1]}}";
44   -// session.sendMessage(new TextMessage(identifyPayload));
45   -
46   - // 发送心跳以保持连接活跃
47   - Thread heartbeatThread = new Thread(() -> {
48   - int interval = 0; // 初始心跳间隔,后续从 Discord 服务器获取
49   - while (!Thread.currentThread().isInterrupted()) {
50   - try {
51   - Thread.sleep(interval * 1000); // 等待指定的心跳间隔
52   - session.sendMessage(new TextMessage("{\"op\":1,\"d\":null}")); // 发送心跳包
53   - } catch (Exception e) {
54   - e.printStackTrace();
55   - break;
56   - }
57   - }
58   - });
59   - heartbeatThread.start();
60   -
61   - // 等待用户输入来保持程序运行(仅用于示例)
62   - System.in.read();
63   -
64   - // 关闭连接和线程
65   - session.close();
66   - heartbeatThread.interrupt();
67   - }
68   -
69   - private static class DiscordWebSocketHandler implements WebSocketHandler {
70   -
71   - @Override
72   - public void afterConnectionEstablished(WebSocketSession session) throws Exception {
73   -
74   - }
75   -
76   - @Override
77   - public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
78   - Object payload = message.getPayload();
79   -
80   - session.sendMessage(new TextMessage(JSON.toJSONString(createAuthData())));
81   - String a= "";
82   - }
83   -
84   - @Override
85   - public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
86   -
87   - }
88   -
89   - @Override
90   - public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
91   -
92   - }
93   -
94   - @Override
95   - public boolean supportsPartialMessages() {
96   - return false;
97   - }
98   -
99   -
100   - private JSONObject createAuthData() {
101   - String userAgentStr = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36";
102   - UserAgent userAgent = UserAgentUtil.parse(userAgentStr);
103   - String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc";
104   -
105   - JSONObject connectionProperties = new JSONObject()
106   - .put("browser", userAgent.getBrowser().getName())
107   - .put("browser_user_agent", userAgentStr)
108   - .put("browser_version", userAgent.getVersion())
109   - .put("client_build_number", 222963)
110   - .put("client_event_source", null)
111   - .put("device", "")
112   - .put("os", userAgent.getOs().getName())
113   - .put("referer", "https://www.midjourney.com")
114   - .put("referrer_current", "")
115   - .put("referring_domain", "www.midjourney.com")
116   - .put("referring_domain_current", "")
117   - .put("release_channel", "stable")
118   - .put("system_locale", "zh-CN");
119   - JSONObject presence = new JSONObject()
120   - .put("activities", "")
121   - .put("afk", false)
122   - .put("since", 0)
123   - .put("status", "online");
124   - JSONObject clientState = new JSONObject()
125   - .put("api_code_version", 0)
126   - .put("guild_versions", "")
127   - .put("highest_last_message_id", "0")
128   - .put("private_channels_version", "0")
129   - .put("read_state_version", 0)
130   - .put("user_guild_settings_version", -1)
131   - .put("user_settings_version", -1);
132   - return new JSONObject()
133   - .put("capabilities", 16381)
134   - .put("client_state", clientState)
135   - .put("compress", false)
136   - .put("presence", presence)
137   - .put("properties", connectionProperties)
138   - .put("token", token);
139   - }
140   - }
141   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MidjourneyApi.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo;
2   -
3   -/**
4   - * 文档: https://www.xiubbs.com/t-401-1-1.html
5   - *
6   - * https://github.com/novicezk/midjourney-proxy/blob/main/README_CN.md
7   - *
8   - * discord4j、https://github.com/discord-jda/JDA
9   - *
10   - */
11   -public class MidjourneyApi {
12   -
13   -
14   -// https://discord.com/api/v9/interactions
15   -//
16   -// payload_json: {"type":2,"application_id":"936929561302675456","guild_id":"1224337694918971392","channel_id":"1224337694918971396","session_id":"696318caed5180a2210e358e44801449","data":{"version":"1166847114203123795","id":"938956540159881230","name":"imagine","type":1,"options":[{"type":3,"name":"prompt","value":"中国的是什么样子"}],"application_command":{"id":"938956540159881230","type":1,"application_id":"936929561302675456","version":"1166847114203123795","name":"imagine","description":"Create images with Midjourney","options":[{"type":3,"name":"prompt","description":"The prompt to imagine","required":true,"description_localized":"The prompt to imagine","name_localized":"prompt"}],"dm_permission":true,"integration_types":[0],"global_popularity_rank":1,"description_localized":"Create images with Midjourney","name_localized":"imagine"},"attachments":[]},"nonce":"1224342266261274624","analytics_location":"slash_ui"}
17   -//
18   -
19   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjExecute.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo;
2   -
3   -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum;
4   -
5   -/**
6   - * mj 命令
7   - */
8   -public interface MjExecute {
9   -
10   - /**
11   - * 执行命令
12   - *
13   - * @param mjCommand
14   - * @param prompt
15   - * @return
16   - */
17   - boolean execute(MidjourneyInteractionsEnum mjCommand, String prompt);
18   -
19   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/MjHttpExecute.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo;
2   -
3   -import cn.hutool.core.io.FileUtil;
4   -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum;
5   -import org.springframework.http.HttpEntity;
6   -import org.springframework.http.HttpHeaders;
7   -import org.springframework.http.MediaType;
8   -import org.springframework.web.client.RestTemplate;
9   -
10   -import java.nio.charset.Charset;
11   -
12   -public class MjHttpExecute implements MjExecute {
13   -
14   - private static final String URL = "https://discord.com/";
15   -
16   - @Override
17   - public boolean execute(MidjourneyInteractionsEnum mjCommand, String prompt) {
18   - // 发送的 uri
19   - String uri = "api/v9/interactions";
20   - // restTemplate 发送post请求
21   -// String result = restTemplate.postForObject(URL + uri, prompt, String.class);
22   - // 加载当前目录下文件
23   - return false;
24   - }
25   -
26   - public static void main(String[] args) {
27   - RestTemplate restTemplate = new RestTemplate();
28   -
29   - String token = "NTY5MDY4NDAxNzEyOTU1Mzky.G4-Fu0.MzD-7ll-ElbXTTgDPHF-WS_UyhMAfbKN3WyyBc";
30   - String body = FileUtil.readString("/Users/fansili/projects/github/ruoyi-vue-pro/yudao-module-ai" +
31   - "/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney" +
32   - "/interactions_type2.json", Charset.forName("utf-8"));
33   - // 创建HTTP头部
34   - HttpHeaders headers = new HttpHeaders();
35   - headers.setContentType(MediaType.APPLICATION_JSON); // 设置内容类型为JSON
36   - headers.set("Authorization", token); // 如果需要,设置认证信息(例如JWT令牌)
37   - headers.set("Referer", "https://discord.com/channels/1221445697157468200/1221445862962630706"); // 如果需要,设置认证信息(例如JWT令牌)
38   - 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"); // 如果需要,设置认证信息(例如JWT令牌)
39   - 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"); // 如果需要,设置认证信息(例如JWT令牌)
40   - // 封装请求体和头部信息
41   - HttpEntity<String> requestEntity = new HttpEntity<>(body, headers);
42   -
43   - // 定义请求URL和返回类型
44   - String uri = "api/v9/interactions";
45   - String res = restTemplate.postForObject(URL + uri, requestEntity, String.class);
46   - System.err.println("11");
47   -
48   -
49   - }
50   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/Constants.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.jad;
2   -
3   -import lombok.experimental.UtilityClass;
4   -
5   -@UtilityClass
6   -public final class Constants {
7   - // 任务扩展属性 start
8   - public static final String TASK_PROPERTY_NOTIFY_HOOK = "notifyHook";
9   - public static final String TASK_PROPERTY_FINAL_PROMPT = "finalPrompt";
10   - public static final String TASK_PROPERTY_MESSAGE_ID = "messageId";
11   - public static final String TASK_PROPERTY_MESSAGE_HASH = "messageHash";
12   - public static final String TASK_PROPERTY_PROGRESS_MESSAGE_ID = "progressMessageId";
13   - public static final String TASK_PROPERTY_FLAGS = "flags";
14   - public static final String TASK_PROPERTY_NONCE = "nonce";
15   - public static final String TASK_PROPERTY_DISCORD_INSTANCE_ID = "discordInstanceId";
16   - // 任务扩展属性 end
17   -
18   - public static final String API_SECRET_HEADER_NAME = "mj-api-secret";
19   - public static final String DEFAULT_DISCORD_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36";
20   -
21   - public static final String MJ_MESSAGE_HANDLED = "mj_proxy_handled";
22   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DiscordAccount.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.jad;
2   -
3   -import com.fasterxml.jackson.annotation.JsonIgnore;
4   -import lombok.Data;
5   -import lombok.EqualsAndHashCode;
6   -
7   -@Data
8   -@EqualsAndHashCode(callSuper = true)
9   -
10   -public class DiscordAccount extends DomainObject {
11   -
12   -
13   - private String guildId;
14   -
15   - private String channelId;
16   -
17   - private String userToken;
18   -
19   - private String userAgent = Constants.DEFAULT_DISCORD_USER_AGENT;
20   -
21   -
22   - private boolean enable = true;
23   -
24   -
25   - private int coreSize = 3;
26   -
27   - private int queueSize = 10;
28   -
29   - private int timeoutMinutes = 5;
30   -
31   - @JsonIgnore
32   - public String getDisplay() {
33   - return this.channelId;
34   - }
35   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/jad/DomainObject.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.jad;
2   -
3   -
4   -import com.fasterxml.jackson.annotation.JsonIgnore;
5   -import lombok.Getter;
6   -import lombok.Setter;
7   -
8   -import java.io.Serializable;
9   -import java.util.HashMap;
10   -import java.util.Map;
11   -
12   -
13   -public class DomainObject implements Serializable {
14   - @Getter
15   - @Setter
16   - protected String id;
17   -
18   - @Setter
19   - protected Map<String, Object> properties; // 扩展属性,仅支持基本类型
20   -
21   - @JsonIgnore
22   - private final transient Object lock = new Object();
23   -
24   - public void sleep() throws InterruptedException {
25   - synchronized (this.lock) {
26   - this.lock.wait();
27   - }
28   - }
29   -
30   - public void awake() {
31   - synchronized (this.lock) {
32   - this.lock.notifyAll();
33   - }
34   - }
35   -
36   - public DomainObject setProperty(String name, Object value) {
37   - getProperties().put(name, value);
38   - return this;
39   - }
40   -
41   - public DomainObject removeProperty(String name) {
42   - getProperties().remove(name);
43   - return this;
44   - }
45   -
46   - public Object getProperty(String name) {
47   - return getProperties().get(name);
48   - }
49   -
50   - @SuppressWarnings("unchecked")
51   - public <T> T getPropertyGeneric(String name) {
52   - return (T) getProperty(name);
53   - }
54   -
55   - public <T> T getProperty(String name, Class<T> clz) {
56   - return getProperty(name, clz, null);
57   - }
58   -
59   - public <T> T getProperty(String name, Class<T> clz, T defaultValue) {
60   - Object value = getProperty(name);
61   - return value == null ? defaultValue : clz.cast(value);
62   - }
63   -
64   - public Map<String, Object> getProperties() {
65   - if (this.properties == null) {
66   - this.properties = new HashMap<>();
67   - }
68   - return this.properties;
69   - }
70   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/AsyncLockUtils.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss;
2   -
3   -import cn.hutool.cache.CacheUtil;
4   -import cn.hutool.cache.impl.TimedCache;
5   -import cn.hutool.core.thread.ThreadUtil;
6   -import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DomainObject;
7   -import lombok.experimental.UtilityClass;
8   -
9   -import java.time.Duration;
10   -import java.util.concurrent.ExecutionException;
11   -import java.util.concurrent.Future;
12   -import java.util.concurrent.TimeUnit;
13   -import java.util.concurrent.TimeoutException;
14   -
15   -@UtilityClass
16   -public class AsyncLockUtils {
17   - private static final TimedCache<String, LockObject> LOCK_MAP = CacheUtil.newTimedCache(Duration.ofDays(1).toMillis());
18   -
19   - public static synchronized LockObject getLock(String key) {
20   - return LOCK_MAP.get(key);
21   - }
22   -
23   - public static LockObject waitForLock(String key, Duration duration) throws TimeoutException {
24   - LockObject lockObject;
25   - synchronized (LOCK_MAP) {
26   - if (LOCK_MAP.containsKey(key)) {
27   - lockObject = LOCK_MAP.get(key);
28   - } else {
29   - lockObject = new LockObject(key);
30   - LOCK_MAP.put(key, lockObject);
31   - }
32   - }
33   - Future<?> future = ThreadUtil.execAsync(() -> {
34   - try {
35   - lockObject.sleep();
36   - } catch (InterruptedException e) {
37   - Thread.currentThread().interrupt();
38   - }
39   - });
40   - try {
41   - future.get(duration.toMillis(), TimeUnit.MILLISECONDS);
42   - } catch (InterruptedException e) {
43   - Thread.currentThread().interrupt();
44   - } catch (ExecutionException e) {
45   - // do nothing
46   - } catch (TimeoutException e) {
47   - future.cancel(true);
48   - throw new TimeoutException("Wait Timeout");
49   - } finally {
50   - LOCK_MAP.remove(lockObject.getId());
51   - }
52   - return lockObject;
53   - }
54   -
55   - public static class LockObject extends DomainObject {
56   -
57   - public LockObject(String id) {
58   - this.id = id;
59   - }
60   - }
61   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/DiscordHelper.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss;
2   -
3   -import cn.hutool.core.text.CharSequenceUtil;
4   -import lombok.RequiredArgsConstructor;
5   -import org.springframework.stereotype.Component;
6   -
7   -@Component
8   -@RequiredArgsConstructor
9   -public class DiscordHelper {
10   - /**
11   - * DISCORD_SERVER_URL.
12   - */
13   - public static final String DISCORD_SERVER_URL = "https://discord.com";
14   - /**
15   - * DISCORD_CDN_URL.
16   - */
17   - public static final String DISCORD_CDN_URL = "https://cdn.discordapp.com";
18   - /**
19   - * DISCORD_WSS_URL.
20   - */
21   - public static final String DISCORD_WSS_URL = "wss://gateway.discord.gg";
22   - /**
23   - * DISCORD_UPLOAD_URL.
24   - */
25   - public static final String DISCORD_UPLOAD_URL = "https://discord-attachments-uploads-prd.storage.googleapis.com";
26   -
27   - public String getServer() {
28   - return DISCORD_SERVER_URL;
29   - }
30   -
31   - public String getCdn() {
32   - return DISCORD_CDN_URL;
33   - }
34   -
35   - public String getWss() {
36   - return DISCORD_WSS_URL;
37   - }
38   -
39   - public String getMessageHash(String imageUrl) {
40   - if (CharSequenceUtil.isBlank(imageUrl)) {
41   - return null;
42   - }
43   - if (CharSequenceUtil.endWith(imageUrl, "_grid_0.webp")) {
44   - int hashStartIndex = imageUrl.lastIndexOf("/");
45   - if (hashStartIndex < 0) {
46   - return null;
47   - }
48   - return CharSequenceUtil.sub(imageUrl, hashStartIndex + 1, imageUrl.length() - "_grid_0.webp".length());
49   - }
50   - int hashStartIndex = imageUrl.lastIndexOf("_");
51   - if (hashStartIndex < 0) {
52   - return null;
53   - }
54   - return CharSequenceUtil.subBefore(imageUrl.substring(hashStartIndex + 1), ".", true);
55   - }
56   -
57   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/UserMessageListener.java deleted
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user;
2   -
3   -
4   -import cn.hutool.core.thread.ThreadUtil;
5   -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.MessageType;
6   -import lombok.extern.slf4j.Slf4j;
7   -import net.dv8tion.jda.api.utils.data.DataObject;
8   -
9   -@Slf4j
10   -public class UserMessageListener {
11   -
12   - public void onMessage(DataObject raw) {
13   - MessageType messageType = MessageType.of(raw.getString("t"));
14   - if (messageType == null || MessageType.DELETE == messageType) {
15   - return;
16   - }
17   - DataObject data = raw.getObject("d");
18   - System.err.println(data);
19   - ThreadUtil.sleep(50);
20   -// for (MessageHandler messageHandler : this.messageHandlers) {
21   -// if (data.getBoolean(Constants.MJ_MESSAGE_HANDLED, false)) {
22   -// return;
23   -// }
24   -// messageHandler.handle(this.instance, messageType, data);
25   -// }
26   - }
27   -}
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjImagineInteractions.java
... ... @@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.ai.midjourney.interactions;
3 3 import cn.hutool.core.util.IdUtil;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig;
6   -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum;
  6 +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjInteractionsEnum;
7 7 import com.google.common.collect.Maps;
8 8 import lombok.extern.slf4j.Slf4j;
9 9  
... ... @@ -27,7 +27,7 @@ public class MjImagineInteractions implements MjInteractions {
27 27 }
28 28  
29 29 @Override
30   - public List<MidjourneyInteractionsEnum> supperInteractions() {
  30 + public List<MjInteractionsEnum> supperInteractions() {
31 31 return null;
32 32 }
33 33  
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/interactions/MjInteractions.java
1 1 package cn.iocoder.yudao.framework.ai.midjourney.interactions;
2 2  
3   -import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyInteractionsEnum;
  3 +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjInteractionsEnum;
4 4  
5 5 import java.util.List;
6 6  
... ... @@ -12,7 +12,7 @@ import java.util.List;
12 12 */
13 13 public interface MjInteractions {
14 14  
15   - List<MidjourneyInteractionsEnum> supperInteractions();
  15 + List<MjInteractionsEnum> supperInteractions();
16 16  
17 17 Boolean execute(String prompt);
18 18 }
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/package-info.java deleted
1   -/**
2   - * author: fansili
3   - * time: 2024/4/3 17:08
4   - */
5   -package cn.iocoder.yudao.framework.ai.midjourney;
6 0 \ No newline at end of file
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/FailureCallback.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/FailureCallback.java
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user;
  1 +package cn.iocoder.yudao.framework.ai.midjourney.webSocket;
2 2  
3 3  
4 4 public interface FailureCallback {
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringUserWebSocketStarter.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/MjWebSocketStarter.java
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user;
  1 +package cn.iocoder.yudao.framework.ai.midjourney.webSocket;
2 2  
3 3  
4   -import cn.hutool.core.exceptions.ValidateException;
5 4 import cn.hutool.core.text.CharSequenceUtil;
6 5 import cn.hutool.core.thread.ThreadUtil;
7   -import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DiscordAccount;
8   -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.AsyncLockUtils;
9   -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.ReturnCode;
10   -import cn.iocoder.yudao.framework.ai.midjourney.demo.wss.WebSocketStarter;
  6 +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig;
  7 +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjNotifyCode;
  8 +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler.MjWebSocketHandler;
  9 +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener;
11 10 import lombok.extern.slf4j.Slf4j;
12 11 import org.apache.tomcat.websocket.Constants;
13 12 import org.jetbrains.annotations.NotNull;
... ... @@ -19,15 +18,14 @@ import org.springframework.web.socket.client.standard.StandardWebSocketClient;
19 18  
20 19 import java.io.IOException;
21 20 import java.net.URI;
22   -import java.time.Duration;
23 21 import java.util.concurrent.TimeoutException;
24 22  
25 23 @Slf4j
26   -public class SpringUserWebSocketStarter implements WebSocketStarter {
  24 +public class MjWebSocketStarter implements WebSocketStarter {
27 25 private static final int CONNECT_RETRY_LIMIT = 5;
28 26  
29   - private final DiscordAccount account;
30   - private final UserMessageListener userMessageListener;
  27 + private final MidjourneyConfig midjourneyConfig;
  28 + private final MjMessageListener userMessageListener;
31 29 private final String wssServer;
32 30 private final String resumeWss;
33 31  
... ... @@ -36,10 +34,10 @@ public class SpringUserWebSocketStarter implements WebSocketStarter {
36 34 private WebSocketSession webSocketSession = null;
37 35 private ResumeData resumeData = null;
38 36  
39   - public SpringUserWebSocketStarter(String wssServer, String resumeWss, DiscordAccount account, UserMessageListener userMessageListener) {
  37 + public MjWebSocketStarter(String wssServer, String resumeWss, MidjourneyConfig midjourneyConfig, MjMessageListener userMessageListener) {
40 38 this.wssServer = wssServer;
41 39 this.resumeWss = resumeWss;
42   - this.account = account;
  40 + this.midjourneyConfig = midjourneyConfig;
43 41 this.userMessageListener = userMessageListener;
44 42 }
45 43  
... ... @@ -55,8 +53,8 @@ public class SpringUserWebSocketStarter implements WebSocketStarter {
55 53 headers.add("Cache-Control", "no-cache");
56 54 headers.add("Pragma", "no-cache");
57 55 headers.add("Sec-Websocket-Extensions", "permessage-deflate; client_max_window_bits");
58   - headers.add("User-Agent", this.account.getUserAgent());
59   - var handler = new SpringWebSocketHandler(this.account, this.userMessageListener, this::onSocketSuccess, this::onSocketFailure);
  56 + headers.add("User-Agent", this.midjourneyConfig.getUserAage());
  57 + var handler = new MjWebSocketHandler(this.midjourneyConfig, this.userMessageListener, this::onSocketSuccess, this::onSocketFailure);
60 58 String gatewayUrl;
61 59 if (reconnect) {
62 60 gatewayUrl = getGatewayServer(this.resumeData.resumeGatewayUrl()) + "/?encoding=json&v=9&compress=zlib-stream";
... ... @@ -72,12 +70,12 @@ public class SpringUserWebSocketStarter implements WebSocketStarter {
72 70 socketSessionFuture.addCallback(new ListenableFutureCallback<>() {
73 71 @Override
74 72 public void onFailure(@NotNull Throwable e) {
75   - onSocketFailure(SpringWebSocketHandler.CLOSE_CODE_EXCEPTION, e.getMessage());
  73 + onSocketFailure(MjWebSocketHandler.CLOSE_CODE_EXCEPTION, e.getMessage());
76 74 }
77 75  
78 76 @Override
79 77 public void onSuccess(WebSocketSession session) {
80   - SpringUserWebSocketStarter.this.webSocketSession = session;
  78 + MjWebSocketStarter.this.webSocketSession = session;
81 79 }
82 80 });
83 81 }
... ... @@ -85,7 +83,7 @@ public class SpringUserWebSocketStarter implements WebSocketStarter {
85 83 private void onSocketSuccess(String sessionId, Object sequence, String resumeGatewayUrl) {
86 84 this.resumeData = new ResumeData(sessionId, sequence, resumeGatewayUrl);
87 85 this.running = true;
88   - notifyWssLock(ReturnCode.SUCCESS, "");
  86 + notifyWssLock(MjNotifyCode.SUCCESS, "");
89 87 }
90 88  
91 89 private void onSocketFailure(int code, String reason) {
... ... @@ -99,13 +97,12 @@ public class SpringUserWebSocketStarter implements WebSocketStarter {
99 97 }
100 98 this.running = false;
101 99 if (code >= 4000) {
102   - log.warn("[wss-{}] Can't reconnect! Account disabled. Closed by {}({}).", this.account.getDisplay(), code, reason);
103   - disableAccount();
  100 + log.warn("[wss-{}] Can't reconnect! Account disabled. Closed by {}({}).", this.midjourneyConfig.getChannelId(), code, reason);
104 101 } else if (code == 2001) {
105   - log.warn("[wss-{}] Closed by {}({}). Try reconnect...", this.account.getDisplay(), code, reason);
  102 + log.warn("[wss-{}] Closed by {}({}). Try reconnect...", this.midjourneyConfig.getChannelId(), code, reason);
106 103 tryReconnect();
107 104 } else {
108   - log.warn("[wss-{}] Closed by {}({}). Try new connection...", this.account.getDisplay(), code, reason);
  105 + log.warn("[wss-{}] Closed by {}({}). Try new connection...", this.midjourneyConfig.getChannelId(), code, reason);
109 106 tryNewConnect();
110 107 }
111 108 }
... ... @@ -117,7 +114,7 @@ public class SpringUserWebSocketStarter implements WebSocketStarter {
117 114 if (e instanceof TimeoutException) {
118 115 closeSocketSessionWhenIsOpen();
119 116 }
120   - log.warn("[wss-{}] Reconnect fail: {}, Try new connection...", this.account.getDisplay(), e.getMessage());
  117 + log.warn("[wss-{}] Reconnect fail: {}, Try new connection...", this.midjourneyConfig.getChannelId(), e.getMessage());
121 118 ThreadUtil.sleep(1000);
122 119 tryNewConnect();
123 120 }
... ... @@ -132,39 +129,19 @@ public class SpringUserWebSocketStarter implements WebSocketStarter {
132 129 if (e instanceof TimeoutException) {
133 130 closeSocketSessionWhenIsOpen();
134 131 }
135   - log.warn("[wss-{}] New connect fail ({}): {}", this.account.getDisplay(), i, e.getMessage());
  132 + log.warn("[wss-{}] New connect fail ({}): {}", this.midjourneyConfig.getChannelId(), i, e.getMessage());
136 133 ThreadUtil.sleep(5000);
137 134 }
138 135 }
139   - log.error("[wss-{}] Account disabled", this.account.getDisplay());
140   - disableAccount();
  136 + log.error("[wss-{}] Account disabled", this.midjourneyConfig.getChannelId());
141 137 }
142 138  
143 139 public void tryStart(boolean reconnect) throws Exception {
144 140 start(reconnect);
145   - AsyncLockUtils.LockObject lock = AsyncLockUtils.waitForLock("wss:" + this.account.getId(), Duration.ofSeconds(20));
146   - int code = lock.getProperty("code", Integer.class, 0);
147   - if (code == ReturnCode.SUCCESS) {
148   - log.debug("[wss-{}] {} success.", this.account.getDisplay(), reconnect ? "Reconnect" : "New connect");
149   - return;
150   - }
151   - throw new ValidateException(lock.getProperty("description", String.class));
152 141 }
153 142  
154 143 private void notifyWssLock(int code, String reason) {
155   - AsyncLockUtils.LockObject lock = AsyncLockUtils.getLock("wss:" + this.account.getId());
156   - if (lock != null) {
157   - lock.setProperty("code", code);
158   - lock.setProperty("description", reason);
159   - lock.awake();
160   - }
161   - }
162   -
163   - private void disableAccount() {
164   - if (Boolean.FALSE.equals(this.account.isEnable())) {
165   - return;
166   - }
167   - this.account.setEnable(false);
  144 + System.err.println("notifyWssLock: " + code + " - " + reason);
168 145 }
169 146  
170 147 private void closeSocketSessionWhenIsOpen() {
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SuccessCallback.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/SuccessCallback.java
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user;
  1 +package cn.iocoder.yudao.framework.ai.midjourney.webSocket;
2 2  
3 3  
4 4 public interface SuccessCallback {
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/WebSocketStarter.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/WebSocketStarter.java
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss;
  1 +package cn.iocoder.yudao.framework.ai.midjourney.webSocket;
2 2  
3 3  
4 4 public interface WebSocketStarter {
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/wss/user/SpringWebSocketHandler.java renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/handler/MjWebSocketHandler.java
1   -package cn.iocoder.yudao.framework.ai.midjourney.demo.wss.user;
  1 +package cn.iocoder.yudao.framework.ai.midjourney.webSocket.handler;
2 2  
3 3 import cn.hutool.core.text.CharSequenceUtil;
4 4 import cn.hutool.core.thread.ThreadUtil;
5 5 import cn.hutool.core.util.RandomUtil;
6 6 import cn.hutool.http.useragent.UserAgent;
7 7 import cn.hutool.http.useragent.UserAgentUtil;
8   -import cn.iocoder.yudao.framework.ai.midjourney.demo.jad.DiscordAccount;
  8 +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig;
  9 +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.FailureCallback;
  10 +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.SuccessCallback;
  11 +import cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener.MjMessageListener;
9 12 import lombok.Setter;
10 13 import lombok.extern.slf4j.Slf4j;
11 14 import net.dv8tion.jda.api.utils.data.DataArray;
... ... @@ -26,13 +29,13 @@ import java.util.concurrent.ScheduledExecutorService;
26 29 import java.util.concurrent.TimeUnit;
27 30  
28 31 @Slf4j
29   -public class SpringWebSocketHandler implements WebSocketHandler {
  32 +public class MjWebSocketHandler implements WebSocketHandler {
30 33 public static final int CLOSE_CODE_RECONNECT = 2001;
31 34 public static final int CLOSE_CODE_INVALIDATE = 1009;
32 35 public static final int CLOSE_CODE_EXCEPTION = 1011;
33 36  
34   - private final DiscordAccount account;
35   - private final UserMessageListener userMessageListener;
  37 + private final MidjourneyConfig midjourneyConfig;
  38 + private final MjMessageListener userMessageListener;
36 39 private final SuccessCallback successCallback;
37 40 private final FailureCallback failureCallback;
38 41  
... ... @@ -54,8 +57,11 @@ public class SpringWebSocketHandler implements WebSocketHandler {
54 57  
55 58 private final Decompressor decompressor = new ZlibDecompressor(2048);
56 59  
57   - public SpringWebSocketHandler(DiscordAccount account, UserMessageListener userMessageListener, SuccessCallback successCallback, FailureCallback failureCallback) {
58   - this.account = account;
  60 + public MjWebSocketHandler(MidjourneyConfig account,
  61 + MjMessageListener userMessageListener,
  62 + SuccessCallback successCallback,
  63 + FailureCallback failureCallback) {
  64 + this.midjourneyConfig = account;
59 65 this.userMessageListener = userMessageListener;
60 66 this.successCallback = successCallback;
61 67 this.failureCallback = failureCallback;
... ... @@ -70,7 +76,7 @@ public class SpringWebSocketHandler implements WebSocketHandler {
70 76  
71 77 @Override
72 78 public void handleTransportError(@NotNull WebSocketSession session, @NotNull Throwable e) throws Exception {
73   - log.error("[wss-{}] Transport error", this.account.getDisplay(), e);
  79 + log.error("[wss-{}] Transport error", this.midjourneyConfig.getChannelId(), e);
74 80 onFailure(CLOSE_CODE_EXCEPTION, "transport error");
75 81 }
76 82  
... ... @@ -108,7 +114,7 @@ public class SpringWebSocketHandler implements WebSocketHandler {
108 114 case WebSocketCode.RECONNECT -> onFailure(CLOSE_CODE_RECONNECT, "receive server reconnect");
109 115 case WebSocketCode.INVALIDATE_SESSION -> onFailure(CLOSE_CODE_INVALIDATE, "receive session invalid");
110 116 case WebSocketCode.DISPATCH -> handleDispatch(data);
111   - default -> log.debug("[wss-{}] Receive unknown code: {}.", account.getDisplay(), data);
  117 + default -> log.debug("[wss-{}] Receive unknown code: {}.", midjourneyConfig.getChannelId(), data);
112 118 }
113 119 }
114 120  
... ... @@ -129,7 +135,7 @@ public class SpringWebSocketHandler implements WebSocketHandler {
129 135 try {
130 136 this.userMessageListener.onMessage(raw);
131 137 } catch (Exception e) {
132   - log.error("[wss-{}] Handle message error", this.account.getDisplay(), e);
  138 + log.error("[wss-{}] Handle message error", this.midjourneyConfig.getChannelId(), e);
133 139 }
134 140 }
135 141 }
... ... @@ -160,7 +166,7 @@ public class SpringWebSocketHandler implements WebSocketHandler {
160 166 if (CharSequenceUtil.isBlank(this.sessionId)) {
161 167 sendMessage(session, WebSocketCode.IDENTIFY, this.authData);
162 168 } else {
163   - var data = DataObject.empty().put("token", this.account.getUserToken())
  169 + var data = DataObject.empty().put("token", this.midjourneyConfig.getToken())
164 170 .put("session_id", this.sessionId).put("seq", this.sequence);
165 171 sendMessage(session, WebSocketCode.RESUME, data);
166 172 }
... ... @@ -171,7 +177,7 @@ public class SpringWebSocketHandler implements WebSocketHandler {
171 177 try {
172 178 session.sendMessage(new TextMessage(data.toString()));
173 179 } catch (IOException e) {
174   - log.error("[wss-{}] Send message error", this.account.getDisplay(), e);
  180 + log.error("[wss-{}] Send message error", this.midjourneyConfig.getChannelId(), e);
175 181 onFailure(CLOSE_CODE_EXCEPTION, "send message error");
176 182 }
177 183 }
... ... @@ -201,10 +207,10 @@ public class SpringWebSocketHandler implements WebSocketHandler {
201 207 }
202 208  
203 209 private DataObject createAuthData() {
204   - UserAgent userAgent = UserAgentUtil.parse(this.account.getUserAgent());
  210 + UserAgent userAgent = UserAgentUtil.parse(this.midjourneyConfig.getUserAage());
205 211 DataObject connectionProperties = DataObject.empty()
206 212 .put("browser", userAgent.getBrowser().getName())
207   - .put("browser_user_agent", this.account.getUserAgent())
  213 + .put("browser_user_agent", this.midjourneyConfig.getUserAage())
208 214 .put("browser_version", userAgent.getVersion())
209 215 .put("client_build_number", 222963)
210 216 .put("client_event_source", null)
... ... @@ -235,6 +241,6 @@ public class SpringWebSocketHandler implements WebSocketHandler {
235 241 .put("compress", false)
236 242 .put("presence", presence)
237 243 .put("properties", connectionProperties)
238   - .put("token", this.account.getUserToken());
  244 + .put("token", this.midjourneyConfig.getToken());
239 245 }
240 246 }
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/webSocket/listener/MjMessageListener.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.ai.midjourney.webSocket.listener;
  2 +
  3 +
  4 +import cn.hutool.core.text.CharSequenceUtil;
  5 +import cn.iocoder.yudao.framework.ai.midjourney.MidjourneyConfig;
  6 +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjConstants;
  7 +import cn.iocoder.yudao.framework.ai.midjourney.constants.MjMessageTypeEnum;
  8 +import lombok.extern.slf4j.Slf4j;
  9 +import net.dv8tion.jda.api.utils.data.DataObject;
  10 +
  11 +@Slf4j
  12 +public class MjMessageListener {
  13 +
  14 + private MidjourneyConfig midjourneyConfig;
  15 +
  16 + public MjMessageListener(MidjourneyConfig midjourneyConfig) {
  17 + this.midjourneyConfig = midjourneyConfig;
  18 + }
  19 +
  20 + public void onMessage(DataObject raw) {
  21 + MjMessageTypeEnum messageType = MjMessageTypeEnum.of(raw.getString("t"));
  22 + if (messageType == null || MjMessageTypeEnum.DELETE == messageType) {
  23 + return;
  24 + }
  25 + DataObject data = raw.getObject("d");
  26 + if (ignoreAndLogMessage(data, messageType)) {
  27 + return;
  28 + }
  29 + System.err.println(data);
  30 +// if (data.getBoolean(Constants.MJ_MESSAGE_HANDLED, false)) {
  31 +// return;
  32 +// }
  33 + }
  34 +
  35 + private boolean ignoreAndLogMessage(DataObject data, MjMessageTypeEnum messageType) {
  36 + String channelId = data.getString(MjConstants.CHANNEL_ID);
  37 + if (!CharSequenceUtil.equals(channelId, midjourneyConfig.getChannelId())) {
  38 + return true;
  39 + }
  40 + String authorName = data.optObject("author").map(a -> a.getString("username")).orElse("System");
  41 + log.debug("{} - {} - {}: {}", midjourneyConfig.getChannelId(), messageType.name(), authorName, data.opt("content").orElse(""));
  42 + return false;
  43 + }
  44 +}
... ...
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type2.json renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type2.json
yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/midjourney/demo/interactions_type3.json renamed to yudao-module-ai/yudao-spring-boot-starter-ai/src/main/resources/http-body/interactions_type3.json