mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-03 12:32:28 +08:00
225 lines
6.8 KiB
Kotlin
225 lines
6.8 KiB
Kotlin
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE")
|
|
|
|
package demo.subscribe
|
|
|
|
import net.mamoe.mirai.Bot
|
|
import net.mamoe.mirai.BotAccount
|
|
import net.mamoe.mirai.alsoLogin
|
|
import net.mamoe.mirai.contact.QQ
|
|
import net.mamoe.mirai.contact.sendMessage
|
|
import net.mamoe.mirai.event.*
|
|
import net.mamoe.mirai.message.FriendMessage
|
|
import net.mamoe.mirai.message.GroupMessage
|
|
import net.mamoe.mirai.message.data.Image
|
|
import net.mamoe.mirai.message.data.PlainText
|
|
import net.mamoe.mirai.message.data.firstOrNull
|
|
import net.mamoe.mirai.message.sendAsImageTo
|
|
import net.mamoe.mirai.qqandroid.Bot
|
|
import net.mamoe.mirai.qqandroid.QQAndroid
|
|
import java.io.File
|
|
|
|
private fun readTestAccount(): BotAccount? {
|
|
val file = File("testAccount.txt")
|
|
if (!file.exists() || !file.canRead()) {
|
|
return null
|
|
}
|
|
|
|
println("Reading account from testAccount.text")
|
|
val lines = file.readLines()
|
|
return try {
|
|
BotAccount(lines[0].toLong(), lines[1])
|
|
} catch (e: IndexOutOfBoundsException) {
|
|
null
|
|
}
|
|
}
|
|
|
|
@Suppress("UNUSED_VARIABLE")
|
|
suspend fun main() {
|
|
val bot = QQAndroid.Bot( // JVM 下也可以不写 `TIMPC.` 引用顶层函数
|
|
1994701121,
|
|
"123456"
|
|
) {
|
|
// 覆盖默认的配置
|
|
randomDeviceName = false
|
|
}.alsoLogin()
|
|
|
|
bot.messageDSL()
|
|
directlySubscribe(bot)
|
|
|
|
bot.network.awaitDisconnection()//等到直到断开连接
|
|
}
|
|
|
|
/**
|
|
* 使用 dsl 监听消息事件
|
|
*
|
|
* @see subscribeFriendMessages
|
|
* @see subscribeMessages
|
|
* @see subscribeGroupMessages
|
|
*
|
|
* @see MessageSubscribersBuilder
|
|
*/
|
|
fun Bot.messageDSL() {
|
|
// 监听这个 bot 的来自所有群和好友的消息
|
|
this.subscribeMessages {
|
|
// 当接收到消息 == "你好" 时就回复 "你好!"
|
|
"你好" reply "你好!"
|
|
|
|
// 当消息 == "查看 subject" 时, 执行 lambda
|
|
case("查看 subject") {
|
|
if (subject is QQ) {
|
|
reply("消息主体为 QQ, 你在发私聊消息")
|
|
} else {
|
|
reply("消息主体为 Group, 你在群里发消息")
|
|
}
|
|
|
|
// 在回复的时候, 一般使用 subject 来作为回复对象.
|
|
// 因为当群消息时, subject 为这个群.
|
|
// 当好友消息时, subject 为这个好友.
|
|
// 所有在 MessagePacket(也就是此时的 this 指代的对象) 中实现的扩展方法, 如刚刚的 "reply", 都是以 subject 作为目标
|
|
}
|
|
|
|
|
|
// 当消息里面包含这个类型的消息时
|
|
has<Image> {
|
|
// this: MessagePacket
|
|
// message: MessageChain
|
|
// sender: QQ
|
|
// it: String (MessageChain.toString)
|
|
|
|
|
|
message[Image].download()
|
|
if (this is GroupMessage) {
|
|
//如果是群消息
|
|
// group: Group
|
|
this.group.sendMessage("你在一个群里")
|
|
// 等同于 reply("你在一个群里")
|
|
}
|
|
|
|
reply("图片, ID= ${message[Image]}")//获取第一个 Image 类型的消息
|
|
reply(message)
|
|
}
|
|
|
|
"hello.*world".toRegex() matchingReply {
|
|
"Hello!"
|
|
}
|
|
|
|
"123" containsReply "你的消息里面包含 123"
|
|
|
|
|
|
// 当收到 "我的qq" 就执行 lambda 并回复 lambda 的返回值 String
|
|
"我的qq" reply { sender.id }
|
|
|
|
|
|
// 如果是这个 QQ 号发送的消息(可以是好友消息也可以是群消息)
|
|
sentBy(123456789) {
|
|
}
|
|
|
|
|
|
// 当消息前缀为 "我是" 时
|
|
startsWith("我是", removePrefix = true) {
|
|
// it: 删除了消息前缀 "我是" 后的消息
|
|
// 如一条消息为 "我是张三", 则此时的 it 为 "张三".
|
|
|
|
reply("你是$it")
|
|
}
|
|
|
|
|
|
// 当消息中包含 "复读" 时
|
|
val listener = (contains("复读1") or contains("复读2")) {
|
|
reply(message)
|
|
}
|
|
|
|
listener.complete() // 停止监听
|
|
|
|
// 自定义的 filter, filter 中 it 为转为 String 的消息.
|
|
// 也可以用任何能在处理时使用的变量, 如 subject, sender, message
|
|
content({ it.length == 3 }) {
|
|
reply("你发送了长度为 3 的消息")
|
|
}
|
|
|
|
|
|
case("上传好友图片") {
|
|
val filename = it.substringAfter("上传好友图片")
|
|
File("C:\\Users\\Him18\\Desktop\\$filename").sendAsImageTo(subject)
|
|
}
|
|
|
|
case("上传群图片") {
|
|
val filename = it.substringAfter("上传好友图片")
|
|
File("C:\\Users\\Him18\\Desktop\\$filename").sendAsImageTo(subject)
|
|
}
|
|
}
|
|
|
|
subscribeMessages {
|
|
case("你好") {
|
|
// this: MessagePacket
|
|
// message: MessageChain
|
|
// sender: QQ
|
|
// it: String (来自 MessageChain.toString)
|
|
// group: Group (如果是群消息)
|
|
reply("你好")
|
|
}
|
|
}
|
|
|
|
subscribeFriendMessages {
|
|
contains("A") {
|
|
// this: FriendMessage
|
|
// message: MessageChain
|
|
// sender: QQ
|
|
// it: String (来自 MessageChain.toString)
|
|
reply("B")
|
|
}
|
|
}
|
|
|
|
subscribeGroupMessages {
|
|
// this: FriendMessage
|
|
// message: MessageChain
|
|
// sender: QQ
|
|
// it: String (来自 MessageChain.toString)
|
|
// group: Group
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 监听单个事件
|
|
*/
|
|
@Suppress("UNUSED_VARIABLE")
|
|
suspend fun directlySubscribe(bot: Bot) {
|
|
// 在当前协程作用域 (CoroutineScope) 下创建一个子 Job, 监听一个事件.
|
|
//
|
|
// 手动处理消息
|
|
// 使用 Bot 的扩展方法监听, 将在处理事件时得到一个 this: Bot.
|
|
// 这样可以调用 Bot 内的一些扩展方法如 UInt.qq():QQ
|
|
//
|
|
// 这个函数返回 Listener, Listener 是一个 CompletableJob. 如果不手动 close 它, 它会一直阻止当前 CoroutineScope 结束.
|
|
// 例如:
|
|
// ```kotlin
|
|
// runBlocking {// this: CoroutineScope
|
|
// bot.subscribeAlways<FriendMessage> {
|
|
// }
|
|
// }
|
|
// ```
|
|
// 则这个 `runBlocking` 永远不会结束, 因为 `subscribeAlways` 在 `runBlocking` 的 `CoroutineScope` 下创建了一个 Job.
|
|
// 正确的用法为:
|
|
bot.subscribeAlways<FriendMessage> {
|
|
// this: FriendMessageEvent
|
|
// event: FriendMessageEvent
|
|
|
|
// 获取第一个纯文本消息, 获取不到会抛出 NoSuchElementException
|
|
// val firstText = message.first<PlainText>()
|
|
|
|
val firstText = message.firstOrNull<PlainText>()
|
|
|
|
// 获取第一个图片
|
|
val firstImage = message.firstOrNull<Image>()
|
|
|
|
when {
|
|
message eq "你好" -> reply("你好!")
|
|
|
|
"复读" in message -> sender.sendMessage(message)
|
|
|
|
"发群消息" in message -> {
|
|
bot.getGroup(580266363).sendMessage(message.toString().substringAfter("发群消息"))
|
|
}
|
|
}
|
|
}
|
|
} |