Skip to content

Commit

Permalink
refactored jpa-sources
Browse files Browse the repository at this point in the history
  • Loading branch information
DEHuckaKpyT committed Jun 28, 2024
1 parent 21f8b53 commit e78e456
Show file tree
Hide file tree
Showing 44 changed files with 363 additions and 290 deletions.
2 changes: 1 addition & 1 deletion Writerside/topics/exposed.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Then add the dependency and specify the sources:
```Gradle
dependencies {
implementation("io.github.dehuckakpyt.telegrambot:telegram-bot-core:%current_version%")
implementation("io.github.dehuckakpyt.telegrambot:telegram-bot-database-source:%current_version%")
implementation("io.github.dehuckakpyt.telegrambot:telegram-bot-source-exposed:%current_version%")
}
```
```kotlin
Expand Down
18 changes: 18 additions & 0 deletions Writerside/topics/sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,21 @@ val config = TelegramBotConfig().apply {
```

How to **save state in database** see <a href="database-integration.md">here</a>.

## Spring only

You can create beans as `ConfigExpression<..Source>` also:

```kotlin
@Bean
fun telegramMessageSourceExpression(): ConfigExpression<MessageSource> =
ConfigExpression { CustomTelegramMessageSource() }

@Bean
fun chainSourceExpression(): ConfigExpression<ChainSource> =
ConfigExpression { CustomChainSource() }

@Bean
fun callbackContentSourceExpression(): ConfigExpression<CallbackContentSource> =
ConfigExpression { CustomCallbackContentSource() }
```
60 changes: 9 additions & 51 deletions Writerside/topics/spring-jpa.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@

## Save all states in database

<procedure>
<step>Add dependency <code>telegram-bot-source-jpa</code>.</step>
<step>Add repositories to <code>@EnableJpaRepositories</code> and entities to <code>@EntityScan</code>.</step>
<step>Change all sources in configuration.</step>
</procedure>

All you have to do is add a dependency for `source-jpa`:
<tabs>
<tab title="Spring 3.0">
<code-block lang="kotlin">
Expand All @@ -29,49 +24,12 @@ dependencies {
</tab>
</tabs>

```kotlin
@EnableTelegramBot
@EnableJpaRepositories(basePackages = ["io.github.dehuckakpyt.telegrambot.repository"])
@EntityScan(basePackages = ["io.github.dehuckakpyt.telegrambot.model"])
@Configuration
class BotConfig {
@Bean
fun telegramBotConfig(): TelegramBotConfig = TelegramBotConfig().apply {
messageSource = { MessageSource.inDatabase }
receiving {
callbackContentSource = { CallbackContentSource.inDatabase }
chainSource = { ChainSource.inDatabase }
}
}
}
```

## Use only certain sources

You can also use only selected resources.

For example, how to save in database only callbacks:

```kotlin
@EnableTelegramBot
@EnableJpaRepositories(basePackages = ["io.github.dehuckakpyt.telegrambot.repository.callback"])
@EntityScan(basePackages = ["io.github.dehuckakpyt.telegrambot.model.callback"])
@Configuration
class BotConfig {
@Bean
fun telegramBotConfig(): TelegramBotConfig = TelegramBotConfig().apply {
receiving {
callbackContentSource = { CallbackContentSource.inDatabase }
}
}
}
```
## Available properties

<chapter title="Package names by source" collapsible="true">
<table style="both">
<tr><td>Source name</td><td>Repository package</td><td>Entity package</td></tr>
<tr><td>messageSource</td><td>io.github.dehuckakpyt.telegrambot.repository.message</td><td>io.github.dehuckakpyt.telegrambot.model.message</td></tr>
<tr><td>callbackContentSource</td><td>io.github.dehuckakpyt.telegrambot.repository.callback</td><td>io.github.dehuckakpyt.telegrambot.model.callback</td></tr>
<tr><td>chainSource</td><td>io.github.dehuckakpyt.telegrambot.repository.chain</td><td>io.github.dehuckakpyt.telegrambot.model.chain</td></tr>
</table>
</chapter>
| PROPERTY | DEFAULT | DESCRIPTION |
|------------------------------------------------------------|---------|----------------------------------------------------------------------|
| `telegram-bot.source-jpa.enabled` | `true` | Disable all default sources |
| `telegram-bot.source-jpa.message-source.enabled` | `true` | Disable default message source |
| `telegram-bot.source-jpa.chain-source.enabled` | `true` | Disable default chain source |
| `telegram-bot.source-jpa.callback-content-source.enabled` | `true` | Disable default callback content source |
| `telegram-bot.source-jpa.callback-content-source.per-user` | `20` | Max count of contents will be saved for every user (`-1` for ignore) |
2 changes: 2 additions & 0 deletions Writerside/topics/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
- Add webhook.
- Complete documentation in code (classes and methods).
- Add to documentation info about `currentContainerContext()`, `InputFactory`.
- Create custom `@ConditionalOnMissingBean` for `source-jpa` `io.github.dehuckakpyt.telegrambot.config`
- Add `ConfigExpression` for all interfaces in TelegramBotConfig (at least for Spring)

## Low priority
- Figure out how to send messages longer than 4096 characters.
Expand Down
2 changes: 1 addition & 1 deletion Writerside/v.list
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE vars SYSTEM "https://resources.jetbrains.com/writerside/1.0/vars.dtd">
<vars>
<var name="current_version" value="0.9.2a"/>
<var name="current_version" value="0.9.3"/>
</vars>
2 changes: 1 addition & 1 deletion Writerside/writerside.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
<ihp version="2.0">
<topics dir="topics" web-path="topics"/>
<images dir="images" web-path="telegram-bot"/>
<instance src="ktb.tree" web-path="/ktb/" version="0.9.2a"/>
<instance src="ktb.tree" web-path="/ktb/" version="0.9.3"/>
</ihp>
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ plugins {

allprojects {
group = "io.github.dehuckakpyt.telegrambot"
version = "0.9.2a"
version = "0.9.3"
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,12 @@ package io.github.dehuckakpyt.telegrambotexample.config

import io.github.dehuckakpyt.telegrambot.annotation.EnableTelegramBot
import io.github.dehuckakpyt.telegrambot.config.TelegramBotConfig
import io.github.dehuckakpyt.telegrambot.config.inDatabase
import io.github.dehuckakpyt.telegrambot.ext.strategy.invocation.fullSync
import io.github.dehuckakpyt.telegrambot.source.callback.CallbackContentSource
import io.github.dehuckakpyt.telegrambot.source.chain.ChainSource
import io.github.dehuckakpyt.telegrambot.source.message.MessageSource
import io.github.dehuckakpyt.telegrambot.strategy.invocation.HandlerInvocationStrategy
import io.github.dehuckakpyt.telegrambotexample.exception.CustomExceptionHandler
import io.github.dehuckakpyt.telegrambotexample.handler.*
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.jpa.repository.config.EnableJpaRepositories


/**
Expand All @@ -23,22 +17,12 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories
* @author Denis Matytsin
*/
@EnableTelegramBot
@EnableJpaRepositories(basePackages = ["io.github.dehuckakpyt.telegrambot.repository"])
@EntityScan(basePackages = ["io.github.dehuckakpyt.telegrambot.model"])
@Configuration
class BotConfig {

@Bean
fun telegramBotConfig(): TelegramBotConfig = TelegramBotConfig().apply {
messageSource = { MessageSource.inDatabase }

receiving {
callbackContentSource = {
CallbackContentSource.inDatabase(
maxCallbackContentsPerUser = 2
)
}
chainSource = { ChainSource.inDatabase }
invocationStrategy = { HandlerInvocationStrategy.fullSync }
exceptionHandler = { CustomExceptionHandler(telegramBot, receiving.messageTemplate, templating.templater) }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import io.github.dehuckakpyt.telegrambot.source.message.MessageSource
*
* IMPORTANT: Values in ...ActualConfig are filling in strict order.
* It means that you can`t use instance from config, which is not yet initialized.
* Limitation due to the fact that no DI is used (like Spring or Koin).
* Limitation due to the fact that no DI is used.
*
* Order of instances:
* - TelegramBotActualConfig.token
Expand Down Expand Up @@ -42,16 +42,16 @@ class TelegramBotConfig(
/** Source for saving messages */
var messageSource: (TelegramBotActualConfig.() -> MessageSource)? = null,
) {
internal var templating: TelegramBotTemplatingConfig.() -> Unit = {}
internal var receiving: UpdateReceiverConfig.() -> Unit = {}
var templating: TelegramBotTemplatingConfig = TelegramBotTemplatingConfig()
var receiving: UpdateReceiverConfig = UpdateReceiverConfig()

/** Configure templating */
fun templating(block: TelegramBotTemplatingConfig.() -> Unit) {
templating = block
templating.apply(block)
}

/** Configure receiving */
fun receiving(block: UpdateReceiverConfig.() -> Unit) {
receiving = block
receiving.apply(block)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import io.github.dehuckakpyt.telegrambot.config.TelegramBotActualConfigImpl
import io.github.dehuckakpyt.telegrambot.config.TelegramBotConfig
import io.github.dehuckakpyt.telegrambot.config.receiver.LongPollingConfig
import io.github.dehuckakpyt.telegrambot.config.receiver.TelegramBotReceiverActualConfigImpl
import io.github.dehuckakpyt.telegrambot.config.receiver.UpdateReceiverConfig
import io.github.dehuckakpyt.telegrambot.config.template.TelegramBotTemplatingActualConfigImpl
import io.github.dehuckakpyt.telegrambot.config.template.TelegramBotTemplatingConfig
import io.github.dehuckakpyt.telegrambot.container.message.factory.*
import io.github.dehuckakpyt.telegrambot.context.TelegramBotContext
import io.github.dehuckakpyt.telegrambot.context.TelegramBotContextImpl
Expand Down Expand Up @@ -86,9 +84,7 @@ object TelegramBotFactory {
return context
}

private fun buildTemplating(config: TelegramBotConfig, actual: TelegramBotActualConfigImpl, context: TelegramBotContextImpl) = with(TelegramBotTemplatingConfig()) {
config.templating.invoke(this)

private fun buildTemplating(config: TelegramBotConfig, actual: TelegramBotActualConfigImpl, context: TelegramBotContextImpl) = with(config.templating) {
val actualTemplating = TelegramBotTemplatingActualConfigImpl()
actual.templating = actualTemplating
actualTemplating.htmlFormatter = htmlFormatter?.invoke(actual) ?: HtmlFormatterImpl()
Expand All @@ -97,9 +93,7 @@ object TelegramBotFactory {
context.templater = actualTemplating.templater
}

private fun buildReceiving(config: TelegramBotConfig, actual: TelegramBotActualConfigImpl, context: TelegramBotContextImpl) = with(UpdateReceiverConfig()) {
config.receiving.invoke(this)

private fun buildReceiving(config: TelegramBotConfig, actual: TelegramBotActualConfigImpl, context: TelegramBotContextImpl) = with(config.receiving) {
val actualReceiving = TelegramBotReceiverActualConfigImpl()
actual.receiving = actualReceiving
actualReceiving.messageTemplate = messageTemplate?.invoke(actual) ?: MessageTemplate()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.github.dehuckakpyt.telegrambot.config

import io.github.dehuckakpyt.telegrambot.config.constant.PropertiesConstant.TELEGRAM_BOT_SOURCE_JPA
import io.github.dehuckakpyt.telegrambot.config.constant.PropertiesConstant.TELEGRAM_BOT_SOURCE_JPA_CALLBACK_CONTENT_SOURCE
import io.github.dehuckakpyt.telegrambot.config.constant.PropertiesConstant.TELEGRAM_BOT_SOURCE_JPA_CALLBACK_CONTENT_SOURCE_PER_USER
import io.github.dehuckakpyt.telegrambot.config.expression.ConfigExpression
import io.github.dehuckakpyt.telegrambot.repository.callback.JpaCallbackContentRepository
import io.github.dehuckakpyt.telegrambot.source.callback.CallbackContentSource
import io.github.dehuckakpyt.telegrambot.source.callback.JpaCallbackContentSource
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.context.annotation.Bean
import org.springframework.data.jpa.repository.config.EnableJpaRepositories


/**
* Created on 22.06.2024.
*
* @author Denis Matytsin
*/
@EntityScan(basePackages = ["io.github.dehuckakpyt.telegrambot.model.callback"])
@EnableJpaRepositories(basePackages = ["io.github.dehuckakpyt.telegrambot.repository.callback"])
@ConditionalOnProperty(name = [TELEGRAM_BOT_SOURCE_JPA, TELEGRAM_BOT_SOURCE_JPA_CALLBACK_CONTENT_SOURCE], havingValue = "true", matchIfMissing = true)
class CallbackContentSourceInitializationConfig {

@Bean
//TODO create custom @ConditionalOnMissingBean
@ConditionalOnMissingBean(name = ["callbackContentSourceExpression"], parameterizedContainer = [ConfigExpression::class])
@ConditionalOnProperty(TELEGRAM_BOT_SOURCE_JPA_CALLBACK_CONTENT_SOURCE, havingValue = "true", matchIfMissing = true)
fun callbackContentSourceExpression(
repository: JpaCallbackContentRepository,
@Value("\${$TELEGRAM_BOT_SOURCE_JPA_CALLBACK_CONTENT_SOURCE_PER_USER}") perUser: Long,
): ConfigExpression<CallbackContentSource> = ConfigExpression { JpaCallbackContentSource(repository, maxCallbackContentsPerUser = perUser) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.github.dehuckakpyt.telegrambot.config

import io.github.dehuckakpyt.telegrambot.config.constant.PropertiesConstant.TELEGRAM_BOT_SOURCE_JPA
import io.github.dehuckakpyt.telegrambot.config.constant.PropertiesConstant.TELEGRAM_BOT_SOURCE_JPA_CHAIN_SOURCE
import io.github.dehuckakpyt.telegrambot.config.expression.ConfigExpression
import io.github.dehuckakpyt.telegrambot.repository.chain.JpaChainRepository
import io.github.dehuckakpyt.telegrambot.source.chain.ChainSource
import io.github.dehuckakpyt.telegrambot.source.chain.JpaChainSource
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.context.annotation.Bean
import org.springframework.data.jpa.repository.config.EnableJpaRepositories


/**
* Created on 22.06.2024.
*
* @author Denis Matytsin
*/
@EntityScan(basePackages = ["io.github.dehuckakpyt.telegrambot.model.chain"])
@EnableJpaRepositories(basePackages = ["io.github.dehuckakpyt.telegrambot.repository.chain"])
@ConditionalOnProperty(name = [TELEGRAM_BOT_SOURCE_JPA, TELEGRAM_BOT_SOURCE_JPA_CHAIN_SOURCE], havingValue = "true", matchIfMissing = true)
class ChainSourceInitializationConfig {

@Bean
//TODO create custom @ConditionalOnMissingBean
@ConditionalOnMissingBean(name = ["chainSourceExpression"], parameterizedContainer = [ConfigExpression::class])
@ConditionalOnProperty(TELEGRAM_BOT_SOURCE_JPA_CHAIN_SOURCE, havingValue = "true", matchIfMissing = true)
fun chainSourceExpression(repository: JpaChainRepository): ConfigExpression<ChainSource> = ConfigExpression { JpaChainSource(repository) }
}

This file was deleted.

Loading

0 comments on commit e78e456

Please sign in to comment.