Compare commits
5 Commits
master
...
feature/te
| Author | SHA1 | Date |
|---|---|---|
|
|
b507a92de0 | |
|
|
d9d98dceb8 | |
|
|
02e0df53a3 | |
|
|
d05e4fe4c5 | |
|
|
2282514dc7 |
|
|
@ -19,12 +19,12 @@ object StringUtils {
|
|||
}
|
||||
|
||||
nextUpperCase -> {
|
||||
this.append(char.toUpperCase())
|
||||
this.append(char.uppercase())
|
||||
nextUpperCase = false
|
||||
}
|
||||
|
||||
!nextUpperCase -> {
|
||||
this.append(char.toLowerCase())
|
||||
else -> {
|
||||
this.append(char.lowercase())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,8 +34,8 @@ object StringUtils {
|
|||
fun String.removeNonPrintableCharacters(): String {
|
||||
return this
|
||||
.transliterateCyrillic()
|
||||
.replace("[\\p{Cntrl}&&[^\r\n\t]]".toRegex(), "")// erases all the ASCII control characters
|
||||
.replace("\\p{C}".toRegex(), "")// removes non-printable characters from Unicode
|
||||
.replace("\\p{Cntrl}&&[^\r\n\t]".toRegex(), "") // erases all the ASCII control characters
|
||||
.replace("\\p{C}".toRegex(), "") // removes non-printable characters from Unicode
|
||||
.trim()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,3 +61,4 @@ include("server-info-spring-web")
|
|||
include("geoip-core")
|
||||
include("user-agent")
|
||||
include("smart-migration")
|
||||
include("telegram-bot-spring")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
HELP.md
|
||||
.gradle
|
||||
build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
## Библиотека написания телеграмм-ботов
|
||||
|
||||
```kotlin
|
||||
@Component
|
||||
class MyTelegramBot(
|
||||
private val messageHandlers: List<MessageHandler>,
|
||||
) : TelegramLongPollingBot() {
|
||||
|
||||
override fun onUpdateReceived(update: Update?) {
|
||||
// create MessageContext
|
||||
// messageHandlers.takeWhile { it.process(ctx, this) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
class HelloMessageHandler: AbstractMessageHandler {
|
||||
|
||||
override fun isSupported(ctx: MessageContext): Booleat {
|
||||
ctx.messageCommand.message.equals("hi")
|
||||
}
|
||||
|
||||
override fun process(ctx: MessageContext, sender: AbsSender): Boolean {
|
||||
val message = SendMessage().apply {
|
||||
this.chatId = ctx.chatId
|
||||
this.text = "Hello"
|
||||
}
|
||||
|
||||
sender.execute(message)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
plugins {
|
||||
id 'kotlin'
|
||||
id 'kotlin-spring'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api 'org.telegram:telegrambots-spring-boot-starter:6.3.0'
|
||||
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind'
|
||||
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
|
||||
implementation 'org.springframework.boot:spring-boot'
|
||||
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin")
|
||||
testImplementation("org.mockito:mockito-inline")
|
||||
testImplementation 'junit:junit'
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package ru.touchin.spring.telegram.bot
|
||||
|
||||
import org.springframework.context.annotation.Import
|
||||
|
||||
@Import(value = [TelegramBotConfiguration::class])
|
||||
annotation class EnableSpringTelegramBot
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package ru.touchin.spring.telegram.bot
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.context.annotation.ComponentScan
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
@ConfigurationPropertiesScan
|
||||
@ComponentScan
|
||||
class TelegramBotConfiguration
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package ru.touchin.spring.telegram.bot.messages
|
||||
|
||||
import org.telegram.telegrambots.meta.bots.AbsSender
|
||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageContext
|
||||
|
||||
abstract class AbstractMessageHandler<C: MessageContext<U, S>, U, S>:
|
||||
MessageHandler<C, U, S>,
|
||||
MessageFilter<C, U, S>,
|
||||
HelpMessage
|
||||
{
|
||||
|
||||
override fun process(context: C, sender: AbsSender): Boolean {
|
||||
if (!isSupported(context)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return internalProcess(context, sender)
|
||||
}
|
||||
|
||||
abstract fun internalProcess(context: C, sender: AbsSender): Boolean
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package ru.touchin.spring.telegram.bot.messages
|
||||
|
||||
interface HelpMessage {
|
||||
|
||||
fun helpMessage(): String? = null
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package ru.touchin.spring.telegram.bot.messages
|
||||
|
||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageContext
|
||||
|
||||
interface MessageFilter<C: MessageContext<U, S>, U, S> {
|
||||
|
||||
fun isSupported(context: C): Boolean
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package ru.touchin.spring.telegram.bot.messages
|
||||
|
||||
import org.telegram.telegrambots.meta.bots.AbsSender
|
||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageContext
|
||||
|
||||
interface MessageHandler<C: MessageContext<U, S>, U, S> {
|
||||
|
||||
fun process(context: C, sender: AbsSender): Boolean
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package ru.touchin.spring.telegram.bot.messages
|
||||
|
||||
@Suppress("unused")
|
||||
object Order {
|
||||
const val HIGH_PRIORITY = 1024
|
||||
const val NORMAL_PRIORITY = 2048
|
||||
const val LOW_PRIORITY = 3072
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package ru.touchin.spring.telegram.bot.messages.dto
|
||||
|
||||
data class MessageCommand(
|
||||
val command: String,
|
||||
val message: String
|
||||
) {
|
||||
|
||||
fun hasCommand() = command != NO_COMMAND
|
||||
|
||||
companion object {
|
||||
private const val NO_COMMAND = ""
|
||||
|
||||
fun createNoCommandMessage(message: String) = MessageCommand(
|
||||
command = NO_COMMAND,
|
||||
message = message
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package ru.touchin.spring.telegram.bot.messages.dto
|
||||
|
||||
import org.telegram.telegrambots.meta.api.objects.Update
|
||||
|
||||
open class MessageContext<U, S>(
|
||||
val origin: Update,
|
||||
val user: U,
|
||||
val messageCommand: MessageCommand,
|
||||
val state: S
|
||||
) {
|
||||
|
||||
fun hasCommand(command: String) = messageCommand.command == command
|
||||
|
||||
val chatId: String
|
||||
get() = origin.message?.chatId?.toString()
|
||||
?: origin.callbackQuery.message.chatId.toString()
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package ru.touchin.spring.telegram.bot.messages.services
|
||||
|
||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageCommand
|
||||
|
||||
interface TelegramMessageCommandResolver {
|
||||
|
||||
fun resolve(rawMessage: String): MessageCommand
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package ru.touchin.spring.telegram.bot.messages.services.impl
|
||||
|
||||
import org.springframework.stereotype.Service
|
||||
import ru.touchin.spring.telegram.bot.messages.dto.MessageCommand
|
||||
import ru.touchin.spring.telegram.bot.messages.services.TelegramMessageCommandResolver
|
||||
|
||||
@Service
|
||||
class TelegramMessageCommandResolverImpl : TelegramMessageCommandResolver {
|
||||
|
||||
override fun resolve(rawMessage: String): MessageCommand {
|
||||
val message = rawMessage.trim()
|
||||
|
||||
if (message.isBlank() || !message.startsWith("/")) {
|
||||
return MessageCommand.createNoCommandMessage(rawMessage)
|
||||
}
|
||||
|
||||
return MessageCommand(
|
||||
command = message.substringBefore(' ').trim().lowercase(),
|
||||
message = message.substringAfter(' ', missingDelimiterValue = "")
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package ru.touchin.spring.telegram.bot
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
|
||||
@SpringBootApplication
|
||||
open class TestApplication
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package ru.touchin.spring.telegram.bot.messages.services.impl
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
import ru.touchin.spring.telegram.bot.messages.services.TelegramMessageCommandResolver
|
||||
|
||||
@ActiveProfiles("test")
|
||||
@SpringBootTest
|
||||
internal class TelegramMessageCommandResolverImplTest {
|
||||
|
||||
@Autowired
|
||||
private lateinit var telegramMessageCommandResolver: TelegramMessageCommandResolver
|
||||
|
||||
@Test
|
||||
fun shouldBeEmptyCommand() {
|
||||
telegramMessageCommandResolver.resolve("hello").also {
|
||||
assertFalse(it.hasCommand())
|
||||
assertEquals("hello", it.message)
|
||||
}
|
||||
|
||||
telegramMessageCommandResolver.resolve("").also {
|
||||
assertFalse(it.hasCommand())
|
||||
assertEquals("", it.message)
|
||||
}
|
||||
|
||||
telegramMessageCommandResolver.resolve(" ").also {
|
||||
assertFalse(it.hasCommand())
|
||||
assertEquals(" ", it.message)
|
||||
}
|
||||
|
||||
telegramMessageCommandResolver.resolve("hello world").also {
|
||||
assertFalse(it.hasCommand())
|
||||
assertEquals("hello world", it.message)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldResolveCommand() {
|
||||
telegramMessageCommandResolver.resolve("/hello").also {
|
||||
assertTrue(it.hasCommand())
|
||||
assertEquals("/hello", it.command)
|
||||
assertEquals("", it.message)
|
||||
}
|
||||
|
||||
telegramMessageCommandResolver.resolve("/hello world").also {
|
||||
assertTrue(it.hasCommand())
|
||||
assertEquals("/hello", it.command)
|
||||
assertEquals("world", it.message)
|
||||
}
|
||||
|
||||
telegramMessageCommandResolver.resolve("/hello /world").also {
|
||||
assertTrue(it.hasCommand())
|
||||
assertEquals("/hello", it.command)
|
||||
assertEquals("/world", it.message)
|
||||
}
|
||||
|
||||
telegramMessageCommandResolver.resolve(" /hello /world").also {
|
||||
assertTrue(it.hasCommand())
|
||||
assertEquals("/hello", it.command)
|
||||
assertEquals(" /world", it.message)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue