diff --git a/docs/config.md b/docs/config.md
index af449b64..c8355aa2 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -20,6 +20,7 @@
| mj.ng-discord.server | 否 | https://discord.com 反代地址 |
| mj.ng-discord.cdn | 否 | https://cdn.discordapp.com 反代地址 |
| mj.ng-discord.wss | 否 | wss://gateway.discord.gg 反代地址 |
+| mj.ng-discord.upload-server | 否 | https://discord-attachments-uploads-prd.storage.googleapis.com 反代地址 |
| mj.translate-way | 否 | 中文prompt翻译成英文的方式,可选null(默认)、baidu、gpt |
| mj.baidu-translate.appid | 否 | 百度翻译的appid |
| mj.baidu-translate.app-secret | 否 | 百度翻译的app-secret |
diff --git a/docs/docker-start.md b/docs/docker-start.md
index ae6a3e20..55d2335e 100644
--- a/docs/docker-start.md
+++ b/docs/docker-start.md
@@ -6,7 +6,7 @@
docker run -d --name midjourney-proxy \
-p 8080:8080 \
-v /xxx/xxx/config:/home/spring/config \
- kratos1937/midjourney-proxy:v1.0.7
+ kratos1937/midjourney-proxy:v1.1.0
```
3. 访问 `http://ip:port/mj` 查看API文档
@@ -17,5 +17,5 @@ docker run -d --name midjourney-proxy \
-e mj.discord.guild-id=xxx \
-e mj.discord.channel-id=xxx \
-e mj.discord.user-token=xxx \
- kratos1937/midjourney-proxy:v1.0.8
+ kratos1937/midjourney-proxy:v1.1.0
```
diff --git a/pom.xml b/pom.xml
index 6b50d7e3..140c6863 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
5.8.18
20220924
5.0.0-beta.9
- 1.1.1-beta0
+ 1.1.2-beta0
2.0.0
4.1.0
1.21
diff --git a/src/main/java/com/github/novicezk/midjourney/ProxyProperties.java b/src/main/java/com/github/novicezk/midjourney/ProxyProperties.java
index ae4ae488..2455f850 100644
--- a/src/main/java/com/github/novicezk/midjourney/ProxyProperties.java
+++ b/src/main/java/com/github/novicezk/midjourney/ProxyProperties.java
@@ -187,6 +187,10 @@ public static class NgDiscordConfig {
* wss://gateway.discord.gg 反代.
*/
private String wss;
+ /**
+ * https://discord-attachments-uploads-prd.storage.googleapis.com 反代.
+ */
+ private String uploadServer;
}
@Data
diff --git a/src/main/java/com/github/novicezk/midjourney/loadbalancer/DiscordInstance.java b/src/main/java/com/github/novicezk/midjourney/loadbalancer/DiscordInstance.java
index 61994dbf..fcb89704 100644
--- a/src/main/java/com/github/novicezk/midjourney/loadbalancer/DiscordInstance.java
+++ b/src/main/java/com/github/novicezk/midjourney/loadbalancer/DiscordInstance.java
@@ -2,7 +2,6 @@
import com.github.novicezk.midjourney.domain.DiscordAccount;
-import com.github.novicezk.midjourney.enums.TaskAction;
import com.github.novicezk.midjourney.result.Message;
import com.github.novicezk.midjourney.result.SubmitResultVO;
import com.github.novicezk.midjourney.service.DiscordService;
diff --git a/src/main/java/com/github/novicezk/midjourney/loadbalancer/DiscordInstanceImpl.java b/src/main/java/com/github/novicezk/midjourney/loadbalancer/DiscordInstanceImpl.java
index b68399b0..2c922f22 100644
--- a/src/main/java/com/github/novicezk/midjourney/loadbalancer/DiscordInstanceImpl.java
+++ b/src/main/java/com/github/novicezk/midjourney/loadbalancer/DiscordInstanceImpl.java
@@ -42,13 +42,12 @@ public class DiscordInstanceImpl implements DiscordInstance {
private final Map> taskFutureMap = Collections.synchronizedMap(new HashMap<>());
public DiscordInstanceImpl(DiscordAccount account, UserWebSocketStarter socketStarter, RestTemplate restTemplate,
- TaskStoreService taskStoreService, NotifyService notifyService,
- String discordServer, Map paramsMap) {
+ TaskStoreService taskStoreService, NotifyService notifyService, Map paramsMap) {
this.account = account;
this.socketStarter = socketStarter;
this.taskStoreService = taskStoreService;
this.notifyService = notifyService;
- this.service = new DiscordServiceImpl(account, restTemplate, discordServer, paramsMap);
+ this.service = new DiscordServiceImpl(account, restTemplate, paramsMap);
this.runningTasks = new CopyOnWriteArrayList<>();
this.taskExecutor = new ThreadPoolTaskExecutor();
this.taskExecutor.setCorePoolSize(account.getCoreSize());
diff --git a/src/main/java/com/github/novicezk/midjourney/loadbalancer/rule/BestWaitIdleRule.java b/src/main/java/com/github/novicezk/midjourney/loadbalancer/rule/BestWaitIdleRule.java
index f214df79..c277f099 100644
--- a/src/main/java/com/github/novicezk/midjourney/loadbalancer/rule/BestWaitIdleRule.java
+++ b/src/main/java/com/github/novicezk/midjourney/loadbalancer/rule/BestWaitIdleRule.java
@@ -1,12 +1,16 @@
package com.github.novicezk.midjourney.loadbalancer.rule;
+import cn.hutool.core.util.RandomUtil;
import com.github.novicezk.midjourney.loadbalancer.DiscordInstance;
+import java.util.Comparator;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
/**
* 最少等待空闲.
- * 选择等待数最少的实例,如果都不需要等待,则选择空闲数最多的实例
+ * 选择等待数最少的实例,如果都不需要等待,则随机选择
*/
public class BestWaitIdleRule implements IRule {
@@ -15,17 +19,13 @@ public DiscordInstance choose(List instances) {
if (instances.isEmpty()) {
return null;
}
- return instances.stream().min((i1, i2) -> {
- int wait1 = i1.getRunningFutures().size() - i1.account().getCoreSize();
- int wait2 = i2.getRunningFutures().size() - i2.account().getCoreSize();
- if (wait1 == wait2 && wait1 == 0) {
- // 都不需要等待时,选择空闲数最多的
- int idle1 = i1.account().getCoreSize() - i1.getRunningTasks().size();
- int idle2 = i2.account().getCoreSize() - i2.getRunningTasks().size();
- return idle2 - idle1;
- }
- return wait1 - wait2;
- }).orElse(null);
+ Map> map = instances.stream()
+ .collect(Collectors.groupingBy(i -> {
+ int wait = i.getRunningFutures().size() - i.account().getCoreSize();
+ return wait >= 0 ? wait : -1;
+ }));
+ List instanceList = map.entrySet().stream().min(Comparator.comparingInt(Map.Entry::getKey)).orElseThrow().getValue();
+ return RandomUtil.randomEle(instanceList);
}
}
diff --git a/src/main/java/com/github/novicezk/midjourney/service/DiscordServiceImpl.java b/src/main/java/com/github/novicezk/midjourney/service/DiscordServiceImpl.java
index babe6430..e600b80c 100644
--- a/src/main/java/com/github/novicezk/midjourney/service/DiscordServiceImpl.java
+++ b/src/main/java/com/github/novicezk/midjourney/service/DiscordServiceImpl.java
@@ -6,11 +6,17 @@
import com.github.novicezk.midjourney.domain.DiscordAccount;
import com.github.novicezk.midjourney.enums.BlendDimensions;
import com.github.novicezk.midjourney.result.Message;
+import com.github.novicezk.midjourney.support.DiscordHelper;
+import com.github.novicezk.midjourney.support.SpringContextHolder;
import eu.maxschuster.dataurl.DataUrl;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONArray;
import org.json.JSONObject;
-import org.springframework.http.*;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
@@ -24,21 +30,21 @@ public class DiscordServiceImpl implements DiscordService {
private final DiscordAccount account;
private final Map paramsMap;
private final RestTemplate restTemplate;
+ private final DiscordHelper discordHelper;
private final String discordInteractionUrl;
private final String discordAttachmentUrl;
private final String discordMessageUrl;
- private final String regionUrl;
-
- public DiscordServiceImpl(DiscordAccount account, RestTemplate restTemplate, String discordServer, Map paramsMap) {
+ public DiscordServiceImpl(DiscordAccount account, RestTemplate restTemplate, Map paramsMap) {
this.account = account;
this.restTemplate = restTemplate;
+ this.discordHelper = SpringContextHolder.getApplicationContext().getBean(DiscordHelper.class);
this.paramsMap = paramsMap;
+ String discordServer = this.discordHelper.getServer();
this.discordInteractionUrl = discordServer + "/api/v9/interactions";
this.discordAttachmentUrl = discordServer + "/api/v9/channels/" + account.getChannelId() + "/attachments";
this.discordMessageUrl = discordServer + "/api/v9/channels/" + account.getChannelId() + "/messages";
- this.regionUrl = "https://936929561302675456.discordsays.com/inpaint/api/submit-job";
}
@Override
@@ -116,7 +122,6 @@ public Message vary(String messageId, String messageHash, String nonce, St
.replace("$vary",vary)
.replace("$message_id", messageId)
.replace("$message_hash", messageHash);
-
return postJsonAndCheckStatus(paramsStr);
}
@@ -222,6 +227,7 @@ public Message sendImageMessage(String content, String finalFileName) {
}
private void putFile(String uploadUrl, DataUrl dataUrl) {
+ uploadUrl = this.discordHelper.getDiscordUploadUrl(uploadUrl);
HttpHeaders headers = new HttpHeaders();
headers.add("User-Agent", this.account.getUserAgent());
headers.setContentType(MediaType.valueOf(dataUrl.getMimeType()));
diff --git a/src/main/java/com/github/novicezk/midjourney/support/DiscordAccountHelper.java b/src/main/java/com/github/novicezk/midjourney/support/DiscordAccountHelper.java
index 4ce5875f..1d15a978 100644
--- a/src/main/java/com/github/novicezk/midjourney/support/DiscordAccountHelper.java
+++ b/src/main/java/com/github/novicezk/midjourney/support/DiscordAccountHelper.java
@@ -38,7 +38,6 @@ public DiscordInstance createDiscordInstance(DiscordAccount account) {
var messageListener = new UserMessageListener(account, this.messageHandlers);
var webSocketStarter = new UserWebSocketStarter(this.discordHelper.getWss(), account, messageListener, this.properties.getProxy());
return new DiscordInstanceImpl(account, webSocketStarter, this.restTemplate,
- this.taskStoreService, this.notifyService,
- this.discordHelper.getServer(), this.paramsMap);
+ this.taskStoreService, this.notifyService, this.paramsMap);
}
}
diff --git a/src/main/java/com/github/novicezk/midjourney/support/DiscordHelper.java b/src/main/java/com/github/novicezk/midjourney/support/DiscordHelper.java
index 0107c112..44ec2c26 100644
--- a/src/main/java/com/github/novicezk/midjourney/support/DiscordHelper.java
+++ b/src/main/java/com/github/novicezk/midjourney/support/DiscordHelper.java
@@ -21,6 +21,10 @@ public class DiscordHelper {
* DISCORD_WSS_URL.
*/
public static final String DISCORD_WSS_URL = "wss://gateway.discord.gg";
+ /**
+ * DISCORD_UPLOAD_URL.
+ */
+ public static final String DISCORD_UPLOAD_URL = "https://discord-attachments-uploads-prd.storage.googleapis.com";
public String getServer() {
if (CharSequenceUtil.isBlank(this.properties.getNgDiscord().getServer())) {
@@ -55,6 +59,17 @@ public String getWss() {
return wssUrl;
}
+ public String getDiscordUploadUrl(String uploadUrl) {
+ if (CharSequenceUtil.isBlank(this.properties.getNgDiscord().getUploadServer()) || CharSequenceUtil.isBlank(uploadUrl)) {
+ return uploadUrl;
+ }
+ String uploadServer = this.properties.getNgDiscord().getUploadServer();
+ if (uploadServer.endsWith("/")) {
+ uploadServer = uploadServer.substring(0, uploadServer.length() - 1);
+ }
+ return uploadUrl.replaceFirst(DISCORD_UPLOAD_URL, uploadServer);
+ }
+
public String findTaskIdWithCdnUrl(String url) {
if (!CharSequenceUtil.startWith(url, DISCORD_CDN_URL)) {
return null;
diff --git a/src/main/java/com/github/novicezk/midjourney/support/SpringContextHolder.java b/src/main/java/com/github/novicezk/midjourney/support/SpringContextHolder.java
new file mode 100644
index 00000000..058c201f
--- /dev/null
+++ b/src/main/java/com/github/novicezk/midjourney/support/SpringContextHolder.java
@@ -0,0 +1,23 @@
+package com.github.novicezk.midjourney.support;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SpringContextHolder implements ApplicationContextAware {
+ private static ApplicationContext APPLICATION_CONTEXT;
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ APPLICATION_CONTEXT = applicationContext;
+ }
+
+ public static ApplicationContext getApplicationContext() {
+ if (APPLICATION_CONTEXT == null) {
+ throw new IllegalStateException("SpringContextHolder is not ready.");
+ }
+ return APPLICATION_CONTEXT;
+ }
+}
diff --git a/src/main/resources/api-params/list-settings.json b/src/main/resources/api-params/list-settings.json
new file mode 100644
index 00000000..c8cc8c8f
--- /dev/null
+++ b/src/main/resources/api-params/list-settings.json
@@ -0,0 +1,32 @@
+{
+ "type": 2,
+ "application_id": "936929561302675456",
+ "guild_id": "$guild_id",
+ "channel_id": "$channel_id",
+ "session_id": "12b3d9d8dbc0db4536a0fc4664ab7bad",
+ "data": {
+ "version": "1166847114609958943",
+ "id": "1000850743479255081",
+ "name": "settings",
+ "type": 1,
+ "options": [],
+ "application_command": {
+ "id": "1000850743479255081",
+ "application_id": "936929561302675456",
+ "version": "1166847114609958943",
+ "default_member_permissions": null,
+ "type": 1,
+ "nsfw": false,
+ "name": "settings",
+ "description": "View and adjust your personal settings.",
+ "dm_permission": true,
+ "contexts": null,
+ "integration_types": [
+ 0
+ ]
+ },
+ "attachments": []
+ },
+ "nonce": "$nonce",
+ "analytics_location": "slash_ui"
+}
\ No newline at end of file
diff --git a/src/main/resources/api-params/settings.json b/src/main/resources/api-params/settings.json
index fe14072e..1f1f3f6e 100644
--- a/src/main/resources/api-params/settings.json
+++ b/src/main/resources/api-params/settings.json
@@ -4,7 +4,7 @@
"guild_id": "$guild_id",
"channel_id": "$channel_id",
"message_flags": 64,
- "message_id": "1160405256170110986",
+ "message_id": "1174275851265781770",
"application_id": "936929561302675456",
"session_id": "$session_id",
"data": {
diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt
index 5f7c1938..a3581415 100644
--- a/src/main/resources/banner.txt
+++ b/src/main/resources/banner.txt
@@ -5,4 +5,4 @@ ___ _(/ ___ __ __ _ __ __ _____/
.-/ .-/ .-/ / .-/
(_/ (_/ (_/ (_/
-:: MidJourney Proxy :: v2.5.4
+:: MidJourney Proxy :: v2.5.5
diff --git a/src/main/resources/config/application.yml b/src/main/resources/config/application.yml
index 0c607145..1ae61c20 100644
--- a/src/main/resources/config/application.yml
+++ b/src/main/resources/config/application.yml
@@ -13,7 +13,7 @@ knife4j:
description: 代理 MidJourney 的discord频道,实现api形式调用AI绘图
concat: novicezk
url: https://github.com/novicezk/midjourney-proxy
- version: v2.5.4
+ version: v2.5.5
terms-of-service-url: https://github.com/novicezk/midjourney-proxy
group:
api: