Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .github/workflows/test-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ jobs:
os: [ macos-latest, windows-latest, ubuntu-latest ]
runs-on: ${{ matrix.os }}
steps:
# https://github.com/actions/checkout/issues/242#issuecomment-627501270
# fix `Filename too long` 👆
- name: git configure long path
run: git config --global core.longpaths true
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
Expand Down
3 changes: 2 additions & 1 deletion simbot-component-onebot-common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.simbot.api)
implementation(libs.simbot.common.annotations)
api(libs.simbot.common.annotations)
}

commonTest.dependencies {
Expand All @@ -61,6 +61,7 @@ kotlin {

jvmMain {
dependencies {
compileOnly(libs.simbot.api)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ package love.forte.simbot.component.onebot.common.annotations
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@MustBeDocumented
public annotation class OneBotInternalImplementationsOnly

// TODO be SubclassOptInRequired ?

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,12 @@ kotlin {

sourceSets {
commonMain.dependencies {
// JVM compileOnly
implementation(libs.simbot.api)
implementation(libs.simbot.common.annotations)
implementation(libs.jetbrains.annotations)

api(libs.simbot.common.annotations)
implementation(libs.simbot.common.atomic)

api(project(":simbot-component-onebot-common"))
api(project(":simbot-component-onebot-v11:simbot-component-onebot-v11-common"))
Expand All @@ -88,7 +92,9 @@ kotlin {

jvmMain {
dependencies {
compileOnly(libs.simbot.api)
compileOnly(libs.ktor.client.contentNegotiation)
compileOnly(libs.jetbrains.annotations)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2025. 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.actor.internal

import love.forte.simbot.ability.SendSupport
import love.forte.simbot.component.onebot.v11.core.api.SendMsgResult
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.messageinteraction.OneBotInternalMessagePostSendEvent
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotSegmentsInteractionMessage
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.segmentsOrNull
import love.forte.simbot.component.onebot.v11.core.internal.message.toReceipt
import love.forte.simbot.component.onebot.v11.core.utils.emitMessagePreSendEventAndUseCurrentMessage
import love.forte.simbot.component.onebot.v11.core.utils.resolveInteractionMessage
import love.forte.simbot.component.onebot.v11.core.utils.resolveToOneBotSegmentList
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
import love.forte.simbot.event.InteractionMessage
import love.forte.simbot.message.Message
import love.forte.simbot.message.MessageContent
import love.forte.simbot.message.PlainText


/**
*
* @author ForteScarlet
*/
internal abstract class AbstractSendSupport : SendSupport {
protected abstract val bot: OneBotBotImpl

protected abstract fun preSendEvent(
interactionMessage: OneBotSegmentsInteractionMessage
): AbstractMessagePreSendEventImpl

protected abstract fun OneBotMessageReceipt.postSendEvent(
interactionMessage: InteractionMessage
): OneBotInternalMessagePostSendEvent

protected abstract suspend fun sendText(text: String): SendMsgResult

protected abstract suspend fun sendSegments(segments: List<OneBotMessageSegment>): SendMsgResult

protected suspend fun sendMessage(message: Message): SendMsgResult {
return when (message) {
is PlainText -> sendText(message.text)
else -> sendSegments(message.resolveToOneBotSegmentList(bot))
}
}

override suspend fun send(text: String): OneBotMessageReceipt {
val interactionMessage = OneBotSegmentsInteractionMessage(text = text)
return interceptionAndSend(interactionMessage)
}

override suspend fun send(messageContent: MessageContent): OneBotMessageReceipt {
val interactionMessage = OneBotSegmentsInteractionMessage(content = messageContent)
return interceptionAndSend(interactionMessage)
}

override suspend fun send(message: Message): OneBotMessageReceipt {
val interactionMessage = OneBotSegmentsInteractionMessage(message = message, bot = bot)
return interceptionAndSend(interactionMessage)
}

protected suspend fun interceptionAndSend(
interactionMessage: OneBotSegmentsInteractionMessage
): OneBotMessageReceipt {
val event = preSendEvent(interactionMessage)

val currentMessage = bot.emitMessagePreSendEventAndUseCurrentMessage(event)
val segments = currentMessage.segmentsOrNull
if (segments != null) {
return sendSegments(segments).toReceipt(bot).alsoPostSend(currentMessage)
}

return sendByInteractionMessage(currentMessage).toReceipt(bot).alsoPostSend(currentMessage)
}

/**
* 解析一个 [InteractionMessage] 为一个 [OneBotMessageSegment] 的列表并发送。
* 始终认为 `segments` 为 `null`。
*/
protected suspend fun sendByInteractionMessage(interactionMessage: InteractionMessage): SendMsgResult {
return resolveInteractionMessage(
interactionMessage = interactionMessage,
onSegments = { sendSegments(it) },
onMessage = { sendMessage(it) },
onText = { sendText(it) },
)
}

protected fun OneBotMessageReceipt.alsoPostSend(
interactionMessage: InteractionMessage
): OneBotMessageReceipt = apply {
val event = postSendEvent(interactionMessage)
bot.pushEventAndLaunch(event)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,50 +23,60 @@ 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.SendLikeApi
import love.forte.simbot.component.onebot.v11.core.api.SendMsgResult
import love.forte.simbot.component.onebot.v11.core.bot.internal.OneBotBotImpl
import love.forte.simbot.component.onebot.v11.core.internal.message.toReceipt
import love.forte.simbot.component.onebot.v11.core.utils.resolveToOneBotSegmentList
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.AbstractMessagePreSendEventImpl
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotFriendPostSendEventImpl
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotFriendPreSendEventImpl
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotInternalMessagePostSendEvent
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotSegmentsInteractionMessage
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.toOneBotSegmentsInteractionMessage
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.OneBotMessageContent
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
import love.forte.simbot.message.Message
import love.forte.simbot.message.MessageContent
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
import love.forte.simbot.event.InteractionMessage
import kotlin.coroutines.CoroutineContext

internal abstract class OneBotFriendImpl : OneBotFriend {
protected abstract val bot: OneBotBotImpl
internal abstract class OneBotFriendImpl : AbstractSendSupport(), OneBotFriend {
abstract override val bot: OneBotBotImpl

override suspend fun send(text: String): OneBotMessageReceipt {
override fun preSendEvent(interactionMessage: OneBotSegmentsInteractionMessage): AbstractMessagePreSendEventImpl {
return OneBotFriendPreSendEventImpl(
this,
bot,
interactionMessage
)
}

override suspend fun sendText(text: String): SendMsgResult {
return bot.executeData(
sendPrivateTextMsgApi(
target = id,
text = text,
)
).toReceipt(bot)
}

override suspend fun send(messageContent: MessageContent): OneBotMessageReceipt {
if (messageContent is OneBotMessageContent) {
return bot.executeData(
sendPrivateMsgApi(
target = id,
message = messageContent.sourceSegments,
)
).toReceipt(bot)
}

return send(messageContent.messages)
)
}

override suspend fun send(message: Message): OneBotMessageReceipt {
override suspend fun sendSegments(segments: List<OneBotMessageSegment>): SendMsgResult {
return bot.executeData(
sendPrivateMsgApi(
target = id,
message = message.resolveToOneBotSegmentList(bot)
message = segments,
)
).toReceipt(bot)
)
}

override fun OneBotMessageReceipt.postSendEvent(
interactionMessage: InteractionMessage
): OneBotInternalMessagePostSendEvent {
return OneBotFriendPostSendEventImpl(
content = this@OneBotFriendImpl,
bot = bot,
receipt = this,
message = interactionMessage.toOneBotSegmentsInteractionMessage()
)
}

override suspend fun sendLike(times: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,26 @@ import love.forte.simbot.component.onebot.v11.core.actor.OneBotGroupDeleteOption
import love.forte.simbot.component.onebot.v11.core.actor.OneBotMember
import love.forte.simbot.component.onebot.v11.core.api.*
import love.forte.simbot.component.onebot.v11.core.bot.internal.OneBotBotImpl
import love.forte.simbot.component.onebot.v11.core.internal.message.toReceipt
import love.forte.simbot.component.onebot.v11.core.utils.resolveToOneBotSegmentList
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.AbstractMessagePreSendEventImpl
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotGroupPostSendEventImpl
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotGroupPreSendEventImpl
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotInternalMessagePostSendEvent
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotSegmentsInteractionMessage
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.toOneBotSegmentsInteractionMessage
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.OneBotMessageContent
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
import love.forte.simbot.message.Message
import love.forte.simbot.message.MessageContent
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
import love.forte.simbot.event.InteractionMessage
import kotlin.concurrent.Volatile
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmInline


internal abstract class OneBotGroupImpl(
initialName: String
) : OneBotGroup {
protected abstract val bot: OneBotBotImpl
) : AbstractSendSupport(), OneBotGroup {
abstract override val bot: OneBotBotImpl

@Volatile
override var name: String = initialName
Expand Down Expand Up @@ -76,7 +79,6 @@ internal abstract class OneBotGroupImpl(
return result.dataOrThrow.toMember(bot)
}


override suspend fun setAnonymous(enable: Boolean) {
bot.executeData(
SetGroupAnonymousApi.create(
Expand All @@ -86,35 +88,42 @@ internal abstract class OneBotGroupImpl(
)
}

override suspend fun send(text: String): OneBotMessageReceipt {
override fun preSendEvent(interactionMessage: OneBotSegmentsInteractionMessage): AbstractMessagePreSendEventImpl {
return OneBotGroupPreSendEventImpl(
this,
bot,
interactionMessage
)
}


override suspend fun sendText(text: String): SendMsgResult {
return bot.executeData(
sendGroupTextMsgApi(
target = id,
text = text,
)
).toReceipt(bot)
}

override suspend fun send(messageContent: MessageContent): OneBotMessageReceipt {
if (messageContent is OneBotMessageContent) {
return bot.executeData(
sendGroupMsgApi(
target = id,
message = messageContent.sourceSegments,
)
).toReceipt(bot)
}

return send(messageContent.messages)
)
}

override suspend fun send(message: Message): OneBotMessageReceipt {
override suspend fun sendSegments(segments: List<OneBotMessageSegment>): SendMsgResult {
return bot.executeData(
sendGroupMsgApi(
target = id,
message = message.resolveToOneBotSegmentList(bot)
message = segments,
)
).toReceipt(bot)
)
}

override fun OneBotMessageReceipt.postSendEvent(
interactionMessage: InteractionMessage
): OneBotInternalMessagePostSendEvent {
return OneBotGroupPostSendEventImpl(
content = this@OneBotGroupImpl,
bot = bot,
receipt = this,
message = interactionMessage.toOneBotSegmentsInteractionMessage()
)
}

override suspend fun delete(vararg options: DeleteOption) {
Expand Down Expand Up @@ -206,6 +215,23 @@ internal abstract class OneBotGroupImpl(
bot.executeData(GetGroupHonorInfoApi.create(groupId = id, type = type))

override fun toString(): String = "OneBotGroup(id=$id, bot=${bot.id})"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is OneBotGroupImpl) return false

if (name != other.name) return false
if (bot != other.bot) return false

return true
}

override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + bot.hashCode()
return result
}


}

/**
Expand Down
Loading
Loading