@@ -32,13 +32,21 @@ fun MiraiPluginModuleBuilder.createRoot(): VirtualFile? {
3232fun MiraiPluginModuleBuilder.createDic (
3333 root : VirtualFile
3434) {
35- val sourceDirectory = VfsUtil .createDirectories(root.path + " /src/main/kotlin" )
35+ val sourceDirectory: VirtualFile
36+ val testDirectory: VirtualFile
37+ when (CreateConfig .language) {
38+ CreateConfig .LANGUAGE_KOTLIN -> {
39+ sourceDirectory = VfsUtil .createDirectories(root.path + " /src/main/kotlin" )
40+ testDirectory = VfsUtil .createDirectories(root.path + " /src/test/kotlin" )
41+ }
42+ CreateConfig .LANGUAGE_JAVA -> {
43+ sourceDirectory = VfsUtil .createDirectories(root.path + " /src/main/java" )
44+ testDirectory = VfsUtil .createDirectories(root.path + " /src/test/java" )
45+ }
46+ else -> error(" internal error: illegal language: ${CreateConfig .language} " )
47+ }
3648 VfsUtil .createDirectories(root.path + " /src/main/resources" )
37- VfsUtil .createDirectories(root.path + " /src/test/kotlin" )
3849 VfsUtil .createDirectories(root.path + " /src/test/resources" )
39- // val resourceDirectory = VfsUtil.createDirectories(root.path + "/src/main/resources")
40- // val testSourceDirectory = VfsUtil.createDirectories(root.path + "/src/test/kotlin")
41- // val testResourceDirectory = VfsUtil.createDirectories(root.path + "/src/test/resources")
4250
4351 val buildToolFiles: List <String > = when (CreateConfig .buildTool) {
4452 CreateConfig .BUILD_GRADLE_KOTLIN -> Template .gradleCommon + Template .gradleKotlinDsl
@@ -57,7 +65,7 @@ fun MiraiPluginModuleBuilder.createDic(
5765 @Suppress(" EXPERIMENTAL_API_USAGE" )
5866 fun String.replaceTemplateVariables (): String {
5967 return runBlocking {
60- this @replaceTemplateVariables.replace(" <GROUP>" , CreateConfig .groupId)
68+ this @replaceTemplateVariables.replace(" <GROUP>" , CreateConfig .groupId)
6169 .replace(" <PROJECT_NAME>" , CreateConfig .artifactId)
6270 .replace(" <VERSION>" , CreateConfig .version)
6371 .replace(" <MIRAI_CONSOLE_VERSION>" , consoleVersion().await())
@@ -82,6 +90,10 @@ fun MiraiPluginModuleBuilder.createDic(
8290 pluginBaseClassName
8391 ).replace(" PACKAGE" , packageName)
8492 )
93+ testDirectory.writeChild(
94+ " mirai/RunMirai.kt" ,
95+ Template .testConsoleRunnerKotlin
96+ )
8597 }
8698 CreateConfig .LANGUAGE_JAVA -> {
8799 sourceDirectory.writeChild(
@@ -91,6 +103,10 @@ fun MiraiPluginModuleBuilder.createDic(
91103 pluginBaseClassName
92104 ).replace(" PACKAGE" , packageName)
93105 )
106+ testDirectory.writeChild(
107+ " mirai/RunMirai.java" ,
108+ Template .testConsoleRunnerJava
109+ )
94110 }
95111 }
96112
@@ -100,7 +116,10 @@ fun MiraiPluginModuleBuilder.createDic(
100116 .replace(" AUTHOR" , CreateConfig .author)
101117 .replace(" MAIN" , CreateConfig .mainClassQualifiedName)
102118 .replace(" INFO" , CreateConfig .info)
103- .replace(" DEPENDS" , CreateConfig .depends.takeIf { it.isNotEmpty() }?.joinToString { " \n -$it " } ? : " []" )
119+ .replace(
120+ " DEPENDS" ,
121+ CreateConfig .depends.filter { it.isNotBlank() }.takeIf { it.isNotEmpty() }?.joinToString { " \n -$it " }
122+ ? : " []" )
104123 )
105124}
106125
@@ -162,6 +181,30 @@ object Template {
162181 }
163182 """ .trimIndent().let { it.replace(" \\ \$ \\ {" , " \$ {" ) } // bug also
164183
184+
185+ @Language(" kotlin" )
186+ val testConsoleRunnerKotlin: String = """
187+ package mirai
188+
189+ import kotlinx.coroutines.runBlocking
190+ import net.mamoe.mirai.console.command.CommandManager
191+ import net.mamoe.mirai.console.pure.MiraiConsolePureLoader
192+
193+ object RunMirai {
194+
195+ // 执行 gradle task: runMiraiConsole 来自动编译, shadow, 复制, 并启动 pure console.
196+
197+ @JvmStatic
198+ fun main(args: Array<String>) {
199+ // 默认在 /test 目录下运行
200+
201+ MiraiConsolePureLoader.load(args[0], args[1]) // 启动 console
202+
203+ runBlocking { CommandManager.join() } // 阻止主线程退出
204+ }
205+ }
206+ """ .trimIndent()
207+
165208 @Language(" java" )
166209 val pluginBaseJava: String = """
167210 package PACKAGE;
@@ -171,8 +214,65 @@ object Template {
171214 class ExamplePluginMain extends PluginBase {
172215
173216 public void onLoad(){
174- //start your code here
175- //欢迎使用Kotlin
217+ bot.getFriends().forEach(friend -> {
218+ System.out.println(friend.getId() + ":" + friend.getNick());
219+ return Unit.INSTANCE; // kotlin 的所有函数都有返回值. Unit 为最基本的返回值. 请在这里永远返回 Unit
220+ });
221+
222+ Events.subscribeAlways(GroupMessage.class, (GroupMessage event) -> {
223+
224+ if (event.getMessage().contains("reply")) {
225+ // 引用回复
226+ final QuoteReplyToSend quote = MessageUtils.quote(event.getMessage(), event.getSender());
227+ event.getGroup().sendMessage(quote.plus("引用回复"));
228+
229+ } else if (event.getMessage().contains("at")) {
230+ // at
231+ event.getGroup().sendMessage(new At(event.getSender()));
232+
233+ } else if (event.getMessage().contains("permission")) {
234+ // 成员权限
235+ event.getGroup().sendMessage(event.getPermission().toString());
236+
237+ } else if (event.getMessage().contains("mixed")) {
238+ // 复合消息, 通过 .plus 连接两个消息
239+ event.getGroup().sendMessage(
240+ MessageUtils.newImage("{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png") // 演示图片, 可能已过期
241+ .plus("Hello") // 文本消息
242+ .plus(new At(event.getSender())) // at 群成员
243+ .plus(AtAll.INSTANCE) // at 全体成员
244+ );
245+
246+ } else if (event.getMessage().contains("recall1")) {
247+ event.getGroup().sendMessage("你看不到这条消息").recall();
248+ // 发送消息马上就撤回. 因速度太快, 客户端将看不到这个消息.
249+
250+ } else if (event.getMessage().contains("recall2")) {
251+ final Job job = event.getGroup().sendMessage("3秒后撤回").recallIn(3000);
252+
253+ // job.cancel(new CancellationException()); // 可取消这个任务
254+
255+ } else if (event.getMessage().contains("上传图片")) {
256+ File file = new File("myImage.jpg");
257+ if (file.exists()) {
258+ final Image image = event.getGroup().uploadImage(new File("myImage.jpg"));
259+ // 上传一个图片并得到 Image 类型的 Message
260+
261+ final String imageId = image.getImageId(); // 可以拿到 ID
262+ final Image fromId = MessageUtils.newImage(imageId); // ID 转换得到 Image
263+
264+ event.getGroup().sendMessage(image); // 发送图片
265+ }
266+
267+ } else if (event.getMessage().contains("friend")) {
268+ final Future<MessageReceipt<? extends Contact>> future = event.getSender().sendMessageAsync("Async send"); // 异步发送
269+ try {
270+ future.get();
271+ } catch (InterruptedException | ExecutionException e) {
272+ e.printStackTrace();
273+ }
274+ }
275+ });
176276 }
177277
178278 public void onEnable(){
@@ -182,6 +282,29 @@ object Template {
182282 }
183283 """ .trimIndent()
184284
285+ @Language(" java" )
286+ val testConsoleRunnerJava: String = """
287+ package mirai;
288+
289+ import kotlinx.coroutines.BuildersKt;
290+ import kotlinx.coroutines.GlobalScope;
291+ import net.mamoe.mirai.console.command.CommandManager;
292+ import net.mamoe.mirai.console.pure.MiraiConsolePureLoader;
293+
294+ public class RunMirai {
295+
296+ // 执行 gradle task: runMiraiConsole 来自动编译, shadow, 复制, 并启动 pure console.
297+
298+ public static void main(String[] args) throws InterruptedException {
299+ // 默认在 /test 目录下运行
300+
301+ MiraiConsolePureLoader.load(args[0], args[1]); // 启动 console
302+
303+ // 阻止主线程退出
304+ BuildersKt.runBlocking(GlobalScope.INSTANCE.getCoroutineContext(), (coroutineScope, continuation) -> CommandManager.INSTANCE.join(continuation));
305+ }
306+ }
307+ """ .trimIndent()
185308
186309 @Language(" yaml" )
187310 val pluginYml: String = """
0 commit comments