Compare commits

..

108 Commits

Author SHA1 Message Date
bd26cbd4d8 small cleanup of updates 2025-12-17 14:24:52 +06:00
8b7ca70d5f update dependencies
org.jetbrains.kotlin:kotlin-stdlib 2.2.20 -> 2.2.21
com.google.devtools.ksp:symbol-processing-gradle-plugin 2.2.20-2.0.4 -> 2.2.21-2.0.4
dev.inmo:micro_utils 0.26.6 -> 0.26.8
dev.inmo:tgbotapi 30.0.0 -> 30.0.2
com.gradleup.nmcp:nmcp-aggregation 1.2.0 -> 1.3.0
2025-12-17 14:22:04 +06:00
e356abc373 start 10.10.0 2025-12-17 14:15:13 +06:00
fdff6c7178 Merge pull request #119 from InsanusMokrassar/10.9.0
10.9.0
2025-10-21 23:13:32 +06:00
636614e4e3 revert sqlite 2025-10-21 23:13:22 +06:00
9747bcd79d update dependencies 2025-10-21 23:12:35 +06:00
f8b7e261f4 start 10.9.0 2025-10-21 23:03:43 +06:00
0a5272b1c8 Merge pull request #118 from InsanusMokrassar/10.8.0
10.8.0
2025-09-04 17:31:52 +06:00
214403ee88 update dependencies 2025-09-04 17:30:46 +06:00
c19a4bbcf9 start 10.8.0 2025-09-04 17:22:51 +06:00
58ba7c1e32 update dependencies 2025-08-04 13:33:02 +06:00
431b1bf1f2 start 10.7.0 2025-08-04 13:19:26 +06:00
ad23cc9202 Update github_release.gradle 2025-06-27 10:03:30 +06:00
e9bf2dfc64 Update github_release.gradle 2025-06-27 09:57:22 +06:00
61ea5e93b3 Merge pull request #115 from InsanusMokrassar/10.6.0
10.6.0
2025-06-27 09:36:26 +06:00
ff0d819bd2 update nmcp config 2025-06-27 09:35:43 +06:00
1919d8840a update dependencies 2025-06-27 09:31:27 +06:00
98c539b198 update publication way 2025-06-16 17:18:37 +06:00
7e02bb3583 start 10.6.0 2025-06-16 17:14:09 +06:00
d6e10d1dd1 Merge pull request #114 from InsanusMokrassar/10.5.0
10.5.0
2025-04-30 13:29:34 +06:00
b30aee0109 update dependencies 2025-04-30 13:26:31 +06:00
be45f94070 start 10.5.0 2025-03-27 08:31:24 +06:00
485d0d1fbf Merge pull request #113 from InsanusMokrassar/10.4.0
10.4.0
2025-02-16 09:22:03 +06:00
69e97223ce update dependencies 2025-02-16 09:21:30 +06:00
f067033678 start 10.4.0 2025-02-16 09:19:24 +06:00
37920521a0 Merge pull request #112 from InsanusMokrassar/10.3.1
10.3.1
2025-01-29 14:29:07 +06:00
d78f8adbea Update CHANGELOG.md 2025-01-29 14:28:55 +06:00
487ce413f1 update dependencies 2025-01-29 12:04:12 +06:00
556ded1e84 start 10.3.1 2025-01-29 12:02:34 +06:00
605fb956a4 Merge pull request #111 from InsanusMokrassar/10.3.0
10.3.0
2024-12-08 15:00:54 +06:00
b907f8d53b update dependencies 2024-12-07 10:10:17 +06:00
2a0cd5d6a8 start 10.3.0 2024-12-07 10:09:23 +06:00
00f3485959 Merge pull request #110 from InsanusMokrassar/10.2.1
10.2.1
2024-12-03 11:30:48 +06:00
856ae65fa8 add support of subcontext initial actions 2024-12-03 11:28:07 +06:00
d9488f8ccd start 10.2.1 2024-12-03 09:18:07 +06:00
2f06a65cc6 Merge pull request #109 from InsanusMokrassar/10.2.0
10.2.0
2024-12-01 12:00:01 +06:00
f3e6b55861 update dependencies 2024-12-01 11:59:02 +06:00
7bdb525f01 start 10.2.0 2024-12-01 11:57:22 +06:00
e6a2add7f8 Merge pull request #108 from InsanusMokrassar/10.1.1
10.1.1
2024-11-11 16:05:46 +06:00
3d7cb28c92 update tgbotapi 2024-11-11 16:02:10 +06:00
81a1ed6613 start 10.1.1 2024-11-11 15:59:14 +06:00
b43efb4255 Merge pull request #107 from InsanusMokrassar/10.1.0
10.1.0
2024-11-04 22:11:56 +06:00
8d3d9f8c6a update dependencies 2024-11-04 22:05:24 +06:00
6cb241642b start 10.1.0 2024-11-04 22:00:01 +06:00
f551f471d9 Merge pull request #106 from InsanusMokrassar/10.0.0
10.0.0
2024-09-22 19:40:02 +06:00
4342e04e3f replace database extension into externded file 2024-09-22 19:39:45 +06:00
a7fe1e3d82 improve registerConfig 2024-09-22 18:33:22 +06:00
c2d6afccc2 add koin extensions for plugins 2024-09-22 18:12:46 +06:00
d928db7e74 rework of plagubot system 2024-09-22 15:29:17 +06:00
893f3a95a1 migration onto 10.0.0 2024-09-22 14:46:20 +06:00
f9b7d444a6 add note about startPlugin in setupBotPlugin 2024-09-22 13:33:53 +06:00
47f5086ebd Plugin#setupBotPlugin will call startPlugin by default 2024-09-22 13:32:59 +06:00
bc29d4f83a start 9.3.1 2024-09-22 13:32:09 +06:00
26b34a470b Merge pull request #104 from InsanusMokrassar/9.3.0
9.3.0
2024-09-14 21:21:52 +06:00
3b507a5668 a lot of improvements 2024-09-14 21:06:06 +06:00
bb06ba1ca7 Add opportunity to use config in setup bot client 2024-09-14 20:17:38 +06:00
d772d275b3 start 9.3.0 2024-09-14 20:17:10 +06:00
e1e7c7a547 Merge pull request #103 from InsanusMokrassar/9.2.0
9.2.0
2024-09-06 00:11:20 +06:00
d8403dd3b7 update dependencies 2024-09-06 00:09:41 +06:00
17ac66f7fe start 9.2.0 2024-09-06 00:05:26 +06:00
b23c9b755a Merge pull request #102 from InsanusMokrassar/9.1.0
9.1.0
2024-08-15 21:32:02 +06:00
629ff7ee4e update dependencies 2024-08-15 21:30:04 +06:00
666ba9926e start 9.1.0 2024-08-15 21:29:17 +06:00
995bce3885 Merge pull request #101 from InsanusMokrassar/9.0.0
9.0.0
2024-08-12 16:35:14 +06:00
d597539b9e update dependencies 2024-08-12 16:24:34 +06:00
c80a7a1bda start 9.0.0 2024-08-12 16:22:42 +06:00
bd20c2d60f Merge pull request #100 from InsanusMokrassar/8.5.1
8.5.1
2024-07-24 16:10:12 +06:00
cfd42af6bc update dependencies 2024-07-24 16:08:27 +06:00
5c39fd2491 start 8.5.1 2024-07-24 16:06:56 +06:00
745b9cad72 Merge pull request #99 from InsanusMokrassar/8.5.0
8.5.0
2024-07-11 23:03:40 +06:00
f39947edd6 update dependencies 2024-07-11 23:01:37 +06:00
cacc1ef828 start 8.5.0 2024-07-11 23:00:11 +06:00
136d106b4c Merge pull request #98 from InsanusMokrassar/8.4.0
8.4.0
2024-06-27 23:20:42 +06:00
ddd3854d78 update dependencies 2024-06-27 22:31:45 +06:00
1c2bcb6907 start 8.4.0 2024-06-27 22:29:07 +06:00
8bd80c1c0c Merge pull request #97 from InsanusMokrassar/8.3.0
8.3.0
2024-04-23 18:50:57 +06:00
2234ffd55d update gradle wrapper 2024-04-23 18:44:51 +06:00
1a9d8b0d5e update dependencies 2024-04-23 18:44:26 +06:00
e00f40d06a start 8.3.0 2024-04-23 18:37:33 +06:00
9883d2b3b1 Merge pull request #96 from InsanusMokrassar/8.2.0
8.2.0
2024-02-18 21:34:04 +06:00
bdfd3b816c update dependencies 2024-02-18 21:31:45 +06:00
dd37ae0f2f start 8.2.0 2024-02-18 21:27:22 +06:00
8efe977e76 Merge pull request #95 from InsanusMokrassar/8.1.1
8.1.1
2024-02-10 23:45:26 +06:00
8290a68654 update dependencies 2024-02-10 23:44:52 +06:00
493a18a0f7 start 8.1.1 2024-02-10 23:41:36 +06:00
36608937af Merge pull request #94 from InsanusMokrassar/8.1.0
8.1.0
2024-01-14 18:42:36 +06:00
1b1b069d93 integrate startup launcher 2024-01-14 18:33:41 +06:00
37b5b8e867 start 8.1.0 2024-01-14 18:21:26 +06:00
468310c819 Merge pull request #93 from InsanusMokrassar/8.0.0
8.0.0
2024-01-12 20:28:24 +06:00
0d27a4f6f7 update dependencies 2024-01-12 20:12:58 +06:00
f9d131866f start 8.0.0 2024-01-12 20:11:29 +06:00
451b2bbc39 Merge pull request #92 from InsanusMokrassar/7.4.2
7.4.2
2023-12-24 23:25:42 +06:00
d51e2d8e7c fix of #90 and #91 2023-12-24 23:24:04 +06:00
6c45a8c848 update dependencies 2023-12-24 23:17:29 +06:00
8a7e05580d start 7.4.2 2023-12-24 23:14:24 +06:00
8b78f2901f Merge pull request #89 from InsanusMokrassar/7.4.1
7.4.1
2023-12-10 14:47:39 +06:00
cad8743ced update dependencies and fill changelog 2023-12-10 14:46:13 +06:00
8f827e9f79 start 7.4.1 2023-12-10 14:34:52 +06:00
28039df992 Merge pull request #88 from InsanusMokrassar/7.4.0
7.4.0
2023-11-26 20:56:04 +06:00
18019c37ea remove expicit KSLog dependency 2023-11-26 19:29:29 +06:00
8a84f65a12 Update CHANGELOG.md 2023-11-26 19:02:00 +06:00
49f30ab939 Update libs.versions.toml 2023-11-26 18:52:26 +06:00
8a15deceb8 Update gradle.properties 2023-11-26 18:49:43 +06:00
ea3273c4cf Merge pull request #87 from InsanusMokrassar/7.3.0
7.3.0
2023-11-06 15:17:37 +06:00
439972e783 update dependencies 2023-11-05 20:52:30 +06:00
08907291c5 update dependencies 2023-11-05 19:34:43 +06:00
0f4819a83d start 7.3.0 2023-11-05 19:14:12 +06:00
7abdf18491 Merge pull request #86 from InsanusMokrassar/7.2.3
7.2.3
2023-10-11 15:31:46 +06:00
23 changed files with 676 additions and 219 deletions

View File

@@ -8,9 +8,9 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up JDK 11 - name: Set up JDK 17
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 11 java-version: 17
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew build run: ./gradlew build

View File

@@ -1,5 +1,254 @@
# Changelog # Changelog
## 10.10.0
* `Versions`:
* `kotlin`: `2.2.21`
* `microutils`: `0.26.8`
* `tgbotapi`: `30.0.2`
## 10.9.0
* `Versions`:
* `kotlin`: `2.2.20`
* `microutils`: `0.26.6`
* `tgbotapi`: `30.0.0`
* `koin`: `4.1.1`
## 10.8.0
* `Versions`:
* `kotlin`: `2.2.10`
* `microutils`: `0.26.3`
* `tgbotapi`: `28.0.1`
## 10.7.0
* `Versions`:
* `kotlin`: `2.2.0`
* `serialization`: `1.9.0`
* `microutils`: `0.26.2`
* `tgbotapi`: `27.1.1`
* `koin`: `4.1.0`
## 10.6.0
* `Versions`:
* `microutils`: `0.25.8`
* `tgbotapi`: `26.0.0`
* `sqlite`: `3.50.1.0`
## 10.5.0
* `Versions`:
* `kotlin`: `2.1.20`
* `serialization`: `1.8.1`
* `coroutines`: `1.10.2`
* `microutils`: `0.25.5`
* `tgbotapi`: `24.0.2`
* `exposed`: `0.61.0`
* `sqlite`: `3.49.1.0`
* `koin`: `4.0.4`
## 10.4.0
* `Versions`:
* `microutils`: `0.24.6`
* `tgbotapi`: `23.2.0`
* `exposed`: `0.59.0`
* `sqlite`: `3.49.0.0`
## 10.3.1
* `Versions`:
* `kotlin`: `2.1.10`
* `serialization`: `1.8.0`
* `coroutines`: `1.10.1`
* `microutils`: `0.24.5`
* `tgbotapi`: `23.1.2`
* `exposed`: `0.58.0`
* `sqlite`: `3.48.0.0`
* `koin`: `4.0.2`
## 10.3.0
* `Versions`:
* `microutils`: `0.23.2`
* `tgbotapi`: `22.0.0`
* `exposed`: `0.57.0`
## 10.2.1
* `Versions`:
* `tgbotapi`: `21.0.1`
* `Bot`:
* Now all `CombinedSubcontextInitialAction.SubItem`s will be taken from `Koin` to setup root `subcontextInitialAction`
## 10.2.0
* `Versions`:
* `kotlin`: `2.1.0`
* `microutils`: `0.23.1`
* `tgbotapi`: `21.0.0`
* `exposed`: `0.56.0`
* `sqlite`: `3.47.1.0`
## 10.1.1
* `Versions`:
* `tgbotapi`: `20.0.1`
## 10.1.0
* `Versions`:
* `kotlin`: `2.0.21`
* `serialization`: `1.7.3`
* `coroutines`: `1.9.0`
* `microutils`: `0.23.0`
* `tgbotapi`: `20.0.0`
* `exposed`: `0.55.0`
* `sqlite`: `3.47.0.0`
* `koin`: `4.0.0`
## 10.0.0
**OVERALL LOGIC OF PLAGUBOT INITIALIZATION AND WORK HAS BEEN CHANGED**
First of all, since this update `PlaguBot` will use default `StartPlugin` logic and will be built on top of it.
All special methods of `Plugin` will be called from one of `PlaguBot` initialization phases:
* `setupBotClient` will be called from `single` initialization of `telegramBot` (in `setupDI` phase)
* `setupBotPlugin` will be called from `startPlugin` method in time of `buildBehaviourWithFSM` initialization
* `Plugin`:
* Extension `Module.setupDI(Database,JsonObject)` has been dropped. Use `database` extension in `Module.setupDI(JsonObject)`
* `Bot`:
* `dev.inmo.plagubot.config.Config` lost its `plugins` section. Now you may retrieve plugins from `Koin` only
* `defaultJsonFormat` became `Warning` feature due to the fact of its fully default nature
* `PlaguBot` lost old `start` method and took two new: with `args` as `Array<String>` and `initialConfig` as `JsonObject`
**Migration:**
* If you are running bot and doing it using `StartPlugin` launcher, add `dev.inmo.plagubot.PlaguBot` explicitly
* In plugins: replace your `setupDI` overrides with `Database` as argument by the same one, but `database` will be
available as extension in `single` or `factory` calls (as extension to `Scope` and `Koin`)
## 9.3.0
* `Bot`:
* Now bot is not built-in into `PlaguBot` and setted up as all other `Koin` dependencies
* Now it is possible to use `testServer` parameter for bots out of the box
* `Plugin`:
* New method `setupBotClient` with arguments to let plugin setup bot more freely
## 9.2.0
* `Versions`:
* `kotlin`: `2.0.20`
* `serialization`: `1.7.2`
* `microutils`: `0.22.2`
* `tgbotapi`: `18.1.0`
* `exposed`: `0.54.0`
* `sqlite`: `3.46.1.0`
## 9.1.0
* `Versions`:
* `tgbotapi`: `17.0.0`
## 9.0.0
* `Versions`:
* `Kotlin`: `2.0.10`
* `Serialization`: `1.7.1`
* `MicroUtils`: `0.22.0`
* `tgbotapi`: `16.0.0`
* `Exposed`: `0.53.0`
## 8.5.1
* `Versions`:
* `MicroUtils`: `0.21.4`
* `tgbotapi`: `15.2.0`
## 8.5.0
* `Versions`:
* `MicroUtils`: `0.21.2`
* `tgbotapi`: `15.1.0`
## 8.4.0
* `Versions`:
* `Coroutines`: `1.8.1`
* `MicroUtils`: `0.21.1`
* `tgbotapi`: `15.0.0`
* `Exposed`: `0.51.1`
## 8.3.0
* `Versions`:
* `Serialization`: `1.6.3`
* `MicroUtils`: `0.20.45`
* `tgbotapi`: `12.0.1`
* `Exposed`: `0.49.0`
* `SQLite`: `3.45.3.0`
* `Koin`: `3.5.6`
## 8.2.0
* `Versions`:
* `Coroutines`: `1.8.0`
* `tgbotapi`: `10.1.0`
* `MicroUtils`: `0.20.35`
## 8.1.1
* `Versions`:
* `tgbotapi`: `10.0.1`
* `MicroUtils`: `0.20.32`
* `Exposed`: `0.47.0`
## 8.1.0
* Integrate `dev.inmo:micro_utils.startup` into project
## 8.0.0
* `Versions`:
* `tgbotapi`: `10.0.0`
* `MicroUtils`: `0.20.26`
* `Exposed`: `0.46.0`
## 7.4.2
* `Versions`:
* `Kotlin`: `1.9.22`
* `tgbotapi`: `9.4.3`
* `MicroUtils`: `0.20.23`
* `Koin`: `3.5.7`
## 7.4.1
* `Versions`:
* `Serialization`: `1.6.2`
* `tgbotapi`: `9.4.2`
* `Exposed`: `0.45.0`
* `SQLite`: `3.44.1.0`
* `MicroUtils`: `0.20.19`
* `uuid`: `0.8.2`
* `ktor`: `2.3.7`
## 7.3.0
* `Versions`:
* `Kotlin`: `1.9.21`
* `Serialization`: `1.6.1`
* `tgbotapi`: `9.4.1`
* `ktor`: `2.3.6`
* `KSLog`: Removed explicit dependency, now it is declared in tgbotapi
* `MicroUtils`: `0.20.15`
## 7.2.3 ## 7.2.3
* `Versions`: * `Versions`:

View File

@@ -19,6 +19,8 @@ That is a set of libraries for plagubots. Look at the
### Technical help ### Technical help
#### FSM
In this bot has been used variant with FSM. That means that you may use all the [Behaviour Builder with FSM](https://bookstack.inmo.dev/books/telegrambotapi/page/behaviour-builder-with-fsm) functionality. In case you wish to setup states repo, you should use the next code in the `setupDI` of your plugin: In this bot has been used variant with FSM. That means that you may use all the [Behaviour Builder with FSM](https://bookstack.inmo.dev/books/telegrambotapi/page/behaviour-builder-with-fsm) functionality. In case you wish to setup states repo, you should use the next code in the `setupDI` of your plugin:
```kotlin ```kotlin
@@ -41,3 +43,16 @@ single<StateHandlingErrorHandler<State>> {
} }
} }
``` ```
#### Subcontext initial actions
Bot will take all the `CombinedSubcontextInitialAction.SubItem`s from `Koin` to include it in root of
`behaviourBuilder`. To create your own subitem:
```kotlin
singleWithRandomQualifier<CombinedSubcontextInitialAction.SubItem> {
CombinedSubcontextInitialAction.SubItem {
// do some action or throw error to rerun on next round
}
}
```

View File

@@ -20,7 +20,7 @@ dependencies {
api libs.tgbotapi.behaviourBuilder.fsm api libs.tgbotapi.behaviourBuilder.fsm
api libs.microutils.repos.exposed api libs.microutils.repos.exposed
api libs.microutils.koin api libs.microutils.koin
api libs.kslog api libs.microutils.startup.launcher
api libs.sqlite api libs.sqlite
@@ -34,8 +34,8 @@ application {
} }
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_17
} }
ksp { // this generator do not require any arguments and we should left `ksp` empty ksp { // this generator do not require any arguments and we should left `ksp` empty

View File

@@ -1,12 +1,14 @@
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
task javadocJar(type: Jar) { task javadocJar(type: Jar) {
from javadoc from javadoc
classifier = 'javadoc' archiveClassifier = 'javadoc'
} }
task sourcesJar(type: Jar) { task sourcesJar(type: Jar) {
from sourceSets.main.allSource from sourceSets.main.allSource
classifier = 'sources' archiveClassifier = 'sources'
} }
publishing { publishing {
@@ -48,34 +50,28 @@ publishing {
} }
} }
repositories { }
if (project.hasProperty('GITEA_TOKEN') || System.getenv('GITEA_TOKEN') != null) { }
maven { repositories {
name = "Gitea" if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) {
url = uri("https://git.inmo.dev/api/packages/InsanusMokrassar/maven") maven {
name = "InmoNexus"
credentials(HttpHeaderCredentials) { url = uri("https://nexus.inmo.dev/repository/maven-releases/")
name = "Authorization"
value = project.hasProperty('GITEA_TOKEN') ? project.property('GITEA_TOKEN') : System.getenv('GITEA_TOKEN') credentials {
} username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER')
password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD')
authentication {
header(HttpHeaderAuthentication)
}
}
} }
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) { }
maven { }
name = "sonatype" if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/") maven {
name = "sonatype"
credentials { url = uri("https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/")
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD') credentials {
} username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
} }
} }
} }
@@ -84,16 +80,39 @@ publishing {
if (project.hasProperty("signing.gnupg.keyName")) { if (project.hasProperty("signing.gnupg.keyName")) {
apply plugin: 'signing' apply plugin: 'signing'
signing { signing {
useGpgCmd() useGpgCmd()
sign publishing.publications sign publishing.publications
} }
task signAll { task signAll {
tasks.withType(Sign).forEach { tasks.withType(Sign).forEach {
dependsOn(it) dependsOn(it)
} }
} }
// Workaround to make android sign operations depend on signing tasks
project.getTasks().withType(AbstractPublishToMaven.class).configureEach {
def signingTasks = project.getTasks().withType(Sign.class)
mustRunAfter(signingTasks)
}
// Workaround to make test tasks use sign
project.getTasks().withType(Sign.class).configureEach { signTask ->
def withoutSign = (signTask.name.startsWith("sign") ? signTask.name.minus("sign") : signTask.name)
def pubName = withoutSign.endsWith("Publication") ? withoutSign.substring(0, withoutSign.length() - "Publication".length()) : withoutSign
// These tasks only exist for native targets, hence findByName() to avoid trying to find them for other targets
// Task ':linkDebugTest<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def debugTestTask = tasks.findByName("linkDebugTest$pubName")
if (debugTestTask != null) {
signTask.mustRunAfter(debugTestTask)
}
// Task ':compileTestKotlin<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def testTask = tasks.findByName("compileTestKotlin$pubName")
if (testTask != null) {
signTask.mustRunAfter(testTask)
}
}
} }

View File

@@ -1 +1 @@
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/PlaguBot/LICENSE"}],"mavenConfig":{"name":"PlaguBot Bot","description":"Base PlaguBot project","url":"https://github.com/InsanusMokrassar/PlaguBot","vcsUrl":"ssh://git@github.com/InsanusMokrassar/PlaguBot.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"Gitea","url":"https://git.inmo.dev/api/packages/InsanusMokrassar/maven","credsType":{"type":"dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository.CredentialsType.HttpHeaderCredentials","headerName":"Authorization","headerValueProperty":"GITEA_TOKEN"}},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}},"type":"JVM"} {"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/PlaguBot/LICENSE"}],"mavenConfig":{"name":"PlaguBot Bot","description":"Base PlaguBot project","url":"https://github.com/InsanusMokrassar/PlaguBot","vcsUrl":"ssh://git@github.com/InsanusMokrassar/PlaguBot.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"InmoNexus","url":"https://nexus.inmo.dev/repository/maven-releases/"},{"name":"sonatype","url":"https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}},"type":"JVM"}

View File

@@ -1,25 +1,11 @@
package dev.inmo.plagubot package dev.inmo.plagubot
import dev.inmo.kslog.common.KSLog
import dev.inmo.kslog.common.i
import dev.inmo.plagubot.config.Config
import dev.inmo.plagubot.config.defaultJsonFormat
import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.json.jsonObject
import java.io.File
/** /**
* This method by default expects one argument in [args] field: path to config * This method by default expects one argument in [args] field: path to config
*/ */
@InternalSerializationApi @InternalSerializationApi
suspend fun main(args: Array<String>) { suspend fun main(args: Array<String>) {
KSLog.default = KSLog("PlaguBot") PlaguBot.start(args).join()
val (configPath) = args
val file = File(configPath)
KSLog.i("Start read config from ${file.absolutePath}")
val json = defaultJsonFormat.parseToJsonElement(file.readText()).jsonObject
val config = defaultJsonFormat.decodeFromJsonElement(Config.serializer(), json)
KSLog.i("Config has been read")
PlaguBot(json, config).start().join()
} }

View File

@@ -0,0 +1,28 @@
package dev.inmo.plagubot
import org.koin.core.Koin
import org.koin.core.definition.Definition
import org.koin.core.module.Module
import org.koin.core.qualifier.Qualifier
import org.koin.core.qualifier.StringQualifier
import org.koin.core.scope.Scope
val Scope.plagubot: PlaguBot
get() = get()
val Koin.plagubot: PlaguBot
get() = get()
private val pluginsQualifier = StringQualifier("plagubotPlugins")
internal fun Module.singlePlugins(
createdAtStart: Boolean = false,
definition: Definition<List<Plugin>>
) = single(pluginsQualifier, createdAtStart, definition)
val Scope.plugins: List<Plugin>
get() = get(pluginsQualifier)
val Koin.plugins: List<Plugin>
get() = get(pluginsQualifier)

View File

@@ -7,64 +7,106 @@ import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.micro_utils.fsm.common.StatesManager import dev.inmo.micro_utils.fsm.common.StatesManager
import dev.inmo.micro_utils.fsm.common.managers.* import dev.inmo.micro_utils.fsm.common.managers.*
import dev.inmo.micro_utils.koin.getAllDistinct import dev.inmo.micro_utils.koin.getAllDistinct
import dev.inmo.micro_utils.pagination.utils.getAll
import dev.inmo.micro_utils.startup.launcher.StartLauncherPlugin
import dev.inmo.plagubot.config.* import dev.inmo.plagubot.config.*
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.bot.ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.webhook.deleteWebhook import dev.inmo.tgbotapi.extensions.api.webhook.deleteWebhook
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.startGettingOfUpdatesByLongPolling
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.json.*
import kotlinx.serialization.json.JsonObject
import org.jetbrains.exposed.sql.Database
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.KoinApplication
import org.koin.core.context.GlobalContext
import org.koin.core.module.Module import org.koin.core.module.Module
import org.koin.core.scope.Scope import org.koin.core.scope.Scope
import org.koin.dsl.module import java.io.File
val Scope.plagubot: PlaguBot
get() = get()
val Koin.plagubot: PlaguBot
get() = get()
@OptIn(Warning::class) @OptIn(Warning::class)
@Serializable @Serializable
data class PlaguBot( object PlaguBot : Plugin {
private val json: JsonObject, override fun KtorRequestsExecutorBuilder.setupBotClient(scope: Scope, params: JsonObject) {
private val config: Config scope.plugins.filter { it !== this@PlaguBot }.forEach {
) : Plugin { with(it) {
@Transient setupBotClient(scope, params)
private val bot = telegramBot(config.botToken)
override fun Module.setupDI(database: Database, params: JsonObject) {
single { config }
single { config.plugins }
single { config.databaseConfig }
single { config.databaseConfig.database }
single { defaultJsonFormat }
single { this@PlaguBot }
single { bot }
includes(
config.plugins.mapNotNull {
runCatching {
module {
with(it) {
setupDI(database, params)
}
}
}.onFailure { e ->
logger.w("Unable to load DI part of $it", e)
}.getOrNull()
} }
) }
} }
override fun Module.setupDI(config: JsonObject) {
single { get<Json>().decodeFromJsonElement(Config.serializer(), config) }
single { config }
single { get<Config>().databaseConfig }
single { get<Config>().databaseConfig.database }
single { this@PlaguBot }
singlePlugins { get<dev.inmo.micro_utils.startup.launcher.Config>().plugins.filterIsInstance<Plugin>() }
single {
val config = get<Config>()
telegramBot(
token = config.botToken,
testServer = config.testServer,
apiUrl = config.botApiServer
) {
setupBotClient(this@single, get<JsonObject>())
}
}
}
/**
* Getting all [OnStartContextsConflictResolver], [OnUpdateContextsConflictResolver], [StatesManager] and [DefaultStatesManagerRepo]
* and pass them into [buildBehaviourWithFSM] on top of [TelegramBot] took from [koin]. In time of
* [buildBehaviourWithFSM] configuration will call [setupBotPlugin] and [deleteWebhook].
*
* After all preparation, the result of [buildBehaviourWithFSM] will be passed to [startGettingOfUpdatesByLongPolling]
* as [CoroutineScope] and [UpdatesFilter].
*
* The [Job] took from [startGettingOfUpdatesByLongPolling] will be used to prevent app stopping by calling [Job.join]
* on it
*/
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
val scope = koin.get<CoroutineScope>()
lateinit var behaviourContext: BehaviourContext
val onStartContextsConflictResolver by lazy { koin.getAllDistinct<OnStartContextsConflictResolver>() }
val onUpdateContextsConflictResolver by lazy { koin.getAllDistinct<OnUpdateContextsConflictResolver>() }
val bot = koin.get<TelegramBot>()
bot.buildBehaviourWithFSM(
scope = scope,
defaultExceptionsHandler = {
logger.e("Something went wrong", it)
},
statesManager = koin.getOrNull<StatesManager<State>>() ?: DefaultStatesManager(
koin.getOrNull<DefaultStatesManagerRepo<State>>() ?: InMemoryDefaultStatesManagerRepo<State>(),
onStartContextsConflictResolver = { old, new -> onStartContextsConflictResolver.firstNotNullOfOrNull { it(old, new) } ?: false },
onUpdateContextsConflictResolver = { old, new, currentNew -> onUpdateContextsConflictResolver.firstNotNullOfOrNull { it(old, new, currentNew) } ?: false }
),
onStateHandlingErrorHandler = koin.getOrNull<StateHandlingErrorHandler<State>>() ?: { state, e ->
logger.eS(e) { "Unable to handle state $state" }
null
},
subcontextInitialAction = CombinedSubcontextInitialAction(koin.getAllDistinct()).subcontextInitialAction
) {
logger.i("Start setup of bot part")
behaviourContext = this
setupBotPlugin(koin)
deleteWebhook()
}.start()
logger.i("Behaviour builder has been setup")
bot.startGettingOfUpdatesByLongPolling(scope = behaviourContext, updatesFilter = behaviourContext).also {
logger.i("Long polling has been started")
}.join()
}
/**
* Initializing [Plugin]s from [koin] took by [plugins] extension. [PlaguBot] itself will be filtered out from
* list of plugins to be inited
*/
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) { override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
config.plugins.forEach { plugin -> koin.plugins.filter { it !== this@PlaguBot }.forEach { plugin ->
runCatchingSafely { runCatchingSafely {
logger.i("Start loading of $plugin") logger.i("Start loading of $plugin")
with(plugin) { with(plugin) {
@@ -79,47 +121,47 @@ data class PlaguBot(
} }
/** /**
* This method will create an [Job] which will be the main [Job] of ran instance * Starting plugins system using [StartLauncherPlugin.start]. In time of parsing [initialJson] [PlaguBot] may
* add itself in its `plugins` section in case of its absence there. So, by launching this [start] it is guaranteed
* that [PlaguBot] will be in list of plugins to be loaded by [StartLauncherPlugin]
*/ */
suspend fun start( suspend fun start(initialJson: JsonObject): Job {
scope: CoroutineScope = CoroutineScope(Dispatchers.IO) val initialConfig = defaultJsonFormat.decodeFromJsonElement(dev.inmo.micro_utils.startup.launcher.Config.serializer(), initialJson)
): Job {
logger.i("Start initialization") KSLog.i("Config has been read")
val koinApp = KoinApplication.init()
koinApp.modules( // Adding of PlaguBot when it absent in config
module { val (resultJson, resultConfig) = if (PlaguBot in initialConfig.plugins) {
setupDI(config.databaseConfig.database, json) KSLog.i("Initial config contains PlaguBot, pass config as is to StartLauncherPlugin")
} initialJson to initialConfig
) } else {
logger.i("Modules loaded") KSLog.i("Start fixing of PlaguBot absence. If PlaguBot has been skipped by some reason, use dev.inmo.micro_utils.startup.launcher.main as startup point or StartLauncherPlugin directly")
GlobalContext.startKoin(koinApp) val resultJson = JsonObject(
logger.i("Koin started") initialJson + Pair("plugins", JsonArray(initialJson["plugins"]!!.jsonArray + JsonPrimitive(PlaguBot::class.qualifiedName!!)))
lateinit var behaviourContext: BehaviourContext )
val onStartContextsConflictResolver by lazy { koinApp.koin.getAllDistinct<OnStartContextsConflictResolver>() } val resultConfig = defaultJsonFormat.decodeFromJsonElement(dev.inmo.micro_utils.startup.launcher.Config.serializer(), resultJson)
val onUpdateContextsConflictResolver by lazy { koinApp.koin.getAllDistinct<OnUpdateContextsConflictResolver>() } resultJson to resultConfig
bot.buildBehaviourWithFSM(
scope = scope,
defaultExceptionsHandler = {
logger.e("Something went wrong", it)
},
statesManager = koinApp.koin.getOrNull<StatesManager<State>>() ?: DefaultStatesManager(
koinApp.koin.getOrNull<DefaultStatesManagerRepo<State>>() ?: InMemoryDefaultStatesManagerRepo<State>(),
onStartContextsConflictResolver = { old, new -> onStartContextsConflictResolver.firstNotNullOfOrNull { it(old, new) } ?: false },
onUpdateContextsConflictResolver = { old, new, currentNew -> onUpdateContextsConflictResolver.firstNotNullOfOrNull { it(old, new, currentNew) } ?: false }
),
onStateHandlingErrorHandler = koinApp.koin.getOrNull<StateHandlingErrorHandler<State>>() ?: { state, e ->
logger.eS(e) { "Unable to handle state $state" }
null
}
) {
logger.i("Start setup of bot part")
behaviourContext = this
setupBotPlugin(koinApp.koin)
deleteWebhook()
}.start()
logger.i("Behaviour builder has been setup")
return bot.startGettingOfUpdatesByLongPolling(scope = behaviourContext, updatesFilter = behaviourContext).also {
logger.i("Long polling has been started")
} }
KSLog.i("Config initialization done. Passing config to StartLauncherPlugin")
return StartLauncherPlugin.start(
resultConfig,
resultJson
).koin.get<CoroutineScope>().coroutineContext.job
}
/**
* Accepts single argument in [args] which will be interpreted as [File] path with [StartLauncherPlugin]
* configuration content. After reading of that file as [JsonObject] will pass it in [start] with [JsonObject] as
* argument
*/
suspend fun start(args: Array<String>): Job {
KSLog.default = KSLog("PlaguBot")
val (configPath) = args
val file = File(configPath)
KSLog.i("Start read config from ${file.absolutePath}")
val initialJson = defaultJsonFormat.parseToJsonElement(file.readText()).jsonObject
return start(initialJson)
} }
} }

View File

@@ -1,15 +1,18 @@
package dev.inmo.plagubot.config package dev.inmo.plagubot.config
import dev.inmo.micro_utils.common.Warning import dev.inmo.micro_utils.common.Warning
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import dev.inmo.plagubot.Plugin import dev.inmo.plagubot.Plugin
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Warning("This API is internal and can be changed without notifications of mentions of changes") @Warning("This API is internal and can be changed without notifications or mentions of changes")
@Serializable @Serializable
data class Config( data class Config(
val botToken: String, val botToken: String,
val plugins: List<Plugin>,
@SerialName("database") @SerialName("database")
val databaseConfig: DatabaseConfig = DatabaseConfig(), val databaseConfig: DatabaseConfig = DatabaseConfig(),
val botApiServer: String = telegramBotAPIDefaultUrl,
val testServer: Boolean = false
) )

View File

@@ -1,7 +1,9 @@
package dev.inmo.plagubot.config package dev.inmo.plagubot.config
import dev.inmo.micro_utils.common.Warning
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@Warning("This format will not be configured throw StartPlugin system. Use it will caution, it has no any configured things")
val defaultJsonFormat = Json { val defaultJsonFormat = Json {
ignoreUnknownKeys = true ignoreUnknownKeys = true
} }

View File

@@ -12,12 +12,30 @@ buildscript {
} }
} }
plugins {
alias(libs.plugins.nmcp.aggregation)
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
nmcpAggregation {
centralPortal {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
validationTimeout = Duration.ofHours(4)
publishingType = System.getenv('PUBLISHING_TYPE') != "" ? System.getenv('PUBLISHING_TYPE') : "USER_MANAGED"
}
publishAllProjectsProbablyBreakingProjectIsolation()
}
}
allprojects { allprojects {
repositories { repositories {
mavenCentral() mavenCentral()
mavenLocal() mavenLocal()
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
maven { url "https://git.inmo.dev/api/packages/InsanusMokrassar/maven" } maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
} }
} }

View File

@@ -11,22 +11,29 @@ private String getCurrentVersionChangelog() {
return changelogDataOS.toString().trim() return changelogDataOS.toString().trim()
} }
if (new File(projectDir, "secret.gradle").exists()) { def githubTokenVariableName = "GITHUB_RELEASE_TOKEN"
apply from: './secret.gradle' def githubTokenVariableFromEnv = System.getenv(githubTokenVariableName)
def secretFile = new File(projectDir, "secret.gradle")
if (secretFile.exists() || project.hasProperty(githubTokenVariableName) || (githubTokenVariableFromEnv != "" && githubTokenVariableFromEnv != null)) {
if (secretFile.exists()) {
apply from: './secret.gradle'
}
apply plugin: "com.github.breadmoirai.github-release" apply plugin: "com.github.breadmoirai.github-release"
def githubReleaseToken = project.hasProperty(githubTokenVariableName) ? project.property(githubTokenVariableName).toString() : githubTokenVariableFromEnv
githubRelease { githubRelease {
token "${project.property('GITHUB_RELEASE_TOKEN')}" token githubReleaseToken
releaseAssets.from('bot/build/distributions') releaseAssets.from('bot/build/distributions')
owner "InsanusMokrassar" owner = "InsanusMokrassar"
repo "PlaguBot" repo = "PlaguBot"
tagName "v${project.version}" tagName = "v${project.version}"
releaseName "${project.version}" releaseName = "${project.version}"
targetCommitish "${project.version}" targetCommitish = "${project.version}"
body getCurrentVersionChangelog() body = getCurrentVersionChangelog()
} }
} }

View File

@@ -5,4 +5,4 @@ kotlin.js.generate.externals=true
kotlin.incremental=true kotlin.incremental=true
group=dev.inmo group=dev.inmo
version=7.2.3 version=10.10.0

View File

@@ -1,28 +1,24 @@
[versions] [versions]
kt = "1.8.22" kt = "2.2.21"
kt-serialization = "1.5.1" kt-serialization = "1.9.0"
kt-coroutines = "1.7.3" kt-coroutines = "1.10.2"
microutils = "0.19.9" microutils = "0.26.8"
tgbotapi = "9.2.2" tgbotapi = "30.0.2"
kslog = "1.1.2"
ksp = "1.8.22-1.0.11" ksp = "2.3.2"
jb-exposed = "0.44.0" jb-exposed = "0.61.0"
jb-dokka = "1.8.20" jb-dokka = "2.1.0"
sqlite = "3.43.0.0" sqlite = "3.50.1.0"
klock = "4.0.3" gh-release = "2.5.2"
uuid = "0.7.1"
ktor = "2.3.5" koin = "4.1.1"
gh-release = "2.4.1" nmcp = "1.3.0"
koin = "3.5.0"
[libraries] [libraries]
@@ -36,7 +32,8 @@ tgbotapi-behaviourBuilder-fsm = { module = "dev.inmo:tgbotapi.behaviour_builder.
microutils-repos-exposed = { module = "dev.inmo:micro_utils.repos.exposed", version.ref = "microutils" } microutils-repos-exposed = { module = "dev.inmo:micro_utils.repos.exposed", version.ref = "microutils" }
microutils-koin = { module = "dev.inmo:micro_utils.koin", version.ref = "microutils" } microutils-koin = { module = "dev.inmo:micro_utils.koin", version.ref = "microutils" }
microutils-koin-generator = { module = "dev.inmo:micro_utils.koin.generator", version.ref = "microutils" } microutils-koin-generator = { module = "dev.inmo:micro_utils.koin.generator", version.ref = "microutils" }
kslog = { module = "dev.inmo:kslog", version.ref = "kslog" } microutils-startup-launcher = { module = "dev.inmo:micro_utils.startup.launcher", version.ref = "microutils" }
microutils-startup-plugin = { module = "dev.inmo:micro_utils.startup.plugin", version.ref = "microutils" }
koin = { module = "io.insert-koin:koin-core", version.ref = "koin" } koin = { module = "io.insert-koin:koin-core", version.ref = "koin" }
@@ -53,3 +50,7 @@ buildscript-kt-serialization = { module = "org.jetbrains.kotlin:kotlin-serializa
buildscript-jb-dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "jb-dokka" } buildscript-jb-dokka = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "jb-dokka" }
buildscript-gh-release = { module = "com.github.breadmoirai:github-release", version.ref = "gh-release" } buildscript-gh-release = { module = "com.github.breadmoirai:github-release", version.ref = "gh-release" }
buildscript-ksp = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } buildscript-ksp = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" }
[plugins]
nmcp-aggregation = { id = "com.gradleup.nmcp.aggregation", version.ref = "nmcp" }

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@@ -14,11 +14,12 @@ dependencies {
api libs.tgbotapi api libs.tgbotapi
api libs.microutils.repos.exposed api libs.microutils.repos.exposed
api libs.microutils.startup.plugin
api libs.koin api libs.koin
} }
java { java {
sourceCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_17
} }

View File

@@ -1,12 +1,14 @@
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
task javadocJar(type: Jar) { task javadocJar(type: Jar) {
from javadoc from javadoc
classifier = 'javadoc' archiveClassifier = 'javadoc'
} }
task sourcesJar(type: Jar) { task sourcesJar(type: Jar) {
from sourceSets.main.allSource from sourceSets.main.allSource
classifier = 'sources' archiveClassifier = 'sources'
} }
publishing { publishing {
@@ -48,34 +50,28 @@ publishing {
} }
} }
repositories { }
if (project.hasProperty('GITEA_TOKEN') || System.getenv('GITEA_TOKEN') != null) { }
maven { repositories {
name = "Gitea" if ((project.hasProperty('INMONEXUS_USER') || System.getenv('INMONEXUS_USER') != null) && (project.hasProperty('INMONEXUS_PASSWORD') || System.getenv('INMONEXUS_PASSWORD') != null)) {
url = uri("https://git.inmo.dev/api/packages/InsanusMokrassar/maven") maven {
name = "InmoNexus"
credentials(HttpHeaderCredentials) { url = uri("https://nexus.inmo.dev/repository/maven-releases/")
name = "Authorization"
value = project.hasProperty('GITEA_TOKEN') ? project.property('GITEA_TOKEN') : System.getenv('GITEA_TOKEN') credentials {
} username = project.hasProperty('INMONEXUS_USER') ? project.property('INMONEXUS_USER') : System.getenv('INMONEXUS_USER')
password = project.hasProperty('INMONEXUS_PASSWORD') ? project.property('INMONEXUS_PASSWORD') : System.getenv('INMONEXUS_PASSWORD')
authentication {
header(HttpHeaderAuthentication)
}
}
} }
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) { }
maven { }
name = "sonatype" if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/") maven {
name = "sonatype"
credentials { url = uri("https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/")
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD') credentials {
} username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
} }
} }
} }
@@ -84,16 +80,39 @@ publishing {
if (project.hasProperty("signing.gnupg.keyName")) { if (project.hasProperty("signing.gnupg.keyName")) {
apply plugin: 'signing' apply plugin: 'signing'
signing { signing {
useGpgCmd() useGpgCmd()
sign publishing.publications sign publishing.publications
} }
task signAll { task signAll {
tasks.withType(Sign).forEach { tasks.withType(Sign).forEach {
dependsOn(it) dependsOn(it)
} }
} }
// Workaround to make android sign operations depend on signing tasks
project.getTasks().withType(AbstractPublishToMaven.class).configureEach {
def signingTasks = project.getTasks().withType(Sign.class)
mustRunAfter(signingTasks)
}
// Workaround to make test tasks use sign
project.getTasks().withType(Sign.class).configureEach { signTask ->
def withoutSign = (signTask.name.startsWith("sign") ? signTask.name.minus("sign") : signTask.name)
def pubName = withoutSign.endsWith("Publication") ? withoutSign.substring(0, withoutSign.length() - "Publication".length()) : withoutSign
// These tasks only exist for native targets, hence findByName() to avoid trying to find them for other targets
// Task ':linkDebugTest<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def debugTestTask = tasks.findByName("linkDebugTest$pubName")
if (debugTestTask != null) {
signTask.mustRunAfter(debugTestTask)
}
// Task ':compileTestKotlin<platform>' uses this output of task ':sign<platform>Publication' without declaring an explicit or implicit dependency
def testTask = tasks.findByName("compileTestKotlin$pubName")
if (testTask != null) {
signTask.mustRunAfter(testTask)
}
}
} }

View File

@@ -1 +1 @@
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/PlaguBot/LICENSE"}],"mavenConfig":{"name":"PlaguBot Plugin","description":"Base dependency for whole PlaguBot project","url":"https://github.com/InsanusMokrassar/PlaguBot","vcsUrl":"ssh://git@github.com/InsanusMokrassar/PlaguBot.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"Gitea","url":"https://git.inmo.dev/api/packages/InsanusMokrassar/maven","credsType":{"type":"dev.inmo.kmppscriptbuilder.core.models.MavenPublishingRepository.CredentialsType.HttpHeaderCredentials","headerName":"Authorization","headerValueProperty":"GITEA_TOKEN"}},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}},"type":"JVM"} {"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/PlaguBot/LICENSE"}],"mavenConfig":{"name":"PlaguBot Plugin","description":"Base dependency for whole PlaguBot project","url":"https://github.com/InsanusMokrassar/PlaguBot","vcsUrl":"ssh://git@github.com/InsanusMokrassar/PlaguBot.git","developers":[{"id":"InsanusMokrassar","name":"Aleksei Ovsiannikov","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"InmoNexus","url":"https://nexus.inmo.dev/repository/maven-releases/"},{"name":"sonatype","url":"https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/"}],"gpgSigning":{"type":"dev.inmo.kmppscriptbuilder.core.models.GpgSigning.Optional"}},"type":"JVM"}

View File

@@ -2,22 +2,18 @@ package dev.inmo.plagubot
import dev.inmo.kslog.common.* import dev.inmo.kslog.common.*
import dev.inmo.micro_utils.fsm.common.State import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.plagubot.HelloPlugin.setupBotPlugin
import dev.inmo.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.send.reply import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.sendMessage import dev.inmo.tgbotapi.extensions.api.send.sendMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitText
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitTextMessage import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitTextMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onUnhandledCommand
import dev.inmo.tgbotapi.types.IdChatIdentifier import dev.inmo.tgbotapi.types.IdChatIdentifier
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import org.jetbrains.exposed.sql.Database
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.module.Module import org.koin.core.module.Module
@@ -29,12 +25,8 @@ object HelloPlugin : Plugin {
val print: String val print: String
) )
override fun Module.setupDI(database: Database, params: JsonObject) { override fun Module.setupDI(config: JsonObject) {
single { registerConfig<HelloPluginConfig>("helloPlugin") { null }
get<Json>().decodeFromJsonElement(HelloPluginConfig.serializer(), params["helloPlugin"] ?: return@single null)
}
} }
private sealed interface InternalFSMState : State { private sealed interface InternalFSMState : State {
@@ -43,8 +35,13 @@ object HelloPlugin : Plugin {
data class SaidHelloOnce(override val context: IdChatIdentifier) : InternalFSMState data class SaidHelloOnce(override val context: IdChatIdentifier) : InternalFSMState
} }
override suspend fun startPlugin(koin: Koin) {
super.startPlugin(koin)
logger.i { "This logic called BEFORE the bot will be started and setup" }
}
override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) { override suspend fun BehaviourContextWithFSM<State>.setupBotPlugin(koin: Koin) {
val toPrint = koin.getOrNull<HelloPluginConfig>() ?.print ?: "Hello :)" val toPrint = koin.configOrNull<HelloPluginConfig>() ?.print ?: "Hello :)"
logger.d { toPrint } logger.d { toPrint }
logger.dS { getMe().toString() } logger.dS { getMe().toString() }
onCommand("hello_world") { onCommand("hello_world") {

View File

@@ -0,0 +1,11 @@
package dev.inmo.plagubot
import org.jetbrains.exposed.sql.Database
import org.koin.core.Koin
import org.koin.core.scope.Scope
val Scope.database: Database
get() = get()
val Koin.database: Database
get() = get()

View File

@@ -0,0 +1,55 @@
package dev.inmo.plagubot
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.serializer
import org.jetbrains.exposed.sql.Database
import org.koin.core.Koin
import org.koin.core.module.Module
import org.koin.core.scope.Scope
import kotlin.reflect.KClass
/**
* Using [single] to register `T` with serializer [configSerializer]
*
* @param default Will be used if [field] is absent as an alternative way of config allocation. If null passed, error
* will be thrown
*/
inline fun <reified T> Module.registerConfig(configSerializer: KSerializer<T>, field: String?, noinline default: (Scope.(JsonObject) -> T?)? = null) {
single {
val fieldValue = get<JsonObject>().let {
if (field == null) {
it
} else {
it[field] ?: default ?.let { _ ->
return@single default(it)
} ?: error("Unable to take field $field from config")
}
}
get<Json>().decodeFromJsonElement(configSerializer, fieldValue)
}
}
/**
* Using [single] to register config with getting of [serializer] from [kClass]
*
* @param default Will be used if [field] is absent as an alternative way of config allocation. If null passed, error
* will be thrown
*/
@OptIn(InternalSerializationApi::class)
inline fun <reified T : Any> Module.registerConfig(kClass: KClass<T>, field: String?, noinline default: (Scope.(JsonObject) -> T?)? = null) = registerConfig(kClass.serializer(), field, default)
/**
* Using [single] to register config with getting of [serializer] from [kClass]
*
* @param default Will be used if [field] is absent as an alternative way of config allocation. If null passed, error
* will be thrown
*/
inline fun <reified T : Any> Module.registerConfig(field: String?, noinline default: (Scope.(JsonObject) -> T?)? = null) = registerConfig(T::class, field, default)
inline fun <reified T : Any> Scope.config() = get<T>()
inline fun <reified T : Any> Koin.config() = get<T>()
inline fun <reified T : Any> Scope.configOrNull() = getOrNull<T>()
inline fun <reified T : Any> Koin.configOrNull() = getOrNull<T>()

View File

@@ -1,13 +1,14 @@
package dev.inmo.plagubot package dev.inmo.plagubot
import dev.inmo.micro_utils.fsm.common.State import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.micro_utils.startup.plugin.StartPlugin
import dev.inmo.tgbotapi.bot.ktor.KtorRequestsExecutorBuilder
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContextWithFSM
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import org.jetbrains.exposed.sql.Database
import org.koin.core.Koin import org.koin.core.Koin
import org.koin.core.module.Module import org.koin.core.scope.Scope
/** /**
* **ANY REALIZATION OF [Plugin] MUST HAVE CONSTRUCTOR WITH ABSENCE OF INCOMING PARAMETERS** * **ANY REALIZATION OF [Plugin] MUST HAVE CONSTRUCTOR WITH ABSENCE OF INCOMING PARAMETERS**
@@ -17,14 +18,17 @@ import org.koin.core.module.Module
* too. * too.
*/ */
@Serializable(PluginSerializer::class) @Serializable(PluginSerializer::class)
interface Plugin { interface Plugin : StartPlugin {
@Deprecated("Deprecated in favor to setupBotClient with arguments")
fun KtorRequestsExecutorBuilder.setupBotClient() {}
/** /**
* This method will be called when this plugin should configure di module based on the incoming params * Will be called on stage of bot setup
*
* @param scope The scope of [org.koin.core.module.Module.single] of bot definition
* @param params Params (in fact, the whole bot config)
*/ */
fun Module.setupDI( fun KtorRequestsExecutorBuilder.setupBotClient(scope: Scope, params: JsonObject) = setupBotClient()
database: Database,
params: JsonObject
) {}
/** /**
* Override this method in cases when you want to declare common bot behaviour. In case you wish to use FSM, you * Override this method in cases when you want to declare common bot behaviour. In case you wish to use FSM, you