Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9bde2b8
Merge pull request #65 from simple-robot/dev/main
ForteScarlet Jul 1, 2024
b1fceaa
Merge pull request #66 from simple-robot/dev/main
ForteScarlet Jul 1, 2024
3675a9d
Merge pull request #71 from simple-robot/dev/main
ForteScarlet Jul 26, 2024
1c1b8d6
Merge pull request #78 from simple-robot/dev/main
ForteScarlet Aug 4, 2024
907b349
Merge pull request #93 from simple-robot/dev/main
ForteScarlet Aug 9, 2024
d2da4a5
Merge pull request #96 from simple-robot/dev/main
ForteScarlet Aug 17, 2024
dd6c44d
Merge pull request #100 from simple-robot/dev/main
ForteScarlet Aug 27, 2024
eac34ad
Merge pull request #104 from simple-robot/dev/main
ForteScarlet Aug 30, 2024
a188e9e
Merge pull request #110 from simple-robot/dev/main
ForteScarlet Sep 6, 2024
d757d5b
Merge pull request #130 from simple-robot/dev/main
ForteScarlet Oct 18, 2024
258e90d
Merge pull request #136 from simple-robot/dev/main
ForteScarlet Oct 31, 2024
dae30f4
Merge pull request #141 from simple-robot/dev/main
ForteScarlet Nov 22, 2024
3b00631
Merge pull request #152 from simple-robot/dev/main
ForteScarlet Dec 12, 2024
d3db48b
Merge pull request #182 from simple-robot/dev/main
ForteScarlet Mar 3, 2025
394f63a
Merge pull request #190 from simple-robot/dev/main
ForteScarlet Mar 23, 2025
d72c15b
Merge pull request #199 from simple-robot/dev/main
ForteScarlet Apr 23, 2025
ca84aba
Merge pull request #210 from simple-robot/dev/main
ForteScarlet May 19, 2025
01cc419
Merge pull request #215 from simple-robot/dev/main
ForteScarlet May 30, 2025
a5faabd
Merge pull request #228 from simple-robot/dev/main
ForteScarlet Jul 2, 2025
1cb5906
Update README.md
ForteScarlet Aug 8, 2025
b36f94f
Update README.md
ForteScarlet Aug 8, 2025
9223673
add `OneBotBrand`
Aliorpse Sep 13, 2025
20dc3ee
send forward msg support (untested)
Aliorpse Sep 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
<img alt="repo size" src="https://img.shields.io/github/repo-size/simple-robot/simbot-component-onebot" />
<img alt="issues" src="https://img.shields.io/github/issues-closed/simple-robot/simbot-component-onebot?color=green" />
<img alt="last commit" src="https://img.shields.io/github/last-commit/simple-robot/simbot-component-onebot" />
<a href="./COPYING"><img alt="copying" src="https://img.shields.io/github/license/simple-robot/simbot-component-onebot" /></a>
<a href="./COPYING"><img alt="copying" src="https://img.shields.io/github/license/simple-robot/simbot-component-onebot" /></a>
<a href="https://deepwiki.com/simple-robot/simbot-component-onebot"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
</p>
<p>
<img src="https://img.shields.io/badge/OneBot-11-black?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAxQTFRF////29vbr6+vAAAAk1hCcwAAAAR0Uk5T////AEAqqfQAAAKcSURBVHja7NrbctswDATQXfD//zlpO7FlmwAWIOnOtNaTM5JwDMa8E+PNFz7g3waJ24fviyDPgfhz8fHP39cBcBL9KoJbQUxjA2iYqHL3FAnvzhL4GtVNUcoSZe6eSHizBcK5LL7dBr2AUZlev1ARRHCljzRALIEog6H3U6bCIyqIZdAT0eBuJYaGiJaHSjmkYIZd+qSGWAQnIaz2OArVnX6vrItQvbhZJtVGB5qX9wKqCMkb9W7aexfCO/rwQRBzsDIsYx4AOz0nhAtWu7bqkEQBO0Pr+Ftjt5fFCUEbm0Sbgdu8WSgJ5NgH2iu46R/o1UcBXJsFusWF/QUaz3RwJMEgngfaGGdSxJkE/Yg4lOBryBiMwvAhZrVMUUvwqU7F05b5WLaUIN4M4hRocQQRnEedgsn7TZB3UCpRrIJwQfqvGwsg18EnI2uSVNC8t+0QmMXogvbPg/xk+Mnw/6kW/rraUlvqgmFreAA09xW5t0AFlHrQZ3CsgvZm0FbHNKyBmheBKIF2cCA8A600aHPmFtRB1XvMsJAiza7LpPog0UJwccKdzw8rdf8MyN2ePYF896LC5hTzdZqxb6VNXInaupARLDNBWgI8spq4T0Qb5H4vWfPmHo8OyB1ito+AysNNz0oglj1U955sjUN9d41LnrX2D/u7eRwxyOaOpfyevCWbTgDEoilsOnu7zsKhjRCsnD/QzhdkYLBLXjiK4f3UWmcx2M7PO21CKVTH84638NTplt6JIQH0ZwCNuiWAfvuLhdrcOYPVO9eW3A67l7hZtgaY9GZo9AFc6cryjoeFBIWeU+npnk/nLE0OxCHL1eQsc1IciehjpJv5mqCsjeopaH6r15/MrxNnVhu7tmcslay2gO2Z1QfcfX0JMACG41/u0RrI9QAAAABJRU5ErkJggg==" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ import love.forte.simbot.common.id.ID
import love.forte.simbot.common.id.literal
import love.forte.simbot.component.onebot.common.annotations.OneBotInternalImplementationsOnly
import love.forte.simbot.component.onebot.v11.common.utils.qqAvatar640
import love.forte.simbot.component.onebot.v11.core.api.SendMsgResult
import love.forte.simbot.component.onebot.v11.core.bot.OneBotBot
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
import love.forte.simbot.definition.Contact
import love.forte.simbot.message.Message
import love.forte.simbot.message.MessageContent
import love.forte.simbot.message.Messages
import love.forte.simbot.suspendrunner.ST
import kotlin.coroutines.CoroutineContext

Expand Down Expand Up @@ -82,4 +84,11 @@ public interface OneBotFriend : Contact, SendLikeSupport, OneBotStrangerAware {
@ST
override suspend fun send(text: String): OneBotMessageReceipt

/**
* 向好友发送合并转发消息。
*
* @throws Throwable 任何可能在请求API时产生的异常
*/
@ST
public suspend fun sendForward(messages: Messages): SendMsgResult
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
import love.forte.simbot.definition.ChatGroup
import love.forte.simbot.message.Message
import love.forte.simbot.message.MessageContent
import love.forte.simbot.message.Messages
import love.forte.simbot.suspendrunner.ST
import love.forte.simbot.suspendrunner.STP
import kotlin.coroutines.CoroutineContext
Expand Down Expand Up @@ -166,6 +167,14 @@ public interface OneBotGroup : ChatGroup, DeleteSupport {
@ST
override suspend fun send(text: String): OneBotMessageReceipt

/**
* 向此群内发送合并转发消息。
*
* @throws Throwable 任何可能在请求API时产生的异常
*/
@ST
public suspend fun sendForward(messages: Messages): SendGroupForwardMsgResult

/**
* 让当前bot退出/离开此群。
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import love.forte.simbot.component.onebot.v11.core.actor.OneBotFriend
import love.forte.simbot.component.onebot.v11.core.actor.OneBotStranger
import love.forte.simbot.component.onebot.v11.core.api.GetFriendListResult
import love.forte.simbot.component.onebot.v11.core.api.GetStrangerInfoApi
import love.forte.simbot.component.onebot.v11.core.api.OneBotMessageOutgoing
import love.forte.simbot.component.onebot.v11.core.api.SendLikeApi
import love.forte.simbot.component.onebot.v11.core.api.SendMsgResult
import love.forte.simbot.component.onebot.v11.core.api.SendPrivateForwardMsgApi
import love.forte.simbot.component.onebot.v11.core.bot.internal.OneBotBotImpl
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.AbstractMessagePreSendEventImpl
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotFriendPostSendEventImpl
Expand All @@ -35,8 +37,10 @@ import love.forte.simbot.component.onebot.v11.core.utils.sendPrivateMsgApi
import love.forte.simbot.component.onebot.v11.core.utils.sendPrivateTextMsgApi
import love.forte.simbot.component.onebot.v11.event.message.RawPrivateMessageEvent
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
import love.forte.simbot.component.onebot.v11.message.resolveToOneBotSegmentList
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
import love.forte.simbot.event.InteractionMessage
import love.forte.simbot.message.Messages
import kotlin.coroutines.CoroutineContext

internal abstract class OneBotFriendImpl : AbstractSendSupport(), OneBotFriend {
Expand Down Expand Up @@ -68,6 +72,17 @@ internal abstract class OneBotFriendImpl : AbstractSendSupport(), OneBotFriend {
)
}

override suspend fun sendForward(messages: Messages): SendMsgResult {
return bot.executeData(
SendPrivateForwardMsgApi.create(
userId = id,
messages = OneBotMessageOutgoing.create(
messages.resolveToOneBotSegmentList()
)
)
)
}

override fun OneBotMessageReceipt.postSendEvent(
interactionMessage: InteractionMessage
): OneBotInternalMessagePostSendEvent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.toOn
import love.forte.simbot.component.onebot.v11.core.utils.sendGroupMsgApi
import love.forte.simbot.component.onebot.v11.core.utils.sendGroupTextMsgApi
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
import love.forte.simbot.component.onebot.v11.message.resolveToOneBotSegmentList
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
import love.forte.simbot.event.InteractionMessage
import love.forte.simbot.message.Messages
import kotlin.concurrent.Volatile
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmInline
Expand Down Expand Up @@ -115,6 +117,17 @@ internal abstract class OneBotGroupImpl(
)
}

override suspend fun sendForward(messages: Messages): SendGroupForwardMsgResult {
return bot.executeData(
SendGroupForwardMsgApi.create(
groupId = id,
messages = OneBotMessageOutgoing.create(
messages.resolveToOneBotSegmentList()
)
)
)
}

override fun OneBotMessageReceipt.postSendEvent(
interactionMessage: InteractionMessage
): OneBotInternalMessagePostSendEvent {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* This file is part of simbot-component-onebot.
*
* simbot-component-onebot is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* simbot-component-onebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with simbot-component-onebot.
* If not, see <https://www.gnu.org/licenses/>.
*/

package love.forte.simbot.component.onebot.v11.core.api

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import love.forte.simbot.common.id.ID
import love.forte.simbot.common.id.IntID
import love.forte.simbot.common.id.StringID
import love.forte.simbot.common.id.literal
import love.forte.simbot.component.onebot.common.annotations.ApiResultConstructor
import kotlin.jvm.JvmStatic

/**
* [`send_group_forward_msg`-发送群合并转发消息 - 非标准接口](https://llonebot.apifox.cn/api-226189162)
*
* @author Aliorpse
*/
public class SendGroupForwardMsgApi private constructor(
override val body: Any,
) : OneBotApi<SendGroupForwardMsgResult> {
override val action: String
get() = ACTION

override val resultDeserializer: DeserializationStrategy<SendGroupForwardMsgResult>
get() = SendGroupForwardMsgResult.serializer()

override val apiResultDeserializer: DeserializationStrategy<OneBotApiResult<SendGroupForwardMsgResult>>
get() = RES_SER

public companion object Factory {
private const val ACTION: String = "send_group_forward_msg"

private val RES_SER = OneBotApiResult.serializer(SendGroupForwardMsgResult.serializer())

/**
* 构建一个 [SendGroupMsgApi].
*
* @param groupId 群号
* @param messages 要发送的内容
*/
@JvmStatic
public fun create(
groupId: ID,
messages: OneBotMessageOutgoing,
): SendGroupForwardMsgApi = SendGroupForwardMsgApi(Body(groupId.literal, messages))
}

/**
* @property groupId 群聊 QQ 号
* @property messages 要发送的内容
*/
@Serializable
internal data class Body(
@SerialName("group_id")
val groupId: String,
val messages: OneBotMessageOutgoing,
)
}

/**
* [SendGroupForwardMsgApi] 的响应体。
*
* @property messageId 消息 ID
* @property forwardId RES ID
*/
@Serializable
public data class SendGroupForwardMsgResult @ApiResultConstructor constructor(
@SerialName("message_id")
public val messageId: IntID,
@SerialName("forward_id")
public val forwardId: StringID
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* This file is part of simbot-component-onebot.
*
* simbot-component-onebot is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* simbot-component-onebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with simbot-component-onebot.
* If not, see <https://www.gnu.org/licenses/>.
*/

package love.forte.simbot.component.onebot.v11.core.api

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import love.forte.simbot.common.id.ID
import love.forte.simbot.common.id.literal
import kotlin.jvm.JvmStatic

/**
* [`send_private_forward_msg`-发送私聊合并转发消息 - 非标准接口](https://llonebot.apifox.cn/api-226189040)
*
* @author Aliorpse
*/
public class SendPrivateForwardMsgApi private constructor(
override val body: Any
) : OneBotApi<SendMsgResult> {

override val action: String
get() = ACTION

override val resultDeserializer: DeserializationStrategy<SendMsgResult>
get() = SendMsgResult.serializer()

override val apiResultDeserializer: DeserializationStrategy<OneBotApiResult<SendMsgResult>>
get() = RES_SER

public companion object Factory {
private const val ACTION = "send_private_forward_msg"
private val RES_SER = OneBotApiResult.serializer(SendMsgResult.serializer())

/**
* 构建一个 [SendPrivateForwardMsgApi].
* @param userId 对方 QQ 号
* @param messages 要发送的内容
*/
@JvmStatic
public fun create(
userId: ID,
messages: OneBotMessageOutgoing,
): SendPrivateForwardMsgApi = SendPrivateForwardMsgApi(Body(userId.literal, messages))
}

/**
* @property userId 对方 QQ 号
* @property messages 要发送的内容
*/
@Serializable
internal data class Body(
@SerialName("user_id")
val userId: String,
val messages: OneBotMessageOutgoing,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import kotlin.jvm.JvmStatic


/**
* [send_private_msg 发送私聊消息](https://github.com/botuniverse/onebot-11/blob/master/api/public.md#send_private_msg-发送私聊消息)
* [`send_private_msg`-发送私聊消息](https://github.com/botuniverse/onebot-11/blob/master/api/public.md#send_private_msg-发送私聊消息)
*
* @author ForteScarlet
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,19 @@ internal class OneBotBotImpl(
private var wsSession: WsEventSession? = null
private val startLock = Mutex()

enum class OneBotBrand(val displayName: String) {
LLONEBOT("LLOneBot"),
LAGRANGE("Lagrange"),
UNKNOWN("Unknown");

override fun toString(): String = displayName
}

/**
* 当前协议端实现 e.g. LLOneBot, Lagrange
*/
var onebotImpl: OneBotBrand = OneBotBrand.UNKNOWN
private set

override suspend fun start(): Unit = startLock.withLock {
job.ensureActive()
Expand All @@ -341,6 +354,21 @@ internal class OneBotBotImpl(
logger.debug("WebSocket connection is disabled because of the `eventServerHost` is null")
}

onebotImpl = try {
val versionInfo = executeData(GetVersionInfoApi.create())
val name = versionInfo.appName.lowercase()
when {
name.contains("llonebot") -> OneBotBrand.LLONEBOT
name.contains("lagrange") -> OneBotBrand.LAGRANGE
else -> OneBotBrand.UNKNOWN
}
} catch (e: Exception) {
logger.debug("Failed to get OneBot implementation info via `/get_version_info`, using UNKNOWN instead.", e)
OneBotBrand.UNKNOWN
}

logger.debug("Current OneBot implementation: {}", onebotImpl)

if (!isStarted) {
isStarted = true
launch {
Expand Down
Loading