mirror of
				https://github.com/ddaodan/minechatgpt.git
				synced 2025-11-04 05:34:14 +08:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			b815cc1129
			...
			452fc8c1fc
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 452fc8c1fc | |||
| 62f1a443ea | 
							
								
								
									
										14
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								build.gradle
									
									
									
									
									
								
							@@ -4,7 +4,7 @@ plugins {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
group = 'com'
 | 
			
		||||
version = '2.6'
 | 
			
		||||
version = '2.7'
 | 
			
		||||
 | 
			
		||||
repositories {
 | 
			
		||||
    mavenCentral()
 | 
			
		||||
@@ -24,12 +24,22 @@ repositories {
 | 
			
		||||
dependencies {
 | 
			
		||||
    compileOnly "org.spigotmc:spigot-api:1.13-R0.1-SNAPSHOT"
 | 
			
		||||
    implementation 'org.bstats:bstats-bukkit:3.0.2'
 | 
			
		||||
    implementation 'org.jodd:jodd-http:6.3.0'
 | 
			
		||||
    implementation('org.jodd:jodd-http:6.3.0') {
 | 
			
		||||
        exclude group: 'org.jodd', module: 'jodd-core'
 | 
			
		||||
        exclude group: 'org.jodd', module: 'jodd-bean'
 | 
			
		||||
    }
 | 
			
		||||
    implementation 'org.json:json:20231013'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
shadowJar {
 | 
			
		||||
    archiveFileName = "MineChatGPT-${project.version}.jar"
 | 
			
		||||
    minimize()
 | 
			
		||||
    mergeServiceFiles()
 | 
			
		||||
 | 
			
		||||
    exclude 'META-INF/**'
 | 
			
		||||
    exclude '**/*.properties'
 | 
			
		||||
    exclude '**/jodd/http/upload/**'
 | 
			
		||||
    
 | 
			
		||||
    relocate 'jodd', 'com.ddaodan.shaded.jodd'
 | 
			
		||||
    relocate 'org.json', 'com.ddaodan.minechatgpt.libs.org.json'
 | 
			
		||||
    relocate 'org.bstats', 'com.ddaodan.minechatgpt.libs.org.bstats'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,11 @@
 | 
			
		||||
# 更新日志
 | 
			
		||||
## 2.7
 | 
			
		||||
- 多语言支持
 | 
			
		||||
- 配置文件添加双语注释
 | 
			
		||||
- 新增负载均衡,可轮询或随机选择API key
 | 
			
		||||
- 优化构建配置,插件体积减小
 | 
			
		||||
- 项目规范化
 | 
			
		||||
在此感谢Trae,以上功能都是靠它才能实现的!
 | 
			
		||||
## 2.6
 | 
			
		||||
- 添加角色功能
 | 
			
		||||
- 移除prompt功能
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										135
									
								
								readme.md
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								readme.md
									
									
									
									
									
								
							@@ -1,10 +1,9 @@
 | 
			
		||||
# MineChatGPT
 | 
			
		||||
  
 | 
			
		||||
     
 | 
			
		||||
    
 | 
			
		||||
[](https://modrinth.com/plugin/minechatgpt) [](https://www.spigotmc.org/resources/minechatgpt.118963/)    
 | 
			
		||||
   [](https://modrinth.com/plugin/minechatgpt/versions) [](https://www.spigotmc.org/resources/minechatgpt.118963/)
 | 
			
		||||
 | 
			
		||||
在Minecraft中与ChatGPT交流  
 | 
			
		||||
理论支持全版本,欢迎测试
 | 
			
		||||
 | 
			
		||||
所有的代码都是ChatGPT写的哦
 | 
			
		||||
 | 
			
		||||
@@ -12,6 +11,7 @@
 | 
			
		||||
- OpenAPI格式
 | 
			
		||||
- 自定义模型
 | 
			
		||||
- ChatGPT反代
 | 
			
		||||
- 负载均衡
 | 
			
		||||
- 指令补全
 | 
			
		||||
- 上下文对话
 | 
			
		||||
- 多角色
 | 
			
		||||
@@ -20,98 +20,52 @@
 | 
			
		||||
## 安装
 | 
			
		||||
1. 下载插件,放在plugins文件夹中
 | 
			
		||||
2. 重启服务器
 | 
			
		||||
> 为兼容更多版本,插件没有规定Bukkit API version,因此在较高版本加载插件时,控制台可能会出现以下错误信息,这属于正常现象。  
 | 
			
		||||
> ```
 | 
			
		||||
> [Server thread/WARN]: Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!
 | 
			
		||||
> [Server thread/WARN]: Legacy plugin MineChatGPT v1.0 does not specify an api-version.
 | 
			
		||||
> ```
 | 
			
		||||
3. 打开配置文件`config.yml`,修改以下两项设置:
 | 
			
		||||
```yaml
 | 
			
		||||
# API 相关设置
 | 
			
		||||
api:
 | 
			
		||||
  # 你的 OpenAI API key,用于身份验证
 | 
			
		||||
  # 获取 API key 的方法:访问 https://platform.openai.com/account/api-keys 并创建一个新的 API key
 | 
			
		||||
  key: "sk-your_openai_api_key"
 | 
			
		||||
  # OpenAI API 的基础 URL,用于构建请求
 | 
			
		||||
  base_url: "https://api.openai.com/v1"
 | 
			
		||||
```
 | 
			
		||||
  > 为兼容更多版本,插件没有规定Bukkit API version,因此在较高版本加载插件时,控制台可能会出现以下错误信息,这属于正常现象。  
 | 
			
		||||
  > ```
 | 
			
		||||
  > [Server thread/WARN]: Initializing Legacy Material Support. Unless you have legacy plugins and/or data this is a bug!
 | 
			
		||||
  > [Server thread/WARN]: Legacy plugin MineChatGPT v1.0 does not specify an api-version.
 | 
			
		||||
  > ```
 | 
			
		||||
3. 打开配置文件`config.yml`,修改以下设置:
 | 
			
		||||
  ```yaml
 | 
			
		||||
  # ======================================================
 | 
			
		||||
  # API Configuration
 | 
			
		||||
  # API 设置
 | 
			
		||||
  # ======================================================
 | 
			
		||||
  api:
 | 
			
		||||
    # Your OpenAI API keys, used for authentication
 | 
			
		||||
    # To obtain an API key, visit https://platform.openai.com/account/api-keys and create a new API key
 | 
			
		||||
    # 你的 OpenAI API key,用于身份验证
 | 
			
		||||
    # 获取 API key 的方法:访问 https://platform.openai.com/account/api-keys 并创建一个新的 API key
 | 
			
		||||
    keys:
 | 
			
		||||
      - "sk-your_openai_api_key_1"
 | 
			
		||||
      # You can add multiple API keys below
 | 
			
		||||
      # 可以添加多个API key
 | 
			
		||||
      # - "sk-your_openai_api_key_2"
 | 
			
		||||
      # - "sk-your_openai_api_key_3"
 | 
			
		||||
    
 | 
			
		||||
    # API key selection method: "round_robin" or "random"
 | 
			
		||||
    # Round Robin: Use each API key in turn
 | 
			
		||||
    # Random: Randomly select an API key
 | 
			
		||||
    # API key 选择方法:"round_robin"(轮询)或 "random"(随机)
 | 
			
		||||
    # 轮询:依次使用每个API key
 | 
			
		||||
    # 随机:随机选择一个API key
 | 
			
		||||
    selection_method: "round_robin"
 | 
			
		||||
    
 | 
			
		||||
    # The base URL for the OpenAI API, used to construct requests
 | 
			
		||||
    # If you cannot access the official API, you can use a proxy service
 | 
			
		||||
    # OpenAI API 的基础 URL,用于构建请求
 | 
			
		||||
    # 如果你无法访问官方API,可以使用代理服务
 | 
			
		||||
    base_url: "https://api.openai.com/v1"
 | 
			
		||||
  ```
 | 
			
		||||
4. 在控制台中输入`/chatgpt reload`重新加载配置文件
 | 
			
		||||
 | 
			
		||||
## 截图
 | 
			
		||||
- 服务端截图(Spigot 1.20.1)
 | 
			
		||||

 | 
			
		||||

 | 
			
		||||
- 插件截图
 | 
			
		||||

 | 
			
		||||

 | 
			
		||||
- 对话截图(使用FastGPT训练的自定义知识库)
 | 
			
		||||

 | 
			
		||||
## 配置文件`config.yml`
 | 
			
		||||
```yaml
 | 
			
		||||
# API 相关设置
 | 
			
		||||
api:
 | 
			
		||||
  # 你的 OpenAI API key,用于身份验证
 | 
			
		||||
  # 获取 API key 的方法:访问 https://platform.openai.com/account/api-keys 并创建一个新的 API key
 | 
			
		||||
  key: "sk-your_openai_api_key"
 | 
			
		||||
  # OpenAI API 的基础 URL,用于构建请求
 | 
			
		||||
  base_url: "https://api.openai.com/v1"
 | 
			
		||||
# 支持的模型列表
 | 
			
		||||
models:
 | 
			
		||||
  # OpenAI ChatGPT
 | 
			
		||||
  - "gpt-3.5-turbo"
 | 
			
		||||
  - "gpt-3.5-turbo-instruct"
 | 
			
		||||
  - "gpt-4"
 | 
			
		||||
  - "gpt-4-turbo"
 | 
			
		||||
  - "gpt-4-turbo-preview"
 | 
			
		||||
  - "gpt-4o"
 | 
			
		||||
  - "gpt-4o-mini"
 | 
			
		||||
  # Google Gemini
 | 
			
		||||
  # - "gemini-pro"
 | 
			
		||||
  # - "gemini-1.5-pro"
 | 
			
		||||
  # Anthropic Claude
 | 
			
		||||
  # - "claude-3-opus"
 | 
			
		||||
  # - "claude-3-5-sonnet"
 | 
			
		||||
  # 以及更多...
 | 
			
		||||
# 默认使用的模型
 | 
			
		||||
default_model: "gpt-3.5-turbo"
 | 
			
		||||
# 连续对话设置
 | 
			
		||||
conversation:
 | 
			
		||||
  # 连续对话开关
 | 
			
		||||
  context_enabled: false
 | 
			
		||||
  # 最大历史记录保留数量
 | 
			
		||||
  max_history_size: 10
 | 
			
		||||
# 角色设置
 | 
			
		||||
characters:
 | 
			
		||||
  # 格式:
 | 
			
		||||
  # 角色名称: "角色提示词"
 | 
			
		||||
  ChatGPT: "You are a helpful assistant."
 | 
			
		||||
# 消息相关设置
 | 
			
		||||
messages:
 | 
			
		||||
  reload: "&a已重新加载配置文件!"
 | 
			
		||||
  clear: "&a对话历史已清空!"
 | 
			
		||||
  help: "&e===== MineChatGPT 帮助 ====="
 | 
			
		||||
  help_ask: "&e/chatgpt <text> - 向ChatGPT提问"
 | 
			
		||||
  help_reload: "&e/chatgpt reload - 重新加载配置文件"
 | 
			
		||||
  help_model: "&e/chatgpt model <model_name> - 切换至其他模型"
 | 
			
		||||
  help_modellist: "&e/chatgpt modellist - 可用的模型列表"
 | 
			
		||||
  help_context: "&e/chatgpt context - 切换连续对话模式"
 | 
			
		||||
  help_clear: "&e/chatgpt clear - 清空对话历史"
 | 
			
		||||
  help_character: "&e/chatgpt character [character_name] - 列出或切换角色"
 | 
			
		||||
  context_toggle: "&e连续对话模式已%s。"
 | 
			
		||||
  context_toggle_enabled: "&a开启"
 | 
			
		||||
  context_toggle_disabled: "&c关闭"
 | 
			
		||||
  current_model_info: "&e当前模型:%s,输入 /chatgpt model <model_name> 来切换模型。"
 | 
			
		||||
  model_switch: "&a已切换至模型 %s"
 | 
			
		||||
  chatgpt_error: "&c无法联系ChatGPT。"
 | 
			
		||||
  chatgpt_response: "&b%s: %s"
 | 
			
		||||
  question: "&b你: %s"
 | 
			
		||||
  character_switched: "&a已切换至角色: %s"
 | 
			
		||||
  available_characters: "&e可用的角色列表:"
 | 
			
		||||
  invalid_character: "&c无效的角色。使用 /chatgpt character 查看所有可用的角色。"
 | 
			
		||||
  invalid_model: "&c模型无效。使用 /chatgpt modellist 查看可用模型。"
 | 
			
		||||
  available_models: "&e可用模型列表:"
 | 
			
		||||
  no_permission: "&c你没有权限使用这个指令。需要的权限:%s"
 | 
			
		||||
# 如果你不知道这是什么,请不要动
 | 
			
		||||
debug: false
 | 
			
		||||
```
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
## 指令与权限
 | 
			
		||||
|指令|权限|描述|
 | 
			
		||||
@@ -143,11 +97,12 @@ debug: false
 | 
			
		||||
检查`config.yml`中的`base_url`能否正常访问。如果你无法连接到OpenAI官方的API地址,可以考虑使用其他反代。
 | 
			
		||||
### 我可以添加其他模型吗?
 | 
			
		||||
可以,只要模型支持OpenAI的API,就可以使用。  
 | 
			
		||||
不推荐使用推理模型,因为推理模型的响应时间较长,在没有流式响应的情况下,玩家会认为插件出现了问题。
 | 
			
		||||
### 我没有ChatGPT的账号,可以用吗?
 | 
			
		||||
可以,目前有很多代理网站,可以很轻松地使用,而且还支持其他模型,费用通常来说也会比官方便宜。如果你愿意,也可以使用我的代理,目前仅在我的QQ群:226385797中提供。
 | 
			
		||||
### 是否会支持Folia
 | 
			
		||||
理论上插件可以在Folia上运行,但插件的代码并没有针对Folia进行过优化,因此可能会有一些问题。如果你愿意,可以尝试使用Folia运行插件,但不保证插件可以正常运行。
 | 
			
		||||
## 赞助
 | 
			
		||||
[](https://afdian.com/a/ddaodan)
 | 
			
		||||
[](https://afdian.com/a/ddaodan)
 | 
			
		||||
## 统计
 | 
			
		||||
[](https://bstats.org/plugin/bukkit/MineChatGPT/22635)
 | 
			
		||||
@@ -1,231 +1,52 @@
 | 
			
		||||
package com.ddaodan.MineChatGPT;
 | 
			
		||||
 | 
			
		||||
import com.ddaodan.MineChatGPT.service.ApiService;
 | 
			
		||||
import com.ddaodan.MineChatGPT.service.CommandService;
 | 
			
		||||
import com.ddaodan.MineChatGPT.service.UserSessionManager;
 | 
			
		||||
import org.bukkit.command.Command;
 | 
			
		||||
import org.bukkit.command.CommandExecutor;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
import org.json.JSONArray;
 | 
			
		||||
import org.json.JSONObject;
 | 
			
		||||
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.CompletableFuture;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
 | 
			
		||||
import jodd.http.HttpRequest;
 | 
			
		||||
import jodd.http.HttpResponse;
 | 
			
		||||
public class CommandHandler implements CommandExecutor {
 | 
			
		||||
    private final Main plugin;
 | 
			
		||||
    private final ConfigManager configManager;
 | 
			
		||||
    private static final Logger logger = Logger.getLogger(CommandHandler.class.getName());
 | 
			
		||||
    private final Map<String, ConversationContext> userContexts;
 | 
			
		||||
    private final Map<String, Boolean> userContextEnabled;
 | 
			
		||||
    private final CommandService commandService;
 | 
			
		||||
    private final UserSessionManager sessionManager;
 | 
			
		||||
 | 
			
		||||
    public CommandHandler(Main plugin, ConfigManager configManager) {
 | 
			
		||||
        this.plugin = plugin;
 | 
			
		||||
        this.configManager = configManager;
 | 
			
		||||
        this.userContexts = new HashMap<>();
 | 
			
		||||
        this.userContextEnabled = new HashMap<>();
 | 
			
		||||
        this.sessionManager = new UserSessionManager(configManager);
 | 
			
		||||
        ApiService apiService = new ApiService(configManager);
 | 
			
		||||
        this.commandService = new CommandService(configManager, apiService, sessionManager);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
 | 
			
		||||
        String userId = sender.getName();
 | 
			
		||||
 | 
			
		||||
        if (!userContexts.containsKey(userId)) {
 | 
			
		||||
            userContexts.put(userId, new ConversationContext(configManager.getMaxHistorySize()));
 | 
			
		||||
            userContextEnabled.put(userId, configManager.isContextEnabled());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ConversationContext conversationContext = userContexts.get(userId);
 | 
			
		||||
        boolean contextEnabled = userContextEnabled.get(userId);
 | 
			
		||||
 | 
			
		||||
        if (command.getName().equalsIgnoreCase("chatgpt")) {
 | 
			
		||||
            if (args.length == 0) {
 | 
			
		||||
                sendHelpMessage(sender);
 | 
			
		||||
                commandService.sendHelpMessage(sender);
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            String subCommand = args[0];
 | 
			
		||||
            if (subCommand.equalsIgnoreCase("reload")) {
 | 
			
		||||
                if (!sender.hasPermission("minechatgpt.reload")) {
 | 
			
		||||
                    sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.reload"));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                configManager.reloadConfig();
 | 
			
		||||
                sender.sendMessage(configManager.getReloadMessage());
 | 
			
		||||
                return true;
 | 
			
		||||
                return commandService.handleReloadCommand(sender);
 | 
			
		||||
            } else if (subCommand.equalsIgnoreCase("model")) {
 | 
			
		||||
                if (!sender.hasPermission("minechatgpt.model")) {
 | 
			
		||||
                    sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.model"));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                if (args.length < 2) {
 | 
			
		||||
                    String currentModel = configManager.getCurrentModel();
 | 
			
		||||
                    sender.sendMessage(configManager.getCurrentModelInfoMessage().replace("%s", currentModel));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                String model = args[1];
 | 
			
		||||
                List<String> models = configManager.getModels();
 | 
			
		||||
                if (models.contains(model)) {
 | 
			
		||||
                    configManager.setCurrentModel(model);
 | 
			
		||||
                    sender.sendMessage(configManager.getModelSwitchMessage().replace("%s", model));
 | 
			
		||||
                } else {
 | 
			
		||||
                    sender.sendMessage(configManager.getInvalidModelMessage());
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
                return commandService.handleModelCommand(sender, args);
 | 
			
		||||
            } else if (subCommand.equalsIgnoreCase("modellist")) {
 | 
			
		||||
                if (!sender.hasPermission("minechatgpt.modellist")) {
 | 
			
		||||
                    sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.modellist"));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                List<String> models = configManager.getModels();
 | 
			
		||||
                sender.sendMessage(configManager.getAvailableModelsMessage());
 | 
			
		||||
                for (String model : models) {
 | 
			
		||||
                    sender.sendMessage("- " + model);
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
            } else if (args.length > 0 && args[0].equalsIgnoreCase("context")) {
 | 
			
		||||
                contextEnabled = !contextEnabled;
 | 
			
		||||
                userContextEnabled.put(userId, contextEnabled);
 | 
			
		||||
                String status = contextEnabled ? configManager.getContextToggleEnabledMessage() : configManager.getContextToggleDisabledMessage();
 | 
			
		||||
                sender.sendMessage(configManager.getContextToggleMessage().replace("%s", status));
 | 
			
		||||
                return true;
 | 
			
		||||
                return commandService.handleModelListCommand(sender);
 | 
			
		||||
            } else if (subCommand.equalsIgnoreCase("context")) {
 | 
			
		||||
                return commandService.handleContextCommand(sender, userId);
 | 
			
		||||
            } else if (subCommand.equalsIgnoreCase("clear")) {
 | 
			
		||||
                if (!sender.hasPermission("minechatgpt.clear")) {
 | 
			
		||||
                    sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.clear"));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                conversationContext.clearHistory();
 | 
			
		||||
                sender.sendMessage(configManager.getClearMessage());
 | 
			
		||||
                return true;
 | 
			
		||||
                return commandService.handleClearCommand(sender, userId);
 | 
			
		||||
            } else if (subCommand.equalsIgnoreCase("character")) {
 | 
			
		||||
                    if (!sender.hasPermission("minechatgpt.character")) {
 | 
			
		||||
                        sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.character"));
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                    Map<String, String> characters = configManager.getCharacters();
 | 
			
		||||
                    if (args.length < 2) {
 | 
			
		||||
                        sender.sendMessage(configManager.getAvailableCharactersMessage());
 | 
			
		||||
                        for (String character : characters.keySet()) {
 | 
			
		||||
                            sender.sendMessage("- " + character);
 | 
			
		||||
                        }
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                    String character = args[1];
 | 
			
		||||
                    if (characters.containsKey(character)) {
 | 
			
		||||
                        configManager.setCurrentCharacter(userId, character);
 | 
			
		||||
                        sender.sendMessage(configManager.getCharacterSwitchedMessage().replace("%s", character));
 | 
			
		||||
                    } else {
 | 
			
		||||
                        sender.sendMessage(configManager.getInvalidCharacterMessage());
 | 
			
		||||
                    }
 | 
			
		||||
                    return true;
 | 
			
		||||
                return commandService.handleCharacterCommand(sender, args, userId);
 | 
			
		||||
            } else {
 | 
			
		||||
                if (!sender.hasPermission("minechatgpt.use")) {
 | 
			
		||||
                    sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.use"));
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
                String question = String.join(" ", args);
 | 
			
		||||
                if (contextEnabled) {
 | 
			
		||||
                    conversationContext.addMessage(question);
 | 
			
		||||
                }
 | 
			
		||||
                sender.sendMessage(configManager.getQuestionMessage().replace("%s", question));
 | 
			
		||||
                askChatGPT(sender, question, conversationContext, contextEnabled, userId);
 | 
			
		||||
                return true;
 | 
			
		||||
                return commandService.handleAskCommand(sender, args, userId);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void askChatGPT(CommandSender sender, String question, ConversationContext conversationContext, boolean contextEnabled, String userId) {
 | 
			
		||||
        String utf8Question = convertToUTF8(question);
 | 
			
		||||
        JSONObject json = new JSONObject();
 | 
			
		||||
        json.put("model", configManager.getDefaultModel());
 | 
			
		||||
        JSONArray messages = new JSONArray();
 | 
			
		||||
        // 添加自定义 prompt
 | 
			
		||||
        String currentCharacter = configManager.getCurrentCharacter(userId);
 | 
			
		||||
        String customPrompt = configManager.getCharacters().get(currentCharacter);
 | 
			
		||||
        if (customPrompt != null && !customPrompt.isEmpty()) {
 | 
			
		||||
            JSONObject promptMessage = new JSONObject();
 | 
			
		||||
            promptMessage.put("role", "system");
 | 
			
		||||
            promptMessage.put("content", customPrompt);
 | 
			
		||||
            messages.put(promptMessage);
 | 
			
		||||
        }
 | 
			
		||||
        JSONObject message = new JSONObject();
 | 
			
		||||
        message.put("role", "user");
 | 
			
		||||
        message.put("content", utf8Question);
 | 
			
		||||
        messages.put(message);
 | 
			
		||||
        if (contextEnabled) {
 | 
			
		||||
            String history = conversationContext.getConversationHistory();
 | 
			
		||||
            if (!history.isEmpty()) {
 | 
			
		||||
                JSONObject historyMessage = new JSONObject();
 | 
			
		||||
                historyMessage.put("role", "system");
 | 
			
		||||
                historyMessage.put("content", history);
 | 
			
		||||
                messages.put(historyMessage);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        json.put("messages", messages);
 | 
			
		||||
        json.put("model", configManager.getCurrentModel());
 | 
			
		||||
        if (configManager.isDebugMode()) {
 | 
			
		||||
            logger.info("Built request: " + json.toString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        HttpRequest request = HttpRequest.post(configManager.getBaseUrl() + "/chat/completions")
 | 
			
		||||
                .header("Content-Type", "application/json; charset=UTF-8")
 | 
			
		||||
                .header("Authorization", "Bearer " + configManager.getApiKey())
 | 
			
		||||
                .bodyText(json.toString());
 | 
			
		||||
 | 
			
		||||
        if (configManager.isDebugMode()) {
 | 
			
		||||
            logger.info("Sending request to ChatGPT: " + request.toString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //HttpResponse response = request.send();
 | 
			
		||||
        CompletableFuture.supplyAsync(() -> request.send())
 | 
			
		||||
                .thenAccept(response -> {
 | 
			
		||||
                    if (configManager.isDebugMode()) {
 | 
			
		||||
                        logger.info("Received response from ChatGPT: " + response.toString());
 | 
			
		||||
                    }
 | 
			
		||||
                    if (response.statusCode() == 200) {
 | 
			
		||||
                        String responseBody = response.bodyText();
 | 
			
		||||
                        String utf8ResponseBody = new String(responseBody.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
 | 
			
		||||
                        JSONObject jsonResponse = new JSONObject(utf8ResponseBody);
 | 
			
		||||
                        String answer = jsonResponse.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
 | 
			
		||||
                        sender.sendMessage(configManager.getChatGPTResponseMessage().replaceFirst("%s", currentCharacter).replaceFirst("%s", answer));
 | 
			
		||||
                        if (contextEnabled) {
 | 
			
		||||
                            conversationContext.addMessage(answer); // 仅在启用上下文时添加AI响应到历史记录
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        String errorBody = response.bodyText();
 | 
			
		||||
                        logger.log(Level.SEVERE, "Failed to get a response from ChatGPT: " + errorBody);
 | 
			
		||||
                        sender.sendMessage(configManager.getChatGPTErrorMessage());
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
                .exceptionally(e -> {
 | 
			
		||||
                    logger.log(Level.SEVERE, "Exception occurred while processing request: " + e.getMessage(), e);
 | 
			
		||||
                    sender.sendMessage(configManager.getChatGPTErrorMessage());
 | 
			
		||||
                    return null;
 | 
			
		||||
                });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String convertToUTF8(String input) {
 | 
			
		||||
        try {
 | 
			
		||||
            // 尝试将输入字符串转换为 UTF-8 编码
 | 
			
		||||
            byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
 | 
			
		||||
            return new String(bytes, StandardCharsets.UTF_8);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.severe("Failed to convert input to UTF-8: " + e.getMessage());
 | 
			
		||||
            return input; // 如果转换失败,返回原始输入
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private void sendHelpMessage(CommandSender sender) {
 | 
			
		||||
        sender.sendMessage(configManager.getHelpMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpAskMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpReloadMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpModelMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpModelListMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpContextMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpClearMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpCharacterMessage());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -11,10 +11,14 @@ public class ConfigManager {
 | 
			
		||||
    private final Main plugin;
 | 
			
		||||
    private FileConfiguration config;
 | 
			
		||||
    private String currentModel;
 | 
			
		||||
    private LanguageManager languageManager;
 | 
			
		||||
 | 
			
		||||
    public ConfigManager(Main plugin) {
 | 
			
		||||
        this.plugin = plugin;
 | 
			
		||||
        reloadConfig();
 | 
			
		||||
        // 获取语言设置
 | 
			
		||||
        String language = config.getString("language", "en");
 | 
			
		||||
        this.languageManager = new LanguageManager(plugin, language);
 | 
			
		||||
    }
 | 
			
		||||
    public boolean isDebugMode() {
 | 
			
		||||
        return config.getBoolean("debug", false);
 | 
			
		||||
@@ -23,6 +27,12 @@ public class ConfigManager {
 | 
			
		||||
        plugin.reloadConfig();
 | 
			
		||||
        config = plugin.getConfig();
 | 
			
		||||
        currentModel = config.getString("default_model");
 | 
			
		||||
        
 | 
			
		||||
        // 重新加载语言文件
 | 
			
		||||
        if (languageManager != null) {
 | 
			
		||||
            String language = config.getString("language", "en");
 | 
			
		||||
            languageManager.setLanguage(language);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String translateColorCodes(String message) {
 | 
			
		||||
@@ -34,8 +44,31 @@ public class ConfigManager {
 | 
			
		||||
    public void setCurrentModel(String model) {
 | 
			
		||||
        currentModel = model;
 | 
			
		||||
    }
 | 
			
		||||
    private int currentKeyIndex = 0;
 | 
			
		||||
    
 | 
			
		||||
    public String getApiKey() {
 | 
			
		||||
        return config.getString("api.key");
 | 
			
		||||
        List<String> keys = config.getStringList("api.keys");
 | 
			
		||||
        if (keys.isEmpty()) {
 | 
			
		||||
            // 向后兼容:如果没有找到keys列表,尝试使用旧的单一key配置
 | 
			
		||||
            String legacyKey = config.getString("api.key");
 | 
			
		||||
            if (legacyKey != null && !legacyKey.isEmpty()) {
 | 
			
		||||
                return legacyKey;
 | 
			
		||||
            }
 | 
			
		||||
            return "";
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        String selectionMethod = config.getString("api.selection_method", "round_robin");
 | 
			
		||||
        
 | 
			
		||||
        if ("random".equalsIgnoreCase(selectionMethod)) {
 | 
			
		||||
            // 随机选择一个key
 | 
			
		||||
            int randomIndex = (int) (Math.random() * keys.size());
 | 
			
		||||
            return keys.get(randomIndex);
 | 
			
		||||
        } else {
 | 
			
		||||
            // 默认使用轮询方式
 | 
			
		||||
            String key = keys.get(currentKeyIndex);
 | 
			
		||||
            currentKeyIndex = (currentKeyIndex + 1) % keys.size();
 | 
			
		||||
            return key;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public String getBaseUrl() {
 | 
			
		||||
        return config.getString("api.base_url");
 | 
			
		||||
@@ -44,58 +77,58 @@ public class ConfigManager {
 | 
			
		||||
        return config.getString("default_model");
 | 
			
		||||
    }
 | 
			
		||||
    public String getReloadMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.reload"));
 | 
			
		||||
        return languageManager.getMessage("reload");
 | 
			
		||||
    }
 | 
			
		||||
    public List<String> getModels() {
 | 
			
		||||
        return config.getStringList("models");
 | 
			
		||||
    }
 | 
			
		||||
    public String getHelpMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.help"));
 | 
			
		||||
        return languageManager.getMessage("help");
 | 
			
		||||
    }
 | 
			
		||||
    public String getHelpAskMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.help_ask"));
 | 
			
		||||
        return languageManager.getMessage("help_ask");
 | 
			
		||||
    }
 | 
			
		||||
    public String getHelpReloadMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.help_reload"));
 | 
			
		||||
        return languageManager.getMessage("help_reload");
 | 
			
		||||
    }
 | 
			
		||||
    public String getHelpModelMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.help_model"));
 | 
			
		||||
        return languageManager.getMessage("help_model");
 | 
			
		||||
    }
 | 
			
		||||
    public String getHelpModelListMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.help_modellist"));
 | 
			
		||||
        return languageManager.getMessage("help_modellist");
 | 
			
		||||
    }
 | 
			
		||||
    public String getHelpContextMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.help_context", "&e/chatgpt context - Toggle context mode."));
 | 
			
		||||
        return languageManager.getMessage("help_context");
 | 
			
		||||
    }
 | 
			
		||||
    public String getHelpClearMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.help_clear", "&e/chatgpt clear - Clear conversation history."));
 | 
			
		||||
        return languageManager.getMessage("help_clear");
 | 
			
		||||
    }
 | 
			
		||||
    public String getHelpCharacterMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.help_character", "&e/chatgpt character [character_name] - List or switch to a character."));
 | 
			
		||||
        return languageManager.getMessage("help_character");
 | 
			
		||||
    }
 | 
			
		||||
    public String getModelSwitchMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.model_switch"));
 | 
			
		||||
        return languageManager.getMessage("model_switch");
 | 
			
		||||
    }
 | 
			
		||||
    public String getChatGPTErrorMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.chatgpt_error"));
 | 
			
		||||
        return languageManager.getMessage("chatgpt_error");
 | 
			
		||||
    }
 | 
			
		||||
    public String getChatGPTResponseMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.chatgpt_response", "&b%s: %s"));
 | 
			
		||||
        return languageManager.getMessage("chatgpt_response", "&b%s: %s");
 | 
			
		||||
    }
 | 
			
		||||
    public String getQuestionMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.question"));
 | 
			
		||||
        return languageManager.getMessage("question");
 | 
			
		||||
    }
 | 
			
		||||
    public String getInvalidModelMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.invalid_model"));
 | 
			
		||||
        return languageManager.getMessage("invalid_model");
 | 
			
		||||
    }
 | 
			
		||||
    public String getAvailableModelsMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.available_models"));
 | 
			
		||||
        return languageManager.getMessage("available_models");
 | 
			
		||||
    }
 | 
			
		||||
    public String getNoPermissionMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.no_permission"));
 | 
			
		||||
        return languageManager.getMessage("no_permission");
 | 
			
		||||
    }
 | 
			
		||||
    public String getCurrentModelInfoMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.current_model_info"));
 | 
			
		||||
        return languageManager.getMessage("current_model_info");
 | 
			
		||||
    }
 | 
			
		||||
    public int getMaxHistorySize() {
 | 
			
		||||
        return config.getInt("conversation.max_history_size", 10);
 | 
			
		||||
@@ -104,25 +137,25 @@ public class ConfigManager {
 | 
			
		||||
        return config.getBoolean("conversation.context_enabled", false);
 | 
			
		||||
    }
 | 
			
		||||
    public String getContextToggleMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.context_toggle", "&eContext is now %s."));
 | 
			
		||||
        return languageManager.getMessage("context_toggle", "&eContext is now %s.");
 | 
			
		||||
    }
 | 
			
		||||
    public String getContextToggleEnabledMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.context_toggle_enabled", "&aenabled"));
 | 
			
		||||
        return languageManager.getMessage("context_toggle_enabled", "&aenabled");
 | 
			
		||||
    }
 | 
			
		||||
    public String getContextToggleDisabledMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.context_toggle_disabled", "&edisabled"));
 | 
			
		||||
        return languageManager.getMessage("context_toggle_disabled", "&edisabled");
 | 
			
		||||
    }
 | 
			
		||||
    public String getClearMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.clear", "&aConversation history has been cleared."));
 | 
			
		||||
        return languageManager.getMessage("clear", "&aConversation history has been cleared.");
 | 
			
		||||
    }
 | 
			
		||||
    public String getCharacterSwitchedMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.character_switched", "&aSwitched to character: %s"));
 | 
			
		||||
        return languageManager.getMessage("character_switched", "&aSwitched to character: %s");
 | 
			
		||||
    }
 | 
			
		||||
    public String getAvailableCharactersMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.available_characters", "&eAvailable characters:"));
 | 
			
		||||
        return languageManager.getMessage("available_characters", "&eAvailable characters:");
 | 
			
		||||
    }
 | 
			
		||||
    public String getInvalidCharacterMessage() {
 | 
			
		||||
        return translateColorCodes(config.getString("messages.invalid_character", "&cInvalid character. Use /chatgpt character to list available characters."));
 | 
			
		||||
        return languageManager.getMessage("invalid_character", "&cInvalid character. Use /chatgpt character to list available characters.");
 | 
			
		||||
    }
 | 
			
		||||
    public Map<String, String> getCharacters() {
 | 
			
		||||
        Map<String, String> characters = new HashMap<>();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										65
									
								
								src/main/java/com/ddaodan/MineChatGPT/LanguageManager.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/main/java/com/ddaodan/MineChatGPT/LanguageManager.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
package com.ddaodan.MineChatGPT;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.ChatColor;
 | 
			
		||||
import org.bukkit.configuration.file.FileConfiguration;
 | 
			
		||||
import org.bukkit.configuration.file.YamlConfiguration;
 | 
			
		||||
 | 
			
		||||
import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
 | 
			
		||||
public class LanguageManager {
 | 
			
		||||
    private final Main plugin;
 | 
			
		||||
    private FileConfiguration langConfig;
 | 
			
		||||
    private String currentLanguage;
 | 
			
		||||
    private File langFile;
 | 
			
		||||
 | 
			
		||||
    public LanguageManager(Main plugin, String language) {
 | 
			
		||||
        this.plugin = plugin;
 | 
			
		||||
        this.currentLanguage = language;
 | 
			
		||||
        loadLanguage();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void loadLanguage() {
 | 
			
		||||
        langFile = new File(plugin.getDataFolder(), "lang" + File.separator + currentLanguage + ".yml");
 | 
			
		||||
        
 | 
			
		||||
        // 如果语言文件不存在,创建默认语言文件
 | 
			
		||||
        if (!langFile.exists()) {
 | 
			
		||||
            langFile.getParentFile().mkdirs();
 | 
			
		||||
            plugin.saveResource("lang/" + currentLanguage + ".yml", false);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        langConfig = YamlConfiguration.loadConfiguration(langFile);
 | 
			
		||||
        
 | 
			
		||||
        // 设置默认值,以防语言文件中缺少某些键
 | 
			
		||||
        InputStream defaultLangStream = plugin.getResource("lang/" + currentLanguage + ".yml");
 | 
			
		||||
        if (defaultLangStream != null) {
 | 
			
		||||
            YamlConfiguration defaultLang = YamlConfiguration.loadConfiguration(
 | 
			
		||||
                    new InputStreamReader(defaultLangStream, StandardCharsets.UTF_8));
 | 
			
		||||
            langConfig.setDefaults(defaultLang);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setLanguage(String language) {
 | 
			
		||||
        this.currentLanguage = language;
 | 
			
		||||
        loadLanguage();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getCurrentLanguage() {
 | 
			
		||||
        return currentLanguage;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String translateColorCodes(String message) {
 | 
			
		||||
        return ChatColor.translateAlternateColorCodes('&', message);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getMessage(String path) {
 | 
			
		||||
        return translateColorCodes(langConfig.getString("messages." + path, "Missing message: " + path));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getMessage(String path, String defaultValue) {
 | 
			
		||||
        return translateColorCodes(langConfig.getString("messages." + path, defaultValue));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -9,11 +9,15 @@ public final class Main extends JavaPlugin {
 | 
			
		||||
    private ConfigManager configManager;
 | 
			
		||||
    private CommandHandler commandHandler;
 | 
			
		||||
    private MineChatGPTTabCompleter tabCompleter;
 | 
			
		||||
    private LanguageManager languageManager;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onEnable() {
 | 
			
		||||
        saveDefaultConfig();
 | 
			
		||||
        configManager = new ConfigManager(this);
 | 
			
		||||
        // 初始化语言管理器
 | 
			
		||||
        String language = getConfig().getString("language", "en");
 | 
			
		||||
        languageManager = new LanguageManager(this, language);
 | 
			
		||||
        commandHandler = new CommandHandler(this, configManager);
 | 
			
		||||
        tabCompleter = new MineChatGPTTabCompleter(configManager);
 | 
			
		||||
        Objects.requireNonNull(getCommand("chatgpt")).setExecutor(commandHandler);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										155
									
								
								src/main/java/com/ddaodan/MineChatGPT/service/ApiService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								src/main/java/com/ddaodan/MineChatGPT/service/ApiService.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,155 @@
 | 
			
		||||
package com.ddaodan.MineChatGPT.service;
 | 
			
		||||
 | 
			
		||||
import com.ddaodan.MineChatGPT.ConfigManager;
 | 
			
		||||
import com.ddaodan.MineChatGPT.ConversationContext;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
import org.json.JSONArray;
 | 
			
		||||
import org.json.JSONObject;
 | 
			
		||||
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.util.concurrent.CompletableFuture;
 | 
			
		||||
import java.util.logging.Level;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
import jodd.http.HttpRequest;
 | 
			
		||||
import jodd.http.HttpResponse;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * API服务类,负责处理与OpenAI API的通信
 | 
			
		||||
 */
 | 
			
		||||
public class ApiService {
 | 
			
		||||
    private final ConfigManager configManager;
 | 
			
		||||
    private static final Logger logger = Logger.getLogger(ApiService.class.getName());
 | 
			
		||||
 | 
			
		||||
    public ApiService(ConfigManager configManager) {
 | 
			
		||||
        this.configManager = configManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 向ChatGPT发送请求
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param question 问题内容
 | 
			
		||||
     * @param conversationContext 对话上下文
 | 
			
		||||
     * @param contextEnabled 是否启用上下文
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     */
 | 
			
		||||
    public void askChatGPT(CommandSender sender, String question, ConversationContext conversationContext, boolean contextEnabled, String userId) {
 | 
			
		||||
        String utf8Question = convertToUTF8(question);
 | 
			
		||||
        JSONObject json = new JSONObject();
 | 
			
		||||
        json.put("model", configManager.getCurrentModel());
 | 
			
		||||
        JSONArray messages = new JSONArray();
 | 
			
		||||
        
 | 
			
		||||
        // 添加自定义 prompt
 | 
			
		||||
        String currentCharacter = configManager.getCurrentCharacter(userId);
 | 
			
		||||
        String customPrompt = configManager.getCharacters().get(currentCharacter);
 | 
			
		||||
        if (customPrompt != null && !customPrompt.isEmpty()) {
 | 
			
		||||
            JSONObject promptMessage = new JSONObject();
 | 
			
		||||
            promptMessage.put("role", "system");
 | 
			
		||||
            promptMessage.put("content", customPrompt);
 | 
			
		||||
            messages.put(promptMessage);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        JSONObject message = new JSONObject();
 | 
			
		||||
        message.put("role", "user");
 | 
			
		||||
        message.put("content", utf8Question);
 | 
			
		||||
        messages.put(message);
 | 
			
		||||
        
 | 
			
		||||
        if (contextEnabled) {
 | 
			
		||||
            String history = conversationContext.getConversationHistory();
 | 
			
		||||
            if (!history.isEmpty()) {
 | 
			
		||||
                JSONObject historyMessage = new JSONObject();
 | 
			
		||||
                historyMessage.put("role", "system");
 | 
			
		||||
                historyMessage.put("content", history);
 | 
			
		||||
                messages.put(historyMessage);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        json.put("messages", messages);
 | 
			
		||||
        
 | 
			
		||||
        if (configManager.isDebugMode()) {
 | 
			
		||||
            logger.info("Built request: " + json.toString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        HttpRequest request = HttpRequest.post(configManager.getBaseUrl() + "/chat/completions")
 | 
			
		||||
                .header("Content-Type", "application/json; charset=UTF-8")
 | 
			
		||||
                .header("Authorization", "Bearer " + configManager.getApiKey())
 | 
			
		||||
                .bodyText(json.toString());
 | 
			
		||||
 | 
			
		||||
        if (configManager.isDebugMode()) {
 | 
			
		||||
            logger.info("Sending request to ChatGPT: " + request.toString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        CompletableFuture.supplyAsync(() -> request.send())
 | 
			
		||||
                .thenAccept(response -> {
 | 
			
		||||
                    if (configManager.isDebugMode()) {
 | 
			
		||||
                        logger.info("Received response from ChatGPT: " + response.toString());
 | 
			
		||||
                    }
 | 
			
		||||
                    if (response.statusCode() == 200) {
 | 
			
		||||
                        processSuccessResponse(response, sender, conversationContext, contextEnabled, currentCharacter);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        processErrorResponse(response, sender);
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
                .exceptionally(e -> {
 | 
			
		||||
                    logger.log(Level.SEVERE, "Exception occurred while processing request: " + e.getMessage(), e);
 | 
			
		||||
                    sender.sendMessage(configManager.getChatGPTErrorMessage());
 | 
			
		||||
                    return null;
 | 
			
		||||
                });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理成功的API响应
 | 
			
		||||
     *
 | 
			
		||||
     * @param response HTTP响应
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param conversationContext 对话上下文
 | 
			
		||||
     * @param contextEnabled 是否启用上下文
 | 
			
		||||
     * @param currentCharacter 当前角色
 | 
			
		||||
     */
 | 
			
		||||
    private void processSuccessResponse(HttpResponse response, CommandSender sender, 
 | 
			
		||||
                                       ConversationContext conversationContext, 
 | 
			
		||||
                                       boolean contextEnabled, String currentCharacter) {
 | 
			
		||||
        String responseBody = response.bodyText();
 | 
			
		||||
        String utf8ResponseBody = new String(responseBody.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
 | 
			
		||||
        try {
 | 
			
		||||
            JSONObject jsonResponse = new JSONObject(utf8ResponseBody);
 | 
			
		||||
            String answer = jsonResponse.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
 | 
			
		||||
            sender.sendMessage(configManager.getChatGPTResponseMessage().replaceFirst("%s", currentCharacter).replaceFirst("%s", answer));
 | 
			
		||||
            if (contextEnabled) {
 | 
			
		||||
                conversationContext.addMessage(answer); // 仅在启用上下文时添加AI响应到历史记录
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.log(Level.SEVERE, "Failed to parse ChatGPT response: " + e.getMessage(), e);
 | 
			
		||||
            sender.sendMessage(configManager.getChatGPTErrorMessage());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理错误的API响应
 | 
			
		||||
     *
 | 
			
		||||
     * @param response HTTP响应
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     */
 | 
			
		||||
    private void processErrorResponse(HttpResponse response, CommandSender sender) {
 | 
			
		||||
        String errorBody = response.bodyText();
 | 
			
		||||
        logger.log(Level.SEVERE, "Failed to get a response from ChatGPT: " + errorBody);
 | 
			
		||||
        sender.sendMessage(configManager.getChatGPTErrorMessage());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 将字符串转换为UTF-8编码
 | 
			
		||||
     *
 | 
			
		||||
     * @param input 输入字符串
 | 
			
		||||
     * @return UTF-8编码的字符串
 | 
			
		||||
     */
 | 
			
		||||
    private String convertToUTF8(String input) {
 | 
			
		||||
        try {
 | 
			
		||||
            byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
 | 
			
		||||
            return new String(bytes, StandardCharsets.UTF_8);
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            logger.severe("Failed to convert input to UTF-8: " + e.getMessage());
 | 
			
		||||
            return input; // 如果转换失败,返回原始输入
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,191 @@
 | 
			
		||||
package com.ddaodan.MineChatGPT.service;
 | 
			
		||||
 | 
			
		||||
import com.ddaodan.MineChatGPT.ConfigManager;
 | 
			
		||||
import com.ddaodan.MineChatGPT.ConversationContext;
 | 
			
		||||
import org.bukkit.command.CommandSender;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 命令处理服务类,负责处理各种命令的业务逻辑
 | 
			
		||||
 */
 | 
			
		||||
public class CommandService {
 | 
			
		||||
    private final ConfigManager configManager;
 | 
			
		||||
    private final ApiService apiService;
 | 
			
		||||
    private final UserSessionManager sessionManager;
 | 
			
		||||
 | 
			
		||||
    public CommandService(ConfigManager configManager, ApiService apiService, UserSessionManager sessionManager) {
 | 
			
		||||
        this.configManager = configManager;
 | 
			
		||||
        this.apiService = apiService;
 | 
			
		||||
        this.sessionManager = sessionManager;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理重载配置命令
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @return 是否成功处理
 | 
			
		||||
     */
 | 
			
		||||
    public boolean handleReloadCommand(CommandSender sender) {
 | 
			
		||||
        if (!sender.hasPermission("minechatgpt.reload")) {
 | 
			
		||||
            sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.reload"));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        configManager.reloadConfig();
 | 
			
		||||
        sender.sendMessage(configManager.getReloadMessage());
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理模型切换命令
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param args 命令参数
 | 
			
		||||
     * @return 是否成功处理
 | 
			
		||||
     */
 | 
			
		||||
    public boolean handleModelCommand(CommandSender sender, String[] args) {
 | 
			
		||||
        if (!sender.hasPermission("minechatgpt.model")) {
 | 
			
		||||
            sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.model"));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        if (args.length < 2) {
 | 
			
		||||
            String currentModel = configManager.getCurrentModel();
 | 
			
		||||
            sender.sendMessage(configManager.getCurrentModelInfoMessage().replace("%s", currentModel));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        String model = args[1];
 | 
			
		||||
        List<String> models = configManager.getModels();
 | 
			
		||||
        if (models.contains(model)) {
 | 
			
		||||
            configManager.setCurrentModel(model);
 | 
			
		||||
            sender.sendMessage(configManager.getModelSwitchMessage().replace("%s", model));
 | 
			
		||||
        } else {
 | 
			
		||||
            sender.sendMessage(configManager.getInvalidModelMessage());
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理模型列表命令
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @return 是否成功处理
 | 
			
		||||
     */
 | 
			
		||||
    public boolean handleModelListCommand(CommandSender sender) {
 | 
			
		||||
        if (!sender.hasPermission("minechatgpt.modellist")) {
 | 
			
		||||
            sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.modellist"));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        List<String> models = configManager.getModels();
 | 
			
		||||
        sender.sendMessage(configManager.getAvailableModelsMessage());
 | 
			
		||||
        for (String model : models) {
 | 
			
		||||
            sender.sendMessage("- " + model);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理上下文切换命令
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @return 是否成功处理
 | 
			
		||||
     */
 | 
			
		||||
    public boolean handleContextCommand(CommandSender sender, String userId) {
 | 
			
		||||
        boolean contextEnabled = !sessionManager.isContextEnabled(userId);
 | 
			
		||||
        sessionManager.setContextEnabled(userId, contextEnabled);
 | 
			
		||||
        String status = contextEnabled ? configManager.getContextToggleEnabledMessage() : configManager.getContextToggleDisabledMessage();
 | 
			
		||||
        sender.sendMessage(configManager.getContextToggleMessage().replace("%s", status));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理清除历史记录命令
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @return 是否成功处理
 | 
			
		||||
     */
 | 
			
		||||
    public boolean handleClearCommand(CommandSender sender, String userId) {
 | 
			
		||||
        if (!sender.hasPermission("minechatgpt.clear")) {
 | 
			
		||||
            sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.clear"));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        sessionManager.clearConversationHistory(userId);
 | 
			
		||||
        sender.sendMessage(configManager.getClearMessage());
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理角色切换命令
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param args 命令参数
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @return 是否成功处理
 | 
			
		||||
     */
 | 
			
		||||
    public boolean handleCharacterCommand(CommandSender sender, String[] args, String userId) {
 | 
			
		||||
        if (!sender.hasPermission("minechatgpt.character")) {
 | 
			
		||||
            sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.character"));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        Map<String, String> characters = configManager.getCharacters();
 | 
			
		||||
        if (args.length < 2) {
 | 
			
		||||
            sender.sendMessage(configManager.getAvailableCharactersMessage());
 | 
			
		||||
            for (String character : characters.keySet()) {
 | 
			
		||||
                sender.sendMessage("- " + character);
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        String character = args[1];
 | 
			
		||||
        if (characters.containsKey(character)) {
 | 
			
		||||
            sessionManager.setCurrentCharacter(userId, character);
 | 
			
		||||
            sender.sendMessage(configManager.getCharacterSwitchedMessage().replace("%s", character));
 | 
			
		||||
        } else {
 | 
			
		||||
            sender.sendMessage(configManager.getInvalidCharacterMessage());
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 处理向ChatGPT提问的命令
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     * @param args 命令参数
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @return 是否成功处理
 | 
			
		||||
     */
 | 
			
		||||
    public boolean handleAskCommand(CommandSender sender, String[] args, String userId) {
 | 
			
		||||
        if (!sender.hasPermission("minechatgpt.use")) {
 | 
			
		||||
            sender.sendMessage(configManager.getNoPermissionMessage().replace("%s", "minechatgpt.use"));
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        String question = String.join(" ", args);
 | 
			
		||||
        ConversationContext conversationContext = sessionManager.getConversationContext(userId);
 | 
			
		||||
        boolean contextEnabled = sessionManager.isContextEnabled(userId);
 | 
			
		||||
        
 | 
			
		||||
        if (contextEnabled) {
 | 
			
		||||
            conversationContext.addMessage(question);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        sender.sendMessage(configManager.getQuestionMessage().replace("%s", question));
 | 
			
		||||
        apiService.askChatGPT(sender, question, conversationContext, contextEnabled, userId);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 发送帮助信息
 | 
			
		||||
     *
 | 
			
		||||
     * @param sender 命令发送者
 | 
			
		||||
     */
 | 
			
		||||
    public void sendHelpMessage(CommandSender sender) {
 | 
			
		||||
        sender.sendMessage(configManager.getHelpMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpAskMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpReloadMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpModelMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpModelListMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpContextMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpClearMessage());
 | 
			
		||||
        sender.sendMessage(configManager.getHelpCharacterMessage());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,95 @@
 | 
			
		||||
package com.ddaodan.MineChatGPT.service;
 | 
			
		||||
 | 
			
		||||
import com.ddaodan.MineChatGPT.ConfigManager;
 | 
			
		||||
import com.ddaodan.MineChatGPT.ConversationContext;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 用户会话管理类,负责管理用户的会话状态和上下文
 | 
			
		||||
 */
 | 
			
		||||
public class UserSessionManager {
 | 
			
		||||
    private final ConfigManager configManager;
 | 
			
		||||
    private final Map<String, ConversationContext> userContexts;
 | 
			
		||||
    private final Map<String, Boolean> userContextEnabled;
 | 
			
		||||
    private final Map<String, String> userCurrentCharacter;
 | 
			
		||||
 | 
			
		||||
    public UserSessionManager(ConfigManager configManager) {
 | 
			
		||||
        this.configManager = configManager;
 | 
			
		||||
        this.userContexts = new HashMap<>();
 | 
			
		||||
        this.userContextEnabled = new HashMap<>();
 | 
			
		||||
        this.userCurrentCharacter = new HashMap<>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户的对话上下文
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @return 对话上下文
 | 
			
		||||
     */
 | 
			
		||||
    public ConversationContext getConversationContext(String userId) {
 | 
			
		||||
        if (!userContexts.containsKey(userId)) {
 | 
			
		||||
            userContexts.put(userId, new ConversationContext(configManager.getMaxHistorySize()));
 | 
			
		||||
            userContextEnabled.put(userId, configManager.isContextEnabled());
 | 
			
		||||
        }
 | 
			
		||||
        return userContexts.get(userId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 判断用户是否启用了上下文
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @return 是否启用上下文
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isContextEnabled(String userId) {
 | 
			
		||||
        if (!userContextEnabled.containsKey(userId)) {
 | 
			
		||||
            userContextEnabled.put(userId, configManager.isContextEnabled());
 | 
			
		||||
        }
 | 
			
		||||
        return userContextEnabled.get(userId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置用户的上下文启用状态
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @param enabled 是否启用
 | 
			
		||||
     */
 | 
			
		||||
    public void setContextEnabled(String userId, boolean enabled) {
 | 
			
		||||
        userContextEnabled.put(userId, enabled);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 清除用户的对话历史
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     */
 | 
			
		||||
    public void clearConversationHistory(String userId) {
 | 
			
		||||
        ConversationContext context = getConversationContext(userId);
 | 
			
		||||
        context.clearHistory();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取用户当前使用的角色
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @return 角色名称
 | 
			
		||||
     */
 | 
			
		||||
    public String getCurrentCharacter(String userId) {
 | 
			
		||||
        if (!userCurrentCharacter.containsKey(userId)) {
 | 
			
		||||
            userCurrentCharacter.put(userId, configManager.getCurrentCharacter(userId));
 | 
			
		||||
        }
 | 
			
		||||
        return userCurrentCharacter.get(userId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 设置用户当前使用的角色
 | 
			
		||||
     *
 | 
			
		||||
     * @param userId 用户ID
 | 
			
		||||
     * @param character 角色名称
 | 
			
		||||
     */
 | 
			
		||||
    public void setCurrentCharacter(String userId, String character) {
 | 
			
		||||
        userCurrentCharacter.put(userId, character);
 | 
			
		||||
        configManager.setCurrentCharacter(userId, character);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,9 @@
 | 
			
		||||
package com.ddaodan.MineChatGPT.util;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.ChatColor;
 | 
			
		||||
 | 
			
		||||
public class ChatUtils {
 | 
			
		||||
    public static String translateColorCodes(String message) {
 | 
			
		||||
        return ChatColor.translateAlternateColorCodes('&', message);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,65 +1,104 @@
 | 
			
		||||
# OpenAI API key setting
 | 
			
		||||
# ======================================================
 | 
			
		||||
# Language Settings
 | 
			
		||||
# 语言设置
 | 
			
		||||
# ======================================================
 | 
			
		||||
# Available languages: en, zh
 | 
			
		||||
# 可用语言:en(英文), zh(中文)
 | 
			
		||||
language: "en"
 | 
			
		||||
# ======================================================
 | 
			
		||||
# API Configuration
 | 
			
		||||
# API 设置
 | 
			
		||||
# ======================================================
 | 
			
		||||
api:
 | 
			
		||||
  # Your OpenAI API key, used for authentication
 | 
			
		||||
  # Your OpenAI API keys, used for authentication
 | 
			
		||||
  # To obtain an API key, visit https://platform.openai.com/account/api-keys and create a new API key
 | 
			
		||||
  key: "sk-your_openai_api_key"
 | 
			
		||||
  # 你的 OpenAI API key,用于身份验证
 | 
			
		||||
  # 获取 API key 的方法:访问 https://platform.openai.com/account/api-keys 并创建一个新的 API key
 | 
			
		||||
  keys:
 | 
			
		||||
    - "sk-your_openai_api_key_1"
 | 
			
		||||
    # You can add multiple API keys below
 | 
			
		||||
    # 可以添加多个API key
 | 
			
		||||
    # - "sk-your_openai_api_key_2"
 | 
			
		||||
    # - "sk-your_openai_api_key_3"
 | 
			
		||||
  
 | 
			
		||||
  # API key selection method: "round_robin" or "random"
 | 
			
		||||
  # Round Robin: Use each API key in turn
 | 
			
		||||
  # Random: Randomly select an API key
 | 
			
		||||
  # API key 选择方法:"round_robin"(轮询)或 "random"(随机)
 | 
			
		||||
  # 轮询:依次使用每个API key
 | 
			
		||||
  # 随机:随机选择一个API key
 | 
			
		||||
  selection_method: "round_robin"
 | 
			
		||||
  
 | 
			
		||||
  # The base URL for the OpenAI API, used to construct requests
 | 
			
		||||
  # If you cannot access the official API, you can use a proxy service
 | 
			
		||||
  # OpenAI API 的基础 URL,用于构建请求
 | 
			
		||||
  # 如果你无法访问官方API,可以使用代理服务
 | 
			
		||||
  base_url: "https://api.openai.com/v1"
 | 
			
		||||
# ======================================================
 | 
			
		||||
# Model Configuration
 | 
			
		||||
# 模型设置
 | 
			
		||||
# ======================================================
 | 
			
		||||
# List of supported models
 | 
			
		||||
# 支持的模型列表
 | 
			
		||||
models:
 | 
			
		||||
  # OpenAI ChatGPT
 | 
			
		||||
  - "gpt-3.5-turbo"
 | 
			
		||||
  - "gpt-3.5-turbo-instruct"
 | 
			
		||||
  - "gpt-4"
 | 
			
		||||
  - "gpt-4-turbo"
 | 
			
		||||
  - "gpt-4-turbo-preview"
 | 
			
		||||
  - "gpt-4o"
 | 
			
		||||
  - "gpt-4o-mini"
 | 
			
		||||
  # Google Gemini
 | 
			
		||||
  # - "gemini-pro"
 | 
			
		||||
  # - "gemini-1.5-pro"
 | 
			
		||||
  # Anthropic Claude
 | 
			
		||||
  # - "claude-3-opus"
 | 
			
		||||
  # - "claude-3-5-sonnet"
 | 
			
		||||
  # Deepseek
 | 
			
		||||
  # - "deepseek-coder"
 | 
			
		||||
  # - "deepseek-reasoner"
 | 
			
		||||
  # And more...
 | 
			
		||||
  # 以及更多...
 | 
			
		||||
 | 
			
		||||
# The default model to use
 | 
			
		||||
default_model: "gpt-3.5-turbo"
 | 
			
		||||
# Conversation setting
 | 
			
		||||
# 默认使用的模型
 | 
			
		||||
default_model: "gpt-4o-mini"
 | 
			
		||||
# ======================================================
 | 
			
		||||
# Conversation Settings
 | 
			
		||||
# 对话设置
 | 
			
		||||
# ======================================================
 | 
			
		||||
conversation:
 | 
			
		||||
  # Continuous conversation switch
 | 
			
		||||
  # When enabled, the plugin will remember the conversation history
 | 
			
		||||
  # 连续对话开关
 | 
			
		||||
  # 启用时,插件将记住对话历史
 | 
			
		||||
  context_enabled: false
 | 
			
		||||
  
 | 
			
		||||
  # Maximum number of historical records retained
 | 
			
		||||
  # Increasing this value will consume more memory
 | 
			
		||||
  # 最大历史记录保留数量
 | 
			
		||||
  # 增加此值将消耗更多内存
 | 
			
		||||
  max_history_size: 10
 | 
			
		||||
# Characters setting
 | 
			
		||||
# ======================================================
 | 
			
		||||
# Character Settings
 | 
			
		||||
# 角色设置
 | 
			
		||||
# ======================================================
 | 
			
		||||
characters:
 | 
			
		||||
  # Format:
 | 
			
		||||
  # Character Name: "Character Prompt"
 | 
			
		||||
  # The prompt will be sent to the AI as a system message
 | 
			
		||||
  # 格式:
 | 
			
		||||
  # 角色名称: "角色提示词"
 | 
			
		||||
  # 提示词将作为系统消息发送给AI
 | 
			
		||||
  
 | 
			
		||||
  # Default character
 | 
			
		||||
  ChatGPT: "You are a helpful assistant."
 | 
			
		||||
# Message settings
 | 
			
		||||
messages:
 | 
			
		||||
  reload: "&aConfiguration reloaded successfully!"
 | 
			
		||||
  clear: "&aConversation history has been cleared!"
 | 
			
		||||
  help: "&e===== MineChatGPT Help ====="
 | 
			
		||||
  help_ask: "&e/chatgpt <text> - Ask ChatGPT a question."
 | 
			
		||||
  help_reload: "&e/chatgpt reload - Reload the configuration file."
 | 
			
		||||
  help_model: "&e/chatgpt model <model_name> - Switch to a different model."
 | 
			
		||||
  help_modellist: "&e/chatgpt modellist - List available models."
 | 
			
		||||
  help_context: "&e/chatgpt context - Toggle context mode."
 | 
			
		||||
  help_clear: "&e/chatgpt clear - Clear conversation history."
 | 
			
		||||
  help_character: "&e/chatgpt character [character_name] - List or switch to a character."
 | 
			
		||||
  context_toggle: "&eContext is now %s."
 | 
			
		||||
  context_toggle_enabled: "&aenabled"
 | 
			
		||||
  context_toggle_disabled: "&cdisabled"
 | 
			
		||||
  current_model_info: "&eCurrent model: %s. Use /chatgpt model <model_name> to switch models."
 | 
			
		||||
  model_switch: "&aModel switched to %s"
 | 
			
		||||
  chatgpt_error: "&cFailed to contact ChatGPT."
 | 
			
		||||
  chatgpt_response: "&b%s: %s"
 | 
			
		||||
  question: "&bYou: %s"
 | 
			
		||||
  character_switched: "&aSwitched to character: %s"
 | 
			
		||||
  available_characters: "&eAvailable characters:"
 | 
			
		||||
  invalid_character: "&cInvalid character. Use /chatgpt character to list available characters."
 | 
			
		||||
  invalid_model: "&cInvalid model. Use /chatgpt modellist to see available models."
 | 
			
		||||
  available_models: "&eAvailable models:"
 | 
			
		||||
  no_permission: "&cYou do not have permission to use this command. Required permission: %s"
 | 
			
		||||
  
 | 
			
		||||
  # You can add more characters below
 | 
			
		||||
  # 你可以在下方添加更多角色
 | 
			
		||||
  # Example:
 | 
			
		||||
  # Minecraft: "You are a Minecraft expert who helps players with game mechanics and building ideas."
 | 
			
		||||
 | 
			
		||||
# ======================================================
 | 
			
		||||
# Other Settings
 | 
			
		||||
# 其他设置
 | 
			
		||||
# ======================================================
 | 
			
		||||
# If you don't know what this is, don't change it
 | 
			
		||||
# 如果你不知道这是什么,请不要动
 | 
			
		||||
debug: false
 | 
			
		||||
							
								
								
									
										27
									
								
								src/main/resources/lang/en.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/main/resources/lang/en.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
# English language file for MineChatGPT
 | 
			
		||||
 | 
			
		||||
messages:
 | 
			
		||||
  reload: "&aConfiguration reloaded successfully!"
 | 
			
		||||
  clear: "&aConversation history has been cleared!"
 | 
			
		||||
  help: "&e===== MineChatGPT Help ====="
 | 
			
		||||
  help_ask: "&e/chatgpt <text> - Ask ChatGPT a question."
 | 
			
		||||
  help_reload: "&e/chatgpt reload - Reload the configuration file."
 | 
			
		||||
  help_model: "&e/chatgpt model <model_name> - Switch to a different model."
 | 
			
		||||
  help_modellist: "&e/chatgpt modellist - List available models."
 | 
			
		||||
  help_context: "&e/chatgpt context - Toggle context mode."
 | 
			
		||||
  help_clear: "&e/chatgpt clear - Clear conversation history."
 | 
			
		||||
  help_character: "&e/chatgpt character [character_name] - List or switch to a character."
 | 
			
		||||
  context_toggle: "&eContext is now %s."
 | 
			
		||||
  context_toggle_enabled: "&aenabled"
 | 
			
		||||
  context_toggle_disabled: "&cdisabled"
 | 
			
		||||
  current_model_info: "&eCurrent model: %s. Use /chatgpt model <model_name> to switch models."
 | 
			
		||||
  model_switch: "&aModel switched to %s"
 | 
			
		||||
  chatgpt_error: "&cFailed to contact ChatGPT."
 | 
			
		||||
  chatgpt_response: "&b%s: %s"
 | 
			
		||||
  question: "&bYou: %s"
 | 
			
		||||
  character_switched: "&aSwitched to character: %s"
 | 
			
		||||
  available_characters: "&eAvailable characters:"
 | 
			
		||||
  invalid_character: "&cInvalid character. Use /chatgpt character to list available characters."
 | 
			
		||||
  invalid_model: "&cInvalid model. Use /chatgpt modellist to see available models."
 | 
			
		||||
  available_models: "&eAvailable models:"
 | 
			
		||||
  no_permission: "&cYou do not have permission to use this command. Required permission: %s"
 | 
			
		||||
@@ -1,41 +1,5 @@
 | 
			
		||||
# API 相关设置
 | 
			
		||||
api:
 | 
			
		||||
  # 你的 OpenAI API key,用于身份验证
 | 
			
		||||
  # 获取 API key 的方法:访问 https://platform.openai.com/account/api-keys 并创建一个新的 API key
 | 
			
		||||
  key: "sk-your_openai_api_key"
 | 
			
		||||
  # OpenAI API 的基础 URL,用于构建请求
 | 
			
		||||
  base_url: "https://api.openai.com/v1"
 | 
			
		||||
# 支持的模型列表
 | 
			
		||||
models:
 | 
			
		||||
  # OpenAI ChatGPT
 | 
			
		||||
  - "gpt-3.5-turbo"
 | 
			
		||||
  - "gpt-3.5-turbo-instruct"
 | 
			
		||||
  - "gpt-4"
 | 
			
		||||
  - "gpt-4-turbo"
 | 
			
		||||
  - "gpt-4-turbo-preview"
 | 
			
		||||
  - "gpt-4o"
 | 
			
		||||
  - "gpt-4o-mini"
 | 
			
		||||
  # Google Gemini
 | 
			
		||||
  # - "gemini-pro"
 | 
			
		||||
  # - "gemini-1.5-pro"
 | 
			
		||||
  # Anthropic Claude
 | 
			
		||||
  # - "claude-3-opus"
 | 
			
		||||
  # - "claude-3-5-sonnet"
 | 
			
		||||
  # 以及更多...
 | 
			
		||||
# 默认使用的模型
 | 
			
		||||
default_model: "gpt-3.5-turbo"
 | 
			
		||||
# 连续对话设置
 | 
			
		||||
conversation:
 | 
			
		||||
  # 连续对话开关
 | 
			
		||||
  context_enabled: false
 | 
			
		||||
  # 最大历史记录保留数量
 | 
			
		||||
  max_history_size: 10
 | 
			
		||||
# 角色设置
 | 
			
		||||
characters:
 | 
			
		||||
  # 格式:
 | 
			
		||||
  # 角色名称: "角色提示词"
 | 
			
		||||
  ChatGPT: "You are a helpful assistant."
 | 
			
		||||
# 消息相关设置
 | 
			
		||||
# 中文语言文件 - MineChatGPT
 | 
			
		||||
 | 
			
		||||
messages:
 | 
			
		||||
  reload: "&a已重新加载配置文件!"
 | 
			
		||||
  clear: "&a对话历史已清空!"
 | 
			
		||||
@@ -61,5 +25,3 @@ messages:
 | 
			
		||||
  invalid_model: "&c模型无效。使用 /chatgpt modellist 查看可用模型。"
 | 
			
		||||
  available_models: "&e可用模型列表:"
 | 
			
		||||
  no_permission: "&c你没有权限使用这个指令。需要的权限:%s"
 | 
			
		||||
# 如果你不知道这是什么,请不要动
 | 
			
		||||
debug: false
 | 
			
		||||
		Reference in New Issue
	
	Block a user