最近chatGPT很火,所以又想整个qq机器人,YuQ好像跑路了,所以只能用Mirai了,我怕我又想写一些其他需要数据库的功能,所以整合一下SpringBoot

使用

mirai文档一样监听事件

使用dsl监听事件

@Component
class ToolController {

    suspend fun GroupMessageSubscribersBuilder.tool() {

        "色图" reply {
            val jsonNode = client.get("https://api.kukuqaq.com/lolicon/random").body<JsonNode>()
            val quickUrl = jsonNode[0]["quickUrl"].asText()
            client.get(quickUrl).body<InputStream>().toExternalResource().use { er ->
                subject.uploadImage(er)
            }
        }

    }
}

使用 @EventHandler 注解标注的方法监听事件不需要继承类和加注解

@Service
class ContextSession {

    fun GroupMessageEvent.wait() {
        println(message)
    }

}

配置

Spring的配置文件:

kuku:
  mirai:
    qq:
    password:
    # 协议,可选android_phone、android_pad、android_watch、ipad、macos
    protocol: android_phone

初始化mirai

@Component
class MiraiBean(
    private val miraiConfig: MiraiConfig,
    private val applicationContext: ApplicationContext
) {

    private fun superclasses(kClass: KClass<*>?, set: MutableSet<KClass<*>> = mutableSetOf()): Set<KClass<*>> {
        val superclasses = kClass?.superclasses ?: return set
        set.addAll(superclasses)
        for (superclass in superclasses) {
            val suSuper = superclass.superclasses
            if (suSuper.isNotEmpty()) {
                suSuper.forEach { superclasses(it, set) }
            }
        }
        return set
    }

    @Bean
    fun mirai(): Bot {

        val bot = BotFactory.newBot(miraiConfig.qq, miraiConfig.password) {
            fileBasedDeviceInfo()
            protocol = miraiConfig.protocol
        }
        val eventChannel = bot.eventChannel
        val names = applicationContext.beanDefinitionNames
        val clazzList = mutableListOf<Class<*>>()
        for (name in names) {
            applicationContext.getType(name)?.let {
                clazzList.add(it)
            }
        }
        for (clazz in clazzList) {
            val functions = kotlin.runCatching {
                clazz.kotlin.declaredMemberExtensionFunctions
            }.getOrNull() ?: continue
            for (function in functions) {
                val type = function.extensionReceiverParameter?.type
                val kClass = type?.classifier as? KClass<*>
                if (superclasses(kClass).contains(Event::class)) {
                    @Suppress("UNCHECKED_CAST")
                    eventChannel.subscribeAlways(kClass as KClass<out Event>) {
                        function.callSuspend(applicationContext.getBean(clazz), this)
                    }
                }
                if (kClass?.jvmName == "net.mamoe.mirai.event.MessageSubscribersBuilder") {
                    when (type.arguments[0].type?.classifier) {
                        GroupMessageEvent::class -> {
                            eventChannel.subscribeGroupMessages {
                                JobManager.now {
                                    function.callSuspend(applicationContext.getBean(clazz), this@subscribeGroupMessages)
                                }
                            }
                        }
                        FriendMessageEvent::class -> {
                            eventChannel.subscribeFriendMessages {
                                JobManager.now {
                                    function.callSuspend(applicationContext.getBean(clazz), this@subscribeFriendMessages)
                                }
                            }
                        }
                        MessageEvent::class -> {
                            eventChannel.subscribeMessages {
                                JobManager.now {
                                    function.callSuspend(applicationContext.getBean(clazz), this@subscribeMessages)
                                }
                            }
                        }
                        UserMessageEvent::class -> {
                            eventChannel.subscribeUserMessages {
                                JobManager.now {
                                    function.callSuspend(applicationContext.getBean(clazz), this@subscribeUserMessages)
                                }
                            }
                        }
                        GroupTempMessageEvent::class -> {
                            eventChannel.subscribeGroupTempMessages {
                                JobManager.now {
                                    function.callSuspend(applicationContext.getBean(clazz), this@subscribeGroupTempMessages)
                                }
                            }
                        }
                        StrangerMessageEvent::class -> {
                            eventChannel.subscribeStrangerMessages {
                                JobManager.now {
                                    function.callSuspend(applicationContext.getBean(clazz), this@subscribeStrangerMessages)
                                }
                            }
                        }
                        OtherClientMessageEvent::class -> {
                            eventChannel.subscribeOtherClientMessages {
                                JobManager.now {
                                    function.callSuspend(applicationContext.getBean(clazz), this@subscribeOtherClientMessages)
                                }
                            }
                        }
                    }
                }
            }
        }
        runBlocking {
            bot.login()
        }
        return bot
    }


}

@Component
@ConfigurationProperties(prefix = "kuku.mirai")
class MiraiConfig {
    var qq: Long = 0
    var password: String = ""
    var protocol: BotConfiguration.MiraiProtocol = BotConfiguration.MiraiProtocol.ANDROID_PHONE
}

gradle文件:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    val kotlinVersion = "1.7.22"
    kotlin("jvm") version kotlinVersion
    kotlin("plugin.spring") version kotlinVersion
    id("org.jetbrains.kotlin.kapt") version kotlinVersion
    id("org.springframework.boot") version "3.0.0"
    id("io.spring.dependency-management") version "1.1.0"
}

group = "me.kuku"
version = "1.0-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17

repositories {
    maven("https://nexus.kuku.me/repository/maven-public/")
    mavenCentral()
}

dependencies {
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
    implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
    implementation("org.springframework.boot:spring-boot-starter-mail")
    implementation("me.kuku:utils:2.2.1.1")
    implementation("net.mamoe:mirai-core:2.13.2")
    kapt("org.springframework.boot:spring-boot-configuration-processor")
    testImplementation(kotlin("test"))
}

tasks.test {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "17"
    kotlinOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xcontext-receivers")
}
最后修改:2022 年 12 月 12 日
如果觉得我的文章对你有用,请随意赞赏