mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-25 15:40:28 +08:00
commit
7faa9112a6
@ -99,7 +99,6 @@ Demos: [mirai-demos](https://github.com/mamoe/mirai-demos)
|
|||||||
[<img width="60px" height="60px" src="https://avatars0.githubusercontent.com/u/25280943?s=60&v=4" />](https://github.com/HoshinoTented)
|
[<img width="60px" height="60px" src="https://avatars0.githubusercontent.com/u/25280943?s=60&v=4" />](https://github.com/HoshinoTented)
|
||||||
[<img width="60px" height="60px" src="https://avatars3.githubusercontent.com/u/40517459?s=60&v=4" />](https://github.com/Cyenoch)
|
[<img width="60px" height="60px" src="https://avatars3.githubusercontent.com/u/40517459?s=60&v=4" />](https://github.com/Cyenoch)
|
||||||
|
|
||||||
|
|
||||||
## 鸣谢
|
## 鸣谢
|
||||||
|
|
||||||
特别感谢 [JetBrains](https://www.jetbrains.com/?from=mirai) 为开源项目提供免费的 [IntelliJ IDEA](https://www.jetbrains.com/idea/?from=mirai) 等 IDE 的授权
|
特别感谢 [JetBrains](https://www.jetbrains.com/?from=mirai) 为开源项目提供免费的 [IntelliJ IDEA](https://www.jetbrains.com/idea/?from=mirai) 等 IDE 的授权
|
||||||
|
@ -110,6 +110,7 @@ kotlin {
|
|||||||
runtimeOnly(files("build/classes/kotlin/jvm/main")) // classpath is not properly set by IDE
|
runtimeOnly(files("build/classes/kotlin/jvm/main")) // classpath is not properly set by IDE
|
||||||
api(kotlinx("serialization-runtime", serializationVersion))
|
api(kotlinx("serialization-runtime", serializationVersion))
|
||||||
//api(kotlinx("serialization-protobuf", serializationVersion))
|
//api(kotlinx("serialization-protobuf", serializationVersion))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,9 +9,19 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.qqandroid
|
package net.mamoe.mirai.qqandroid
|
||||||
|
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.request.*
|
||||||
|
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||||
|
import io.ktor.client.request.forms.formData
|
||||||
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import kotlinx.io.core.Closeable
|
import kotlinx.io.core.Closeable
|
||||||
|
import kotlinx.serialization.MissingFieldException
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
|
import kotlinx.serialization.json.int
|
||||||
|
import kotlinx.serialization.json.long
|
||||||
import net.mamoe.mirai.LowLevelAPI
|
import net.mamoe.mirai.LowLevelAPI
|
||||||
import net.mamoe.mirai.contact.*
|
import net.mamoe.mirai.contact.*
|
||||||
import net.mamoe.mirai.data.*
|
import net.mamoe.mirai.data.*
|
||||||
@ -35,6 +45,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.LongConn
|
|||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
|
||||||
import net.mamoe.mirai.qqandroid.utils.toIpV4AddressString
|
import net.mamoe.mirai.qqandroid.utils.toIpV4AddressString
|
||||||
import net.mamoe.mirai.utils.*
|
import net.mamoe.mirai.utils.*
|
||||||
|
import net.mamoe.mirai.utils.io.encodeToString
|
||||||
import net.mamoe.mirai.utils.io.toUHexString
|
import net.mamoe.mirai.utils.io.toUHexString
|
||||||
import kotlin.contracts.ExperimentalContracts
|
import kotlin.contracts.ExperimentalContracts
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
@ -719,4 +730,6 @@ internal class GroupImpl(
|
|||||||
if (this::class != other::class) return false
|
if (this::class != other::class) return false
|
||||||
return this.id == other.id && this.bot == other.bot
|
return this.id == other.id && this.bot == other.bot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -9,18 +9,25 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.qqandroid
|
package net.mamoe.mirai.qqandroid
|
||||||
|
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||||
|
import io.ktor.client.request.forms.formData
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
|
import io.ktor.client.request.headers
|
||||||
|
import io.ktor.client.request.post
|
||||||
|
import io.ktor.client.request.url
|
||||||
import io.ktor.client.statement.HttpResponse
|
import io.ktor.client.statement.HttpResponse
|
||||||
import kotlinx.coroutines.CoroutineName
|
import kotlinx.coroutines.CoroutineName
|
||||||
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.io.ByteReadChannel
|
import kotlinx.coroutines.io.ByteReadChannel
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
|
import kotlinx.serialization.json.int
|
||||||
import net.mamoe.mirai.BotAccount
|
import net.mamoe.mirai.BotAccount
|
||||||
import net.mamoe.mirai.BotImpl
|
import net.mamoe.mirai.BotImpl
|
||||||
import net.mamoe.mirai.LowLevelAPI
|
import net.mamoe.mirai.LowLevelAPI
|
||||||
import net.mamoe.mirai.contact.*
|
import net.mamoe.mirai.contact.*
|
||||||
import net.mamoe.mirai.data.AddFriendResult
|
import net.mamoe.mirai.data.*
|
||||||
import net.mamoe.mirai.data.FriendInfo
|
|
||||||
import net.mamoe.mirai.data.GroupInfo
|
|
||||||
import net.mamoe.mirai.data.MemberInfo
|
|
||||||
import net.mamoe.mirai.event.broadcast
|
import net.mamoe.mirai.event.broadcast
|
||||||
import net.mamoe.mirai.event.events.MessageRecallEvent
|
import net.mamoe.mirai.event.events.MessageRecallEvent
|
||||||
import net.mamoe.mirai.message.data.*
|
import net.mamoe.mirai.message.data.*
|
||||||
@ -33,6 +40,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.PbMessageSvc
|
|||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
|
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
|
||||||
import net.mamoe.mirai.utils.*
|
import net.mamoe.mirai.utils.*
|
||||||
|
import net.mamoe.mirai.utils.io.encodeToString
|
||||||
import kotlin.collections.asSequence
|
import kotlin.collections.asSequence
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
@ -59,6 +67,10 @@ internal abstract class QQAndroidBotBase constructor(
|
|||||||
internal var firstLoginSucceed: Boolean = false
|
internal var firstLoginSucceed: Boolean = false
|
||||||
override val uin: Long get() = client.uin
|
override val uin: Long get() = client.uin
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val json = Json(JsonConfiguration(ignoreUnknownKeys = true, encodeDefaults = true))
|
||||||
|
}
|
||||||
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"use friends instead",
|
"use friends instead",
|
||||||
level = DeprecationLevel.ERROR,
|
level = DeprecationLevel.ERROR,
|
||||||
@ -198,7 +210,7 @@ internal abstract class QQAndroidBotBase constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(LowLevelAPI::class)
|
@LowLevelAPI
|
||||||
override suspend fun _lowLevelRecallGroupMessage(groupId: Long, messageId: Long) {
|
override suspend fun _lowLevelRecallGroupMessage(groupId: Long, messageId: Long) {
|
||||||
network.run {
|
network.run {
|
||||||
val response: PbMessageSvc.PbMsgWithDraw.Response =
|
val response: PbMessageSvc.PbMsgWithDraw.Response =
|
||||||
@ -209,6 +221,129 @@ internal abstract class QQAndroidBotBase constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@LowLevelAPI
|
||||||
|
@MiraiExperimentalAPI
|
||||||
|
override suspend fun _lowLevelGetAnnouncements(groupId: Long, page: Int, amount: Int): GroupAnnouncementList {
|
||||||
|
val data = network.async {
|
||||||
|
HttpClient().post<String> {
|
||||||
|
url("https://web.qun.qq.com/cgi-bin/announce/list_announce")
|
||||||
|
body = MultiPartFormDataContent(formData {
|
||||||
|
append("qid", groupId)
|
||||||
|
append("bkn", bkn)
|
||||||
|
append("ft", 23) //好像是一个用来识别应用的参数
|
||||||
|
append("s", if (page == 1) 0 else -(page * amount + 1)) // 第一页这里的参数应该是-1
|
||||||
|
append("n", amount)
|
||||||
|
append("ni", if (page == 1) 1 else 0)
|
||||||
|
append("format", "json")
|
||||||
|
})
|
||||||
|
headers {
|
||||||
|
append(
|
||||||
|
"cookie",
|
||||||
|
"uin=o${selfQQ.id}; skey=${client.wLoginSigInfo.sKey.data.encodeToString()}; p_uin=o${selfQQ.id};"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val rep = data.await()
|
||||||
|
// bot.network.logger.error(rep)
|
||||||
|
return json.parse(GroupAnnouncementList.serializer(), rep)
|
||||||
|
}
|
||||||
|
|
||||||
|
@LowLevelAPI
|
||||||
|
@MiraiExperimentalAPI
|
||||||
|
override suspend fun _lowLevelSendAnnouncement(groupId: Long, announcement: GroupAnnouncement): String {
|
||||||
|
val rep = network.async {
|
||||||
|
HttpClient().post<String> {
|
||||||
|
url("https://web.qun.qq.com/cgi-bin/announce/add_qun_notice")
|
||||||
|
body = MultiPartFormDataContent(formData {
|
||||||
|
append("qid", groupId)
|
||||||
|
append("bkn", bkn)
|
||||||
|
append("text", announcement.msg.text)
|
||||||
|
append("pinned", announcement.pinned)
|
||||||
|
append(
|
||||||
|
"settings",
|
||||||
|
json.stringify(
|
||||||
|
GroupAnnouncementSettings.serializer(),
|
||||||
|
announcement.settings ?: GroupAnnouncementSettings()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
append("format", "json")
|
||||||
|
})
|
||||||
|
headers {
|
||||||
|
append(
|
||||||
|
"cookie",
|
||||||
|
"uin=o${selfQQ.id};" +
|
||||||
|
" skey=${client.wLoginSigInfo.sKey.data.encodeToString()};" +
|
||||||
|
" p_uin=o${selfQQ.id};" +
|
||||||
|
" p_skey=${client.wLoginSigInfo.psKeyMap["qun.qq.com"]?.data?.encodeToString()}; "
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val jsonObj = json.parseJson(rep.await())
|
||||||
|
return jsonObj.jsonObject["new_fid"]?.primitive?.content
|
||||||
|
?: throw throw IllegalStateException("Send Announcement fail group:$groupId msg:${jsonObj.jsonObject["em"]} content:${announcement.msg.text}")
|
||||||
|
}
|
||||||
|
|
||||||
|
@LowLevelAPI
|
||||||
|
@MiraiExperimentalAPI
|
||||||
|
override suspend fun _lowLevelDeleteAnnouncement(groupId: Long, fid: String) {
|
||||||
|
val rep = network.async {
|
||||||
|
HttpClient().post<String> {
|
||||||
|
url("https://web.qun.qq.com/cgi-bin/announce/del_feed")
|
||||||
|
body = MultiPartFormDataContent(formData {
|
||||||
|
append("qid", groupId)
|
||||||
|
append("bkn", bkn)
|
||||||
|
append("fid", fid)
|
||||||
|
append("format", "json")
|
||||||
|
})
|
||||||
|
headers {
|
||||||
|
append(
|
||||||
|
"cookie",
|
||||||
|
"uin=o${selfQQ.id};" +
|
||||||
|
" skey=${client.wLoginSigInfo.sKey.data.encodeToString()};" +
|
||||||
|
" p_uin=o${selfQQ.id};" +
|
||||||
|
" p_skey=${client.wLoginSigInfo.psKeyMap["qun.qq.com"]?.data?.encodeToString()}; "
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val data = rep.await()
|
||||||
|
val jsonObj = json.parseJson(data)
|
||||||
|
if (jsonObj.jsonObject["ec"]?.int ?: 1 != 0) {
|
||||||
|
throw throw IllegalStateException("delete Announcement fail group:$groupId msg:${jsonObj.jsonObject["em"]} fid:$fid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(LowLevelAPI::class)
|
||||||
|
@MiraiExperimentalAPI
|
||||||
|
override suspend fun _lowLevelGetAnnouncement(groupId: Long, fid: String): GroupAnnouncement {
|
||||||
|
val data = network.async {
|
||||||
|
HttpClient().post<String> {
|
||||||
|
url("https://web.qun.qq.com/cgi-bin/announce/get_feed")
|
||||||
|
body = MultiPartFormDataContent(formData {
|
||||||
|
append("qid", groupId)
|
||||||
|
append("bkn", bkn)
|
||||||
|
append("fid", fid)
|
||||||
|
append("format", "json")
|
||||||
|
})
|
||||||
|
headers {
|
||||||
|
append(
|
||||||
|
"cookie",
|
||||||
|
"uin=o${selfQQ.id}; skey=${client.wLoginSigInfo.sKey.data.encodeToString()}; p_uin=o${selfQQ.id};"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val rep = data.await()
|
||||||
|
// bot.network.logger.error(rep)
|
||||||
|
return json.parse(GroupAnnouncement.serializer(), rep)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun queryImageUrl(image: Image): String = when (image) {
|
override suspend fun queryImageUrl(image: Image): String = when (image) {
|
||||||
is OnlineFriendImageImpl -> image.originUrl
|
is OnlineFriendImageImpl -> image.originUrl
|
||||||
is OnlineGroupImageImpl -> image.originUrl
|
is OnlineGroupImageImpl -> image.originUrl
|
||||||
@ -224,6 +359,19 @@ internal abstract class QQAndroidBotBase constructor(
|
|||||||
override suspend fun openChannel(image: Image): ByteReadChannel {
|
override suspend fun openChannel(image: Image): ByteReadChannel {
|
||||||
return MiraiPlatformUtils.Http.get<HttpResponse>(queryImageUrl(image)).content.toKotlinByteReadChannel()
|
return MiraiPlatformUtils.Http.get<HttpResponse>(queryImageUrl(image)).content.toKotlinByteReadChannel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 获取群公告 所需的bkn参数
|
||||||
|
* */
|
||||||
|
val bkn: Int
|
||||||
|
get() {
|
||||||
|
val str = client.wLoginSigInfo.sKey.data.encodeToString()
|
||||||
|
var magic = 5381
|
||||||
|
for (i in str) {
|
||||||
|
magic += magic.shl(5) + i.toInt()
|
||||||
|
}
|
||||||
|
return Int.MAX_VALUE.and(magic)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
|
@ -602,6 +602,7 @@ internal class WtLogin {
|
|||||||
userA5 = UserA5(tlvMap119.getOrEmpty(0x10b), creationTime),
|
userA5 = UserA5(tlvMap119.getOrEmpty(0x10b), creationTime),
|
||||||
userA8 = UserA8(tlvMap119.getOrEmpty(0x102), creationTime, expireTime)
|
userA8 = UserA8(tlvMap119.getOrEmpty(0x102), creationTime, expireTime)
|
||||||
)
|
)
|
||||||
|
//bot.network.logger.error(client.wLoginSigInfo.psKeyMap["qun.qq.com"]?.data?.encodeToString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,12 @@
|
|||||||
package net.mamoe.mirai.contact
|
package net.mamoe.mirai.contact
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.serialization.SerialInfo
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
|
import net.mamoe.mirai.data.GroupAnnouncement
|
||||||
|
import net.mamoe.mirai.data.GroupAnnouncementList
|
||||||
import net.mamoe.mirai.data.MemberInfo
|
import net.mamoe.mirai.data.MemberInfo
|
||||||
import net.mamoe.mirai.event.events.*
|
import net.mamoe.mirai.event.events.*
|
||||||
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
||||||
@ -148,6 +153,8 @@ expect abstract class Group() : Contact, CoroutineScope {
|
|||||||
*/
|
*/
|
||||||
abstract operator fun contains(id: Long): Boolean
|
abstract operator fun contains(id: Long): Boolean
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
|
* 让机器人退出这个群. 机器人必须为非群主才能退出. 否则将会失败
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package net.mamoe.mirai.data
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 群公告数据类
|
||||||
|
* getGroupAnnouncementList时,如果page=1,那么你可以在inst里拿到一些置顶公告
|
||||||
|
*
|
||||||
|
* 发公告时只需要填写text,其他参数可为默认值
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
data class GroupAnnouncementList(
|
||||||
|
val ec: Int, //状态码 0 是正常的
|
||||||
|
@SerialName("em") val msg: String, //信息
|
||||||
|
val feeds: List<GroupAnnouncement>? = null, //群公告列表
|
||||||
|
val inst: List<GroupAnnouncement>? = null //置顶列表?
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GroupAnnouncement(
|
||||||
|
@SerialName("u") val sender: Long = 0,
|
||||||
|
val msg: GroupAnnouncementMsg,
|
||||||
|
val settings: GroupAnnouncementSettings? = null,
|
||||||
|
@SerialName("pubt") val time: Long = 0,
|
||||||
|
@SerialName("read_num") val readNum: Int = 0,
|
||||||
|
@SerialName("is_read") val isRead: Int = 0,
|
||||||
|
val pinned: Int = 0,
|
||||||
|
val fid:String? = null //公告的id
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GroupAnnouncementMsg(
|
||||||
|
val text: String,
|
||||||
|
val text_face: String? = null,
|
||||||
|
val title: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GroupAnnouncementSettings(
|
||||||
|
@SerialName("is_show_edit_card") val isShowEditCard: Int = 0,
|
||||||
|
@SerialName("remind_ts") val remindTs: Int = 0,
|
||||||
|
@SerialName("tip_window_type") val tipWindowType: Int = 0,
|
||||||
|
@SerialName("confirm_required") val confirmRequired: Int = 0
|
||||||
|
)
|
@ -12,9 +12,7 @@ package net.mamoe.mirai
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import net.mamoe.mirai.contact.Group
|
import net.mamoe.mirai.contact.Group
|
||||||
import net.mamoe.mirai.contact.QQ
|
import net.mamoe.mirai.contact.QQ
|
||||||
import net.mamoe.mirai.data.FriendInfo
|
import net.mamoe.mirai.data.*
|
||||||
import net.mamoe.mirai.data.GroupInfo
|
|
||||||
import net.mamoe.mirai.data.MemberInfo
|
|
||||||
import net.mamoe.mirai.message.data.MessageSource
|
import net.mamoe.mirai.message.data.MessageSource
|
||||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||||
@ -94,6 +92,41 @@ interface LowLevelBotAPIAccessor {
|
|||||||
*/
|
*/
|
||||||
@LowLevelAPI
|
@LowLevelAPI
|
||||||
suspend fun _lowLevelRecallGroupMessage(groupId: Long, messageId: Long)
|
suspend fun _lowLevelRecallGroupMessage(groupId: Long, messageId: Long)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取群公告列表
|
||||||
|
* @param page 页码
|
||||||
|
* */
|
||||||
|
@LowLevelAPI
|
||||||
|
@MiraiExperimentalAPI
|
||||||
|
suspend fun _lowLevelGetAnnouncements(groupId: Long, page: Int = 1, amount: Int = 10): GroupAnnouncementList
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送群公告
|
||||||
|
*
|
||||||
|
* @return 公告的fid
|
||||||
|
* */
|
||||||
|
@LowLevelAPI
|
||||||
|
@MiraiExperimentalAPI
|
||||||
|
suspend fun _lowLevelSendAnnouncement(groupId: Long, announcement: GroupAnnouncement): String
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除群公告
|
||||||
|
* @param fid [GroupAnnouncement.fid]
|
||||||
|
* */
|
||||||
|
@LowLevelAPI
|
||||||
|
@MiraiExperimentalAPI
|
||||||
|
suspend fun _lowLevelDeleteAnnouncement(groupId: Long, fid: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取一条群公告
|
||||||
|
* @param fid [GroupAnnouncement.fid]
|
||||||
|
* */
|
||||||
|
@LowLevelAPI
|
||||||
|
@MiraiExperimentalAPI
|
||||||
|
suspend fun _lowLevelGetAnnouncement(groupId: Long, fid: String): GroupAnnouncement
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,8 @@ package net.mamoe.mirai.contact
|
|||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
|
import net.mamoe.mirai.data.GroupAnnouncement
|
||||||
|
import net.mamoe.mirai.data.GroupAnnouncementList
|
||||||
import net.mamoe.mirai.data.MemberInfo
|
import net.mamoe.mirai.data.MemberInfo
|
||||||
import net.mamoe.mirai.event.events.*
|
import net.mamoe.mirai.event.events.*
|
||||||
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
||||||
@ -146,6 +148,7 @@ actual abstract class Group : Contact(), CoroutineScope {
|
|||||||
*/
|
*/
|
||||||
actual abstract fun getOrNull(id: Long): Member?
|
actual abstract fun getOrNull(id: Long): Member?
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查此 id 的群成员是否存在
|
* 检查此 id 的群成员是否存在
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user