diff --git a/.gitignore b/.gitignore index 0d5e07a..bb36621 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ **/build/ **/.idea/ !src/**/build/ +!src/test/ # Ignore Gradle GUI config gradle-app.setting diff --git a/CozeProxy/build.gradle b/CozeProxy/build.gradle index 8218ebb..dfd21b6 100644 --- a/CozeProxy/build.gradle +++ b/CozeProxy/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java' +<<<<<<< HEAD id 'com.github.johnrengelman.shadow' version '7.1.2' } @@ -7,6 +8,8 @@ build{ dependsOn { shadowJar } +======= +>>>>>>> dev } jar { @@ -23,13 +26,21 @@ tasks.withType(JavaCompile).configureEach { } group = 'catx.feitu' +<<<<<<< HEAD version = '1.0.0213' +======= +version = '1.0.0222' +>>>>>>> dev repositories { mavenCentral() } dependencies { +<<<<<<< HEAD +======= + // 协议 +>>>>>>> dev // Discord API implementation 'org.javacord:javacord:3.8.0' @@ -38,4 +49,14 @@ dependencies { implementation "com.slack.api:bolt-servlet:1.38.1" implementation "com.slack.api:bolt-jetty:1.38.1" implementation "org.slf4j:slf4j-simple:1.7.36" +<<<<<<< HEAD } +======= + + // 依赖 + // fastjson + implementation 'com.alibaba:fastjson:1.1.77.android_noneautotype' + + implementation project(':DiscordSelfBot') +} +>>>>>>> dev diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/ConversationManage/ConversationData.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/ConversationManage/ConversationData.java similarity index 87% rename from src/main/java/catx/feitu/coze_discord_bridge/api/ConversationManage/ConversationData.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/ConversationManage/ConversationData.java index 00ef095..f8f6757 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/ConversationManage/ConversationData.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/ConversationManage/ConversationData.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.ConversationManage; +package catx.feitu.CozeProxy.ConversationManage; import java.util.concurrent.ConcurrentHashMap; @@ -9,6 +9,7 @@ public ConversationData(ConcurrentHashMap conversations) { this.conversations = conversations; } public void put(String name,String conversationID) { + if (name == null || conversationID == null) { return; } conversations.put(name, conversationID); } diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/ConversationManage/ConversationHelper.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/ConversationManage/ConversationHelper.java similarity index 95% rename from src/main/java/catx/feitu/coze_discord_bridge/api/ConversationManage/ConversationHelper.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/ConversationManage/ConversationHelper.java index 4da34c5..0ff30e1 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/ConversationManage/ConversationHelper.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/ConversationManage/ConversationHelper.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.ConversationManage; +package catx.feitu.CozeProxy.ConversationManage; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/CozeGPT.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/CozeGPT.java new file mode 100644 index 0000000..e132741 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/CozeGPT.java @@ -0,0 +1,280 @@ +package catx.feitu.CozeProxy; + +import catx.feitu.CozeProxy.ConversationManage.ConversationData; +import catx.feitu.CozeProxy.Exceptions.*; +import catx.feitu.CozeProxy.Listen.CozeEventListener; +import catx.feitu.CozeProxy.LockManage.LockManage; +import catx.feitu.CozeProxy.Protocol.ProtocolUtil; +import catx.feitu.CozeProxy.Protocol.Types.UploadFile; +import catx.feitu.CozeProxy.Protocol.UniversalEventListenerConfig; +import catx.feitu.CozeProxy.Types.ConversationInfo; +import catx.feitu.CozeProxy.Types.GPTFile; +import catx.feitu.CozeProxy.Types.GenerateMessage; +import catx.feitu.CozeProxy.FunctionalInterface.ChatStreamEvent; +import catx.feitu.CozeProxy.MessageManage.BotResponseType; + +import java.io.ByteArrayInputStream; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class CozeGPT { + private final CozeGPTConfig config; + private final LockManage LockManage = new LockManage(); + public CozeEventListener cozeEventListener; + public ConversationData conversations = new ConversationData(); + public ProtocolUtil protocol = new ProtocolUtil(); + + + public CozeGPT(CozeGPTConfig config) { + this.config = config; + } + public CozeGPT(CozeGPTConfig config,boolean autoLogin) throws Exception { + this.config = config; + if (autoLogin) { + this.login(); + } + } + /** + * Discord登录 + */ + public void login() throws Exception { + cozeEventListener = new CozeEventListener(); + protocol.setConfig(new UniversalEventListenerConfig(config.serverID ,config.botID)); + protocol.eventListener = cozeEventListener; + protocol.login(config.loginApp ,config.token ,config.Proxy ,config.token2); + } + /** + * Discord登出 + * + * @throws Exception 如果Bot未登录,可能会抛出 BotNotLoginException 异常 + */ + public void disconnect() throws Exception { + protocol.disconnect(); + } + /** + * 获取标记 + */ + public String getMark() { + return config.Mark; + } + /** + * 设置标记 + */ + public void setMark(String mark) { + config.Mark = mark; + } + /** + * 发送一条消息到对话列表并等待Bot回复 + * + * @param Prompts 提示词,即用户发送的消息,可以填入url上传附件. + * @param conversationName 对话ID/名称,可通过 CreateConversation(String name); 获取,必须提供,用于储存上下文信息. + * @param Files 上传本地文件,可为多个. + * @param event 填入以支持消息流返回,返回 true 继续生成,返回 false 停止生成. + * @return 生成的消息信息. + * @throws Exception 如果消息生成过程遇到任何问题,则抛出异常. + */ + public catx.feitu.CozeProxy.Types.GenerateMessage chat(String Prompts, String conversationName, List Files, ChatStreamEvent event) throws Exception { + if (Objects.equals(Prompts, "") || Prompts == null) { + throw new InvalidPromptException(); + } + String conversationID = conversations.get(conversationName); + // 锁定 避免同频道多次对话 + LockManage.getLock(conversationID).lock(); + // 初始化回复记录 + cozeEventListener.botGenerateStatusManage.clearGenerateStatus(conversationID); + cozeEventListener.botResponseManage.clearMsg(conversationID); + // 开始 + try { + String sendMessage = protocol.code.mentionUser(config.botID); + List sendFiles = new ArrayList<>(); + if (Prompts.length() > 2000) { // 长文本发送消息 + if (!config.Disable_2000Limit_Unlock) { + throw new PromptTooLongException(Prompts,2000); + } + + sendMessage += config.promptOnSendMore2000Prefix; + sendFiles.add(new UploadFile(new ByteArrayInputStream(Prompts.getBytes()),config.promptOnSendMore2000FileName)); + } else { + sendMessage += Prompts; + } + // 发送附件(图片)处理 + if (Files != null) { + for (GPTFile file : Files) { + sendFiles.add(new UploadFile(file.GetByteArrayInputStream() ,file.GetFileName())); + } + } + protocol.sendMessage(conversationID ,sendMessage ,sendFiles); + // 在此之下为bot回复消息处理阶段 -> 5s 超时 + boolean BotStartGenerate = false; + int attempt = 0; // 重试次数 + int maxRetries = 25; // 最大尝试次数 + /* + while (!BotStartGenerate) { + attempt++; + if (attempt > maxRetries) { + throw new RecvMsgException("超时无回应:未开始生成"); + } + BotStartGenerate = cozeEventListener.botGenerateStatusManage.getGenerateStatus(conversationID); + System.out.println(BotStartGenerate + conversationID); + // 等待200ms + try { Thread.sleep(200); } catch (InterruptedException ignored) {} + } + */ + BotResponseType Response = new BotResponseType(); + String LatestMessage = ""; + attempt = 0; // 重置重试次数 + maxRetries = 120; // 最大尝试次数 + // 超时 2 分钟 + while (!Response.IsCompleted(config.generate_timeout)) { + attempt++; + if (attempt > maxRetries) { + throw new RecvMsgException("超时无回应:超过设定时间"); + } + try { + Response = cozeEventListener.botResponseManage.getMsg(conversationID); + } catch (NullPointerException ignored) {} + if (!event.handle(Response.prompt, Response.prompt.replace(LatestMessage,""))) { + throw new StopGenerateException(); + } + LatestMessage = Response.prompt; + try { Thread.sleep(500); } catch (InterruptedException ignored) {} + } + GenerateMessage return_info = new GenerateMessage(); + return_info.Message = Response.prompt; + return_info.Files = Response.files; + LockManage.getLock(conversationID).unlock(); + return return_info; + } catch (Exception e) { + LockManage.getLock(conversationID).unlock(); + throw e; + } + } + /** + * 发送一条消息到对话列表并等待Bot回复 + * + * @param Prompts 提示词,即用户发送的消息,可以填入url上传附件. + * @param ConversationID 对话ID,可通过 CreateConversation(String name); 获取,必须提供,用于储存上下文信息. + * @param Files 上传本地文件,可为多个. + * @return 生成的消息信息. + * @throws Exception 如果消息生成过程遇到任何问题,则抛出异常. + */ + public GenerateMessage chat(String Prompts, String ConversationID, List Files) throws Exception { + return chat(Prompts ,ConversationID ,Files ,(ALLGenerateMessages, NewGenerateMessage) -> { return true; }); + } + /** + * 发送一条消息到对话列表并等待Bot回复 + * + * @param Prompts 提示词,即用户发送的消息,可以填入url上传附件. + * @param ConversationID 对话ID,可通过 CreateConversation(String name); 获取,必须提供,用于储存上下文信息. + * @param event 填入以支持消息流返回,返回 true 继续生成,返回 false 停止生成. + * @return 生成的消息信息. + * @throws Exception 如果消息生成过程遇到任何问题,则抛出异常. + */ + public GenerateMessage chat(String Prompts, String ConversationID, ChatStreamEvent event) throws Exception { + return chat(Prompts ,ConversationID ,null ,event); + } + /** + * 发送一条消息到对话列表并等待Bot回复 + * + * @param Prompts 提示词,即用户发送的消息,可以填入url上传附件. + * @param ConversationID 对话ID,可通过 CreateConversation(String name); 获取,必须提供,用于储存上下文信息. + * @return 生成的消息信息. + * @throws Exception 如果消息生成过程遇到任何问题,则抛出异常. + */ + public GenerateMessage chat(String Prompts, String ConversationID) throws Exception { + return chat(Prompts ,ConversationID ,(ALLGenerateMessages, NewGenerateMessage) -> { return true; }); + } + /** + * 创建新的对话列表 + * + * @param conversationName 对话名词,如果没有关闭对话名词索引功能则后续可以通过对话名词调用对话 + * @return 对话ID,一段数字,后续可通过此ID调用 + * @throws Exception 如果遇到任何问题,则抛出异常. + */ + public String createConversation (String conversationName) throws Exception { + // 已有对话名称检查 + if (protocol.isChannelFound(conversations.get(conversationName))) { + throw new ConversationAlreadyExistsException(conversationName); + } + String conversationID = protocol.createChannel(conversationName ,config.Discord_CreateChannel_Category); + protocol.inviteBotInChannel(conversationID ,config.botID); + // 写入存储 + conversations.put(conversationName ,conversationID); + // 返回数据 + return conversationID; + } + /** + * 创建新的对话列表 + * + * @return 对话ID,一段数字,后续可通过此ID调用 + * @throws Exception 如果遇到任何问题,则抛出异常. + */ + public String createConversation () throws Exception { + return createConversation(null); + } + /** + * 删除对话列表 + * + * @param conversationName 对话名词/对话ID + * @throws Exception 如果遇到任何问题,则抛出异常. + */ + public void deleteConversation (String conversationName) throws Exception { + protocol.deleteChannel(conversations.get(conversationName)); + conversations.remove(conversationName); + } + /** + * 修改某个对话的名词 + * 注:对话ID无法修改 + * + * @param oldConversationName 旧的对话名词/对话ID + * @param newConversationName 新的对话名词 + * @throws Exception 如果遇到任何问题,则抛出异常. + */ + public String renameConversation (String oldConversationName, String newConversationName) throws Exception { + String conversationID = conversations.get(oldConversationName); + protocol.setChannelName(conversationID ,newConversationName); + conversations.put(newConversationName ,conversationID); + conversations.remove(oldConversationName); + return conversationID; + } + /** + * 修改某个对话的名词 + * 注:对话ID无法修改 + * + * @param key 对话名词/对话ID + * @return 对话信息 + * @throws Exception 如果遇到任何问题,则抛出异常. + */ + public ConversationInfo getConversationInfo (String key) throws Exception { + ConversationInfo return_info = new ConversationInfo(); + return_info.Name = protocol.getChannelName(conversations.get(key)); + return_info.ID = conversations.get(key); + return return_info; + } + /** + * 取bot是否在线 + * + * @return 是否在线 true 在线 false 离线 + * @throws Exception 如果遇到任何问题,则抛出异常. + */ + public boolean isCozeBotOnline() throws Exception { + return protocol.isUserOnline(config.botID); + } + /** + * 取出最后一次发送消息时间 + * @return 返回 Instant 类型 如果没有记录 返回类创建时间 + */ + public Instant getLatestSendMsgInstant () { + return cozeEventListener.getLatestSendMessageInstant(); + } + /** + * 取出最后一次接收Coze Bot消息时间 + * @return 返回 Instant 类型 如果没有记录 返回类创建时间 + */ + public Instant getLatestReceiveCozeMsgInstant () { + return cozeEventListener.getLatestReceiveMessageInstant(); + } + +} diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/CozeGPTConfig.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/CozeGPTConfig.java similarity index 70% rename from src/main/java/catx/feitu/coze_discord_bridge/api/CozeGPTConfig.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/CozeGPTConfig.java index 91a3f7e..82b06bc 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/CozeGPTConfig.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/CozeGPTConfig.java @@ -1,13 +1,21 @@ -package catx.feitu.coze_discord_bridge.api; +package catx.feitu.CozeProxy; + +import catx.feitu.CozeProxy.Protocol.Protocols; public class CozeGPTConfig { + public String loginApp = Protocols.DISCORD; /** * #Discord bot token 获取方法 * 浏览器打开 Discord开发者平台 * 创建Application > 点击Bot > 点击 Reset Token 然后复制过来即可 * 注意 还需要打开Privileged Gateway Intents下面的选项 (MESSAGE CONTENT INTENT一定要开) */ - public String Discord_Bot_Token = ""; + public String token = ""; + /** + * 用户Token 发消息使用 + * Coze现在屏蔽bot账号发送消息 必须换成用户账号发送 + */ + public String token2 = ""; /** * 连接到Discord服务器时所使用的代理 * 对于某些无法直连Discord的地区很有帮助 @@ -18,12 +26,12 @@ public class CozeGPTConfig { * Discord服务器ID * 打开Discord开发者模式后直接右键右侧服务器列表中Bot所在且有管理权限的服务器即可复制ID */ - public String Server_id = ""; + public String serverID = ""; /** * Discord中被Coze托管的机器人用户ID * 打开Discord开发者模式后在服务器内直接右键机器人即可复制ID */ - public String CozeBot_id = ""; + public String botID = ""; public String Discord_CreateChannel_Category = ""; @@ -33,6 +41,9 @@ public class CozeGPTConfig { public boolean Disable_Name_Cache = false; public boolean Disable_2000Limit_Unlock = false; + public String promptOnSendMore2000Prefix = "根据Prompt.txt内容做出回应"; + public String promptOnSendMore2000FileName = "Prompt.txt"; + /** * 额外标记 可填写任意内容 */ diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/ConversationAlreadyExistsException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/ConversationAlreadyExistsException.java similarity index 85% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/ConversationAlreadyExistsException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/ConversationAlreadyExistsException.java index 8f9b52f..1b6e314 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/ConversationAlreadyExistsException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/ConversationAlreadyExistsException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class ConversationAlreadyExistsException extends Exception { private String Prv_Conversation = ""; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidConfigException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidConfigException.java similarity index 91% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidConfigException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidConfigException.java index 21268b4..3b91782 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidConfigException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidConfigException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class InvalidConfigException extends Exception { private String Prv_Config_name = ""; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidConversationException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidConversationException.java similarity index 85% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidConversationException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidConversationException.java index 10a8572..3018080 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidConversationException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidConversationException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class InvalidConversationException extends Exception { private String Prv_Conversation = ""; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidCozeBotUserIDException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidCozeBotUserIDException.java similarity index 70% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidCozeBotUserIDException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidCozeBotUserIDException.java index 2458fce..02130e7 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidCozeBotUserIDException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidCozeBotUserIDException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class InvalidCozeBotUserIDException extends Exception { public InvalidCozeBotUserIDException() { diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidDiscordChannelException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidDiscordChannelException.java new file mode 100644 index 0000000..b846473 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidDiscordChannelException.java @@ -0,0 +1,12 @@ +package catx.feitu.CozeProxy.Exceptions; + +public class InvalidDiscordChannelException extends Exception { + private String Prv_Conversation = ""; + public InvalidDiscordChannelException(String Conversation) { + super(Conversation); + Prv_Conversation = Conversation; + } + public String Get_Conversation() { + return Prv_Conversation; + } +} diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidDiscordServerException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidDiscordServerException.java similarity index 70% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidDiscordServerException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidDiscordServerException.java index 76dae1e..dce3b1e 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidDiscordServerException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidDiscordServerException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class InvalidDiscordServerException extends Exception { public InvalidDiscordServerException() { diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidPromptException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidPromptException.java similarity index 68% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidPromptException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidPromptException.java index 3e412f2..3ea0d6a 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/InvalidPromptException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/InvalidPromptException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class InvalidPromptException extends Exception { public InvalidPromptException() { diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/PromptTooLongException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/PromptTooLongException.java similarity index 89% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/PromptTooLongException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/PromptTooLongException.java index 32fe796..7a23c8b 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/PromptTooLongException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/PromptTooLongException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class PromptTooLongException extends Exception { private String Prv_Prompt = ""; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/RecvMsgException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/RecvMsgException.java similarity index 83% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/RecvMsgException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/RecvMsgException.java index 1bfff51..825e0c3 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/RecvMsgException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/RecvMsgException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class RecvMsgException extends Exception { public RecvMsgException() { diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/SendMessageException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/SendMessageException.java similarity index 84% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/SendMessageException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/SendMessageException.java index 65a7775..efdb4a5 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/SendMessageException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/SendMessageException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class SendMessageException extends Exception { public SendMessageException() { diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/StopGenerateException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/StopGenerateException.java similarity index 68% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/StopGenerateException.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/StopGenerateException.java index 949344f..c02cb95 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/StopGenerateException.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Exceptions/StopGenerateException.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; +package catx.feitu.CozeProxy.Exceptions; public class StopGenerateException extends Exception { public StopGenerateException() { diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/FunctionalInterface/ChatStreamEvent.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/FunctionalInterface/ChatStreamEvent.java similarity index 67% rename from src/main/java/catx/feitu/coze_discord_bridge/api/FunctionalInterface/ChatStreamEvent.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/FunctionalInterface/ChatStreamEvent.java index d694bac..6a10fd5 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/FunctionalInterface/ChatStreamEvent.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/FunctionalInterface/ChatStreamEvent.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.FunctionalInterface; +package catx.feitu.CozeProxy.FunctionalInterface; @FunctionalInterface public interface ChatStreamEvent { diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Listen/CozeEventListener.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Listen/CozeEventListener.java new file mode 100644 index 0000000..d1a24c0 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Listen/CozeEventListener.java @@ -0,0 +1,43 @@ +package catx.feitu.CozeProxy.Listen; + +import catx.feitu.CozeProxy.MessageManage.BotGenerateStatusManage; +import catx.feitu.CozeProxy.MessageManage.BotResponseManage; +import catx.feitu.CozeProxy.MessageManage.BotResponseType; +import catx.feitu.CozeProxy.Protocol.UniversalEventListener; +import catx.feitu.CozeProxy.Protocol.UniversalMessage; + +import java.time.Instant; + +public class CozeEventListener implements UniversalEventListener { + public BotGenerateStatusManage botGenerateStatusManage = new BotGenerateStatusManage(); + public BotResponseManage botResponseManage = new BotResponseManage(); + /** + * 最后一次发送消息时间 + */ + private Instant latestSendMessage = Instant.now(); + /** + * 最后一次接收消息时间 + */ + private Instant latestReceiveCozeMessage = Instant.now(); + + @Override + public void onSelfMessageSend(String channelID) { + latestSendMessage = Instant.now(); + } + @Override + public void onStartGenerate(String channelID) { + botGenerateStatusManage.saveGenerateStatus(channelID); + latestReceiveCozeMessage = Instant.now(); + } + @Override + public void onMessageStream(String channelID ,UniversalMessage message) { + BotResponseType responseType = new BotResponseType(); + responseType.prompt = message.content; + responseType.files = message.files; + responseType.SetCompleted(message.hasButton); + botResponseManage.saveMsg(channelID ,responseType); + latestReceiveCozeMessage = Instant.now(); + } + public Instant getLatestSendMessageInstant() { return latestSendMessage; } + public Instant getLatestReceiveMessageInstant() { return latestReceiveCozeMessage; } +} diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/LockManage/LockManage.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/LockManage/LockManage.java similarity index 86% rename from src/main/java/catx/feitu/coze_discord_bridge/api/LockManage/LockManage.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/LockManage/LockManage.java index 21f3587..9949727 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/LockManage/LockManage.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/LockManage/LockManage.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.LockManage; +package catx.feitu.CozeProxy.LockManage; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotGenerateStatusManage.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotGenerateStatusManage.java similarity index 90% rename from src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotGenerateStatusManage.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotGenerateStatusManage.java index 0732719..67c69a4 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotGenerateStatusManage.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotGenerateStatusManage.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.MessageManage; +package catx.feitu.CozeProxy.MessageManage; import java.util.concurrent.ConcurrentHashMap; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotResponseManage.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotResponseManage.java similarity index 91% rename from src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotResponseManage.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotResponseManage.java index 26a84ea..6239e52 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotResponseManage.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotResponseManage.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.MessageManage; +package catx.feitu.CozeProxy.MessageManage; import java.util.concurrent.ConcurrentHashMap; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotResponseType.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotResponseType.java similarity index 90% rename from src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotResponseType.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotResponseType.java index 319bc05..517d445 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/MessageManage/BotResponseType.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/MessageManage/BotResponseType.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.MessageManage; +package catx.feitu.CozeProxy.MessageManage; import java.time.Instant; import java.util.ArrayList; diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/InvalidChannelException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/InvalidChannelException.java new file mode 100644 index 0000000..13f36ba --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/InvalidChannelException.java @@ -0,0 +1,12 @@ +package catx.feitu.CozeProxy.Protocol.Exception; + +public class InvalidChannelException extends Exception { + private String channelID; + public InvalidChannelException(String channelID) { + super(channelID); + this.channelID = channelID; + } + public String getChannelID() { + return channelID; + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/InvalidUserException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/InvalidUserException.java new file mode 100644 index 0000000..1e1f450 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/InvalidUserException.java @@ -0,0 +1,12 @@ +package catx.feitu.CozeProxy.Protocol.Exception; + +public class InvalidUserException extends Exception { + private String userID; + public InvalidUserException(String userID) { + super(userID); + this.userID = userID; + } + public String getUserID() { + return userID; + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/ProtocolAPIFailedException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/ProtocolAPIFailedException.java new file mode 100644 index 0000000..c622079 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/ProtocolAPIFailedException.java @@ -0,0 +1,4 @@ +package catx.feitu.CozeProxy.Protocol.Exception; + +public class ProtocolAPIFailedException extends Exception { +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/ProtocolNotLoginException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/ProtocolNotLoginException.java new file mode 100644 index 0000000..76eb869 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/ProtocolNotLoginException.java @@ -0,0 +1,7 @@ +package catx.feitu.CozeProxy.Protocol.Exception; + +public class ProtocolNotLoginException extends Exception { + public ProtocolNotLoginException() { + super(); + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/UnSupportedProtocolException.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/UnSupportedProtocolException.java new file mode 100644 index 0000000..b0febe1 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Exception/UnSupportedProtocolException.java @@ -0,0 +1,7 @@ +package catx.feitu.CozeProxy.Protocol.Exception; + +public class UnSupportedProtocolException extends Exception { + public UnSupportedProtocolException() { + super(); + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Listener/DiscordListener.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Listener/DiscordListener.java new file mode 100644 index 0000000..07c0e1d --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Listener/DiscordListener.java @@ -0,0 +1,81 @@ +package catx.feitu.CozeProxy.Protocol.Listener; + +import catx.feitu.CozeProxy.Protocol.UniversalEventListener; +import catx.feitu.CozeProxy.Protocol.UniversalEventListenerConfig; +import catx.feitu.CozeProxy.Protocol.UniversalMessage; +import org.javacord.api.entity.message.embed.Embed; +import org.javacord.api.event.message.MessageCreateEvent; +import org.javacord.api.event.message.MessageEditEvent; +import org.javacord.api.event.user.UserStartTypingEvent; +import org.javacord.api.listener.message.MessageCreateListener; +import org.javacord.api.listener.message.MessageEditListener; +import org.javacord.api.listener.user.UserStartTypingListener; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; + +public class DiscordListener implements MessageCreateListener, MessageEditListener, UserStartTypingListener{ + public UniversalEventListener handle; + public UniversalEventListenerConfig config; + public DiscordListener(UniversalEventListener handle, UniversalEventListenerConfig config) { + this.handle = handle; + this.config = config; + } + @Override + public void onUserStartTyping(UserStartTypingEvent event) { + System.out.println(event.getChannel().getIdAsString()); + if (handle == null) { return; } + if (!Objects.equals(event.getChannel().asServerChannel().isPresent() ? event.getChannel().asServerChannel().get().getIdAsString() : null , config.filterServerID)) { return; } + if (!Objects.equals(event.getUserIdAsString(), config.filterUserID)) { return; } + handle.onStartGenerate(event.getChannel().getIdAsString()); + } + @Override + public void onMessageCreate(MessageCreateEvent event) { + if (handle == null) { return; } + if (!Objects.equals(event.getServer().isPresent() ? event.getServer().get().getIdAsString() : null , config.filterServerID)) { return; } + + if (Objects.equals(event.getMessageAuthor().getIdAsString(), config.filterSelfUserID)) { + handle.onSelfMessageSend(event.getChannel().getIdAsString()); + return; + } + + if (Objects.equals(event.getMessageAuthor().getIdAsString(), config.filterUserID)) { + List embeds = event.getMessage().getEmbeds(); // 获取消息中的所有嵌入内容 + List files = new CopyOnWriteArrayList<>(); // 存储嵌入附件URL + for (Embed embed : embeds) { + if (embed.getImage().isPresent()) { + files.add(embed.getImage().get().getUrl().toString()); + } + } + handle.onMessageStream(event.getChannel().getIdAsString(), + new UniversalMessage() + .setContent(event.getMessageContent()) + .setFiles(files) + .setHasButton(!event.getMessage().getComponents().isEmpty()) + ); + } + } + + @Override + public void onMessageEdit(MessageEditEvent event) { + if (handle == null) { return; } + if (!Objects.equals(event.getServer().isPresent() ? event.getServer().get().getIdAsString() : null , config.filterServerID)) { return; } + if (Objects.equals(event.getMessageAuthor().getIdAsString(), config.filterUserID)) { + List embeds = event.getMessage().getEmbeds(); // 获取消息中的所有嵌入内容 + List files = new CopyOnWriteArrayList<>(); // 存储嵌入附件URL + for (Embed embed : embeds) { + if (embed.getImage().isPresent()) { + files.add(embed.getImage().get().getUrl().toString()); + } + } + handle.onMessageStream(event.getChannel().getIdAsString(), + new UniversalMessage() + .setContent(event.getMessageContent()) + .setFiles(files) + .setHasButton(!event.getMessage().getComponents().isEmpty()) + ); + } + } +} \ No newline at end of file diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Listener/SlackListener.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Listener/SlackListener.java new file mode 100644 index 0000000..573e859 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Listener/SlackListener.java @@ -0,0 +1,45 @@ +package catx.feitu.CozeProxy.Protocol.Listener; + +import catx.feitu.CozeProxy.Protocol.UniversalEventListener; +import catx.feitu.CozeProxy.Protocol.UniversalEventListenerConfig; +import catx.feitu.CozeProxy.Protocol.UniversalMessage; +import com.slack.api.app_backend.events.payload.EventsApiPayload; +import com.slack.api.bolt.handler.BoltEventHandler; +import com.slack.api.bolt.response.Response; +import com.slack.api.bolt.context.builtin.EventContext; +import com.slack.api.methods.SlackApiException; +import com.slack.api.model.event.MessageEvent; + + +import java.io.IOException; +import java.util.Objects; + +public class SlackListener implements BoltEventHandler { + public UniversalEventListener handle; + public UniversalEventListenerConfig config; + public SlackListener(UniversalEventListener handle, UniversalEventListenerConfig config) { + this.handle = handle; + this.config = config; + } + + @Override + public Response apply(EventsApiPayload event, EventContext context) throws IOException, SlackApiException { + /* + List attachments = event.getEvent().getAttachments(); + if (attachments != null && !attachments.isEmpty()) { + for (Attachment attachment : attachments) { + // 打印每个附件的信息, 示例中仅打印附件的回退文本 + System.out.println(attachment.get()); + } + } + */ + if (handle != null && Objects.equals(event.getEvent().getUser(), config.filterUserID)) { + handle.onMessageStream(event.getEvent().getChannel(), + new UniversalMessage() + .setContent(event.getEvent().getText()) + .setHasButton(true) + ); + } + return context.ack(); + } +} \ No newline at end of file diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/ProtocolMessageCode.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/ProtocolMessageCode.java new file mode 100644 index 0000000..a51456d --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/ProtocolMessageCode.java @@ -0,0 +1,17 @@ +package catx.feitu.CozeProxy.Protocol; + +public class ProtocolMessageCode { + private String protocol = ""; + public ProtocolMessageCode(String protocol) { + this.protocol = protocol; + } + public String mentionUser(String userID) { + switch(protocol) { + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + return "<@" + userID + ">"; + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + return "@" + userID; + } + return ""; + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/ProtocolUtil.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/ProtocolUtil.java new file mode 100644 index 0000000..9533a67 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/ProtocolUtil.java @@ -0,0 +1,259 @@ +package catx.feitu.CozeProxy.Protocol; + +import catx.feitu.CozeProxy.Exceptions.InvalidDiscordChannelException; +import catx.feitu.CozeProxy.Protocol.Exception.InvalidUserException; +import catx.feitu.CozeProxy.Protocol.Exception.ProtocolNotLoginException; +import catx.feitu.CozeProxy.Protocol.Exception.ProtocolAPIFailedException; +import catx.feitu.CozeProxy.Protocol.Exception.UnSupportedProtocolException; +import catx.feitu.CozeProxy.Protocol.Listener.DiscordListener; +import catx.feitu.CozeProxy.Protocol.Listener.SlackListener; +import catx.feitu.CozeProxy.Protocol.Types.UploadFile; +import catx.feitu.CozeProxy.Protocol.Utils.DiscordUtils; +import catx.feitu.DiscordSelfClient.client.SelfClient; +import catx.feitu.DiscordSelfClient.client.Types.DiscordAttachment; +import com.slack.api.Slack; +import com.slack.api.bolt.App; +import com.slack.api.bolt.AppConfig; +import com.slack.api.bolt.socket_mode.SocketModeApp; +import com.slack.api.methods.MethodsClient; +import com.slack.api.methods.response.conversations.ConversationsCreateResponse; +import com.slack.api.methods.response.files.FilesUploadResponse; +import com.slack.api.model.Attachment; +import com.slack.api.model.event.MessageEvent; +import org.javacord.api.DiscordApi; +import org.javacord.api.DiscordApiBuilder; +import org.javacord.api.entity.channel.ChannelCategory; +import org.javacord.api.entity.channel.ServerTextChannel; +import org.javacord.api.entity.intent.Intent; +import org.javacord.api.entity.message.MessageBuilder; +import org.javacord.api.entity.user.User; +import org.javacord.api.entity.user.UserStatus; + +import java.net.Proxy; +import java.util.*; +import java.util.stream.Collectors; + +public class ProtocolUtil { + public String apiSelected; + public DiscordApi api_discord; + public SelfClient api_discord2; + public MethodsClient api_slack; + public App api_slack_listen; + public UniversalEventListener eventListener; + public UniversalEventListenerConfig config; + public ProtocolMessageCode code; + + public void setConfig(UniversalEventListenerConfig config) { + this.config = config; + } + public void login(String protocol ,String token ,Proxy proxy,String token2) throws Exception { + code = new ProtocolMessageCode(protocol); + apiSelected = protocol; + switch (protocol){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + api_discord2 = new SelfClient(token2); + api_discord2.setProxy(proxy); + api_discord = new DiscordApiBuilder() + .setToken(token) + .addIntents(Intent.MESSAGE_CONTENT) + .setProxy(proxy) + .login() + .join(); + api_discord.addListener(new DiscordListener(eventListener ,config)); + return; + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + AppConfig config = new AppConfig(); + config.setSingleTeamBotToken(token); + api_slack = new Slack().methods(token); + + api_slack_listen = new App(config); + api_slack_listen.event(MessageEvent.class, new SlackListener(eventListener ,this.config)); + new SocketModeApp(api_slack_listen).start(); + return; + } + throw new UnSupportedProtocolException(); + } + public void disconnect() throws Exception { + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + if (api_discord == null) { + throw new ProtocolNotLoginException(); + } + api_discord.disconnect(); + api_discord= null; + return; + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + new SocketModeApp(api_slack_listen).stop(); + api_slack_listen = null; + api_slack = null; + return; + + } + throw new UnSupportedProtocolException(); + } + public void sendMessage(String channelID , String message , List files) throws Exception { + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + List uploadFiles = new ArrayList<>(); + if (files != null) { + for (UploadFile file : files) { + uploadFiles.add(api_discord2.upLoadAttachment(file.getByte(),file.getFileName(),channelID)); + } + } + api_discord2.sendMessage(message ,channelID ,uploadFiles); + /* + MessageBuilder messageBuilder = new MessageBuilder() + .append(message); + // 发送附件(图片)处理 + if (files != null) { + for (UploadFile file : files) { + messageBuilder.addAttachment(file.getByteArrayInputStream() ,file.getFileName()); + } + } + messageBuilder.send(DiscordUtils.GetDiscordChannelAsTextChannel( + DiscordUtils.GetDiscordServer(api_discord ,config.filterServerID) ,channelID) + ); + */ + return; + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + // by ChatGPT + List fileIds = new ArrayList<>(); + + // 先上传文件 + if (files != null && !files.isEmpty()) { + for (UploadFile file : files) { + FilesUploadResponse uploadResponse = api_slack.filesUpload(req -> req + .channels(Collections.singletonList(channelID)) + .fileData(file.getByte()) + .filename(file.getFileName()) + .title(file.getFileName()) + ); + if (uploadResponse.isOk()) { + fileIds.add(uploadResponse.getFile().getId()); // 每个上传的文件的ID都加入列表 + } else { + //处理上传错误情况 + throw new ProtocolAPIFailedException(); + } + } + if (!api_slack.chatPostMessage(req -> req + .channel(channelID) + .text(message) + .attachments(fileIds.stream().map(fileId -> { + Attachment attachment = new Attachment(); + attachment.setFallback("The file could not be displayed."); + // attachment 中添加 file ID + attachment.setFooter(""); + return attachment; + }).collect(Collectors.toList()))).isOk() + ) { + throw new ProtocolAPIFailedException(); + } + } + return; + } + throw new UnSupportedProtocolException(); + } + public String createChannel(String name ,String category) throws Exception { + String realName = name == null ? "default" : name; + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + ChannelCategory categoryObj = Objects.equals(category, "") || category == null ? + null : + (ChannelCategory) DiscordUtils.GetDiscordChannel(DiscordUtils.GetDiscordServer(api_discord,config.filterServerID),category); + // 创建 + ServerTextChannel channel = DiscordUtils.GetDiscordServer(api_discord,config.filterServerID) + .createTextChannelBuilder() + .setName(realName) + .setCategory(categoryObj) + .create() + .join(); + // 返回数据 + return channel.getIdAsString(); + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + ConversationsCreateResponse response = api_slack.conversationsCreate(req -> req + .name(realName) // 设置你想要创建的频道名 + .isPrivate(false) // 设置频道是否为私有 + ); + if (!response.isOk()) { + throw new ProtocolAPIFailedException(); + } + return response.getChannel().getId(); + } + throw new UnSupportedProtocolException(); + } + public void inviteBotInChannel(String channelID ,String botID) throws Exception { + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + return; + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + if (!api_slack.conversationsInvite(req -> req + .channel(channelID) + .users(Collections.singletonList(botID)) // 需要提供一个或多个用户的 ID + ).isOk()) { + throw new ProtocolAPIFailedException(); + } + return; + } + throw new UnSupportedProtocolException(); + } + public void deleteChannel(String channelID) throws Exception { + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + DiscordUtils.GetDiscordChannelAsServerChannel(DiscordUtils.GetDiscordServer(api_discord,config.filterServerID), + channelID).delete().join(); + return; + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + // 尝试删除 如果失败则bot退出 + if (api_slack.adminConversationsDelete(req -> req.channelId(channelID)).isOk()) return; + if (api_slack.conversationsLeave(req -> req.channel(channelID)).isOk()) return; + throw new ProtocolAPIFailedException(); + } + throw new UnSupportedProtocolException(); + } + public String getChannelName(String channelID) throws Exception { + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + return DiscordUtils.GetDiscordChannelAsServerChannel(DiscordUtils.GetDiscordServer(api_discord,config.filterServerID), + channelID).getName(); + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + } + throw new UnSupportedProtocolException(); + } + public void setChannelName(String channelID ,String name) throws Exception { + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + DiscordUtils.GetDiscordChannelAsServerChannel(DiscordUtils.GetDiscordServer(api_discord,config.filterServerID), + channelID).updateName(name).join(); + return; + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + } + throw new UnSupportedProtocolException(); + } + public boolean isChannelFound(String channelID) throws Exception { + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + try { + DiscordUtils.GetDiscordChannelAsServerChannel(DiscordUtils.GetDiscordServer(api_discord,config.filterServerID), + channelID).getName(); + return true; + } catch (InvalidDiscordChannelException ignored) { + return false; + } + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + } + throw new UnSupportedProtocolException(); + } + public boolean isUserOnline(String userID) throws Exception { + switch (apiSelected){ + case catx.feitu.CozeProxy.Protocol.Protocols.DISCORD: + Optional user = DiscordUtils.GetDiscordServer(api_discord,config.filterServerID) + .getMemberById(userID); + if (user.isEmpty()) { + throw new InvalidUserException(userID); + } + return user.get().getStatus() != UserStatus.OFFLINE; + case catx.feitu.CozeProxy.Protocol.Protocols.SLACK: + } + throw new UnSupportedProtocolException(); + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Protocols.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Protocols.java new file mode 100644 index 0000000..168d284 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Protocols.java @@ -0,0 +1,6 @@ +package catx.feitu.CozeProxy.Protocol; + +public interface Protocols { + String DISCORD = "discord"; + String SLACK = "slack"; +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Types/UploadFile.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Types/UploadFile.java new file mode 100644 index 0000000..196e884 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Types/UploadFile.java @@ -0,0 +1,30 @@ +package catx.feitu.CozeProxy.Protocol.Types; + +import java.io.ByteArrayInputStream; +import java.util.Base64; + +public class UploadFile { + private final ByteArrayInputStream file; + private final String name; + public UploadFile(String base64, String fileName) { + file = new ByteArrayInputStream(Base64.getDecoder().decode(base64)); + name = fileName; + } + public UploadFile(byte[] bytes, String fileName) { + file = new ByteArrayInputStream(bytes); + name = fileName; + } + public UploadFile(ByteArrayInputStream fileInputStream, String fileName) { + file = fileInputStream; + name = fileName; + } + public ByteArrayInputStream getByteArrayInputStream() { + return file; + } + public byte[] getByte() { + return file.readAllBytes(); + } + public String getFileName() { + return name; + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalEventListener.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalEventListener.java new file mode 100644 index 0000000..624d609 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalEventListener.java @@ -0,0 +1,8 @@ +package catx.feitu.CozeProxy.Protocol; + +public interface UniversalEventListener { + void onSelfMessageSend(String channelID); + void onStartGenerate(String channelID); + void onMessageStream(String channelID ,UniversalMessage message); + +} \ No newline at end of file diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalEventListenerConfig.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalEventListenerConfig.java new file mode 100644 index 0000000..044be48 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalEventListenerConfig.java @@ -0,0 +1,12 @@ +package catx.feitu.CozeProxy.Protocol; + + +public class UniversalEventListenerConfig { + public String filterServerID; + public String filterUserID; + public String filterSelfUserID; + public UniversalEventListenerConfig(String serverID, String userID) { + filterServerID = serverID; + filterUserID = userID; + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalMessage.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalMessage.java new file mode 100644 index 0000000..c9ce7f3 --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/UniversalMessage.java @@ -0,0 +1,24 @@ +package catx.feitu.CozeProxy.Protocol; + +import java.util.List; + +public class UniversalMessage { + public String content; + public List files; + public boolean hasButton; + public UniversalMessage setContent (String content) { + UniversalMessage build = this; + build.content = content; + return build; + } + public UniversalMessage setFiles (List content) { + UniversalMessage build = this; + build.files = content; + return build; + } + public UniversalMessage setHasButton (boolean hasButton) { + UniversalMessage build = this; + build.hasButton = hasButton; + return build; + } +} diff --git a/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Utils/DiscordUtils.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Utils/DiscordUtils.java new file mode 100644 index 0000000..7b3df9e --- /dev/null +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Protocol/Utils/DiscordUtils.java @@ -0,0 +1,42 @@ +package catx.feitu.CozeProxy.Protocol.Utils; + +import catx.feitu.CozeProxy.Exceptions.InvalidDiscordChannelException; +import catx.feitu.CozeProxy.Exceptions.InvalidDiscordServerException; +import org.javacord.api.DiscordApi; +import org.javacord.api.entity.channel.Channel; +import org.javacord.api.entity.channel.ServerChannel; +import org.javacord.api.entity.channel.TextChannel; +import org.javacord.api.entity.server.Server; + +import java.util.Optional; + +public class DiscordUtils { + public static Server GetDiscordServer(DiscordApi api , String serverID) throws Exception { + Optional optionalServer = api.getServerById(serverID); + if (optionalServer.isEmpty()) { + throw new InvalidDiscordServerException(); + } + return optionalServer.get(); + } + public static TextChannel GetDiscordChannelAsTextChannel(Server server , String channelID) throws Exception { + Channel Channel = GetDiscordChannel(server ,channelID); + if (!(Channel instanceof TextChannel)) { + throw new InvalidDiscordChannelException(channelID); + } + return (TextChannel) Channel; + } + public static ServerChannel GetDiscordChannelAsServerChannel(Server server , String channelID) throws Exception { + Channel Channel = GetDiscordChannel(server ,channelID); + if (!(Channel instanceof ServerChannel)) { + throw new InvalidDiscordChannelException(channelID); + } + return (ServerChannel) Channel; + } + public static Channel GetDiscordChannel(Server server , String channelID) throws Exception { + Optional Channel = server.getChannelById(channelID); + if (Channel.isEmpty()) { + throw new InvalidDiscordChannelException(channelID); + } + return Channel.get(); + } +} diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Types/ConversationInfo.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/ConversationInfo.java similarity index 66% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Types/ConversationInfo.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/ConversationInfo.java index 3b9ed12..080b051 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Types/ConversationInfo.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/ConversationInfo.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Types; +package catx.feitu.CozeProxy.Types; public class ConversationInfo { diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Types/GPTFile.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/GPTFile.java similarity index 93% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Types/GPTFile.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/GPTFile.java index d005765..b4e14f8 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Types/GPTFile.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/GPTFile.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Types; +package catx.feitu.CozeProxy.Types; import java.io.*; import java.util.Base64; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Types/GenerateMessage.java b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/GenerateMessage.java similarity index 78% rename from src/main/java/catx/feitu/coze_discord_bridge/api/Types/GenerateMessage.java rename to CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/GenerateMessage.java index cf368d9..7462304 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Types/GenerateMessage.java +++ b/CozeProxy/src/main/java/catx/feitu/CozeProxy/Types/GenerateMessage.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.api.Types; +package catx.feitu.CozeProxy.Types; import java.util.ArrayList; import java.util.List; diff --git a/DiscordSelfBot/build.gradle b/DiscordSelfBot/build.gradle new file mode 100644 index 0000000..dd90826 --- /dev/null +++ b/DiscordSelfBot/build.gradle @@ -0,0 +1,27 @@ +plugins { + id 'java' +} + +jar { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +tasks.withType(JavaExec).configureEach { + systemProperty 'file.encoding', 'UTF-8' +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = 'UTF-8' +} + +group = 'catx.feitu' +version = '1.0.0222' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.alibaba:fastjson:1.1.77.android_noneautotype' +} \ No newline at end of file diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidFileException.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidFileException.java new file mode 100644 index 0000000..4a157ba --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidFileException.java @@ -0,0 +1,5 @@ +package catx.feitu.DiscordSelfClient.client.Exceptions; + +public class InvalidFileException extends Exception { + +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidRequestBodyException.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidRequestBodyException.java new file mode 100644 index 0000000..3d38d7f --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidRequestBodyException.java @@ -0,0 +1,5 @@ +package catx.feitu.DiscordSelfClient.client.Exceptions; + +public class InvalidRequestBodyException extends Exception { + +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidTokenException.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidTokenException.java new file mode 100644 index 0000000..171081f --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Exceptions/InvalidTokenException.java @@ -0,0 +1,8 @@ +package catx.feitu.DiscordSelfClient.client.Exceptions; + +public class InvalidTokenException extends Exception { + public String token = ""; + public InvalidTokenException (String token) { + this.token = token; + } +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/SelfClient.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/SelfClient.java new file mode 100644 index 0000000..832635d --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/SelfClient.java @@ -0,0 +1,279 @@ +package catx.feitu.DiscordSelfClient.client; + +import catx.feitu.DiscordSelfClient.client.Exceptions.InvalidFileException; +import catx.feitu.DiscordSelfClient.client.Types.DiscordAttachment; +import catx.feitu.DiscordSelfClient.utils.DiscordAPIRequests; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import catx.feitu.DiscordSelfClient.client.impl.*; + +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +public class SelfClient { + + private final DiscordAPIRequests requests; + + public SelfClient(String token) { + requests = new DiscordAPIRequests(token); + } + public void setProxy(InetSocketAddress address) { + requests.proxy = address; + } + public void setProxy(Proxy address) { + requests.proxy = (InetSocketAddress) address.address(); + } + public void setUserAgent(String agent) { + requests.userAgent = agent; + } + public List getFriends() throws Exception { + List friends = new ArrayList<>(); + + JSONArray data = (JSONArray) requests.get("https://discord.com/api/v8/users/@me/relationships"); + for (int i = 0; i < data.size(); i++) { + JSONObject object = data.getJSONObject(i); + String id = object.getString("id"); + int type = object.getIntValue("type"); + String nickname = object.getString("nickname"); + JSONObject user = object.getJSONObject("user"); + String username = user.getString("username"); + String displayName = user.getString("display_name"); + String avatar = user.getString("avatar"); + String avatarDecoration = user.getString("avatar_decoration"); + String discriminator = user.getString("discriminator"); + int publicFlags = user.getIntValue("public_flags"); + Friend f = new Friend(id, type, nickname, username, displayName, avatar, avatarDecoration, discriminator, publicFlags); + friends.add(f); + } + return friends; + } + + public Token getSelf() throws Exception { + JSONObject data = (JSONObject) requests.get("https://discord.com/api/v9/users/@me"); + String id = data.getString("id"); + String username = data.getString("username"); + String displayName = data.getString("display_name"); + String avatar = data.getString("avatar"); + String avatarDecoration = data.getString("avatar_decoration"); + String discriminator = data.getString("discriminator"); + int publicFlags = data.getIntValue("public_flags"); + int flags = data.getIntValue("flags"); + String banner = data.getString("banner"); + String bannerColor = data.getString("banner_color"); + int accentColor = data.getIntValue("accent_color"); + String bio = data.getString("bio"); + String locale = data.getString("locale"); + boolean nsfw = data.getBooleanValue("nsfw_allowed"); + boolean mfa = data.getBooleanValue("mfa_enabled"); + int premiumType = data.getIntValue("premium_type"); + String email = data.getString("email"); + boolean verified = data.getBooleanValue("verified"); + String phone = data.getString("phone"); + return new Token(id, username, displayName, avatar, avatarDecoration, discriminator, publicFlags, flags, + banner, bannerColor, accentColor, bio, locale, nsfw, mfa, premiumType, email, verified, phone); + } + + + public List getGuilds() throws Exception { + List guilds = new ArrayList<>(); + + JSONArray data = (JSONArray) requests.get(""); + for (int i = 0; i < data.size(); i++) { + JSONObject object = data.getJSONObject(i); + String id = object.getString("id"); + String name = object.getString("name"); + String icon = object.getString("icon"); + boolean owner = object.getBooleanValue("owner"); + String permissions = object.getString("permissions"); + Guild guild = new Guild(id, name, icon, owner, permissions); + guilds.add(guild); + } + return guilds; + } + + public List getChannels() throws Exception { + List channels = new ArrayList<>(); + + JSONArray data = (JSONArray) requests.get(""); + for (int i = 0; i < data.size(); i++) { + JSONObject object = data.getJSONObject(i); + String id = object.getString("id"); + int type = object.getIntValue("type"); + String lastMessageId = object.getString("last_message_id"); + int flags = object.getIntValue("flags"); + Channel channel = new Channel(id, type, lastMessageId, flags); + channels.add(channel); + } + return channels; + } + + public Channel getChannel(String channelId) throws Exception { + JSONObject data = (JSONObject) requests.get("https://discord.com/api/v9/channels/" + channelId); + + String id = data.getString("id"); + Integer type = data.getInteger("type"); + String lastMessageId = data.getString("last_message_id"); + Integer flags = data.getInteger("flags"); + + return new Channel(id, type, lastMessageId, flags); + } + + public List getMessages(String channelId) throws Exception { + List messages = new ArrayList<>(); + JSONArray data = (JSONArray) requests.get("https://discord.com/api/v9/channels/" + channelId + "/messages"); + for (int i = 0; i < data.size(); i++) { + JSONObject object = data.getJSONObject(i); + + String id = object.getString("id"); + int type = object.getIntValue("type"); + String content = object.getString("content"); + + messages.add(new Message(id, type, content)); + } + return messages; + } + public void sendMessage(String message, String channelId, List attachments) throws Exception { + JSONObject json = new JSONObject(); + json.put("content", message); + + if (!attachments.isEmpty()) { + JSONArray json_attachments = new JSONArray(); + for (int i = 0; i < attachments.size(); i++) { + DiscordAttachment attachment = attachments.get(i); + + if (attachment != null) { + JSONObject json_attachments_data = new JSONObject(); + + json_attachments_data.put("id", String.valueOf(i)); + json_attachments_data.put("filename", attachment.fileName); + json_attachments_data.put("uploaded_filename", attachment.uploaded_filename); + + json_attachments.add(json_attachments_data); + } + } + + json.put("channel_id", channelId); + json.put("attachments", json_attachments); + } + requests.post("https://discord.com/api/v9/channels/" + channelId + "/messages", JSON.toJSONString(json)); + } + public DiscordAttachment upLoadAttachment(byte[] fileByte, String fileName, String channelId) throws Exception { + if (fileByte.length == 0) { throw new InvalidFileException(); } + + JSONObject json_files_data = new JSONObject(); + json_files_data.put("filename", fileName); + json_files_data.put("file_size", fileByte.length); + json_files_data.put("id", "1"); + json_files_data.put("is_clip", false); + JSONArray json_files = new JSONArray(); + json_files.add(json_files_data); + JSONObject json = new JSONObject(); + json.put("files", json_files); + + JSONObject jsonResponse = (JSONObject) requests.post("https://discord.com/api/v9/channels/" + channelId + "/attachments", JSON.toJSONString(json)); + URL fileURL = new URL(jsonResponse.getJSONArray("attachments").getJSONObject(0).getString("upload_url")); + + requests.put(fileURL.toString(), fileByte); + + return new DiscordAttachment(fileName, 1, fileURL.getPath().replaceFirst("/", "")); + } + public void leaveGuild(String guildId) throws Exception { + requests.delete("https://discord.com/api/v9/users/@me/guilds/" + guildId); + } + + public void joinGuild(String inviteCode) throws Exception { + requests.post("https://discord.com/api/v9/invites/" + inviteCode, "{}"); + } + + public void deleteGuild(String guildId) throws Exception { + requests.post("https://discord.com/api/v9/guilds/" + guildId + "/delete", "{}"); + } + + public void createGuild(String name, String category) throws Exception { + JSONObject json = new JSONObject(); + json.put("name", name); + if (category != null) json.put("parent_id", category); + + requests.post("", JSON.toJSONString(json)); + } + public void createGuild(String name) throws Exception { + createGuild(name ,null); + } + + public void addFriend(String name, String discriminator) throws Exception { + JSONObject json = new JSONObject(); + json.put("username", name); + json.put("discriminator", discriminator); + requests.post("https://discord.com/api/v9/users/@me/relationships", JSON.toJSONString(json)); + } + + public void deleteFriend(String id) throws Exception { + requests.delete("https://discord.com/api/v9/users/@me/relationships/" + id); + } + + public void blockFriend(String id) throws Exception { + JSONObject json = new JSONObject(); + json.put("type", 2); + requests.put("https://discord.com/api/v9/users/@me/relationships/" + id, JSON.toJSONString(json)); + System.out.println("block friend: [ID:" + id + "]"); + } + + public void changeAvatar(String avatar) throws Exception { + JSONObject json = new JSONObject(); + json.put("avatar", avatar); + + requests.patch("https://discord.com/api/v9/users/@me", JSON.toJSONString(json)); + } + + public void clearAvatar() throws Exception { + changeAvatar(null); + } + + public void deleteMessages(String channelId, String messageId) throws Exception { + requests.delete("https://discord.com/api/v9/channels/" + channelId + "/messages/" + messageId); + } + + + public void closeDms(String channelId) throws Exception { + requests.delete("https://discord.com/api/v8/channels/" + channelId); + } + + public void setStatus(String text) throws Exception { + JSONObject custom_status = new JSONObject(); + custom_status.put("text", text); + JSONObject json = new JSONObject(); + json.put("custom_status", custom_status); + + requests.patch("https://discord.com/api/v8/users/@me/settings", JSON.toJSONString(json)); + } + public void changeBio(String text) throws Exception { + JSONObject json = new JSONObject(); + json.put("bio", text); + + requests.patch("https://discord.com/api/v9/users/@me/profile", JSON.toJSONString(json)); + } + + public void changeTheme(Theme theme) throws Exception { + JSONObject json = new JSONObject(); + switch (theme) { + case DARK: + json.put("theme", "dark"); + break; + case LIGHT: + json.put("theme", "light"); + break; + } + + requests.patch("https://discord.com/api/v8/users/@me/settings", JSON.toJSONString(json)); + } + + + public enum Theme { + LIGHT, DARK; + } +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Types/DiscordAttachment.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Types/DiscordAttachment.java new file mode 100644 index 0000000..fedf11a --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/Types/DiscordAttachment.java @@ -0,0 +1,15 @@ +package catx.feitu.DiscordSelfClient.client.Types; + +public class DiscordAttachment { + public String fileName = ""; + public int id = 0; + public String uploaded_filename = ""; + public DiscordAttachment (String fileName ,int id ,String uploaded_filename) { + this.fileName = fileName; + this.id = id; + this.uploaded_filename = uploaded_filename; + } + public String toString () { + return uploaded_filename; + } +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Channel.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Channel.java new file mode 100644 index 0000000..86a1126 --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Channel.java @@ -0,0 +1,31 @@ +package catx.feitu.DiscordSelfClient.client.impl; + +public class Channel { + private String id; + private int type; + private String lastMessageId; + private int flags; + + public Channel(String _id, int _type, String _lastMessageId, int _flags) { + id = _id; + type = _type; + lastMessageId = _lastMessageId; + flags = _flags; + } + + public String id() { + return id; + } + + public int type() { + return type; + } + + public String last_message_id() { + return lastMessageId; + } + + public int flags() { + return flags; + } +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Friend.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Friend.java new file mode 100644 index 0000000..45820e1 --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Friend.java @@ -0,0 +1,62 @@ +package catx.feitu.DiscordSelfClient.client.impl; + +public class Friend { + private String id; + private int type; + private String nickname; + private String username; + private String displayName; + private String avatar; + private String avatarDecoration; + private String discriminator; + private int publicFlags; + + public Friend(String _id, int _type, String _nickname, String _username, String _displayName, String _avatar, String + _avatarDecoration, String _discriminator, int _publicFlags) { + id = _id; + type = _type; + nickname = _nickname; + username = _username; + displayName = _displayName; + avatar = _avatar; + avatarDecoration = _avatarDecoration; + discriminator = _discriminator; + publicFlags = _publicFlags; + } + + public String id() { + return id; + } + + public int type() { + return type; + } + + public String nickname() { + return nickname; + } + + public String username() { + return username; + } + + public String displayname() { + return displayName; + } + + public String avatar() { + return avatar; + } + + public String avatar_decoration() { + return avatarDecoration; + } + + public String discriminator() { + return discriminator; + } + + public int public_flags() { + return publicFlags; + } +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Guild.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Guild.java new file mode 100644 index 0000000..221ac68 --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Guild.java @@ -0,0 +1,37 @@ +package catx.feitu.DiscordSelfClient.client.impl; + +public class Guild { + private String id; + private String name; + private String icon; + private boolean owner; + private String permissions; + + public Guild(String _id, String _name, String _icon, boolean _owner, String _permissions) { + id = _id; + name = _name; + icon = _icon; + owner = _owner; + permissions = _permissions; + } + + public String id() { + return id; + } + + public String name() { + return name; + } + + public String icon() { + return icon; + } + + public boolean owner() { + return owner; + } + + public String permissions() { + return permissions; + } +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Message.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Message.java new file mode 100644 index 0000000..0f78bae --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Message.java @@ -0,0 +1,26 @@ +package catx.feitu.DiscordSelfClient.client.impl; + +public class Message { + private String id; + private int type; + private String content; + + + public Message(String _id, int _type, String _content) { + id = _id; + type = _type; + content = _content; + } + + public String id() { + return id; + } + + public int type() { + return type; + } + + public String content() { + return content; + } +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Token.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Token.java new file mode 100644 index 0000000..378f677 --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/Token.java @@ -0,0 +1,124 @@ +package catx.feitu.DiscordSelfClient.client.impl; + +public class Token { + private String id; + private String username; + private String displayName; + private String avatar; + private String avatarDecoration; + private String discriminator; + private int publicFlags; + private int flags; + private String banner; + private String bannerColor; + private int accentColor; + private String bio; + private String locale; + private boolean nsfw; + private boolean mfa; + private int premiumType; + private String email; + private boolean verified; + private String phone; + + public Token(String _id, String _username, String _displayName, String _avatar, String _avatarDecoration, + String _discriminator, int _publicFlags, int _flags, String _banner, String _bannerColor, int _accentColor, + String _bio, String _locale, boolean _nsfw, boolean _mfa, int _premiumType, String _email, boolean _verified, + String _phone) { + id = _id; + username = _username; + displayName = _displayName; + avatar = _avatar; + avatarDecoration = _avatarDecoration; + discriminator = _discriminator; + publicFlags = _publicFlags; + flags = _flags; + banner = _banner; + bannerColor = _bannerColor; + accentColor = _accentColor; + bio = _bio; + locale = _locale; + nsfw = _nsfw; + mfa = _mfa; + premiumType = _premiumType; + email = _email; + verified = _verified; + phone = _phone; + } + + public String id() { + return id; + } + + public String username() { + return username; + } + + public String displayname() { + return displayName; + } + + public String avatar() { + return avatar; + } + + public String avatar_decoration() { + return avatarDecoration; + } + + public String discriminator() { + return discriminator; + } + + public int public_flags() { + return publicFlags; + } + + public int flags() { + return flags; + } + + public String banner() { + return banner; + } + + public String banner_color() { + return bannerColor; + } + + public int accent_color() { + return accentColor; + } + + public String bio() { + return bio; + } + + public String locale() { + return locale; + } + + public boolean nsfw() { + return nsfw; + } + + public boolean mfa() { + return mfa; + } + + public int premium_type() { + return premiumType; + } + + public String email() { + return email; + } + + public boolean verified() { + return verified; + } + + public String phone() { + return phone; + } +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/User.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/User.java new file mode 100644 index 0000000..d2e7060 --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/client/impl/User.java @@ -0,0 +1,7 @@ +package catx.feitu.DiscordSelfClient.client.impl; + +public class User { + public String id; + public String username; + public String global_name; +} diff --git a/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/utils/DiscordAPIRequests.java b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/utils/DiscordAPIRequests.java new file mode 100644 index 0000000..57025c2 --- /dev/null +++ b/DiscordSelfBot/src/main/java/catx/feitu/DiscordSelfClient/utils/DiscordAPIRequests.java @@ -0,0 +1,100 @@ +package catx.feitu.DiscordSelfClient.utils; + +import catx.feitu.DiscordSelfClient.client.Exceptions.*; +import com.alibaba.fastjson.JSON; + +import java.net.InetSocketAddress; +import java.net.ProxySelector; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; + +public class DiscordAPIRequests { + public InetSocketAddress proxy = null; + public String token; + public String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"; + + public DiscordAPIRequests(String token) { + this.token = token; + } + + public Object get(String api) throws Exception { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(api)) + .header("User-Agent", userAgent) + .header("Accept", "application/json") + .header("Content-type", "application/json; charset=utf-8") + .header("Authorization", token) + .build(); + return responseHandle(getHttpClient(), request); + } + public Object post(String api, String json) throws Exception { + System.out.println(json); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(api)) + .header("User-Agent", userAgent) + .header("Accept", "application/json") + .header("Content-type", "application/json; charset=utf-8") + .header("Authorization", token) + .POST(HttpRequest.BodyPublishers.ofString(json ,StandardCharsets.UTF_8)) + .build(); + return responseHandle(getHttpClient(), request); + } + public Object put(String api, String content) throws Exception { + return put(api,content.getBytes(StandardCharsets.UTF_8)); + } + public Object put(String api, byte[] bytes) throws Exception { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(api)) + .header("User-Agent", userAgent) + .header("Accept", "application/json") + .header("Content-type", "application/json; charset=utf-8") + .header("Authorization", token) + .PUT(HttpRequest.BodyPublishers.ofByteArray(bytes)) + .build(); + return responseHandle(client, request); + } + public Object delete(String api) throws Exception { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(api)) + .header("User-Agent", userAgent) + .header("Accept", "application/json") + .header("Content-type", "application/json; charset=utf-8") + .header("Authorization", token) + .DELETE() + .build(); + return responseHandle(getHttpClient(), request); + } + public Object patch(String api, String json) throws Exception { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(api)) + .header("User-Agent", userAgent) + .header("Accept", "application/json") + .header("Content-type", "application/json; charset=utf-8") + .header("Authorization", token) + .method("PATCH", HttpRequest.BodyPublishers.ofString(json ,StandardCharsets.UTF_8)) + .build(); + return responseHandle(getHttpClient(), request); + } + + private Object responseHandle(HttpClient client, HttpRequest request) throws java.io.IOException, InterruptedException, InvalidRequestBodyException, InvalidTokenException { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + System.out.println(response.body()); + switch (response.statusCode()) { + case 400: + throw new InvalidRequestBodyException(); + case 401: + throw new InvalidTokenException(token); + default: + return JSON.parse(response.body()); + } + } + private HttpClient getHttpClient() { + HttpClient.Builder response = HttpClient.newBuilder(); + if(this.proxy != null) response.proxy(ProxySelector.of(this.proxy)); + return response.build(); + } +} diff --git a/build.gradle b/build.gradle index 897d850..e59dd96 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ tasks.withType(JavaCompile).configureEach { } group = 'catx.feitu' -version = '1.0.0213' +version = '1.0.0222-TempFix' repositories { mavenCentral() @@ -43,7 +43,16 @@ dependencies { // https://mavenlibs.com/maven/dependency/org.fusesource.jansi/jansi implementation 'org.fusesource.jansi:jansi:2.4.1' // https://mavenlibs.com/maven/dependency/org.apache.logging.log4j/log4j-core + // 我也不知道为什么IDEA提示易受攻击 明明已经升级到了 2.8.2 之后的版本. implementation 'org.apache.logging.log4j:log4j-core:2.20.0' // https://mavenlibs.com/maven/dependency/com.esotericsoftware.yamlbeans/yamlbeans implementation 'com.esotericsoftware.yamlbeans:yamlbeans:1.17' + + implementation project(':CozeProxy') + implementation project(':DiscordSelfBot') + + // 测试 + testImplementation 'junit:junit:4.13.1' + + } diff --git a/settings.gradle b/settings.gradle index 6b34cf3..194a2f0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,3 @@ rootProject.name = 'CozeDiscordBridge' +include 'CozeProxy' +include 'DiscordSelfBot' \ No newline at end of file diff --git a/src/main/java/catx/feitu/coze_discord_bridge/Config/ConfigBotsData.java b/src/main/java/catx/feitu/coze_discord_bridge/Config/ConfigBotsData.java index ebfd3ee..09e465d 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/Config/ConfigBotsData.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/Config/ConfigBotsData.java @@ -2,7 +2,9 @@ public class ConfigBotsData { public String Key = ""; - public String Discord_Bot_Token = ""; + public String Protocol = ""; + public String Token = ""; + public String Token2 = ""; public String CreateChannel_Category = ""; public String CozeBot_id = ""; public String Server_id = ""; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/DockerHelper.java b/src/main/java/catx/feitu/coze_discord_bridge/DockerHelper.java index a4a8241..7636a77 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/DockerHelper.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/DockerHelper.java @@ -14,7 +14,7 @@ public static void dockerHelper() { ConfigBotsData config = new ConfigBotsData(); - config.Discord_Bot_Token = System.getenv("token"); + config.Token = System.getenv("token"); config.Server_id = System.getenv("discord_server"); config.CozeBot_id = System.getenv("coze_bot"); config.Key = System.getenv("key") != null ? diff --git a/src/main/java/catx/feitu/coze_discord_bridge/GPTManage.java b/src/main/java/catx/feitu/coze_discord_bridge/GPTManage.java index 0443c0c..9be9678 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/GPTManage.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/GPTManage.java @@ -1,9 +1,9 @@ package catx.feitu.coze_discord_bridge; +import catx.feitu.CozeProxy.ConversationManage.ConversationHelper; +import catx.feitu.CozeProxy.CozeGPTConfig; import catx.feitu.coze_discord_bridge.Config.ConfigManage; -import catx.feitu.coze_discord_bridge.api.ConversationManage.ConversationHelper; -import catx.feitu.coze_discord_bridge.api.CozeGPT; -import catx.feitu.coze_discord_bridge.api.CozeGPTConfig; +import catx.feitu.CozeProxy.CozeGPT; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -40,7 +40,7 @@ public static void deleteGPT(String botID) { try { CozeGPT GPT = ResponseMap.get(botID); try { - GPT.Logout(); + GPT.disconnect(); } catch (Exception ignored) { } Files.writeString(new File("conversation_" + botID + ".json").toPath(), ConversationHelper.conversation2JsonString(GPT.conversations)); ResponseMap.remove(botID); @@ -67,9 +67,9 @@ public static void keepalive() { ConfigManage.configs.Keepalive_maxIntervalMinutes ) { try { - try { cozeGPT.GetConversationInfo(ConfigManage.configs.Keepalive_sendChannel); } - catch (Exception e) { cozeGPT.CreateConversation(ConfigManage.configs.Keepalive_sendChannel); } - cozeGPT.Chat(ConfigManage.configs.Keepalive_sendChannel ,ConfigManage.configs.Keepalive_sendMessage); + try { cozeGPT.getConversationInfo(ConfigManage.configs.Keepalive_sendChannel); } + catch (Exception e) { cozeGPT.createConversation(ConfigManage.configs.Keepalive_sendChannel); } + cozeGPT.chat(ConfigManage.configs.Keepalive_sendChannel ,ConfigManage.configs.Keepalive_sendMessage); logger.info("[keepalive] " + cozeGPT.getMark() + " 成功"); success++; } catch (Exception e) { diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/HandleType.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/HandleType.java index 213b61c..c6d7dac 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/HandleType.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/HandleType.java @@ -1,6 +1,6 @@ package catx.feitu.coze_discord_bridge.HttpServer; -import catx.feitu.coze_discord_bridge.api.CozeGPT; +import catx.feitu.CozeProxy.CozeGPT; import com.alibaba.fastjson.JSONObject; import com.sun.net.httpserver.HttpExchange; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/HttpServerManage.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/HttpServerManage.java index f7ca402..5391aaf 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/HttpServerManage.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/HttpServerManage.java @@ -4,7 +4,7 @@ import catx.feitu.coze_discord_bridge.GPTManage; import catx.feitu.coze_discord_bridge.HttpServer.api.Ping; import catx.feitu.coze_discord_bridge.HttpServer.api.api.*; -import catx.feitu.coze_discord_bridge.HttpServer.api.api.Discord.*; +import catx.feitu.coze_discord_bridge.HttpServer.api.api.Protocol.*; import catx.feitu.coze_discord_bridge.HttpServer.api.index; import catx.feitu.coze_discord_bridge.HttpServer.api.robots; import catx.feitu.coze_discord_bridge.HttpServer.api.v1.Models; @@ -130,9 +130,7 @@ public void configure(HttpsParameters params) { AddAPI("/api/Keepalive", new Keepalive(), true); AddAPI("/api/GetConversations", new GetConversations(), true); - AddAPI("/api/discord/GetUserInfo", new GetUserInfo(), true); - AddAPI("/api/discord/ReLogin", new ReLogin(), true); - AddAPI("/api/discord/GetChannels", new GetChannels(), true); + AddAPI("/api/protocol/ReLogin", new ReLogin(), true); AddAPI("/v1/models", new Models(), true); AddAPI("/v1/chat/Completions", new Completions(), true); diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Chat.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Chat.java index 8301236..1c8e14d 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Chat.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Chat.java @@ -1,13 +1,10 @@ package catx.feitu.coze_discord_bridge.HttpServer.api.api; +import catx.feitu.CozeProxy.Types.GPTFile; +import catx.feitu.CozeProxy.Types.GenerateMessage; import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidPromptException; -import catx.feitu.coze_discord_bridge.api.Exceptions.PromptTooLongException; -import catx.feitu.coze_discord_bridge.api.Exceptions.RecvMsgException; -import catx.feitu.coze_discord_bridge.api.Types.GPTFile; -import catx.feitu.coze_discord_bridge.api.Types.GenerateMessage; import com.alibaba.fastjson.JSONObject; import java.util.*; @@ -24,7 +21,7 @@ public ResponseType handle(HandleType Handle) { if (Handle.RequestParams.containsKey("image")) { Files.add(new GPTFile(Handle.RequestParams.getString("image"),"default.png")); } - GenerateMessage Generate = Handle.CozeGPT.Chat(Prompt, Name, Files); + GenerateMessage Generate = Handle.CozeGPT.chat(Prompt, Name, Files); Response.code = 200; json.put("code", 200); @@ -33,32 +30,10 @@ public ResponseType handle(HandleType Handle) { json_data.put("prompt", Generate.Message); json_data.put("files", Generate.Files); json.put("data", json_data); - } catch (InvalidPromptException e) { - Response.code = 400; - json.put("code", 400); - json.put("message", "无效的提示词"); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); - } catch (PromptTooLongException e) { - Response.code = 400; - json.put("code", 400); - json.put("message", "提示词超过长度限制 当前长度:" + e.GetPromptLength() + - " > 限制长度:" + e.GetLimitLength()); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); - } catch (RecvMsgException e) { - Response.code = 400; - json.put("code", 400); - json.put("message", e.getMessage()); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); } catch (Exception e) { Response.code = 400; json.put("code", 400); - json.put("message", "未知错误"); + json.put("message", e.getClass().getSimpleName() + ":" + e.getMessage()); JSONObject json_data = new JSONObject(true); json_data.put("status", false); json.put("data", json_data); diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/ChatStream.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/ChatStream.java index 3d16b61..54a131f 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/ChatStream.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/ChatStream.java @@ -1,13 +1,10 @@ package catx.feitu.coze_discord_bridge.HttpServer.api.api; +import catx.feitu.CozeProxy.Types.GPTFile; +import catx.feitu.CozeProxy.Types.GenerateMessage; import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidPromptException; -import catx.feitu.coze_discord_bridge.api.Exceptions.PromptTooLongException; -import catx.feitu.coze_discord_bridge.api.Exceptions.RecvMsgException; -import catx.feitu.coze_discord_bridge.api.Types.GPTFile; -import catx.feitu.coze_discord_bridge.api.Types.GenerateMessage; import com.alibaba.fastjson.JSONObject; import java.io.*; @@ -32,7 +29,7 @@ public ResponseType handle(HandleType Handle) { Handle.HttpExchange.getResponseHeaders().add("Transfer-Encoding", "chunked"); Handle.HttpExchange.sendResponseHeaders(200, 0); - GenerateMessage Generate = Handle.CozeGPT.Chat(Prompt, Name, Files ,(ALLGenerateMessages, NewGenerateMessage) -> { + GenerateMessage Generate = Handle.CozeGPT.chat(Prompt, Name, Files ,(ALLGenerateMessages, NewGenerateMessage) -> { json.put("code", 200); json.put("message", "生成中.."); JSONObject json_data = new JSONObject(true); @@ -60,32 +57,10 @@ public ResponseType handle(HandleType Handle) { os.flush(); os.close(); return null; - } catch (InvalidPromptException e) { - Response.code = 400; - json.put("code", 400); - json.put("message", "无效的提示词"); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); - } catch (PromptTooLongException e) { - Response.code = 400; - json.put("code", 400); - json.put("message", "提示词超过长度限制 当前长度:" + e.GetPromptLength() + - " > 限制长度:" + e.GetLimitLength()); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); - } catch (RecvMsgException e) { - Response.code = 400; - json.put("code", 400); - json.put("message", e.getMessage()); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); } catch (Exception e) { Response.code = 400; json.put("code", 400); - json.put("message", "未知错误"); + json.put("message", e.getClass().getSimpleName() + ":" + e.getMessage()); JSONObject json_data = new JSONObject(true); json_data.put("status", false); json.put("data", json_data); diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/ConversationIsFound.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/ConversationIsFound.java index 46ce52a..aa9a892 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/ConversationIsFound.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/ConversationIsFound.java @@ -1,11 +1,10 @@ package catx.feitu.coze_discord_bridge.HttpServer.api.api; +import catx.feitu.CozeProxy.Exceptions.InvalidConversationException; +import catx.feitu.CozeProxy.Types.ConversationInfo; import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConfigException; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConversationException; -import catx.feitu.coze_discord_bridge.api.Types.ConversationInfo; import com.alibaba.fastjson.JSONObject; public class ConversationIsFound implements APIHandler { @@ -15,7 +14,7 @@ public ResponseType handle(HandleType Handle) { JSONObject json = new JSONObject(true); String Name = Handle.RequestParams.containsKey("name") ? Handle.RequestParams.getString("name") : ""; try { - ConversationInfo Info = Handle.CozeGPT.GetConversationInfo(Name); + ConversationInfo Info = Handle.CozeGPT.getConversationInfo(Name); Response.code = 200; json.put("code", 200); json.put("message", "当前对话存在"); @@ -31,17 +30,10 @@ public ResponseType handle(HandleType Handle) { JSONObject json_data = new JSONObject(true); json_data.put("status", false); json.put("data", json_data); - } catch (InvalidConfigException e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "服务端配置异常:" + e.Get_Invalid_ConfigName() + ":" + e.Get_message()); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); } catch (Exception e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "删除对话失败"); + Response.code = 400; + json.put("code", 400); + json.put("message", "获取失败:" + e.getClass().getSimpleName() + ":" + e.getMessage()); JSONObject json_data = new JSONObject(true); json_data.put("status", false); json.put("data", json_data); diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/CreateConversation.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/CreateConversation.java index 0f2bf90..b56eb6f 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/CreateConversation.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/CreateConversation.java @@ -3,8 +3,6 @@ import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.Exceptions.ConversationAlreadyExistsException; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConfigException; import com.alibaba.fastjson.JSONObject; import static catx.feitu.coze_discord_bridge.Misc.Random.RandomName; @@ -16,35 +14,22 @@ public ResponseType handle(HandleType Handle) { ResponseType Response = new ResponseType(); JSONObject json = new JSONObject(true); - String Name = Handle.RequestParams.containsKey("name") ? Handle.RequestParams.getString("name") : RandomName(); + String name = Handle.RequestParams.containsKey("name") ? Handle.RequestParams.getString("name") : RandomName(); try { - String ChannelID = Handle.CozeGPT.CreateConversation(Name); + String ChannelID = Handle.CozeGPT.createConversation(name); Response.code = 200; JSONObject json_data = new JSONObject(true); json.put("code", 200); json.put("message", "创建子频道成功!"); json_data.put("conversation_id", ChannelID); - json_data.put("conversation_name", Name); + json_data.put("conversation_name", name); json.put("data", json_data); - } catch (InvalidConfigException e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "服务端配置异常:" + e.Get_Invalid_ConfigName() + ":" + e.Get_message()); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); - } catch (ConversationAlreadyExistsException e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "对话已存在"); - json.put("data", null); } catch (Exception e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "创建对话失败"); + Response.code = 400; + json.put("code", 400); + json.put("message", "创建对话失败:" + e.getClass().getSimpleName() + ":" + e.getMessage()); json.put("data", null); - e.printStackTrace(); } Response.msg = json.toJSONString(); return Response; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/DeleteConversation.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/DeleteConversation.java index fbedab8..288f7d3 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/DeleteConversation.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/DeleteConversation.java @@ -3,8 +3,6 @@ import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConfigException; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConversationException; import com.alibaba.fastjson.JSONObject; import static catx.feitu.coze_discord_bridge.Misc.Random.RandomName; @@ -18,7 +16,7 @@ public ResponseType handle(HandleType Handle) { String Name = Handle.RequestParams.containsKey("name") ? Handle.RequestParams.getString("name") : RandomName(); try { - Handle.CozeGPT.DeleteConversation(Name); + Handle.CozeGPT.deleteConversation(Name); Response.code = 200; json.put("code", 200); @@ -26,27 +24,11 @@ public ResponseType handle(HandleType Handle) { JSONObject json_data = new JSONObject(true); json_data.put("status", true); json.put("data", json_data); - } catch (InvalidConfigException e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "服务端配置异常:" + e.Get_Invalid_ConfigName() + ":" + e.Get_message()); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); - } catch (InvalidConversationException e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "当前对话不存在"); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); } catch (Exception e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "删除对话失败"); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); + Response.code = 400; + json.put("code", 400); + json.put("message", "删除对话失败:" + e.getClass().getSimpleName() + ":" + e.getMessage()); + json.put("data", null); } Response.msg = json.toJSONString(); return Response; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/GetChannels.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/GetChannels.java deleted file mode 100644 index 1c1a09d..0000000 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/GetChannels.java +++ /dev/null @@ -1,82 +0,0 @@ -package catx.feitu.coze_discord_bridge.HttpServer.api.api.Discord; - -import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; -import catx.feitu.coze_discord_bridge.HttpServer.HandleType; -import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import org.javacord.api.entity.channel.ChannelCategory; -import org.javacord.api.entity.channel.RegularServerChannel; - -import java.util.ArrayList; -import java.util.List; - -public class GetChannels implements APIHandler { - @Override - public ResponseType handle(HandleType Handle) { - ResponseType Response = new ResponseType(); - JSONObject json = new JSONObject(true); - try { - List categoryChannels = new ArrayList<>(); - - JSONArray json_data = new JSONArray(); - Handle.CozeGPT.private_getServer(); - List categorys = Handle.CozeGPT.server.getChannelCategories(); - // 处理有分组的频道 - for (ChannelCategory category : categorys) { - JSONObject json_data_categorys = new JSONObject(true); - JSONArray json_data_categorys_channels = new JSONArray(); - - json_data_categorys.put("name",category.getName()); - json_data_categorys.put("id",category.getId()); - - categoryChannels.add(category.getId()); - - List channels = category.getChannels(); - for (RegularServerChannel channel : channels) { - JSONObject json_data_categorys_channels_channel = new JSONObject(true); - - categoryChannels.add(channel.getId()); - - json_data_categorys_channels_channel.put("id",channel.getId()); - json_data_categorys_channels_channel.put("name",channel.getName()); - - json_data_categorys_channels.add(json_data_categorys_channels_channel); - } - json_data_categorys.put("channels",json_data_categorys_channels); - json_data.add(json_data_categorys); - } - // 处理没有分组的频道 - JSONArray json_data_no_group_channels = new JSONArray(); - List noGroupChannels = Handle.CozeGPT.server.getRegularChannels(); - for (RegularServerChannel channel : noGroupChannels) { - if (categoryChannels.contains(channel.getId())) { continue; } - JSONObject json_data_no_group_channel = new JSONObject(true); - json_data_no_group_channel.put("id", channel.getId()); - json_data_no_group_channel.put("name", channel.getName()); - - json_data_no_group_channels.add(json_data_no_group_channel); - } - JSONObject noGroupChannelsData = new JSONObject(true); - noGroupChannelsData.put("name", "default"); - noGroupChannelsData.put("id", null); - noGroupChannelsData.put("channels", json_data_no_group_channels); - json_data.add(noGroupChannelsData); - - - Response.code = 200; - json.put("code", 200); - json.put("message", "获取信息成功"); - json.put("data", json_data); - - } catch (Exception e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "获取信息失败"); - JSONObject json_data = new JSONObject(true); - json.put("data", json_data); - } - Response.msg = json.toJSONString(); - return Response; - } -} diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/GetUserInfo.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/GetUserInfo.java deleted file mode 100644 index 030d14b..0000000 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/GetUserInfo.java +++ /dev/null @@ -1,32 +0,0 @@ -package catx.feitu.coze_discord_bridge.HttpServer.api.api.Discord; - -import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; -import catx.feitu.coze_discord_bridge.HttpServer.HandleType; -import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import com.alibaba.fastjson.JSONObject; - -public class GetUserInfo implements APIHandler { - @Override - public ResponseType handle(HandleType Handle) { - ResponseType Response = new ResponseType(); - JSONObject json = new JSONObject(true); - try { - Response.code = 200; - json.put("code", 200); - json.put("message", "获取成功"); - JSONObject json_data = new JSONObject(true); - json_data.put("id", Handle.CozeGPT.discord_api.getYourself().getIdAsString()); - json_data.put("name", Handle.CozeGPT.discord_api.getYourself().getName()); - json_data.put("status", Handle.CozeGPT.discord_api.getYourself().getStatus().getStatusString()); - json.put("data", json_data); - } catch (Exception e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "获取信息失败"); - JSONObject json_data = new JSONObject(true); - json.put("data", json_data); - } - Response.msg = json.toJSONString(); - return Response; - } -} diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/GetConversations.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/GetConversations.java index 2af08c7..19abaac 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/GetConversations.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/GetConversations.java @@ -20,8 +20,7 @@ public ResponseType handle(HandleType Handle) { Response.code = 502; json.put("code", 502); json.put("message", "获取对话列表失败"); - JSONObject json_data = new JSONObject(true); - json.put("data", json_data); + json.put("data", null); } Response.msg = json.toJSONString(); return Response; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/GetLatestMessage.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/GetLatestMessage.java index 4e45b5a..6be933f 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/GetLatestMessage.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/GetLatestMessage.java @@ -1,9 +1,9 @@ package catx.feitu.coze_discord_bridge.HttpServer.api.api; +import catx.feitu.CozeProxy.MessageManage.BotResponseType; import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.MessageManage.BotResponseType; import com.alibaba.fastjson.JSONObject; public class GetLatestMessage implements APIHandler { @@ -14,7 +14,7 @@ public ResponseType handle(HandleType Handle) { JSONObject json = new JSONObject(true); String Name = Handle.RequestParams.containsKey("name") ? Handle.RequestParams.getString("name") : ""; try { - BotResponseType Generate = Handle.CozeGPT.BotResponseManage.getMsg(Handle.CozeGPT.conversations.get(Name)); + BotResponseType Generate = Handle.CozeGPT.cozeEventListener.botResponseManage.getMsg(Handle.CozeGPT.conversations.get(Name)); json.put("code", 200); json.put("message", "成功!"); @@ -28,7 +28,8 @@ public ResponseType handle(HandleType Handle) { json.put("message", "当前对话不存在"); JSONObject json_data = new JSONObject(true); json.put("data", json_data); - } Response.msg = json.toJSONString(); + } + Response.msg = json.toJSONString(); return Response; } } diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/IsBotOnline.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/IsBotOnline.java index bd5fd4c..1cf8f48 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/IsBotOnline.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/IsBotOnline.java @@ -15,7 +15,7 @@ public ResponseType handle(HandleType Handle) { json.put("code", 200); json.put("message", "获取成功"); JSONObject json_data = new JSONObject(true); - json_data.put("status", Handle.CozeGPT.IsCozeBotOnline()); + json_data.put("status", Handle.CozeGPT.isCozeBotOnline()); json.put("data", json_data); } catch (Exception e) { Response.code = 502; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/ReLogin.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Protocol/ReLogin.java similarity index 91% rename from src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/ReLogin.java rename to src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Protocol/ReLogin.java index 8184d80..8c5e2b6 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Discord/ReLogin.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/Protocol/ReLogin.java @@ -1,4 +1,4 @@ -package catx.feitu.coze_discord_bridge.HttpServer.api.api.Discord; +package catx.feitu.coze_discord_bridge.HttpServer.api.api.Protocol; import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; @@ -11,7 +11,7 @@ public ResponseType handle(HandleType Handle) { ResponseType Response = new ResponseType(); JSONObject json = new JSONObject(true); try { - Handle.CozeGPT.Login(); + Handle.CozeGPT.login(); Response.code = 200; json.put("code", 200); json.put("message", "重新登录成功"); diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/RenameConversation.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/RenameConversation.java index 62b03ab..b2b0cc1 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/RenameConversation.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/api/RenameConversation.java @@ -3,8 +3,6 @@ import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConfigException; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConversationException; import com.alibaba.fastjson.JSONObject; public class RenameConversation implements APIHandler { @@ -16,7 +14,7 @@ public ResponseType handle(HandleType Handle) { String OldName = Handle.RequestParams.containsKey("name") ? Handle.RequestParams.getString("name") : ""; String NewName = Handle.RequestParams.containsKey("new_name") ? Handle.RequestParams.getString("new_name") : ""; try { - String ChannelID = Handle.CozeGPT.RenameConversation(OldName,NewName); + String ChannelID = Handle.CozeGPT.renameConversation(OldName,NewName); Response.code = 200; json.put("code", 200); @@ -26,27 +24,11 @@ public ResponseType handle(HandleType Handle) { json_data.put("conversation_id", ChannelID); json_data.put("conversation_name", NewName); json.put("data", json_data); - } catch (InvalidConfigException e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "服务端配置异常:" + e.Get_Invalid_ConfigName() + ":" + e.Get_message()); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); - } catch (InvalidConversationException e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "当前对话不存在"); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); } catch (Exception e) { - Response.code = 502; - json.put("code", 502); - json.put("message", "重命名对话失败"); - JSONObject json_data = new JSONObject(true); - json_data.put("status", false); - json.put("data", json_data); + Response.code = 400; + json.put("code", 400); + json.put("message", "重命名对话失败:" + e.getClass().getSimpleName() + ":" + e.getMessage()); + json.put("data", null); } Response.msg = json.toJSONString(); return Response; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/v1/chat/Completions.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/v1/chat/Completions.java index f3b9780..198de77 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/v1/chat/Completions.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/v1/chat/Completions.java @@ -1,11 +1,11 @@ package catx.feitu.coze_discord_bridge.HttpServer.api.v1.chat; +import catx.feitu.CozeProxy.Exceptions.InvalidConversationException; +import catx.feitu.CozeProxy.Types.GenerateMessage; import catx.feitu.coze_discord_bridge.Config.ConfigManage; import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConversationException; -import catx.feitu.coze_discord_bridge.api.Types.GenerateMessage; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.apache.logging.log4j.LogManager; @@ -138,10 +138,10 @@ public ResponseType handle(HandleType Handle) { os.flush(); } // 创建频道 - try { Handle.CozeGPT.GetConversationInfo(Channel_id); } - catch (InvalidConversationException e) { Handle.CozeGPT.CreateConversation(Channel_id); + try { Handle.CozeGPT.getConversationInfo(Channel_id); } + catch (InvalidConversationException e) { Handle.CozeGPT.createConversation(Channel_id); }; - GenerateMessage Generate = Handle.CozeGPT.Chat(String.join("\n\n", SendMessage), Channel_id,(ALLGenerateMessages, NewGenerateMessage) -> { + GenerateMessage Generate = Handle.CozeGPT.chat(String.join("\n\n", SendMessage), Channel_id,(ALLGenerateMessages, NewGenerateMessage) -> { if (UsingStream) { // 启用流式返回 // 流式返回 JSON JSONObject update_choice = new JSONObject(true); diff --git a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/v1/images/Generations.java b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/v1/images/Generations.java index 8a7948f..0543df8 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/v1/images/Generations.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/HttpServer/api/v1/images/Generations.java @@ -1,11 +1,11 @@ package catx.feitu.coze_discord_bridge.HttpServer.api.v1.images; +import catx.feitu.CozeProxy.Exceptions.InvalidConversationException; +import catx.feitu.CozeProxy.Types.GenerateMessage; import catx.feitu.coze_discord_bridge.Config.ConfigManage; import catx.feitu.coze_discord_bridge.HttpServer.APIHandler; import catx.feitu.coze_discord_bridge.HttpServer.HandleType; import catx.feitu.coze_discord_bridge.HttpServer.ResponseType; -import catx.feitu.coze_discord_bridge.api.Exceptions.InvalidConversationException; -import catx.feitu.coze_discord_bridge.api.Types.GenerateMessage; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -18,9 +18,9 @@ public ResponseType handle(HandleType Handle) { JSONObject json = new JSONObject(true); try { // 创建频道 - try { Handle.CozeGPT.GetConversationInfo(ConfigManage.configs.OpenAPI_ImageGenerate_Default_Channel); } - catch (InvalidConversationException e) { Handle.CozeGPT.CreateConversation(ConfigManage.configs.OpenAPI_ImageGenerate_Default_Channel); } - GenerateMessage Generate = Handle.CozeGPT.Chat( + try { Handle.CozeGPT.getConversationInfo(ConfigManage.configs.OpenAPI_ImageGenerate_Default_Channel); } + catch (InvalidConversationException e) { Handle.CozeGPT.createConversation(ConfigManage.configs.OpenAPI_ImageGenerate_Default_Channel); } + GenerateMessage Generate = Handle.CozeGPT.chat( ConfigManage.configs.OpenAI_ImageGenerate_Prompt_Prefix + Handle.RequestParams.getString("prompt") + ConfigManage.configs.OpenAI_ImageGenerate_Prompt_Suffix, diff --git a/src/main/java/catx/feitu/coze_discord_bridge/Main.java b/src/main/java/catx/feitu/coze_discord_bridge/Main.java index d460ad8..e39e592 100644 --- a/src/main/java/catx/feitu/coze_discord_bridge/Main.java +++ b/src/main/java/catx/feitu/coze_discord_bridge/Main.java @@ -1,9 +1,10 @@ package catx.feitu.coze_discord_bridge; +import catx.feitu.CozeProxy.CozeGPTConfig; +import catx.feitu.CozeProxy.Protocol.Protocols; import catx.feitu.coze_discord_bridge.Config.ConfigBotsData; import catx.feitu.coze_discord_bridge.Config.ConfigManage; import catx.feitu.coze_discord_bridge.HttpServer.HttpServerManage; -import catx.feitu.coze_discord_bridge.api.CozeGPTConfig; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.fusesource.jansi.AnsiConsole; @@ -46,13 +47,15 @@ public static void main(String[] args) { CozeGPTConfig GPTConfig = new CozeGPTConfig(); try { BotData.Key = Objects.equals(BotData.Key, "") ? "default" : BotData.Key; - if (Objects.equals(BotData.Discord_Bot_Token, "")) { - throw new Exception("无效的Discord_Bot_Token"); + if (Objects.equals(BotData.Token, "")) { + throw new Exception("无效的Token"); } - GPTConfig.Discord_Bot_Token = BotData.Discord_Bot_Token; - GPTConfig.Server_id = BotData.Server_id; + GPTConfig.loginApp = BotData.Protocol; + GPTConfig.token = BotData.Token; + GPTConfig.token2 = BotData.Token2; + GPTConfig.serverID = BotData.Server_id; GPTConfig.Discord_CreateChannel_Category = BotData.CreateChannel_Category; - GPTConfig.CozeBot_id = BotData.CozeBot_id; + GPTConfig.botID = BotData.CozeBot_id; GPTConfig.generate_timeout = ConfigManage.configs.generate_timeout; diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/CozeGPT.java b/src/main/java/catx/feitu/coze_discord_bridge/api/CozeGPT.java deleted file mode 100644 index 48f8c52..0000000 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/CozeGPT.java +++ /dev/null @@ -1,361 +0,0 @@ -package catx.feitu.coze_discord_bridge.api; - -import catx.feitu.coze_discord_bridge.api.ConversationManage.ConversationData; -import catx.feitu.coze_discord_bridge.api.Exceptions.*; -import catx.feitu.coze_discord_bridge.api.FunctionalInterface.ChatStreamEvent; -import catx.feitu.coze_discord_bridge.api.Listen.MessageListener; -import catx.feitu.coze_discord_bridge.api.LockManage.LockManage; -import catx.feitu.coze_discord_bridge.api.MessageManage.BotGenerateStatusManage; -import catx.feitu.coze_discord_bridge.api.MessageManage.BotResponseManage; -import catx.feitu.coze_discord_bridge.api.MessageManage.BotResponseType; -import catx.feitu.coze_discord_bridge.api.Types.ConversationInfo; -import catx.feitu.coze_discord_bridge.api.Types.GPTFile; -import catx.feitu.coze_discord_bridge.api.Types.GenerateMessage; - -import org.javacord.api.DiscordApi; -import org.javacord.api.DiscordApiBuilder; -import org.javacord.api.entity.channel.*; -import org.javacord.api.entity.intent.Intent; -import org.javacord.api.entity.message.Message; -import org.javacord.api.entity.server.Server; -import org.javacord.api.entity.user.User; -import org.javacord.api.entity.user.UserStatus; - -import java.io.ByteArrayInputStream; -import java.time.Instant; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - -public class CozeGPT { - public Server server = null; - private final CozeGPTConfig config; - - public BotResponseManage BotResponseManage = new BotResponseManage(); - private final BotGenerateStatusManage BotGenerateStatusManage = new BotGenerateStatusManage(); - private final LockManage LockManage = new LockManage(); - private MessageListener MessageListener; - public ConversationData conversations = new ConversationData(); - public DiscordApi discord_api; - - - public CozeGPT(CozeGPTConfig config) { - this.config = config; - } - public CozeGPT(CozeGPTConfig config,boolean autoLogin) throws Exception { - this.config = config; - if (autoLogin) { - this.Login(); - } - } - /** - * Discord登录 - */ - public void Login() { - if (discord_api != null) { - discord_api.disconnect(); - } - discord_api = new DiscordApiBuilder() - .setToken(config.Discord_Bot_Token) - .addIntents(Intent.MESSAGE_CONTENT) - .setProxy(config.Proxy) - .login() - .join(); - this.MessageListener = new MessageListener(this.BotResponseManage ,this.BotGenerateStatusManage ,this.config); - discord_api.addListener(this.MessageListener); - } - /** - * Discord登出 - * - * @throws Exception 如果Bot未登录,可能会抛出 BotNotLoginException 异常 - */ - public void Logout() throws Exception { - if (discord_api == null) { - throw new BotNotLoginException(); - } - discord_api.disconnect(); - discord_api = null; - } - /** - * 获取标记 - */ - public String getMark() { - return config.Mark; - } - /** - * 设置标记 - */ - public void setMark(String mark) { - config.Mark = mark; - } - /** - * 发送一条消息到对话列表并等待Bot回复 - * - * @param Prompts 提示词,即用户发送的消息,可以填入url上传附件. - * @param ConversationID 对话ID,可通过 CreateConversation(String name); 获取,必须提供,用于储存上下文信息. - * @param Files 上传本地文件,可为多个. - * @param event 填入以支持消息流返回,返回 true 继续生成,返回 false 停止生成. - * @return 生成的消息信息. - * @throws Exception 如果消息生成过程遇到任何问题,则抛出异常. - */ - public GenerateMessage Chat(String Prompts, String ConversationID, List Files, ChatStreamEvent event) throws Exception { - if (Objects.equals(Prompts, "")) { - throw new InvalidPromptException(); - } - // 取服务器对象 - private_getServer(); - // 取对应子频道 - Optional channel = server.getChannelById(conversations.get(ConversationID)); - if (channel.isEmpty()) { - throw new InvalidConversationException(ConversationID); - } - TextChannel textChannel = (TextChannel) channel.get(); - // 锁定 避免同频道多次对话 - LockManage.getLock(textChannel.getIdAsString()).lock(); - // 初始化回复记录 - this.BotGenerateStatusManage.clearGenerateStatus(textChannel.getIdAsString()); - this.BotResponseManage.clearMsg(textChannel.getIdAsString()); - // 开始 - try { - CompletableFuture send = null; - if (Prompts.length() > 2000) { // 长文本发送消息 - if (!config.Disable_2000Limit_Unlock) { - throw new PromptTooLongException(Prompts,2000); - } - // 仅提及(@)唤醒机器人 - send = textChannel.sendMessage( - "<@" + config.CozeBot_id + ">" - ); - send = send.thenCompose(message -> textChannel.sendMessage( new ByteArrayInputStream(Prompts.getBytes()),"Prompt.txt")); - } else { - send = textChannel.sendMessage( // 默认发送消息 - "<@" + config.CozeBot_id + ">" + Prompts - ); - } - // 发送附件(图片)处理 - if (Files != null) { - for (GPTFile file : Files) { - send = send.thenCompose(message -> textChannel.sendMessage(file.GetByteArrayInputStream(),file.GetFileName())); - } - } - // 发送消息 - send.join(); - // 在此之下为bot回复消息处理阶段 -> 5s 超时 - boolean BotStartGenerate = false; - int attempt = 0; // 重试次数 - int maxRetries = 25; // 最大尝试次数 - while (!BotStartGenerate) { - attempt++; - if (attempt > maxRetries) { - throw new RecvMsgException("超时无回应:未开始生成"); - } - BotStartGenerate = this.BotGenerateStatusManage.getGenerateStatus(textChannel.getIdAsString()); - // 等待200ms - try { Thread.sleep(200); } catch (InterruptedException ignored) {} - } - BotResponseType Response = new BotResponseType(); - String LatestMessage = ""; - attempt = 0; // 重置重试次数 - maxRetries = 120; // 最大尝试次数 - // 超时 2 分钟 - while (!Response.IsCompleted(config.generate_timeout)) { - attempt++; - if (attempt > maxRetries) { - throw new RecvMsgException("超时无回应:超过设定时间"); - } - try { - Response = this.BotResponseManage.getMsg(textChannel.getIdAsString()); - } catch (NullPointerException ignored) {} - if (!event.handle(Response.prompt, Response.prompt.replace(LatestMessage,""))) { - throw new StopGenerateException(); - } - LatestMessage = Response.prompt; - try { Thread.sleep(500); } catch (InterruptedException ignored) {} - } - GenerateMessage return_info = new GenerateMessage(); - return_info.Message = Response.prompt; - return_info.Files = Response.files; - LockManage.getLock(textChannel.getIdAsString()).unlock(); - return return_info; - } catch (Exception e) { - LockManage.getLock(textChannel.getIdAsString()).unlock(); - throw e; - } - } - /** - * 发送一条消息到对话列表并等待Bot回复 - * - * @param Prompts 提示词,即用户发送的消息,可以填入url上传附件. - * @param ConversationID 对话ID,可通过 CreateConversation(String name); 获取,必须提供,用于储存上下文信息. - * @param Files 上传本地文件,可为多个. - * @return 生成的消息信息. - * @throws Exception 如果消息生成过程遇到任何问题,则抛出异常. - */ - public GenerateMessage Chat(String Prompts, String ConversationID, List Files) throws Exception { - return Chat(Prompts ,ConversationID ,Files ,(ALLGenerateMessages, NewGenerateMessage) -> { return true; }); - } - /** - * 发送一条消息到对话列表并等待Bot回复 - * - * @param Prompts 提示词,即用户发送的消息,可以填入url上传附件. - * @param ConversationID 对话ID,可通过 CreateConversation(String name); 获取,必须提供,用于储存上下文信息. - * @param event 填入以支持消息流返回,返回 true 继续生成,返回 false 停止生成. - * @return 生成的消息信息. - * @throws Exception 如果消息生成过程遇到任何问题,则抛出异常. - */ - public GenerateMessage Chat(String Prompts, String ConversationID, ChatStreamEvent event) throws Exception { - return Chat(Prompts ,ConversationID ,null ,event); - } - /** - * 发送一条消息到对话列表并等待Bot回复 - * - * @param Prompts 提示词,即用户发送的消息,可以填入url上传附件. - * @param ConversationID 对话ID,可通过 CreateConversation(String name); 获取,必须提供,用于储存上下文信息. - * @return 生成的消息信息. - * @throws Exception 如果消息生成过程遇到任何问题,则抛出异常. - */ - public GenerateMessage Chat(String Prompts, String ConversationID) throws Exception { - return Chat(Prompts ,ConversationID ,(ALLGenerateMessages, NewGenerateMessage) -> { return true; }); - } - /** - * 创建新的对话列表 - * - * @param ConversationName 对话名词,如果没有关闭对话名词索引功能则后续可以通过对话名词调用对话 - * @return 对话ID,一段数字,后续可通过此ID调用 - * @throws Exception 如果遇到任何问题,则抛出异常. - */ - public String CreateConversation (String ConversationName) throws Exception { - private_getServer(); - // 分类处理 - Optional Category = discord_api.getChannelById(config.Discord_CreateChannel_Category); - ChannelCategory category = (ChannelCategory) Category.orElse(null); - // 已有对话名称检查 - String ChannelID = conversations.get(ConversationName); - if (server.getChannelById(ChannelID).isPresent()) { - throw new ConversationAlreadyExistsException(ConversationName); - } - ServerTextChannel channel = server.createTextChannelBuilder() - .setName(ConversationName) - .setCategory(category) - .create() - .join(); - // 写入存储 - conversations.put(channel.getName(),channel.getIdAsString()); - // 返回数据 - return channel.getIdAsString(); - } - /** - * 创建新的对话列表 - * - * @return 对话ID,一段数字,后续可通过此ID调用 - * @throws Exception 如果遇到任何问题,则抛出异常. - */ - public String CreateConversation () throws Exception { - private_getServer(); - // 分类处理 - Optional Category = discord_api.getChannelById(config.Discord_CreateChannel_Category); - ChannelCategory category = (ChannelCategory) Category.orElse(null); - // 创建 - ServerTextChannel channel = server.createTextChannelBuilder() - .setName("default") - .setCategory(category) - .create() - .join(); - // 返回数据 - return channel.getIdAsString(); - } - /** - * 删除对话列表 - * - * @param ConversationName 对话名词/对话ID - * @throws Exception 如果遇到任何问题,则抛出异常. - */ - public void DeleteConversation (String ConversationName) throws Exception { - private_getServer(); - Optional channel = server.getChannelById(conversations.get(ConversationName)); - if (channel.isEmpty()) { - throw new InvalidConversationException(ConversationName); - } - channel.get().delete().join(); - conversations.remove(ConversationName); - } - /** - * 修改某个对话的名词 - * 注:对话ID无法修改 - * - * @param OldConversationName 旧的对话名词/对话ID - * @param NewConversationName 新的对话名词 - * @throws Exception 如果遇到任何问题,则抛出异常. - */ - public String RenameConversation (String OldConversationName, String NewConversationName) throws Exception { - private_getServer(); - Optional channel = server.getChannelById(conversations.get(OldConversationName)); - if (channel.isEmpty()) { - throw new InvalidConversationException(OldConversationName); - } - String ChannelID = conversations.get(NewConversationName); - if (server.getChannelById(ChannelID).isPresent()) { - throw new ConversationAlreadyExistsException(NewConversationName); - } - channel.get().updateName(NewConversationName).join(); - conversations.remove(OldConversationName); - conversations.put(NewConversationName,ChannelID); - return channel.get().getIdAsString(); - } - /** - * 修改某个对话的名词 - * 注:对话ID无法修改 - * - * @param ConversationName 对话名词/对话ID - * @return 对话信息 - * @throws Exception 如果遇到任何问题,则抛出异常. - */ - public ConversationInfo GetConversationInfo (String ConversationName) throws Exception { - private_getServer(); - String ChannelID = conversations.get(ConversationName); - Optional Channel = server.getChannelById(ChannelID); - if (Channel.isEmpty()) { - throw new InvalidConversationException(ConversationName); - } - ConversationInfo return_info = new ConversationInfo(); - return_info.Name = Channel.get().getName(); - return_info.ID = Channel.get().getIdAsString(); - return return_info; - } - public boolean IsCozeBotOnline() throws Exception { - private_getServer(); - Optional cozeBot = server.getMemberById(config.CozeBot_id); - if (cozeBot.isEmpty()) { - throw new InvalidCozeBotUserIDException(); - } - return cozeBot.get().getStatus() != UserStatus.OFFLINE; - } - /** - * 取出最后一次发送消息时间 - * @return 返回 Instant 类型 如果没有记录 返回类创建时间 - */ - public Instant getLatestSendMsgInstant () { - return this.MessageListener.getLatestSendMsgInstant(); - } - /** - * 取出最后一次接收Coze Bot消息时间 - * @return 返回 Instant 类型 如果没有记录 返回类创建时间 - */ - public Instant getLatestReceiveCozeMsgInstant () { - return this.MessageListener.getLatestReceiveCozeMsgInstant(); - } - - public void private_getServer() throws Exception { - if (discord_api == null) { - throw new BotNotLoginException(); - } - if (server == null) { - Optional optionalServer = discord_api.getServerById(config.Server_id); - if (optionalServer.isEmpty()) { - throw new InvalidDiscordServerException(); - } - server = optionalServer.get(); - } - } -} diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/BotNotLoginException.java b/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/BotNotLoginException.java deleted file mode 100644 index 3852ee1..0000000 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Exceptions/BotNotLoginException.java +++ /dev/null @@ -1,7 +0,0 @@ -package catx.feitu.coze_discord_bridge.api.Exceptions; - -public class BotNotLoginException extends Exception { - public BotNotLoginException() { - super(); - } -} diff --git a/src/main/java/catx/feitu/coze_discord_bridge/api/Listen/MessageListener.java b/src/main/java/catx/feitu/coze_discord_bridge/api/Listen/MessageListener.java deleted file mode 100644 index 772bfbc..0000000 --- a/src/main/java/catx/feitu/coze_discord_bridge/api/Listen/MessageListener.java +++ /dev/null @@ -1,97 +0,0 @@ -package catx.feitu.coze_discord_bridge.api.Listen; - -import catx.feitu.coze_discord_bridge.api.CozeGPTConfig; -import catx.feitu.coze_discord_bridge.api.MessageManage.BotGenerateStatusManage; -import catx.feitu.coze_discord_bridge.api.MessageManage.BotResponseManage; -import catx.feitu.coze_discord_bridge.api.MessageManage.BotResponseType; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.javacord.api.entity.message.embed.Embed; -import org.javacord.api.event.message.MessageCreateEvent; -import org.javacord.api.event.message.MessageEditEvent; -import org.javacord.api.event.user.UserStartTypingEvent; -import org.javacord.api.listener.message.MessageCreateListener; -import org.javacord.api.listener.message.MessageEditListener; -import org.javacord.api.listener.user.UserStartTypingListener; - -import java.time.Instant; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class MessageListener implements MessageCreateListener, MessageEditListener, UserStartTypingListener { - private static final Logger logger = LogManager.getLogger(MessageListener.class); - private final BotResponseManage botResponseManage; - private final BotGenerateStatusManage botGenerateStatusManage; - private final CozeGPTConfig config; - /** - * 最后一次发送消息时间 - */ - private Instant latestSendMessage = Instant.now(); - /** - * 最后一次接收消息时间 - */ - private Instant latestReceiveCozeMessage = Instant.now(); - public MessageListener(BotResponseManage botResponseManage, BotGenerateStatusManage botGenerateStatusManage, CozeGPTConfig config) { - this.botResponseManage = botResponseManage; - this.botGenerateStatusManage = botGenerateStatusManage; - this.config = config; - } - - @Override - public void onUserStartTyping(UserStartTypingEvent event) { - if(Objects.equals(event.getUserIdAsString(), config.CozeBot_id)) { - this.botGenerateStatusManage.saveGenerateStatus(event.getChannel().getIdAsString()); - logger.info("[CozeBot Start Generate] " + event.getChannel().getIdAsString()); - } - } - @Override - public void onMessageCreate(MessageCreateEvent event) { - latestSendMessage = Instant.now(); - if (Objects.equals(event.getMessageAuthor().getIdAsString(), event.getApi().getYourself().getIdAsString())) { - logger.info("[Send] " + event.getChannel().getIdAsString() + ": " + event.getMessageContent()); - } - } - - @Override - public void onMessageEdit(MessageEditEvent event) { - if (Objects.equals(event.getMessageAuthor().getIdAsString(), config.CozeBot_id)) { - latestReceiveCozeMessage = Instant.now(); - if (config.Disable_CozeBot_ReplyMsgCheck || event.getMessage().getMentionedUsers().contains(event.getApi().getYourself())) { - boolean Done100 = !event.getMessage().getComponents().isEmpty(); //存在按钮 = 100%响应完毕 - if (Done100) { - logger.info("[CozeBot] " + event.getChannel().getIdAsString() + ":" + event.getMessageContent()); - } - List embeds = event.getMessage().getEmbeds(); // 获取消息中的所有嵌入内容 - List files = new ArrayList<>(); // 存储嵌入图片的URL - for (Embed embed : embeds) { - if (embed.getImage().isPresent()) { - if (Done100) { - logger.info("[CozeBot] 图片URL -> " + embed.getImage().get().getUrl().toString()); - } - files.add(embed.getImage().get().getUrl().toString()); - } - } - BotResponseType Response = new BotResponseType(); - Response.prompt = event.getMessageContent(); - Response.files = files; - Response.SetCompleted(Done100); - this.botResponseManage.saveMsg(event.getChannel().getIdAsString(),Response); - } - } - } - /** - * 取出最后一次发送消息时间 - * @return 返回 Instant 类型 - */ - public Instant getLatestSendMsgInstant () { - return latestSendMessage; - } - /** - * 取出最后一次接收Coze Bot消息时间 - * @return 返回 Instant 类型 - */ - public Instant getLatestReceiveCozeMsgInstant () { - return latestReceiveCozeMessage; - } -} \ No newline at end of file diff --git a/src/main/resources/Config.yml b/src/main/resources/Config.yml index c58cbc7..2a709f6 100644 --- a/src/main/resources/Config.yml +++ b/src/main/resources/Config.yml @@ -6,14 +6,20 @@ Version_minSupport: 0 #创建Bot 根据不同的密钥访问不同的Bot Bots: - - #访问密钥 留空或default 表示无需密钥 通过不同的密钥链接不同的bot + - #访问密钥 留空或default 表示无需密钥 通过不同的密钥链接不同的bot Key: "default" + #登录协议 + Protocol: "discord" #Discord bot token 获取方法 #浏览器打开 https://discord.com/developers/ #创建Application > 点击Bot > 点击 Reset Token 然后复制过来即可 #注意 还需要打开Privileged Gateway Intents下面的选项 (MESSAGE CONTENT INTENT一定要开) - Discord_Bot_Token: "" - #创建频道时使用的父频道 (也可以理解成 分组) 打开开发者模式 右键就可以看到ID 为空关闭 + Token: "" + #Discord user token + #打开Discord(推荐注册小号 因为UserBot 本身Discord就禁止) 按下F12打开开发者模式 + #点进网络 随便选择一个 复制请求头 Authorization 粘贴在这里 + Token2: "" + #[仅Discord可用]创建频道时使用的父频道 (也可以理解成 分组) 打开开发者模式 右键就可以看到ID 为空关闭 CreateChannel_Category: "" #Coze Bot所处的服务器ID 打开Discord开发者模式 右键服务器复制过来即可 Server_id: ""