Commit b2af394e authored by nk2's avatar nk2 🙃

3-alpha

exception
log
parent 98789886
......@@ -2,5 +2,7 @@
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="GroovyAssignabilityCheck" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SpringJavaInjectionPointsAutowiringInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SpringKotlinAutowiring" enabled="false" level="ERROR" enabled_by_default="false" />
</profile>
</component>
\ No newline at end of file
......@@ -5,6 +5,7 @@
<configuration>
<fileset id="fileset" name="TelegramBotImpl" removed="false">
<file>file://$MODULE_DIR$/../../src/main/kotlin/ga/nk2ishere/dev/runtime/config/TelegramBotImpl.kt</file>
<file>file://$MODULE_DIR$/../../src/main/kotlin/ga/nk2ishere/dev/bot/BotCommunicatorImpl.kt</file>
</fileset>
</configuration>
</facet>
......
This diff is collapsed.
package ga.nk2ishere.dev.bot
import ga.nk2ishere.dev.bot.data.FakeBotSubscriberRepository
import ga.nk2ishere.dev.bot.data.Message
import ga.nk2ishere.dev.bot.data.Subscriber
import ga.nk2ishere.dev.bot.interfaces.BotCommunicator
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
@ConditionalOnBean(BotSubscriberRepositoryStarter::class, BotControllerStarter::class)
class BotCommunicatorImpl: BotCommunicator {
private val log = LoggerFactory.getLogger(this.javaClass)
@Bean fun botCommunicator(): BotCommunicator = BotCommunicatorImpl()
@Autowired private lateinit var botStarter: BotStarter
@Autowired private lateinit var botSubscriberRepositoryStarter: BotSubscriberRepositoryStarter
@Autowired private lateinit var botControllerStarter: BotControllerStarter
@Autowired private lateinit var botExceptionControllerStarter: BotExceptionControllerStarter
@Autowired private lateinit var botNoCommandCheckerStarter: BotNoCommandCheckerStarter
private fun handleException(commandName: String, exception: Exception, subscriber: Subscriber, message: Message) {
log.error("Error ${exception.cause} while trying to invoke $commandName")
botExceptionControllerStarter.botControllerMap.asSequence().firstOrNull { exception.cause!!.javaClass.toString() == it.key.toString() }?.let {
log.error("Passing ${exception.cause} to ${it.value.first}")
sendMessage(subscriber, it.value.second.invoke(it.value.first, subscriber, message) as Message)
} ?: return
}
override fun onMessageReceived(subscriber: Subscriber, message: Message) {
log.info("Got message from: $subscriber $message")
botControllerStarter.botControllerMap.filter { it.value.third(message) }.also {
if(it.isEmpty())
botNoCommandCheckerStarter.handleNoCommandMessage(subscriber, message)
}.forEach {
log.info("Passed message to ${it.key}")
try {
sendMessage(subscriber, it.value.second.invoke(it.value.first, subscriber, message) as Message)
} catch (exception: Exception) {
handleException(it.key, exception, subscriber, message)
}
}
}
override fun sendMessage(subscriber: Subscriber, message: Message) {
botStarter.botImplMap.forEach {
it.value.sendMessage(subscriber, message)
}
}
override fun getSubcriberRepository() = botSubscriberRepositoryStarter.botSubscriberRepository ?: FakeBotSubscriberRepository()
}
\ No newline at end of file
......@@ -15,11 +15,8 @@ import java.util.HashMap
@Component
class BotControllerStarter: BeanPostProcessor {
@Autowired lateinit var botStarter: BotStarter
private val log = LoggerFactory.getLogger(this.javaClass)
private val checkerBaseClass = { msg: Message -> true }.javaClass
private val botControllerMap = HashMap<String, Triple<Any, Method, (Message) -> Boolean>>()
val botControllerMap = HashMap<String, Triple<Any, Method, (Message) -> Boolean>>()
override fun postProcessBeforeInitialization(bean: Any, name: String): Any? {
if(bean.javaClass.isAnnotationPresent(BotController::class.java)) {
val checkerList = bean.javaClass.declaredFields.filter { it.isAnnotationPresent(BotMethodChecker::class.java) }
......@@ -27,17 +24,6 @@ class BotControllerStarter: BeanPostProcessor {
val checker = checkerList.firstOrNull { it.getAnnotation(BotMethodChecker::class.java).id == method.getAnnotation(BotMethod::class.java).checker }
checker?.isAccessible = true
// //Fucking up jabba's security, cuz why not
// checker?.let {
// it.isAccessible = true
// val modifiersField = Field::class.java.getDeclaredField("modifiers")
// AccessController.doPrivileged<Any>(PrivilegedAction<Any> {
// modifiersField.isAccessible = true
// null
// })
// modifiersField.setInt(it, it.modifiers and Modifier.FINAL.inv())
// }
when {
method.parameterCount != 2 -> throw BotException("Method ${method.name} must have 2 parameters")
!method.parameters.any { it.type == Message::class.java } -> throw BotException("Method ${method.name} must have parameter Message")
......@@ -51,12 +37,4 @@ class BotControllerStarter: BeanPostProcessor {
}
return bean
}
fun handleMessage(subscriber: Subscriber, message: Message) {
log.info("Got message from: $subscriber $message")
botControllerMap.forEach { if(it.value.third(message)) {
log.info("Passed message to ${it.key}")
botStarter.sendMessage(subscriber, it.value.second.invoke(it.value.first, subscriber, message) as Message)
} }
}
}
\ No newline at end of file
package ga.nk2ishere.dev.bot
import ga.nk2ishere.dev.bot.annotations.*
import ga.nk2ishere.dev.bot.data.Message
import ga.nk2ishere.dev.bot.data.Subscriber
import org.springframework.beans.factory.config.BeanPostProcessor
import org.springframework.stereotype.Component
import java.lang.reflect.Method
import java.util.HashMap
import kotlin.reflect.KClass
@Component
class BotExceptionControllerStarter: BeanPostProcessor {
val botControllerMap = HashMap<KClass<*>, Pair<Any, Method>>()
override fun postProcessBeforeInitialization(bean: Any, name: String): Any? {
if(bean.javaClass.isAnnotationPresent(BotExceptionController::class.java)) {
bean.javaClass.declaredMethods.filter { it.isAnnotationPresent(BotExceptionMethod::class.java) }.forEach { method ->
when {
method.parameterCount != 2 -> throw BotException("Method ${method.name} must have 2 parameters")
!method.parameters.any { it.type == Message::class.java } -> throw BotException("Method ${method.name} must have parameter Message")
!method.parameters.any { it.type == Subscriber::class.java } -> throw BotException("Method ${method.name} must have parameter Subscriber")
method.returnType != Message::class.java -> throw BotException("Method ${method.name} must return Message")
else -> botControllerMap[method.getAnnotation(BotExceptionMethod::class.java).value] = bean to method
}
}
}
return bean
}
}
\ No newline at end of file
package ga.nk2ishere.dev.bot
import ga.nk2ishere.dev.bot.annotations.BotNoCommandCheckerImpl
import ga.nk2ishere.dev.bot.annotations.BotSubscriberRepositoryImpl
import ga.nk2ishere.dev.bot.data.FakeBotNoCommandChecker
import ga.nk2ishere.dev.bot.data.Message
import ga.nk2ishere.dev.bot.data.Subscriber
import ga.nk2ishere.dev.bot.interfaces.BotNoCommandChecker
import ga.nk2ishere.dev.bot.interfaces.BotSubscriberRepository
import org.springframework.beans.factory.config.BeanPostProcessor
import org.springframework.stereotype.Component
@Component
class BotNoCommandCheckerStarter: BeanPostProcessor {
private val defaultBotNoCommandChecker = FakeBotNoCommandChecker()
private var botNoCommandChecker: BotNoCommandChecker? = null
fun handleNoCommandMessage(subscriber: Subscriber, message: Message) = botNoCommandChecker?.onNoCommand(subscriber, message)
?: defaultBotNoCommandChecker.onNoCommand(subscriber, message)
override fun postProcessBeforeInitialization(bean: Any, beanName: String): Any? {
if(bean.javaClass.isAnnotationPresent(BotNoCommandCheckerImpl::class.java))
if(botNoCommandChecker == null) {
when(bean) {
is BotNoCommandChecker -> botNoCommandChecker = bean
else -> throw BotException("Annotated BotNoCommandCheckerImpl class ${bean.javaClass.simpleName} must implement BotNoCommandChecker")
}
} else throw BotException("Only one class can be BotNoCommandCheckerImpl, current: ${bean.javaClass.simpleName}, used: ${botNoCommandChecker?.javaClass?.simpleName}")
return bean
}
}
\ No newline at end of file
......@@ -13,20 +13,12 @@ import java.util.HashMap
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.superclasses
//TODO exception handler
//TODO no command handler
//TODO filter for bot type in subscriber
//TODO abstraction layer for BotStarter
//TODO config handling
@Component
@ConditionalOnBean(BotSubscriberRepositoryStarter::class, BotControllerStarter::class)
class BotStarter: BeanPostProcessor {
@Autowired lateinit var botSubscriberRepositoryStarter: BotSubscriberRepositoryStarter
@Autowired lateinit var botControllerStarter: BotControllerStarter
private val botImplMap = HashMap<String, Bot>()
val botImplMap = HashMap<String, Bot>()
override fun postProcessBeforeInitialization(bean: Any, name: String): Any? {
if(bean.javaClass.superclass.isAnnotationPresent(BotImpl::class.java))
when(bean) {
......@@ -38,8 +30,4 @@ class BotStarter: BeanPostProcessor {
}
return bean
}
fun onMessageReceived(subscriber: Subscriber, message: Message) = botControllerStarter.handleMessage(subscriber, message)
fun sendMessage(subscriber: Subscriber, message: Message) = botImplMap.forEach { it.value.sendMessage(subscriber, message) }
fun getSubcriberRepository() = botSubscriberRepositoryStarter.botSubscriberRepository ?: FakeBotSubscriberRepository()
}
package ga.nk2ishere.dev.bot.annotations
import kotlin.reflect.KClass
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class BotExceptionController
\ No newline at end of file
package ga.nk2ishere.dev.bot.annotations
import kotlin.reflect.KClass
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class BotExceptionMethod(
val value: KClass<*>
)
\ No newline at end of file
package ga.nk2ishere.dev.bot.annotations
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class BotNoCommandCheckerImpl
\ No newline at end of file
package ga.nk2ishere.dev.bot.data
import ga.nk2ishere.dev.bot.interfaces.BotNoCommandChecker
import org.slf4j.LoggerFactory
class FakeBotNoCommandChecker: BotNoCommandChecker {
private val log = LoggerFactory.getLogger(javaClass)
override fun onNoCommand(subscriber: Subscriber, message: Message): Message {
log.info("No command like $message found")
return Message()
}
}
\ No newline at end of file
......@@ -22,4 +22,12 @@ fun Message.hasTextFull(text: String): Boolean = this.getItems()
fun Message.hasText(text: String): Boolean = this.getItems()
.filter { it is MessageText }
.find { (it as MessageText).text.contains(text) } != null
\ No newline at end of file
.find { (it as MessageText).text.contains(text) } != null
fun Message.matchesRegex(regex: Regex): Boolean = this.getItems()
.filter { it is MessageText }
.find { (it as MessageText).text.matches(regex) } != null
fun Message.containsRegex(regex: Regex): Boolean = this.getItems()
.filter { it is MessageText }
.find { (it as MessageText).text.contains(regex) } != null
\ No newline at end of file
package ga.nk2ishere.dev.bot.interfaces
import ga.nk2ishere.dev.bot.data.Message
import ga.nk2ishere.dev.bot.data.Subscriber
interface BotCommunicator {
fun onMessageReceived(subscriber: Subscriber, message: Message)
fun sendMessage(subscriber: Subscriber, message: Message)
fun getSubcriberRepository(): BotSubscriberRepository
}
\ No newline at end of file
package ga.nk2ishere.dev.bot.interfaces
import ga.nk2ishere.dev.bot.data.Message
import ga.nk2ishere.dev.bot.data.Subscriber
interface BotNoCommandChecker {
fun onNoCommand(subscriber: Subscriber, message: Message): Message
}
\ No newline at end of file
package ga.nk2ishere.dev.runtime.bot
import ga.nk2ishere.dev.bot.annotations.BotExceptionController
import ga.nk2ishere.dev.bot.annotations.BotExceptionMethod
import ga.nk2ishere.dev.bot.data.Message
import ga.nk2ishere.dev.bot.data.Subscriber
import org.springframework.stereotype.Component
@Component
@BotExceptionController
class ExceptionUseCase {
@BotExceptionMethod(NullPointerException::class)
fun handleNullPointerException(subscriber: Subscriber, message: Message) =
Message().apply { addText("Uh oh! Something bad happened") }
}
\ No newline at end of file
package ga.nk2ishere.dev.runtime.bot
import ga.nk2ishere.dev.bot.annotations.BotNoCommandCheckerImpl
import ga.nk2ishere.dev.bot.data.Message
import ga.nk2ishere.dev.bot.data.Subscriber
import ga.nk2ishere.dev.bot.interfaces.BotNoCommandChecker
@BotNoCommandCheckerImpl
class NoCommandUseCase: BotNoCommandChecker {
override fun onNoCommand(subscriber: Subscriber, message: Message): Message =
Message().apply { addText("Oh! There's no command found like that") }
}
\ No newline at end of file
......@@ -7,6 +7,7 @@ import ga.nk2ishere.dev.bot.data.MessageImage
import ga.nk2ishere.dev.bot.data.MessageText
import ga.nk2ishere.dev.bot.data.Subscriber
import ga.nk2ishere.dev.bot.interfaces.Bot
import ga.nk2ishere.dev.bot.interfaces.BotCommunicator
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
......@@ -26,7 +27,7 @@ import org.telegram.telegrambots.TelegramBotsApi
@PropertySource("classpath:telegram.properties")
@BotImpl
class TelegramBotImpl: TelegramLongPollingBot(), Bot {
@Autowired private lateinit var botStarter: BotStarter
@Autowired private lateinit var botCommunicator: BotCommunicator
@Autowired private lateinit var telegramBotImpl: TelegramBotImpl
val log = LoggerFactory.getLogger(this.javaClass)
......@@ -60,8 +61,8 @@ class TelegramBotImpl: TelegramLongPollingBot(), Bot {
override fun onUpdateReceived(update: Update?) {
update?.let {
botStarter.onMessageReceived(
botStarter.getSubcriberRepository().get(update.message.chatId)
botCommunicator.onMessageReceived(
botCommunicator.getSubcriberRepository().get(update.message.chatId)
?: Subscriber(update.message.chatId, update.message.from.userName),
Message().apply { this.addText(it.message.text) }
)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment