Compare commits
5 Commits
master
...
feature/te
| Author | SHA1 | Date |
|---|---|---|
|
|
b507a92de0 | |
|
|
d9d98dceb8 | |
|
|
02e0df53a3 | |
|
|
d05e4fe4c5 | |
|
|
2282514dc7 |
|
|
@ -19,12 +19,12 @@ object StringUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
nextUpperCase -> {
|
nextUpperCase -> {
|
||||||
this.append(char.toUpperCase())
|
this.append(char.uppercase())
|
||||||
nextUpperCase = false
|
nextUpperCase = false
|
||||||
}
|
}
|
||||||
|
|
||||||
!nextUpperCase -> {
|
else -> {
|
||||||
this.append(char.toLowerCase())
|
this.append(char.lowercase())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -34,8 +34,8 @@ object StringUtils {
|
||||||
fun String.removeNonPrintableCharacters(): String {
|
fun String.removeNonPrintableCharacters(): String {
|
||||||
return this
|
return this
|
||||||
.transliterateCyrillic()
|
.transliterateCyrillic()
|
||||||
.replace("[\\p{Cntrl}&&[^\r\n\t]]".toRegex(), "")// erases all the ASCII control characters
|
.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{C}".toRegex(), "") // removes non-printable characters from Unicode
|
||||||
.trim()
|
.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,3 +61,4 @@ include("server-info-spring-web")
|
||||||
include("geoip-core")
|
include("geoip-core")
|
||||||
include("user-agent")
|
include("user-agent")
|
||||||
include("smart-migration")
|
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