Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support TelegramBotRegisteredEvent and TelegramBotStartedEvent #29

Merged
merged 1 commit into from
Jul 23, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ package love.forte.simbot.component.telegram.core.bot.internal

import kotlinx.coroutines.Job
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
Expand All @@ -37,12 +39,10 @@ import love.forte.simbot.component.telegram.core.bot.internal.command.TelegramBo
import love.forte.simbot.component.telegram.core.bot.internal.command.toTGCommands
import love.forte.simbot.component.telegram.core.component.TelegramComponent
import love.forte.simbot.component.telegram.core.event.TelegramUnsupportedEvent
import love.forte.simbot.component.telegram.core.event.internal.TelegramChannelMessageEventImpl
import love.forte.simbot.component.telegram.core.event.internal.TelegramChatGroupMessageEventImpl
import love.forte.simbot.component.telegram.core.event.internal.TelegramPrivateMessageEventImpl
import love.forte.simbot.component.telegram.core.event.internal.TelegramSuperGroupMessageEventImpl
import love.forte.simbot.component.telegram.core.event.internal.*
import love.forte.simbot.event.Event
import love.forte.simbot.event.EventDispatcher
import love.forte.simbot.event.EventResult
import love.forte.simbot.event.onEachError
import love.forte.simbot.logger.LoggerFactory
import love.forte.simbot.telegram.api.bot.GetMeApi
Expand Down Expand Up @@ -114,6 +114,9 @@ internal class TelegramBotImpl(

// mark started
isStarted = true
// push start event
eventDispatcher.pushEventWithBot(TelegramBotStartedEventImpl(this), this)
.launchIn(this)
}
}

Expand All @@ -139,9 +142,6 @@ internal class TelegramBotImpl(
}





@OptIn(FragileSimbotAPI::class)
internal fun subscribeInternalProcessor(
bot: TelegramBotImpl,
Expand All @@ -151,14 +151,11 @@ internal fun subscribeInternalProcessor(
val divider = object : SuspendableUpdateDivider<StdlibEvent>() {
private suspend fun pushEvent(event: Event) {
bot.logger.debug("Bot {} on event: {}", bot, event)
eventDispatcher.push(event)
.onEachError { result ->
bot.eventLogger.error("Bot {} on event dispatch error result: {}", bot, result, result.content)
}
.onCompletion {
eventDispatcher.pushEventWithBot(event, bot) { flow ->
flow.onCompletion {
bot.eventLogger.trace("Bot {} event publish completed", bot)
}
.collect()
}.collect()
}

override suspend fun onMismatchUpdateEvent(name: String, value: Any, update: Update?, context: StdlibEvent) {
Expand Down Expand Up @@ -379,3 +376,15 @@ internal fun subscribeInternalProcessor(
}
}


internal inline fun EventDispatcher.pushEventWithBot(
event: Event,
bot: TelegramBotImpl,
block: (Flow<EventResult>) -> Flow<EventResult> = { it }
): Flow<EventResult> {
return push(event)
.onEachError { result ->
bot.eventLogger.error("Bot {} on event dispatch error result: {}", bot, result, result.content)
}
.let(block)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,21 @@
package love.forte.simbot.component.telegram.core.bot.internal

import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import love.forte.simbot.bot.ConflictBotException
import love.forte.simbot.bot.JobBasedBotManager
import love.forte.simbot.common.collection.computeValue
import love.forte.simbot.common.collection.concurrentMutableMap
import love.forte.simbot.common.collection.removeValue
import love.forte.simbot.common.coroutines.mergeWith
import love.forte.simbot.common.id.ID
import love.forte.simbot.common.id.NumericalID
import love.forte.simbot.common.id.literal
import love.forte.simbot.component.telegram.core.bot.TelegramBot
import love.forte.simbot.component.telegram.core.bot.TelegramBotConfiguration
import love.forte.simbot.component.telegram.core.bot.TelegramBotManager
import love.forte.simbot.component.telegram.core.bot.TelegramBotManagerConfiguration
import love.forte.simbot.component.telegram.core.component.TelegramComponent
import love.forte.simbot.component.telegram.core.event.internal.TelegramBotRegisteredEventImpl
import love.forte.simbot.event.EventDispatcher
import love.forte.simbot.telegram.stdlib.bot.Bot
import love.forte.simbot.telegram.stdlib.bot.BotFactory
Expand All @@ -53,7 +54,7 @@ internal class TelegramBotManagerImpl(
private val botsWithTokenKey = concurrentMutableMap<String, TelegramBotImpl>()

// id token cache
private val idTokenMap = concurrentMutableMap<Long, String>()
// private val idTokenMap = concurrentMutableMap<Long, String>()

override fun register(ticket: Bot.Ticket, configuration: TelegramBotConfiguration): TelegramBot {
val token = ticket.token
Expand All @@ -78,30 +79,27 @@ internal class TelegramBotManagerImpl(
createBot()
}!!

// TODO register update idTokenMap

newBot.onCompletion {
botsWithTokenKey.removeValue(token) { newBot }
}

eventDispatcher.pushRegisteredEvent(newBot)

return newBot
}

override fun all(): Sequence<TelegramBot> =
botsWithTokenKey.values.asSequence()

override fun find(id: ID): TelegramBot? {
fun findByLongId(lid: Long): TelegramBot? =
idTokenMap[lid]?.let { token -> botsWithTokenKey[token] }?.takeIf { it.isActive }

if (id is NumericalID) {
return findByLongId(id.toLong())
}

val token = id.literal
val foundByToken = botsWithTokenKey[token]
if (foundByToken != null) return foundByToken

return token.toLongOrNull()?.let { longId -> findByLongId(longId) }
return botsWithTokenKey[token]
}
}

internal fun EventDispatcher.pushRegisteredEvent(
bot: TelegramBotImpl
): Job {
val e = TelegramBotRegisteredEventImpl(bot)
return pushEventWithBot(e, bot).launchIn(bot)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,25 @@ import love.forte.simbot.telegram.type.Message
*/
public typealias StdlibEvent = love.forte.simbot.telegram.stdlib.event.Event

/**
* An telegram bot event.
*
* @see TelegramEvent
*/
public interface TelegramBotEvent : BotEvent {
/**
* The [TelegramBot].
*/
override val bot: TelegramBot
}

/**
* Is a Telegram simbot component event definition type.
* Is an implementation of the event type in the simbot API.
*
* @author ForteScarlet
*/
public interface TelegramEvent : BotEvent {
public interface TelegramEvent : TelegramBotEvent {
// 所有的 Telegram Event 都是建立在 Bot 之上的,
// 因此所有 TelegramEvent 都实现 BotEvent

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* This file is part of simbot-component-telegram.
*
* simbot-component-telegram 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-telegram 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-telegram.
* If not, see <https://www.gnu.org/licenses/>.
*/

package love.forte.simbot.component.telegram.core.event

import love.forte.simbot.component.telegram.core.bot.TelegramBot
import love.forte.simbot.event.BotRegisteredEvent


/**
* An event that indicating a [TelegramBot] has been registered.
*
* This is an event used as a notification
* that the bot may not have been started yet.
*/
public interface TelegramBotRegisteredEvent : BotRegisteredEvent, TelegramBotEvent {
override val bot: TelegramBot
}

/**
* An event that indicating a [TelegramBot] has been started at the first time.
*
* This is an event used as a notification.
* At this point, [bot.isStarted][TelegramBot.isStarted] is already `true`.
*/
public interface TelegramBotStartedEvent : BotRegisteredEvent, TelegramBotEvent {
override val bot: TelegramBot
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* This file is part of simbot-component-telegram.
*
* simbot-component-telegram 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-telegram 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-telegram.
* If not, see <https://www.gnu.org/licenses/>.
*/

package love.forte.simbot.component.telegram.core.event.internal

import love.forte.simbot.annotations.ExperimentalSimbotAPI
import love.forte.simbot.common.id.ID
import love.forte.simbot.common.id.UUID
import love.forte.simbot.common.time.Timestamp
import love.forte.simbot.component.telegram.core.bot.TelegramBot
import love.forte.simbot.component.telegram.core.event.TelegramBotRegisteredEvent
import love.forte.simbot.component.telegram.core.event.TelegramBotStartedEvent

internal class TelegramBotRegisteredEventImpl(override val bot: TelegramBot) : TelegramBotRegisteredEvent {
override val id: ID = UUID.random()

@OptIn(ExperimentalSimbotAPI::class)
override val time: Timestamp = Timestamp.now()
}

internal class TelegramBotStartedEventImpl(override val bot: TelegramBot) : TelegramBotStartedEvent {
override val id: ID = UUID.random()

@OptIn(ExperimentalSimbotAPI::class)
override val time: Timestamp = Timestamp.now()
}
Loading