com.github.stormbit.vksdk.vkapi.MessageRoutes.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vk-bot-sdk-kotlin Show documentation
Show all versions of vk-bot-sdk-kotlin Show documentation
The Kotlin library for working with VK api
The newest version!
package com.github.stormbit.vksdk.vkapi
import com.github.stormbit.vksdk.events.AttachmentEvent
import com.github.stormbit.vksdk.events.MessageEvent
import com.github.stormbit.vksdk.events.ServiceActionEvent
import com.github.stormbit.vksdk.events.chat.*
import com.github.stormbit.vksdk.events.chat.ChatScreenshotEvent
import com.github.stormbit.vksdk.events.message.*
import com.github.stormbit.vksdk.objects.Message
import com.github.stormbit.vksdk.objects.attachments.AttachmentType
import com.github.stormbit.vksdk.objects.models.ServiceAction
internal data class RoutePath(val restOfMessage: CharSequence)
@ContextDsl
open class MessageRoute(
open val context: ApiContext,
open val parent: MessageRoute<*>?,
open val senderType: Message.SenderType?,
open val attachmentType: AttachmentType?,
open val serviceActionType: ServiceAction.Type?,
open val withForwards: Boolean,
open val withReply: Boolean,
open val phrases: List) {
private var handler: (suspend ApiContext.(E) -> Unit)? = null
private var interceptor: (suspend ApiContext.(MessageEvent) -> Unit)? = null
@PublishedApi
internal val children: MutableSet> = mutableSetOf()
@Suppress("unchecked_cast")
internal suspend fun pass(event: MessageEvent, routePath: RoutePath) {
handler?.let { context.it(event as E) }
val iterator = children.iterator()
while (iterator.hasNext()) {
val messageRoute = iterator.next()
val overlapPhrase = messageRoute.phrases.find {
routePath.restOfMessage.startsWith(it, true)
} ?: String()
if (messageRoute.phrases.isNotEmpty() && overlapPhrase.isBlank()) continue
if (messageRoute.senderType != null && messageRoute.senderType != event.message.senderType) continue
if (messageRoute.attachmentType != null && messageRoute.attachmentType !in event.message.attachmentTypes) continue
if (messageRoute.serviceActionType != null && messageRoute.serviceActionType != event.message.serviceActionType) continue
if (messageRoute.withForwards && !event.message.hasForwards) continue
if (messageRoute.withReply && !event.message.hasReply) continue
var restOfMessage = routePath.restOfMessage.substring(overlapPhrase.length)
if (overlapPhrase.isNotBlank()) {
restOfMessage = restOfMessage.trim()
}
val newRoute = RoutePath(routePath.restOfMessage)
when {
messageRoute.senderType != null -> {
when (event.message.senderType) {
Message.SenderType.USER -> messageRoute.pass(event as UserMessageEvent, newRoute)
Message.SenderType.COMMUNITY -> messageRoute.pass(event as CommunityMessageEvent, newRoute)
Message.SenderType.CHAT -> messageRoute.pass(event as ChatMessageEvent, newRoute)
}
}
messageRoute.attachmentType != null -> {
when {
event.message.isAudioMessage -> messageRoute.pass(event as Audio, newRoute)
event.message.isVideoMessage -> messageRoute.pass(event as Video, newRoute)
event.message.isVoiceMessage -> messageRoute.pass(event as Voice, newRoute)
event.message.isPhotoMessage -> messageRoute.pass(event as Photo, newRoute)
event.message.isDocMessage -> messageRoute.pass(event as Document, newRoute)
event.message.isStickerMessage -> messageRoute.pass(event as Sticker, newRoute)
}
}
messageRoute.serviceActionType != null -> {
when (event.message.serviceActionType) {
ServiceAction.Type.CHAT_CREATE -> messageRoute.pass(event as ChatCreate, newRoute)
ServiceAction.Type.CHAT_TITLE_UPDATE -> messageRoute.pass(event as ChatTitleUpdate, newRoute)
ServiceAction.Type.CHAT_INVITE_USER -> messageRoute.pass(event as ChatJoin, newRoute)
ServiceAction.Type.CHAT_KICK_USER -> messageRoute.pass(event as ChatLeave, newRoute)
ServiceAction.Type.CHAT_PHOTO_UPDATE -> messageRoute.pass(event as ChatPhotoUpdate, newRoute)
ServiceAction.Type.CHAT_PHOTO_REMOVE -> messageRoute.pass(event as ChatPhotoRemove, newRoute)
ServiceAction.Type.CHAT_PIN_MESSAGE -> messageRoute.pass(event as ChatPinMessage, newRoute)
ServiceAction.Type.CHAT_UNPIN_MESSAGE -> messageRoute.pass(event as ChatUnpinMessage, newRoute)
ServiceAction.Type.CHAT_INVITE_USER_BY_LINK -> messageRoute.pass(event as ChatInviteUserByLink, newRoute)
ServiceAction.Type.CHAT_SCREENSHOT -> messageRoute.pass(event as ChatScreenshot, newRoute)
ServiceAction.Type.CHAT_GROUP_CALL_IN_PROGRESS -> messageRoute.pass(event as ChatGroupCallInProgress, routePath)
ServiceAction.Type.CHAT_INVITE_USER_BY_CALL -> messageRoute.pass(event as ChatInviteUserByCall, routePath)
}
}
messageRoute.phrases.isNotEmpty() -> {
if (overlapPhrase in messageRoute.phrases) {
messageRoute.pass(CommandMessageEvent(overlapPhrase, restOfMessage.split(" "), event.message), newRoute)
}
}
else -> messageRoute.pass(event, newRoute)
}
return
}
interceptor?.let { context.it(event as E) }
}
fun handle(block: suspend ApiContext.(E) -> Unit) {
if (handler != null)
throw Exception("You can set only one handler")
else handler = block
}
fun intercept(block: suspend ApiContext.(MessageEvent) -> Unit) {
if (interceptor != null)
throw Exception("You can set only one interceptor")
else interceptor = block
}
}
@ContextDsl
@Suppress("unused")
open class TypedMessageRoute(
context: ApiContext,
parent: MessageRoute<*>?,
senderType: Message.SenderType?,
attachmentType: AttachmentType?,
phrases: List
) : MessageRoute(context, parent, senderType, attachmentType, null, false, false, phrases) {
suspend fun onCommand(vararg words: String, block: suspend MessageRoute.() -> Unit) {
onCommand(words.toList(), block)
}
suspend fun onCommand(words: List, block: suspend MessageRoute.() -> Unit) {
MessageRoute(
context, this, null, null, null, withForwards = false, withReply = false, words
).also { children.add(it) }.block()
}
suspend inline fun onMessageWith(noinline block: suspend TypedMessageRoute.() -> Unit) {
val attachmentType = when (T::class) {
Audio::class -> AttachmentType.AUDIO
Video::class -> AttachmentType.VIDEO
Voice::class -> AttachmentType.VOICE
Photo::class -> AttachmentType.PHOTO
Document::class -> AttachmentType.DOC
Sticker::class -> AttachmentType.STICKER
else -> throw IllegalArgumentException("Unknown attachment type class")
}
TypedMessageRoute(context, this, senderType, attachmentType, emptyList())
.also { children.add(it) }.block()
}
suspend fun onMessageWithForwards(block: suspend MessageRoute.() -> Unit) {
MessageRoute(context, this, null, null, null,
withForwards = true,
withReply = false,
emptyList()
).also { children.add(it) }.block()
}
suspend fun onMessageWithReply(block: suspend MessageRoute.() -> Unit) {
MessageRoute(context, this, null, null, null,
withForwards = false,
withReply = true,
emptyList()
).also { children.add(it) }.block()
}
}
@ContextDsl
@Suppress("unused")
class DefaultMessageRoute(
context: ApiContext,
parent: MessageRoute<*>?,
phrases: List
) : MessageRoute(context, parent, null, null, null, false, false, phrases) {
@Suppress("unused")
suspend inline fun > onMessageFrom(noinline block: suspend T.() -> Unit) {
when (T::class) {
User::class -> (UserMessageRoute(context, parent, phrases).also { children.add(it) } as T).block()
Chat::class -> (ChatMessageRoute(context, parent, phrases).also { children.add(it) } as T).block()
Community::class -> (ChatMessageRoute(context, parent, phrases).also { children.add(it) } as T).block()
else -> throw IllegalArgumentException("Unknown sender type class")
}
}
suspend fun onCommand(vararg words: String, block: suspend MessageRoute.() -> Unit) {
onCommand(words.toList(), block)
}
suspend fun onCommand(words: List, block: suspend MessageRoute.() -> Unit) {
MessageRoute(
context, this, null, null, null, withForwards = false, withReply = false, words
).also { children.add(it) }.block()
}
suspend inline fun onMessageWith(noinline block: suspend TypedMessageRoute.() -> Unit) {
val attachmentType = when (T::class) {
Audio::class -> AttachmentType.AUDIO
Video::class -> AttachmentType.VIDEO
Voice::class -> AttachmentType.VOICE
Photo::class -> AttachmentType.PHOTO
Document::class -> AttachmentType.DOC
Sticker::class -> AttachmentType.STICKER
else -> throw IllegalArgumentException("Unknown attachment type class")
}
TypedMessageRoute(context, this, null, attachmentType, emptyList())
.also { children.add(it) }.block()
}
suspend fun onMessageWithForwards(block: suspend MessageRoute.() -> Unit) {
MessageRoute(context, this, null, null, null,
withForwards = true,
withReply = false,
emptyList()
).also { children.add(it) }.block()
}
suspend fun onMessageWithReply(block: suspend MessageRoute.() -> Unit) {
MessageRoute(context, this, null, null, null,
withForwards = false,
withReply = true,
emptyList()
).also { children.add(it) }.block()
}
}
@ContextDsl
class ServiceActionMessageRoute(
context: ApiContext,
parent: MessageRoute<*>?,
serviceActionType: ServiceAction.Type
) : MessageRoute(context, parent, null, null, serviceActionType, false, false, emptyList())
@ContextDsl
class ChatMessageRoute(
context: ApiContext,
parent: MessageRoute<*>?,
phrases: List,
override val senderType: Message.SenderType = Message.SenderType.CHAT
) : TypedMessageRoute(context, parent, senderType, null, phrases) {
@Suppress("unchecked_cast")
suspend inline fun onServiceAction(noinline block: suspend ServiceActionMessageRoute.() -> Unit) {
val serviceActionType = when (T::class) {
ChatCreate::class -> ServiceAction.Type.CHAT_CREATE
ChatTitleUpdate::class -> ServiceAction.Type.CHAT_TITLE_UPDATE
ChatJoin::class -> ServiceAction.Type.CHAT_INVITE_USER
ChatLeave::class -> ServiceAction.Type.CHAT_KICK_USER
ChatPhotoUpdate::class -> ServiceAction.Type.CHAT_PHOTO_UPDATE
ChatPhotoRemove::class -> ServiceAction.Type.CHAT_PHOTO_REMOVE
ChatPinMessage::class -> ServiceAction.Type.CHAT_PIN_MESSAGE
ChatUnpinMessage::class -> ServiceAction.Type.CHAT_UNPIN_MESSAGE
else -> throw IllegalArgumentException("Unknown service action type class")
}
ServiceActionMessageRoute(context, this, serviceActionType)
.also { children.add(it) }.block()
}
}
@ContextDsl
class UserMessageRoute(
context: ApiContext,
parent: MessageRoute<*>?,
phrases: List,
override val senderType: Message.SenderType = Message.SenderType.USER
) : TypedMessageRoute(context, parent, null, null, phrases)
@ContextDsl
class CommunityMessageRoute(
context: ApiContext,
parent: MessageRoute<*>?,
phrases: List,
override val senderType: Message.SenderType = Message.SenderType.COMMUNITY
) : TypedMessageRoute(context, parent, null, null, phrases)
typealias User = UserMessageRoute
typealias Chat = ChatMessageRoute
typealias Community = CommunityMessageRoute
typealias Audio = AudioMessageEvent
typealias Video = VideoMessageEvent
typealias Voice = VoiceMessageEvent
typealias Photo = PhotoMessageEvent
typealias Document = DocumentMessageEvent
typealias Sticker = StickerMessageEvent
typealias ChatCreate = ChatCreateEvent
typealias ChatTitleUpdate = ChatTitleUpdateEvent
typealias ChatJoin = ChatJoinEvent
typealias ChatLeave = ChatLeaveEvent
typealias ChatPhotoUpdate = ChatPhotoUpdateEvent
typealias ChatPhotoRemove = ChatPhotoRemoveEvent
typealias ChatPinMessage = ChatPinMessageEvent
typealias ChatUnpinMessage = ChatUnpinMessageEvent
typealias ChatInviteUserByLink = ChatInviteUserByLinkEvent
typealias ChatScreenshot = ChatScreenshotEvent
typealias ChatInviteUserByCall = ChatInviteUserByCallEvent
typealias ChatGroupCallInProgress = ChatGroupCallInProgressEvent
© 2015 - 2024 Weber Informatics LLC | Privacy Policy