mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2025-11-17 04:20:13 +00:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6dd1825b98 | |||
| bd4eb29fc1 | |||
| 2cc66ef13c | |||
| 9a8175d1c8 | |||
| 25285b2e8a | |||
| bb09f05d7b | |||
| da5e46e59f | |||
| a3f315a73a | |||
| 43583a885a | |||
| ec02257ecd | |||
| 29ee4a9396 | |||
| 2717cb4fc6 | |||
| 1ce2526401 | |||
| 74c480b07e | |||
| 657e9aa770 | |||
| 0d19952ba7 | |||
| f8cccc3e17 | |||
| bc1b7c3f25 | |||
| ec74111a9d | |||
| 2dadeb7eb7 | |||
| 24bd65501b | |||
| 574ca803fa | |||
| 947e3bf34e | |||
| 488158d8fb | |||
| 41bf3c7f0b | |||
| c2032d21cd | |||
| 6650dd9cfe | |||
| af1d6d6f1a | |||
| a5861d659d | |||
| b36f80a6d3 | |||
| 7c4f034a6c | |||
| 3b08bc6dd2 | |||
| ed87c0ad95 | |||
| c8c0fc2ce8 | |||
| 1f40ce1a81 | |||
| b0219389fc | |||
| f6ec82b449 | |||
| 71dac70635 | |||
| 98f68a9e1e | |||
| e7199e7451 | |||
| 33b50c6c68 | |||
| e4ce6f8fc7 | |||
| 8764f18ca8 | |||
| b2fa7fee9d | |||
| 0121e3a104 | |||
| f6e5664632 | |||
| c5b7c4e1f5 | |||
| 53800d49bf | |||
| d83e3eb10a | |||
| 66b4d06064 | |||
| 4fab01b2a2 | |||
| b81086c4bb | |||
| d776071cac | |||
| 5f33d05deb | |||
| 912cc7217c | |||
| 96e00f6e31 | |||
| f8ea5f9515 | |||
| 9f11c4f1c4 | |||
| 9c91980d5d | |||
| 7376eb5b10 | |||
| 6654f27f9d | |||
| 83edda2dfe |
113
CHANGELOG.md
113
CHANGELOG.md
@@ -1,5 +1,118 @@
|
|||||||
# TelegramBotAPI changelog
|
# TelegramBotAPI changelog
|
||||||
|
|
||||||
|
## 0.30.9
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `UUID`: `0.2.2` -> `0.2.3`
|
||||||
|
* `Coroutines`: `1.4.1` -> `1.4.2`
|
||||||
|
* `MicroUtils`: `0.4.3` -> `0.4.6`
|
||||||
|
* `Core`:
|
||||||
|
* Add `BowlingDiceAnimationType`
|
||||||
|
|
||||||
|
## 0.30.8
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `Kotlin`: `1.4.10` -> `1.4.20`
|
||||||
|
* `Klock`: `1.12.1` -> `2.0.0`
|
||||||
|
* `MicroUtils`: `0.4.1` -> `0.4.3`
|
||||||
|
|
||||||
|
## 0.30.7
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `MicroUtils`: `0.4.0` -> `0.4.1`
|
||||||
|
* `Core`:
|
||||||
|
* `TelegramAPIUrlsKeeper` will fix ending of host url since this version
|
||||||
|
* New mechanisms in`PowLimiter` and `CommonLimiter` has been added
|
||||||
|
* New builder `KtorRequestsExecutorBuilder`
|
||||||
|
* New function `telegramBot`
|
||||||
|
* `Utils`:
|
||||||
|
* Simple function `telegramBot(TelegramAPIUrlsKeeper)` has been deprecated with replacement by almost the same
|
||||||
|
function in `Core`
|
||||||
|
|
||||||
|
## 0.30.6
|
||||||
|
|
||||||
|
* `Core`
|
||||||
|
* `TextSource` properties has been renamed:
|
||||||
|
* `asMarkdownSource` -> `markdown`
|
||||||
|
* `asMarkdownV2Source` -> `markdownV2`
|
||||||
|
* `asHtmlSource` -> `html`
|
||||||
|
* `PrivateChat` override `id` property with type `UserId`
|
||||||
|
* Several new extensions and functions in links creation:
|
||||||
|
* New function `makeUsernameLink` with parameter `String`
|
||||||
|
* New extension `Username#link` and function `makeLink(Username)`
|
||||||
|
* Function `makeLinkToMessage` now able to get any type of chat
|
||||||
|
* New extension `Message#link`
|
||||||
|
* Old functions `makeLinkToAddStickerSet...` has been deprecated:
|
||||||
|
* `makeLinkToAddStickerSet`
|
||||||
|
* `makeLinkToAddStickerSetInMarkdownV2`
|
||||||
|
* `makeLinkToAddStickerSetInMarkdown`
|
||||||
|
* `makeLinkToAddStickerSetInHtml`
|
||||||
|
|
||||||
|
## 0.30.5
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `MicroUtils`: `0.3.3` -> `0.4.0`
|
||||||
|
* `Core`:
|
||||||
|
* Mechanism of `ChatMember` serialization has been changed
|
||||||
|
* Since this version any `ChatMember` can be serialized (even outside in case it marked by `@Serializable`)
|
||||||
|
* Since this version any `ChatMember` (included in this project) can be deserialized in common way
|
||||||
|
* `User` property `id` has changed its type: now it is `UserId` (under the hood it is the same as `ChatId`)
|
||||||
|
|
||||||
|
## 0.30.4
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `MicroUtils`: `0.3.1` -> `0.3.3`
|
||||||
|
* `Core`:
|
||||||
|
* `MultilevelTextSource#textSources` has been safely renamed to `subsources`
|
||||||
|
* `TextContent#fullEntitiesList` has been deprecated
|
||||||
|
* Now `TextContent` implements `TextedInput`
|
||||||
|
* `TextContent#entities` has been deprecated
|
||||||
|
* `GroupEventMessage` now overrides `chatEvent` with type `GroupEvent`
|
||||||
|
* `SupergroupEventMessage` now overrides `chatEvent` with type `SupergroupEvent`
|
||||||
|
* Any `ChatEventMessage` now have generic type of its `chatEvent` (just like messages)
|
||||||
|
* `Utils`:
|
||||||
|
* Old extensions related to chat events are deprecated:
|
||||||
|
* `Flow<ChatEventMessage<*>>#divideBySource`
|
||||||
|
* `Flow<ChatEventMessage<*>>#onlyChannelEvents`
|
||||||
|
* `Flow<ChatEventMessage<*>>#onlyGroupEvents`
|
||||||
|
* `Flow<ChatEventMessage<*>>#onlySupergroupEvents`
|
||||||
|
* A lot of extensions for `Flow<ChatEventMessage>` has been added:
|
||||||
|
* `FlowsUpdatesFilter#events`
|
||||||
|
* `FlowsUpdatesFilter#channelEvents`
|
||||||
|
* `FlowsUpdatesFilter#groupEvents`
|
||||||
|
* `FlowsUpdatesFilter#supergroupEvents`
|
||||||
|
* And a lot of other filters with specific types
|
||||||
|
|
||||||
|
## 0.30.3
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `MicroUtils`: `0.3.0` -> `0.3.1`
|
||||||
|
* `Core`:
|
||||||
|
* New type of requests exceptions `TooMuchRequestsException`. In fact it will be rare case when you will get this
|
||||||
|
exception
|
||||||
|
* `EmptyLimiter` has been renamed to `ExceptionsOnlyLimiter` and currently will stop requests after
|
||||||
|
`TooMuchRequestsException` happen until retry time is actual
|
||||||
|
* Now `ExceptionsOnlyLimiter` (previously `EmptyLimiter`) is a class
|
||||||
|
* `AbstractRequestCallFactory` currently will not look at the response and wait if it have `RetryAfter` error. New
|
||||||
|
behaviour aimed on delegating of this work to `RequestsLimiter`
|
||||||
|
|
||||||
|
## 0.30.2
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* `Version`:
|
||||||
|
* `Ktor`: `1.4.1` -> `1.4.2`
|
||||||
|
* `Core`:
|
||||||
|
* New sealed class `SetWebhookRequest` which can be used in `SetWebhook` requests
|
||||||
|
* `Utils`:
|
||||||
|
* Extensions `setWebhookInfoAndStartListenWebhooks` has been united in one extension with `SetWebhookRequest`
|
||||||
|
incoming parameter
|
||||||
|
|
||||||
## 0.30.1
|
## 0.30.1
|
||||||
|
|
||||||
* `Common`:
|
* `Common`:
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -1,8 +1,19 @@
|
|||||||
# TelegramBotAPI
|
# TelegramBotAPI
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><b>I do not wanna read a lot, just give me my bot</b></summary>
|
||||||
|
|
||||||
|
You can simply use [this template](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template) (and button
|
||||||
|
`Use template`) to get your copy of bot and start to code.
|
||||||
|
|
||||||
|
**P.S. Do not forget to look into our [minidocs](https://bookstack.inmo.dev/books/telegrambotapi/) and
|
||||||
|
[kdocs](https://tgbotapi.inmo.dev/docs/index.html)**
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
| Common info | [](https://github.com/KotlinBy/awesome-kotlin) [](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
|
| Common info | [](https://github.com/KotlinBy/awesome-kotlin) [](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
|
||||||
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| Useful links | [](https://t.me/InMoTelegramBotAPI) [](https://tgbotapi.inmo.dev/docs/index.html) [Examples](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/), [Mini tutorial](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|
| Useful links | [](https://t.me/InMoTelegramBotAPI) [](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate) [](https://tgbotapi.inmo.dev/docs/index.html) [Examples](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/), [Mini tutorial](https://bookstack.inmo.dev/books/telegrambotapi/chapter/introduction-tutorial) |
|
||||||
| TelegramBotAPI Core status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.core/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) |
|
| TelegramBotAPI Core status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.core/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) |
|
||||||
| TelegramBotAPI Extensions status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api) |
|
| TelegramBotAPI Extensions status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api) |
|
||||||
| TelegramBotAPI Util Extensions status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils) |
|
| TelegramBotAPI Util Extensions status | [](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/_latestVersion) [](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils) |
|
||||||
@@ -12,6 +23,7 @@
|
|||||||
[kotlinx.serialization#1004](https://github.com/Kotlin/kotlinx.serialization/issues/1004). It is possible, that both JVM
|
[kotlinx.serialization#1004](https://github.com/Kotlin/kotlinx.serialization/issues/1004). It is possible, that both JVM
|
||||||
and JS version may work improperly in some cases with `kotlinx.serialization` version `1.0.0-RC`**
|
and JS version may work improperly in some cases with `kotlinx.serialization` version `1.0.0-RC`**
|
||||||
|
|
||||||
|
## What is it?
|
||||||
|
|
||||||
It is a complex of libraries for working with `TelegramBotAPI` in type-safe and strict way as much as it possible. In
|
It is a complex of libraries for working with `TelegramBotAPI` in type-safe and strict way as much as it possible. In
|
||||||
the list of this complex currently next projects:
|
the list of this complex currently next projects:
|
||||||
|
|||||||
20
badges/template.svg
Normal file
20
badges/template.svg
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="104" height="20">
|
||||||
|
<linearGradient id="b" x2="0" y2="100%">
|
||||||
|
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
||||||
|
<stop offset="1" stop-opacity=".1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<clipPath id="a">
|
||||||
|
<rect width="104" height="20" rx="3" fill="#fff"/>
|
||||||
|
</clipPath>
|
||||||
|
<g clip-path="url(#a)">
|
||||||
|
<path fill="#555" d="M0 0h65v20H0z"/>
|
||||||
|
<path fill="#007ec6" d="M35 0h69v20H35z"/>
|
||||||
|
<path fill="url(#b)" d="M0 0h104v20H0z"/>
|
||||||
|
</g>
|
||||||
|
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
|
||||||
|
<text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">Bot</text>
|
||||||
|
<text x="175" y="140" transform="scale(.1)">Bot</text>
|
||||||
|
<text x="690" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">Template</text>
|
||||||
|
<text x="690" y="140" transform="scale(.1)">Template</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1016 B |
@@ -9,7 +9,6 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
|
|
||||||
classpath "com.github.breadmoirai:github-release:$github_release_plugin_version"
|
classpath "com.github.breadmoirai:github-release:$github_release_plugin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,19 +5,18 @@ kotlin.js.generate.externals=true
|
|||||||
kotlin.incremental=true
|
kotlin.incremental=true
|
||||||
kotlin.incremental.js=true
|
kotlin.incremental.js=true
|
||||||
|
|
||||||
kotlin_version=1.4.10
|
kotlin_version=1.4.20
|
||||||
kotlin_coroutines_version=1.4.1
|
kotlin_coroutines_version=1.4.2
|
||||||
kotlin_serialisation_runtime_version=1.0.1
|
kotlin_serialisation_runtime_version=1.0.1
|
||||||
klock_version=1.12.1
|
klock_version=2.0.0
|
||||||
uuid_version=0.2.2
|
uuid_version=0.2.3
|
||||||
ktor_version=1.4.1
|
ktor_version=1.4.2
|
||||||
|
|
||||||
micro_utils_version=0.3.0
|
micro_utils_version=0.4.6
|
||||||
|
|
||||||
javax_activation_version=1.1.1
|
javax_activation_version=1.1.1
|
||||||
|
|
||||||
library_group=dev.inmo
|
library_group=dev.inmo
|
||||||
library_version=0.30.1
|
library_version=0.30.9
|
||||||
|
|
||||||
gradle_bintray_plugin_version=1.8.5
|
|
||||||
github_release_plugin_version=2.2.12
|
github_release_plugin_version=2.2.12
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
apply plugin: 'maven-publish'
|
|
||||||
|
|
||||||
task javadocsJar(type: Jar) {
|
|
||||||
classifier = 'javadoc'
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
project.publishing.publications.all {
|
|
||||||
// rename artifacts
|
|
||||||
groupId "${project.group}"
|
|
||||||
if (it.name.contains('kotlinMultiplatform')) {
|
|
||||||
artifactId = "${project.name}"
|
|
||||||
} else {
|
|
||||||
artifactId = "${project.name}-$name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications.all {
|
|
||||||
artifact javadocsJar
|
|
||||||
|
|
||||||
pom {
|
|
||||||
description = "Library for Object-Oriented and type-safe work with Telegram Bot API"
|
|
||||||
name = "Telegram Bot API Core"
|
|
||||||
url = "https://insanusmokrassar.github.io/TelegramBotAPI"
|
|
||||||
|
|
||||||
scm {
|
|
||||||
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
}
|
|
||||||
|
|
||||||
developers {
|
|
||||||
|
|
||||||
developer {
|
|
||||||
id = "InsanusMokrassar"
|
|
||||||
name = "Ovsiannikov Aleksei"
|
|
||||||
email = "ovsyannikov.alexey95@gmail.com"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
|
|
||||||
license {
|
|
||||||
name = "Apache Software License 2.0"
|
|
||||||
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +1,65 @@
|
|||||||
apply plugin: 'com.jfrog.bintray'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
apply from: "maven.publish.gradle"
|
task javadocsJar(type: Jar) {
|
||||||
|
classifier = 'javadoc'
|
||||||
bintray {
|
|
||||||
user = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
|
||||||
key = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
|
||||||
filesSpec {
|
|
||||||
from "${buildDir}/publications/"
|
|
||||||
eachFile {
|
|
||||||
String directorySubname = it.getFile().parentFile.name
|
|
||||||
if (it.getName() == "module.json") {
|
|
||||||
if (directorySubname == "kotlinMultiplatform") {
|
|
||||||
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module")
|
|
||||||
} else {
|
|
||||||
it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") {
|
|
||||||
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom")
|
|
||||||
} else {
|
|
||||||
it.exclude()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
into "${project.group}".replace(".", "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
publish = true
|
|
||||||
override = true
|
|
||||||
|
|
||||||
pkg {
|
|
||||||
repo = "TelegramBotAPI"
|
|
||||||
name = "${project.name}"
|
|
||||||
vcsUrl = "https://github.com/InsanusMokrassar/TelegramBotAPI"
|
|
||||||
licenses = ["Apache-2.0"]
|
|
||||||
version {
|
|
||||||
name = "${project.version}"
|
|
||||||
released = new Date()
|
|
||||||
vcsTag = "${project.version}"
|
|
||||||
gpg {
|
|
||||||
sign = true
|
|
||||||
passphrase = project.hasProperty('signing.gnupg.passphrase') ? project.property('signing.gnupg.passphrase') : System.getenv('signing.gnupg.passphrase')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bintrayUpload.doFirst {
|
afterEvaluate {
|
||||||
publications = publishing.publications.collect {
|
project.publishing.publications.all {
|
||||||
|
// rename artifacts
|
||||||
|
groupId "${project.group}"
|
||||||
if (it.name.contains('kotlinMultiplatform')) {
|
if (it.name.contains('kotlinMultiplatform')) {
|
||||||
null
|
artifactId = "${project.name}"
|
||||||
} else {
|
} else {
|
||||||
it.name
|
artifactId = "${project.name}-$name"
|
||||||
}
|
}
|
||||||
} - null
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bintrayUpload.dependsOn publishToMavenLocal
|
publishing {
|
||||||
|
publications.all {
|
||||||
|
artifact javadocsJar
|
||||||
|
|
||||||
|
pom {
|
||||||
|
description = "Library for Object-Oriented and type-safe work with Telegram Bot API"
|
||||||
|
name = "Telegram Bot API Core"
|
||||||
|
url = "https://insanusmokrassar.github.io/TelegramBotAPI"
|
||||||
|
|
||||||
|
scm {
|
||||||
|
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
}
|
||||||
|
|
||||||
|
developers {
|
||||||
|
|
||||||
|
developer {
|
||||||
|
id = "InsanusMokrassar"
|
||||||
|
name = "Ovsiannikov Aleksei"
|
||||||
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
|
||||||
|
license {
|
||||||
|
name = "Apache Software License 2.0"
|
||||||
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "bintray"
|
||||||
|
url = uri("https://api.bintray.com/maven/${project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')}/TelegramBotAPI/${project.name}/;publish=1;override=1")
|
||||||
|
credentials {
|
||||||
|
username = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
||||||
|
password = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,13 +14,23 @@ typealias FullTextSourcesList = List<TextSource>
|
|||||||
typealias FullTextPartsList = List<TextPart>
|
typealias FullTextPartsList = List<TextPart>
|
||||||
|
|
||||||
interface TextSource {
|
interface TextSource {
|
||||||
val asMarkdownSource: String
|
val markdown: String
|
||||||
val asMarkdownV2Source: String
|
val markdownV2: String
|
||||||
val asHtmlSource: String
|
val html: String
|
||||||
val source: String
|
val source: String
|
||||||
|
|
||||||
val asText: String
|
val asText: String
|
||||||
get() = source
|
get() = source
|
||||||
|
|
||||||
|
@Deprecated("Rename", ReplaceWith("markdown"))
|
||||||
|
val asMarkdownSource: String
|
||||||
|
get() = markdown
|
||||||
|
@Deprecated("Rename", ReplaceWith("markdownV2"))
|
||||||
|
val asMarkdownV2Source: String
|
||||||
|
get() = markdownV2
|
||||||
|
@Deprecated("Rename", ReplaceWith("html"))
|
||||||
|
val asHtmlSource: String
|
||||||
|
get() = html
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
@@ -36,7 +46,10 @@ interface MultilevelTextSource : TextSource {
|
|||||||
@Deprecated("Will be removed in near major release")
|
@Deprecated("Will be removed in near major release")
|
||||||
val textParts: List<TextPart>
|
val textParts: List<TextPart>
|
||||||
get() = textParts(0)
|
get() = textParts(0)
|
||||||
|
val subsources: List<TextSource>
|
||||||
|
@Deprecated("Will be removed in near major release", ReplaceWith("subsources"))
|
||||||
val textSources: List<TextSource>
|
val textSources: List<TextSource>
|
||||||
|
get() = subsources
|
||||||
}
|
}
|
||||||
|
|
||||||
data class TextPart(
|
data class TextPart(
|
||||||
@@ -46,7 +59,7 @@ data class TextPart(
|
|||||||
|
|
||||||
fun List<TextPart>.justTextSources() = map { it.source }
|
fun List<TextPart>.justTextSources() = map { it.source }
|
||||||
fun List<TextSource>.makeString() = joinToString("") { it.source }
|
fun List<TextSource>.makeString() = joinToString("") { it.source }
|
||||||
internal fun MultilevelTextSource.textParts(offset: Int): List<TextPart> = textSources.toTextParts(offset)
|
internal fun MultilevelTextSource.textParts(offset: Int): List<TextPart> = subsources.toTextParts(offset)
|
||||||
fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> {
|
fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> {
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
return emptyList()
|
return emptyList()
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package dev.inmo.tgbotapi.bot.Ktor
|
|||||||
import dev.inmo.micro_utils.coroutines.safely
|
import dev.inmo.micro_utils.coroutines.safely
|
||||||
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
|
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
|
||||||
import dev.inmo.tgbotapi.bot.Ktor.base.*
|
import dev.inmo.tgbotapi.bot.Ktor.base.*
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
||||||
import dev.inmo.tgbotapi.bot.settings.limiters.EmptyLimiter
|
import dev.inmo.tgbotapi.bot.settings.limiters.*
|
||||||
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
|
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
import dev.inmo.tgbotapi.types.Response
|
import dev.inmo.tgbotapi.types.Response
|
||||||
import dev.inmo.tgbotapi.utils.*
|
import dev.inmo.tgbotapi.utils.*
|
||||||
@@ -14,12 +14,39 @@ import io.ktor.client.features.*
|
|||||||
import io.ktor.client.statement.readText
|
import io.ktor.client.statement.readText
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
class KtorRequestsExecutorBuilder(
|
||||||
|
var telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
|
||||||
|
) {
|
||||||
|
var client: HttpClient = HttpClient()
|
||||||
|
var callsFactories: List<KtorCallFactory> = emptyList()
|
||||||
|
var excludeDefaultFactories: Boolean = false
|
||||||
|
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter()
|
||||||
|
var jsonFormatter: Json = nonstrictJsonFormat
|
||||||
|
|
||||||
|
fun build() = KtorRequestsExecutor(telegramAPIUrlsKeeper, client, callsFactories, excludeDefaultFactories, requestsLimiter, jsonFormatter)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun telegramBot(
|
||||||
|
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
|
||||||
|
crossinline builder: KtorRequestsExecutorBuilder.() -> Unit = {}
|
||||||
|
): TelegramBot = KtorRequestsExecutorBuilder(telegramAPIUrlsKeeper).apply(builder).build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut for [telegramBot]
|
||||||
|
*/
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun telegramBot(
|
||||||
|
token: String,
|
||||||
|
apiUrl: String = telegramBotAPIDefaultUrl,
|
||||||
|
crossinline builder: KtorRequestsExecutorBuilder.() -> Unit = {}
|
||||||
|
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, apiUrl), builder)
|
||||||
|
|
||||||
class KtorRequestsExecutor(
|
class KtorRequestsExecutor(
|
||||||
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
|
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
|
||||||
client: HttpClient = HttpClient(),
|
client: HttpClient = HttpClient(),
|
||||||
callsFactories: List<KtorCallFactory> = emptyList(),
|
callsFactories: List<KtorCallFactory> = emptyList(),
|
||||||
excludeDefaultFactories: Boolean = false,
|
excludeDefaultFactories: Boolean = false,
|
||||||
private val requestsLimiter: RequestLimiter = EmptyLimiter,
|
private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter(),
|
||||||
private val jsonFormatter: Json = nonstrictJsonFormat
|
private val jsonFormatter: Json = nonstrictJsonFormat
|
||||||
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
|
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
|
||||||
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
|
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.inmo.tgbotapi.bot.Ktor.base
|
package dev.inmo.tgbotapi.bot.Ktor.base
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.safely
|
||||||
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
|
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
|
||||||
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
import dev.inmo.tgbotapi.bot.exceptions.newRequestException
|
||||||
import dev.inmo.tgbotapi.requests.GetUpdates
|
import dev.inmo.tgbotapi.requests.GetUpdates
|
||||||
@@ -51,23 +52,17 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
|
|||||||
val content = response.receive<String>()
|
val content = response.receive<String>()
|
||||||
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
|
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
|
||||||
|
|
||||||
return (responseObject.result?.let {
|
return safely {
|
||||||
jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it)
|
(responseObject.result?.let {
|
||||||
} ?: responseObject.parameters?.let {
|
jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it)
|
||||||
val error = it.error
|
} ?: response.let {
|
||||||
if (error is RetryAfterError) {
|
throw newRequestException(
|
||||||
delay(error.leftToRetry)
|
responseObject,
|
||||||
makeCall(client, urlsKeeper, request, jsonFormatter)
|
content,
|
||||||
} else {
|
"Can't get result object from $content"
|
||||||
null
|
)
|
||||||
}
|
})
|
||||||
} ?: response.let {
|
}
|
||||||
throw newRequestException(
|
|
||||||
responseObject,
|
|
||||||
content,
|
|
||||||
"Can't get result object from $content"
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.bot.exceptions
|
package dev.inmo.tgbotapi.bot.exceptions
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.Response
|
import com.soywiz.klock.DateTime
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
import io.ktor.utils.io.errors.IOException
|
import io.ktor.utils.io.errors.IOException
|
||||||
|
|
||||||
fun newRequestException(
|
fun newRequestException(
|
||||||
@@ -16,6 +17,13 @@ fun newRequestException(
|
|||||||
description == "Unauthorized" -> UnauthorizedException(response, plainAnswer, message, cause)
|
description == "Unauthorized" -> UnauthorizedException(response, plainAnswer, message, cause)
|
||||||
description.contains("PHOTO_INVALID_DIMENSIONS") -> InvalidPhotoDimensionsException(response, plainAnswer, message, cause)
|
description.contains("PHOTO_INVALID_DIMENSIONS") -> InvalidPhotoDimensionsException(response, plainAnswer, message, cause)
|
||||||
description.contains("wrong file identifier") -> WrongFileIdentifierException(response, plainAnswer, message, cause)
|
description.contains("wrong file identifier") -> WrongFileIdentifierException(response, plainAnswer, message, cause)
|
||||||
|
description.contains("Too Many Requests") -> TooMuchRequestsException(
|
||||||
|
(response.parameters ?.error as? RetryAfterError) ?: RetryAfterError(60, DateTime.now().unixMillisLong),
|
||||||
|
response,
|
||||||
|
plainAnswer,
|
||||||
|
message,
|
||||||
|
cause
|
||||||
|
)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
} ?: CommonRequestException(response, plainAnswer, message, cause)
|
} ?: CommonRequestException(response, plainAnswer, message, cause)
|
||||||
@@ -49,3 +57,6 @@ class InvalidPhotoDimensionsException(response: Response, plainAnswer: String, m
|
|||||||
|
|
||||||
class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
|
class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
|
||||||
RequestException(response, plainAnswer, message, cause)
|
RequestException(response, plainAnswer, message, cause)
|
||||||
|
|
||||||
|
class TooMuchRequestsException(val retryAfter: RetryAfterError, response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
|
||||||
|
RequestException(response, plainAnswer, message, cause)
|
||||||
|
|||||||
@@ -1,67 +1,43 @@
|
|||||||
package dev.inmo.tgbotapi.bot.settings.limiters
|
package dev.inmo.tgbotapi.bot.settings.limiters
|
||||||
|
|
||||||
import com.soywiz.klock.DateTime
|
import com.soywiz.klock.DateTime
|
||||||
|
import dev.inmo.micro_utils.coroutines.*
|
||||||
|
import dev.inmo.tgbotapi.types.MilliSeconds
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.sync.Semaphore
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
|
import kotlin.coroutines.Continuation
|
||||||
|
import kotlin.math.roundToLong
|
||||||
|
|
||||||
private fun now(): Long = DateTime.nowUnixLong()
|
private fun now(): Long = DateTime.nowUnixLong()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
class CommonLimiter(
|
class CommonLimiter(
|
||||||
private val lockCount: Int = 10,
|
private val lockCount: Int = 10,
|
||||||
private val regenTime: Long = 20 * 1000L // 20 seconds for full regen of opportunity to send message
|
private val regenTime: MilliSeconds = 15 * 1000, // 15 seconds for full regen of opportunity to send message
|
||||||
|
@Transient
|
||||||
|
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
) : RequestLimiter {
|
) : RequestLimiter {
|
||||||
private var doLimit: Boolean = false
|
private val quotaSemaphore = Semaphore(lockCount)
|
||||||
|
private val counterRegeneratorJob = scope.launch {
|
||||||
private val counterChannel = Channel<Unit>(Channel.UNLIMITED)
|
val regenDelay: MilliSeconds = (regenTime.toDouble() / lockCount).roundToLong()
|
||||||
private val scope = CoroutineScope(Dispatchers.Default)
|
while (isActive) {
|
||||||
private val counterJob = scope.launch {
|
delay(regenDelay)
|
||||||
var wasLastSecond = 0
|
if (quotaSemaphore.availablePermits < lockCount) {
|
||||||
var lastCountTime = now()
|
try {
|
||||||
var limitManagementJob: Job? = null
|
quotaSemaphore.release()
|
||||||
var removeLimitTime: Long = lastCountTime
|
} catch (_: IllegalStateException) {
|
||||||
for (counter in counterChannel) {
|
// Skip IllegalStateException due to the fact that this exception may happens in release method
|
||||||
val now = now()
|
|
||||||
if (now - lastCountTime > 1000) {
|
|
||||||
lastCountTime = now
|
|
||||||
wasLastSecond = 1
|
|
||||||
} else {
|
|
||||||
wasLastSecond++
|
|
||||||
}
|
|
||||||
if (wasLastSecond >= lockCount) {
|
|
||||||
removeLimitTime = now + regenTime
|
|
||||||
if (limitManagementJob == null) {
|
|
||||||
limitManagementJob = launch {
|
|
||||||
doLimit = true
|
|
||||||
var internalNow = now()
|
|
||||||
while (internalNow < removeLimitTime) {
|
|
||||||
delay(removeLimitTime - internalNow)
|
|
||||||
internalNow = now()
|
|
||||||
}
|
|
||||||
doLimit = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (now > removeLimitTime) {
|
|
||||||
limitManagementJob = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val quoterChannel = Channel<Unit>(Channel.CONFLATED)
|
|
||||||
private val tickerJob = scope.launch {
|
|
||||||
while (isActive) {
|
|
||||||
quoterChannel.send(Unit)
|
|
||||||
delay(1000L)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun <T> limit(block: suspend () -> T): T {
|
override suspend fun <T> limit(block: suspend () -> T): T {
|
||||||
counterChannel.send(Unit)
|
quotaSemaphore.acquire()
|
||||||
return if (!doLimit) {
|
return block()
|
||||||
block()
|
|
||||||
} else {
|
|
||||||
quoterChannel.receive()
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package dev.inmo.tgbotapi.bot.settings.limiters
|
|
||||||
|
|
||||||
object EmptyLimiter : RequestLimiter {
|
|
||||||
override suspend fun <T> limit(block: suspend () -> T): T = block()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package dev.inmo.tgbotapi.bot.settings.limiters
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.safely
|
||||||
|
import dev.inmo.tgbotapi.bot.exceptions.TooMuchRequestsException
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import io.ktor.client.features.ClientRequestException
|
||||||
|
import io.ktor.http.HttpStatusCode
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This limiter will limit requests only after getting a [RetryAfterError] or [ClientRequestException] with
|
||||||
|
* [HttpStatusCode.TooManyRequests] status code. Important thing is that in case if some of block has been blocked, all
|
||||||
|
* the others will wait until it will be possible to be called
|
||||||
|
*
|
||||||
|
* @param defaultTooManyRequestsDelay This parameter will be used in case of getting [ClientRequestException] with
|
||||||
|
* [HttpStatusCode.TooManyRequests] as a parameter for delay like it would be [TooMuchRequestsException]. The reason of
|
||||||
|
* it is that in [ClientRequestException] there is no information about required delay between requests
|
||||||
|
*/
|
||||||
|
class ExceptionsOnlyLimiter(
|
||||||
|
private val defaultTooManyRequestsDelay: MilliSeconds = 1000L
|
||||||
|
) : RequestLimiter {
|
||||||
|
private val lockState = MutableStateFlow(false)
|
||||||
|
private suspend fun lock(timeMillis: MilliSeconds) {
|
||||||
|
try {
|
||||||
|
safely {
|
||||||
|
lockState.emit(true)
|
||||||
|
delay(timeMillis)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lockState.emit(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun <T> limit(block: suspend () -> T): T {
|
||||||
|
while (true) {
|
||||||
|
lockState.first { !it }
|
||||||
|
val result = safely({
|
||||||
|
when (it) {
|
||||||
|
is TooMuchRequestsException -> {
|
||||||
|
lock(it.retryAfter.leftToRetry)
|
||||||
|
Result.failure(it)
|
||||||
|
}
|
||||||
|
is ClientRequestException -> {
|
||||||
|
if (it.response.status == HttpStatusCode.TooManyRequests) {
|
||||||
|
lock(defaultTooManyRequestsDelay)
|
||||||
|
} else {
|
||||||
|
throw it
|
||||||
|
}
|
||||||
|
Result.failure(it)
|
||||||
|
}
|
||||||
|
else -> throw it
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
Result.success(block())
|
||||||
|
}
|
||||||
|
if (result.isSuccess) {
|
||||||
|
return result.getOrNull()!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Renamed", ReplaceWith("ExceptionsOnlyLimiter", "dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter"))
|
||||||
|
typealias EmptyLimiter = ExceptionsOnlyLimiter
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.bot.settings.limiters
|
package dev.inmo.tgbotapi.bot.settings.limiters
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.*
|
||||||
|
import dev.inmo.tgbotapi.types.MilliSeconds
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -9,62 +11,60 @@ import kotlin.math.pow
|
|||||||
|
|
||||||
private sealed class RequestEvent
|
private sealed class RequestEvent
|
||||||
private class AddRequest(
|
private class AddRequest(
|
||||||
val continuation: Continuation<Long>
|
val continuation: Continuation<MilliSeconds>
|
||||||
) : RequestEvent()
|
) : RequestEvent()
|
||||||
private object CompleteRequest : RequestEvent()
|
private object CompleteRequest : RequestEvent()
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PowLimiter(
|
data class PowLimiter(
|
||||||
private val minAwaitTime: Long = 0L,
|
private val minAwaitTime: MilliSeconds = 0L,
|
||||||
private val maxAwaitTime: Long = 10000L,
|
private val maxAwaitTime: MilliSeconds = 10000L,
|
||||||
private val powValue: Double = 4.0,
|
private val powValue: Double = 4.0,
|
||||||
private val powK: Double = 0.0016
|
private val powK: Double = 1.6,
|
||||||
|
@Transient
|
||||||
|
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
) : RequestLimiter {
|
) : RequestLimiter {
|
||||||
@Transient
|
|
||||||
private val scope = CoroutineScope(Dispatchers.Default)
|
|
||||||
@Transient
|
|
||||||
private val eventsChannel = Channel<RequestEvent>(Channel.UNLIMITED)
|
|
||||||
@Transient
|
@Transient
|
||||||
private val awaitTimeRange = minAwaitTime .. maxAwaitTime
|
private val awaitTimeRange = minAwaitTime .. maxAwaitTime
|
||||||
|
@Transient
|
||||||
|
private val eventsChannel = let {
|
||||||
|
var requestsInWork = 0.0
|
||||||
|
scope.actor<RequestEvent> {
|
||||||
|
when (it) {
|
||||||
|
is AddRequest -> {
|
||||||
|
val awaitTime = (requestsInWork.pow(powValue) * powK).toLong()
|
||||||
|
requestsInWork++
|
||||||
|
|
||||||
init {
|
it.continuation.resume(
|
||||||
scope.launch {
|
when {
|
||||||
var requestsInWork: Double = 0.0
|
awaitTime in awaitTimeRange -> awaitTime
|
||||||
for (event in eventsChannel) {
|
awaitTime < awaitTimeRange.first -> awaitTimeRange.first
|
||||||
when (event) {
|
else -> awaitTimeRange.last
|
||||||
is AddRequest -> {
|
}
|
||||||
val awaitTime = (((requestsInWork.pow(powValue) * powK) * 1000L).toLong())
|
)
|
||||||
requestsInWork++
|
|
||||||
|
|
||||||
event.continuation.resume(
|
|
||||||
if (awaitTime in awaitTimeRange) {
|
|
||||||
awaitTime
|
|
||||||
} else {
|
|
||||||
if (awaitTime < minAwaitTime) {
|
|
||||||
minAwaitTime
|
|
||||||
} else {
|
|
||||||
maxAwaitTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is CompleteRequest -> requestsInWork--
|
|
||||||
}
|
}
|
||||||
|
is CompleteRequest -> requestsInWork--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun <T> limit(
|
private suspend inline fun <T> withDelay(
|
||||||
block: suspend () -> T
|
crossinline block: suspend () -> T
|
||||||
): T {
|
): T {
|
||||||
val delayMillis = suspendCoroutine<Long> {
|
val delayMillis = suspendCoroutine<Long> {
|
||||||
scope.launch { eventsChannel.send(AddRequest(it)) }
|
scope.launch { eventsChannel.send(AddRequest(it)) }
|
||||||
}
|
}
|
||||||
delay(delayMillis)
|
delay(delayMillis)
|
||||||
return try {
|
return try {
|
||||||
block()
|
safely { block() }
|
||||||
} finally {
|
} finally {
|
||||||
eventsChannel.send(CompleteRequest)
|
eventsChannel.send(CompleteRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun <T> limit(
|
||||||
|
block: suspend () -> T
|
||||||
|
): T {
|
||||||
|
return withDelay(block)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import dev.inmo.tgbotapi.CommonAbstracts.types.ChatRequest
|
|||||||
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
|
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
|
||||||
import dev.inmo.tgbotapi.types.ChatIdentifier
|
import dev.inmo.tgbotapi.types.ChatIdentifier
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMemberSerializerWithoutDeserialization
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMemberSerializer
|
||||||
import dev.inmo.tgbotapi.types.chatIdField
|
import dev.inmo.tgbotapi.types.chatIdField
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.ListSerializer
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
|
|
||||||
private val chatMembersListSerializer = ListSerializer(
|
private val chatMembersListSerializer = ListSerializer(
|
||||||
AdministratorChatMemberSerializerWithoutDeserialization
|
AdministratorChatMemberSerializer
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package dev.inmo.tgbotapi.requests.chat.members
|
|||||||
import dev.inmo.tgbotapi.requests.chat.abstracts.ChatMemberRequest
|
import dev.inmo.tgbotapi.requests.chat.abstracts.ChatMemberRequest
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMemberDeserializationStrategy
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMemberSerializer
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@@ -15,7 +15,7 @@ data class GetChatMember(
|
|||||||
) : ChatMemberRequest<ChatMember> {
|
) : ChatMemberRequest<ChatMember> {
|
||||||
override fun method(): String = "getChatMember"
|
override fun method(): String = "getChatMember"
|
||||||
override val resultDeserializer: DeserializationStrategy<ChatMember>
|
override val resultDeserializer: DeserializationStrategy<ChatMember>
|
||||||
get() = ChatMemberDeserializationStrategy
|
get() = ChatMemberSerializer
|
||||||
override val requestSerializer: SerializationStrategy<*>
|
override val requestSerializer: SerializationStrategy<*>
|
||||||
get() = serializer()
|
get() = serializer()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.requests.webhook
|
package dev.inmo.tgbotapi.requests.webhook
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.*
|
import dev.inmo.tgbotapi.requests.abstracts.*
|
||||||
import dev.inmo.tgbotapi.requests.send.media.base.DataRequest
|
import dev.inmo.tgbotapi.requests.send.media.base.*
|
||||||
import dev.inmo.tgbotapi.requests.send.media.base.MultipartRequestImpl
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
@@ -13,14 +12,15 @@ private fun correctWebhookUrl(sourceUrl: String) = if (sourceUrl.contains("://")
|
|||||||
"https://$sourceUrl"
|
"https://$sourceUrl"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun SetWebhook(
|
sealed class SetWebhookRequest : Request<Boolean>
|
||||||
|
class MultipartSetWebhookRequest(
|
||||||
url: String,
|
url: String,
|
||||||
certificate: MultipartFile,
|
certificate: MultipartFile,
|
||||||
ipAddress: String? = null,
|
ipAddress: String? = null,
|
||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = null,
|
||||||
dropPendingUpdates: Boolean? = null
|
dropPendingUpdates: Boolean? = null
|
||||||
): MultipartRequestImpl<SetWebhook, Map<String, MultipartFile>, Boolean> = MultipartRequestImpl(
|
) : SetWebhookRequest(), MultipartRequest<Boolean> by MultipartRequestImpl(
|
||||||
SetWebhook(
|
SetWebhook(
|
||||||
correctWebhookUrl(url),
|
correctWebhookUrl(url),
|
||||||
null as String?,
|
null as String?,
|
||||||
@@ -32,6 +32,22 @@ fun SetWebhook(
|
|||||||
mapOf(certificateField to certificate)
|
mapOf(certificateField to certificate)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun SetWebhook(
|
||||||
|
url: String,
|
||||||
|
certificate: MultipartFile,
|
||||||
|
ipAddress: String? = null,
|
||||||
|
maxAllowedConnections: Int? = null,
|
||||||
|
allowedUpdates: List<String>? = null,
|
||||||
|
dropPendingUpdates: Boolean? = null
|
||||||
|
): MultipartSetWebhookRequest = MultipartSetWebhookRequest(
|
||||||
|
correctWebhookUrl(url),
|
||||||
|
certificate,
|
||||||
|
ipAddress,
|
||||||
|
maxAllowedConnections,
|
||||||
|
allowedUpdates,
|
||||||
|
dropPendingUpdates
|
||||||
|
)
|
||||||
|
|
||||||
fun SetWebhook(
|
fun SetWebhook(
|
||||||
url: String,
|
url: String,
|
||||||
certificate: FileId,
|
certificate: FileId,
|
||||||
@@ -63,7 +79,7 @@ fun SetWebhook(
|
|||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = null,
|
||||||
dropPendingUpdates: Boolean? = null
|
dropPendingUpdates: Boolean? = null
|
||||||
): Request<Boolean> = when (certificate) {
|
) = when (certificate) {
|
||||||
is MultipartFile -> SetWebhook(correctWebhookUrl(url), certificate as MultipartFile, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
|
is MultipartFile -> SetWebhook(correctWebhookUrl(url), certificate as MultipartFile, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
|
||||||
is FileId -> SetWebhook(correctWebhookUrl(url), certificate as FileId, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
|
is FileId -> SetWebhook(correctWebhookUrl(url), certificate as FileId, ipAddress, maxAllowedConnections, allowedUpdates, dropPendingUpdates)
|
||||||
}
|
}
|
||||||
@@ -82,7 +98,7 @@ fun SetWebhook(
|
|||||||
maxAllowedConnections: Int? = null,
|
maxAllowedConnections: Int? = null,
|
||||||
allowedUpdates: List<String>? = null,
|
allowedUpdates: List<String>? = null,
|
||||||
dropPendingUpdates: Boolean? = null
|
dropPendingUpdates: Boolean? = null
|
||||||
): Request<Boolean> = SetWebhook(
|
) = SetWebhook(
|
||||||
correctWebhookUrl(url),
|
correctWebhookUrl(url),
|
||||||
null,
|
null,
|
||||||
ipAddress,
|
ipAddress,
|
||||||
@@ -112,7 +128,7 @@ data class SetWebhook internal constructor(
|
|||||||
val allowedUpdates: List<String>? = null,
|
val allowedUpdates: List<String>? = null,
|
||||||
@SerialName(dropPendingUpdatesField)
|
@SerialName(dropPendingUpdatesField)
|
||||||
val dropPendingUpdates: Boolean? = null
|
val dropPendingUpdates: Boolean? = null
|
||||||
) : DataRequest<Boolean> {
|
) : SetWebhookRequest(), DataRequest<Boolean> {
|
||||||
override fun method(): String = "setWebhook"
|
override fun method(): String = "setWebhook"
|
||||||
override val resultDeserializer: DeserializationStrategy<Boolean>
|
override val resultDeserializer: DeserializationStrategy<Boolean>
|
||||||
get() = Boolean.serializer()
|
get() = Boolean.serializer()
|
||||||
|
|||||||
@@ -1,19 +1,37 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember
|
package dev.inmo.tgbotapi.types.ChatMember
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
||||||
import dev.inmo.tgbotapi.types.User
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class AdministratorChatMemberImpl(
|
data class AdministratorChatMemberImpl(
|
||||||
|
@SerialName(userField)
|
||||||
override val user: User,
|
override val user: User,
|
||||||
override val canBeEdited: Boolean,
|
@SerialName(canBeEditedField)
|
||||||
override val canChangeInfo: Boolean,
|
override val canBeEdited: Boolean = false,
|
||||||
override val canPostMessages: Boolean,
|
@SerialName(canChangeInfoField)
|
||||||
override val canEditMessages: Boolean,
|
override val canChangeInfo: Boolean = false,
|
||||||
override val canRemoveMessages: Boolean,
|
@SerialName(canPostMessagesField)
|
||||||
override val canInviteUsers: Boolean,
|
override val canPostMessages: Boolean = false,
|
||||||
override val canRestrictMembers: Boolean,
|
@SerialName(canEditMessagesField)
|
||||||
override val canPinMessages: Boolean,
|
override val canEditMessages: Boolean = false,
|
||||||
override val canPromoteMembers: Boolean,
|
@SerialName(canDeleteMessagesField)
|
||||||
override val isAnonymous: Boolean,
|
override val canRemoveMessages: Boolean = false,
|
||||||
override val customTitle: String?
|
@SerialName(canInviteUsersField)
|
||||||
) : AdministratorChatMember
|
override val canInviteUsers: Boolean = false,
|
||||||
|
@SerialName(canRestrictMembersField)
|
||||||
|
override val canRestrictMembers: Boolean = false,
|
||||||
|
@SerialName(canPinMessagesField)
|
||||||
|
override val canPinMessages: Boolean = false,
|
||||||
|
@SerialName(canPromoteMembersField)
|
||||||
|
override val canPromoteMembers: Boolean = false,
|
||||||
|
@SerialName(isAnonymousField)
|
||||||
|
override val isAnonymous: Boolean = false,
|
||||||
|
@SerialName(customTitleField)
|
||||||
|
override val customTitle: String? = null
|
||||||
|
) : AdministratorChatMember {
|
||||||
|
@SerialName(statusField)
|
||||||
|
@Required
|
||||||
|
private val type: String = "administrator"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +1,36 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember
|
package dev.inmo.tgbotapi.types.ChatMember
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
|
||||||
import dev.inmo.tgbotapi.types.User
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class CreatorChatMember(
|
data class CreatorChatMember(
|
||||||
override val user: User,
|
override val user: User,
|
||||||
override val isAnonymous: Boolean,
|
@SerialName(isAnonymousField)
|
||||||
override val customTitle: String?
|
override val isAnonymous: Boolean = false,
|
||||||
|
@SerialName(customTitleField)
|
||||||
|
override val customTitle: String? = null
|
||||||
) : AdministratorChatMember {
|
) : AdministratorChatMember {
|
||||||
|
@Transient
|
||||||
override val canBeEdited: Boolean = true
|
override val canBeEdited: Boolean = true
|
||||||
|
@Transient
|
||||||
override val canChangeInfo: Boolean = true
|
override val canChangeInfo: Boolean = true
|
||||||
|
@Transient
|
||||||
override val canPostMessages: Boolean = true
|
override val canPostMessages: Boolean = true
|
||||||
|
@Transient
|
||||||
override val canEditMessages: Boolean = true
|
override val canEditMessages: Boolean = true
|
||||||
|
@Transient
|
||||||
override val canRemoveMessages: Boolean = true
|
override val canRemoveMessages: Boolean = true
|
||||||
|
@Transient
|
||||||
override val canInviteUsers: Boolean = true
|
override val canInviteUsers: Boolean = true
|
||||||
|
@Transient
|
||||||
override val canRestrictMembers: Boolean = true
|
override val canRestrictMembers: Boolean = true
|
||||||
|
@Transient
|
||||||
override val canPinMessages: Boolean = true
|
override val canPinMessages: Boolean = true
|
||||||
|
@Transient
|
||||||
override val canPromoteMembers: Boolean = true
|
override val canPromoteMembers: Boolean = true
|
||||||
|
@SerialName(statusField)
|
||||||
|
@Required
|
||||||
|
private val type: String = "creator"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember
|
package dev.inmo.tgbotapi.types.ChatMember
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.BannedChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.BannedChatMember
|
||||||
import dev.inmo.tgbotapi.types.TelegramDate
|
import kotlinx.serialization.*
|
||||||
import dev.inmo.tgbotapi.types.User
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class KickedChatMember(
|
data class KickedChatMember(
|
||||||
|
@SerialName(userField)
|
||||||
override val user: User,
|
override val user: User,
|
||||||
override val untilDate: TelegramDate?
|
@SerialName(untilDateField)
|
||||||
) : BannedChatMember
|
override val untilDate: TelegramDate? = null
|
||||||
|
) : BannedChatMember {
|
||||||
|
@SerialName(statusField)
|
||||||
|
@Required
|
||||||
|
private val type: String = "kicked"
|
||||||
|
}
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember
|
package dev.inmo.tgbotapi.types.ChatMember
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
|
||||||
import dev.inmo.tgbotapi.types.User
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
data class LeftChatMember(override val user: User) :
|
@Serializable
|
||||||
ChatMember
|
data class LeftChatMember(@SerialName(userField) override val user: User) : ChatMember {
|
||||||
|
@SerialName(statusField)
|
||||||
|
@Required
|
||||||
|
private val type: String = "left"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember
|
package dev.inmo.tgbotapi.types.ChatMember
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
|
||||||
import dev.inmo.tgbotapi.types.User
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
data class MemberChatMember(override val user: User) :
|
@Serializable
|
||||||
ChatMember
|
data class MemberChatMember(@SerialName(userField) override val user: User) : ChatMember {
|
||||||
|
@SerialName(statusField)
|
||||||
|
@Required
|
||||||
|
private val type: String = "member"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember
|
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
internal data class RawChatMember(
|
|
||||||
val user: User,
|
|
||||||
private val status: String,
|
|
||||||
private val until_date: TelegramDate? = null,
|
|
||||||
@SerialName(canBeEditedField)
|
|
||||||
private val canBeEdited: Boolean = false,
|
|
||||||
@SerialName(canChangeInfoField)
|
|
||||||
private val canChangeInfo: Boolean = false,
|
|
||||||
@SerialName(canPostMessagesField)
|
|
||||||
private val canPostMessages: Boolean = false,
|
|
||||||
@SerialName(canEditMessagesField)
|
|
||||||
private val canEditMessages: Boolean = false,
|
|
||||||
@SerialName(canDeleteMessagesField)
|
|
||||||
private val canDeleteMessages: Boolean = false,
|
|
||||||
@SerialName(canInviteUsersField)
|
|
||||||
private val canInviteUsers: Boolean = false,
|
|
||||||
@SerialName(canRestrictMembersField)
|
|
||||||
private val canRestrictMembers: Boolean = false,
|
|
||||||
@SerialName(canPinMessagesField)
|
|
||||||
private val canPinMessages: Boolean = false,
|
|
||||||
@SerialName(canPromoteMembersField)
|
|
||||||
private val canPromoteMembers: Boolean = false,
|
|
||||||
@SerialName(isMemberField)
|
|
||||||
private val isMember: Boolean = false,
|
|
||||||
@SerialName(canSendMessagesField)
|
|
||||||
private val canSendMessages: Boolean = false,
|
|
||||||
@SerialName(canSendMediaMessagesField)
|
|
||||||
private val canSendMediaMessages: Boolean = false,
|
|
||||||
@SerialName(canSendPollsField)
|
|
||||||
private val canSendPolls: Boolean = false,
|
|
||||||
@SerialName(canSendOtherMessagesField)
|
|
||||||
private val canSendOtherMessages: Boolean = false,
|
|
||||||
@SerialName(canAddWebPagePreviewsField)
|
|
||||||
private val canAddWebPagePreviews: Boolean = false,
|
|
||||||
@SerialName(isAnonymousField)
|
|
||||||
private val isAnonymous: Boolean = false,
|
|
||||||
@SerialName(customTitleField)
|
|
||||||
private val customTitle: String? = null
|
|
||||||
) {
|
|
||||||
val asChatMember: ChatMember by lazy {
|
|
||||||
when (status) {
|
|
||||||
"creator" -> CreatorChatMember(user, isAnonymous, customTitle)
|
|
||||||
"administrator" -> AdministratorChatMemberImpl(
|
|
||||||
user,
|
|
||||||
canBeEdited,
|
|
||||||
canChangeInfo,
|
|
||||||
canPostMessages,
|
|
||||||
canEditMessages,
|
|
||||||
canDeleteMessages,
|
|
||||||
canInviteUsers,
|
|
||||||
canRestrictMembers,
|
|
||||||
canPinMessages,
|
|
||||||
canPromoteMembers,
|
|
||||||
isAnonymous,
|
|
||||||
customTitle
|
|
||||||
)
|
|
||||||
"member" -> MemberChatMember(user)
|
|
||||||
"restricted" -> RestrictedChatMember(
|
|
||||||
user,
|
|
||||||
until_date,
|
|
||||||
isMember,
|
|
||||||
canSendMessages,
|
|
||||||
canSendMediaMessages,
|
|
||||||
canSendPolls,
|
|
||||||
canSendOtherMessages,
|
|
||||||
canAddWebPagePreviews,
|
|
||||||
canChangeInfo,
|
|
||||||
canInviteUsers,
|
|
||||||
canPinMessages
|
|
||||||
)
|
|
||||||
"left" -> LeftChatMember(user)
|
|
||||||
"kicked" -> KickedChatMember(
|
|
||||||
user,
|
|
||||||
until_date
|
|
||||||
)
|
|
||||||
else -> throw IllegalStateException("Can't understand type of user: $status")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,36 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember
|
package dev.inmo.tgbotapi.types.ChatMember
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.*
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.BannedChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.BannedChatMember
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.abstracts.SpecialRightsChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.abstracts.SpecialRightsChatMember
|
||||||
import dev.inmo.tgbotapi.types.TelegramDate
|
import kotlinx.serialization.*
|
||||||
import dev.inmo.tgbotapi.types.User
|
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class RestrictedChatMember(
|
data class RestrictedChatMember(
|
||||||
|
@SerialName(userField)
|
||||||
override val user: User,
|
override val user: User,
|
||||||
override val untilDate: TelegramDate?,
|
@SerialName(untilDateField)
|
||||||
val isMember: Boolean,
|
override val untilDate: TelegramDate? = null,
|
||||||
val canSendMessages: Boolean,
|
@SerialName(isMemberField)
|
||||||
val canSendMediaMessages: Boolean,
|
val isMember: Boolean = false,
|
||||||
val canSendPolls: Boolean,
|
@SerialName(canSendMessagesField)
|
||||||
val canSendOtherMessages: Boolean,
|
val canSendMessages: Boolean = false,
|
||||||
val canAddWebpagePreviews: Boolean,
|
@SerialName(canSendMediaMessagesField)
|
||||||
override val canChangeInfo: Boolean,
|
val canSendMediaMessages: Boolean = false,
|
||||||
override val canInviteUsers: Boolean,
|
@SerialName(canSendPollsField)
|
||||||
override val canPinMessages: Boolean
|
val canSendPolls: Boolean = false,
|
||||||
) : BannedChatMember, SpecialRightsChatMember
|
@SerialName(canSendOtherMessagesField)
|
||||||
|
val canSendOtherMessages: Boolean = false,
|
||||||
|
@SerialName(canAddWebPagePreviewsField)
|
||||||
|
val canAddWebpagePreviews: Boolean = false,
|
||||||
|
@SerialName(canChangeInfoField)
|
||||||
|
override val canChangeInfo: Boolean = false,
|
||||||
|
@SerialName(canInviteUsersField)
|
||||||
|
override val canInviteUsers: Boolean = false,
|
||||||
|
@SerialName(canPinMessagesField)
|
||||||
|
override val canPinMessages: Boolean = false
|
||||||
|
) : BannedChatMember, SpecialRightsChatMember {
|
||||||
|
@SerialName(statusField)
|
||||||
|
@Required
|
||||||
|
private val type: String = "restricted"
|
||||||
|
}
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember.abstracts
|
package dev.inmo.tgbotapi.types.ChatMember.abstracts
|
||||||
|
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
|
||||||
|
@Serializable(AdministratorChatMemberSerializer::class)
|
||||||
interface AdministratorChatMember : SpecialRightsChatMember {
|
interface AdministratorChatMember : SpecialRightsChatMember {
|
||||||
val canBeEdited: Boolean
|
val canBeEdited: Boolean
|
||||||
val canPostMessages: Boolean
|
val canPostMessages: Boolean
|
||||||
@@ -9,4 +15,12 @@ interface AdministratorChatMember : SpecialRightsChatMember {
|
|||||||
val canPromoteMembers: Boolean
|
val canPromoteMembers: Boolean
|
||||||
val isAnonymous: Boolean
|
val isAnonymous: Boolean
|
||||||
val customTitle: String?
|
val customTitle: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializer(AdministratorChatMember::class)
|
||||||
|
internal object AdministratorChatMemberSerializer : KSerializer<AdministratorChatMember> {
|
||||||
|
override val descriptor: SerialDescriptor = ChatMemberSerializer.descriptor
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): AdministratorChatMember = ChatMemberSerializer.deserialize(decoder) as AdministratorChatMember
|
||||||
|
override fun serialize(encoder: Encoder, value: AdministratorChatMember) = ChatMemberSerializer.serialize(encoder, value)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember.abstracts
|
package dev.inmo.tgbotapi.types.ChatMember.abstracts
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.CommonAbstracts.types.UntilDate
|
import dev.inmo.tgbotapi.CommonAbstracts.types.UntilDate
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable(ChatMemberSerializer::class)
|
||||||
interface BannedChatMember : ChatMember, UntilDate
|
interface BannedChatMember : ChatMember, UntilDate
|
||||||
@@ -1,27 +1,46 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember.abstracts
|
package dev.inmo.tgbotapi.types.ChatMember.abstracts
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.ChatMember.RawChatMember
|
import dev.inmo.tgbotapi.types.ChatMember.*
|
||||||
import dev.inmo.tgbotapi.types.User
|
import dev.inmo.tgbotapi.types.User
|
||||||
import kotlinx.serialization.DeserializationStrategy
|
import dev.inmo.tgbotapi.types.statusField
|
||||||
import kotlinx.serialization.KSerializer
|
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
|
||||||
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
|
||||||
|
@Serializable(ChatMemberSerializer::class)
|
||||||
interface ChatMember {
|
interface ChatMember {
|
||||||
val user: User
|
val user: User
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object AdministratorChatMemberSerializerWithoutDeserialization : KSerializer<AdministratorChatMember> {
|
@Serializer(ChatMember::class)
|
||||||
override val descriptor: SerialDescriptor = ChatMemberDeserializationStrategy.descriptor
|
internal object ChatMemberSerializer : KSerializer<ChatMember> {
|
||||||
|
override val descriptor: SerialDescriptor = JsonObject.serializer().descriptor
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): AdministratorChatMember
|
override fun deserialize(decoder: Decoder): ChatMember {
|
||||||
= ChatMemberDeserializationStrategy.deserialize(decoder) as AdministratorChatMember
|
val json = JsonObject.serializer().deserialize(decoder)
|
||||||
override fun serialize(encoder: Encoder, value: AdministratorChatMember) = throw UnsupportedOperationException()
|
return when (json[statusField] ?.jsonPrimitive ?.content ?: error("Status field of chat member must be specified, but incoming json contains next: $json")) {
|
||||||
}
|
"creator" -> nonstrictJsonFormat.decodeFromJsonElement(CreatorChatMember.serializer(), json)
|
||||||
|
"administrator" -> nonstrictJsonFormat.decodeFromJsonElement(AdministratorChatMemberImpl.serializer(), json)
|
||||||
internal object ChatMemberDeserializationStrategy : DeserializationStrategy<ChatMember> {
|
"member" -> nonstrictJsonFormat.decodeFromJsonElement(MemberChatMember.serializer(), json)
|
||||||
override val descriptor: SerialDescriptor = RawChatMember.serializer().descriptor
|
"restricted" -> nonstrictJsonFormat.decodeFromJsonElement(RestrictedChatMember.serializer(), json)
|
||||||
|
"left" -> nonstrictJsonFormat.decodeFromJsonElement(LeftChatMember.serializer(), json)
|
||||||
override fun deserialize(decoder: Decoder): ChatMember = RawChatMember.serializer().deserialize(decoder).asChatMember
|
"kicked" -> nonstrictJsonFormat.decodeFromJsonElement(KickedChatMember.serializer(), json)
|
||||||
|
else -> error("Unknown type of chat member in json: $json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun serialize(encoder: Encoder, value: ChatMember) {
|
||||||
|
when (value) {
|
||||||
|
is CreatorChatMember -> CreatorChatMember.serializer()
|
||||||
|
is AdministratorChatMemberImpl -> AdministratorChatMemberImpl.serializer()
|
||||||
|
is MemberChatMember -> MemberChatMember.serializer()
|
||||||
|
is RestrictedChatMember -> RestrictedChatMember.serializer()
|
||||||
|
is LeftChatMember -> LeftChatMember.serializer()
|
||||||
|
is KickedChatMember -> KickedChatMember.serializer()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package dev.inmo.tgbotapi.types.ChatMember.abstracts
|
package dev.inmo.tgbotapi.types.ChatMember.abstracts
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable(ChatMemberSerializer::class)
|
||||||
interface SpecialRightsChatMember : ChatMember {
|
interface SpecialRightsChatMember : ChatMember {
|
||||||
val canChangeInfo: Boolean
|
val canChangeInfo: Boolean
|
||||||
val canInviteUsers: Boolean
|
val canInviteUsers: Boolean
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ typealias GooglePlaceId = String
|
|||||||
typealias GooglePlaceType = String
|
typealias GooglePlaceType = String
|
||||||
|
|
||||||
typealias Seconds = Int
|
typealias Seconds = Int
|
||||||
|
typealias MilliSeconds = Long
|
||||||
typealias LongSeconds = Long
|
typealias LongSeconds = Long
|
||||||
|
|
||||||
typealias Meters = Float
|
typealias Meters = Float
|
||||||
@@ -60,10 +61,13 @@ val inlineQueryAnswerResultsLimit = 0 .. 50
|
|||||||
|
|
||||||
val customTitleLength = 0 .. 16
|
val customTitleLength = 0 .. 16
|
||||||
|
|
||||||
val dartsAndCubeDiceResultLimit = 1 .. 6
|
val dartsCubeAndBowlingDiceResultLimit = 1 .. 6
|
||||||
@Deprecated("Renamed", ReplaceWith("dartsAndCubeDiceResultLimit", "dev.inmo.tgbotapi.types.dartsAndCubeDiceResultLimit"))
|
@Deprecated("Renamed", ReplaceWith("dartsCubeAndBowlingDiceResultLimit", "dev.inmo.tgbotapi.types.dartsCubeAndBowlingDiceResultLimit"))
|
||||||
|
val dartsAndCubeDiceResultLimit
|
||||||
|
get() = dartsCubeAndBowlingDiceResultLimit
|
||||||
|
@Deprecated("Renamed", ReplaceWith("dartsCubeAndBowlingDiceResultLimit", "dev.inmo.tgbotapi.types.dartsCubeAndBowlingDiceResultLimit"))
|
||||||
val diceResultLimit
|
val diceResultLimit
|
||||||
get() = dartsAndCubeDiceResultLimit
|
get() = dartsCubeAndBowlingDiceResultLimit
|
||||||
val basketballAndFootballDiceResultLimit = 1 .. 5
|
val basketballAndFootballDiceResultLimit = 1 .. 5
|
||||||
val slotMachineDiceResultLimit = 1 .. 64
|
val slotMachineDiceResultLimit = 1 .. 64
|
||||||
|
|
||||||
@@ -231,6 +235,7 @@ const val canSendPollsField = "can_send_polls"
|
|||||||
const val canAddWebPagePreviewsField = "can_add_web_page_previews"
|
const val canAddWebPagePreviewsField = "can_add_web_page_previews"
|
||||||
const val canSetStickerSetField = "can_set_sticker_set"
|
const val canSetStickerSetField = "can_set_sticker_set"
|
||||||
|
|
||||||
|
const val statusField = "status"
|
||||||
const val canBeEditedField = "can_be_edited"
|
const val canBeEditedField = "can_be_edited"
|
||||||
const val canChangeInfoField = "can_change_info"
|
const val canChangeInfoField = "can_change_info"
|
||||||
const val canPostMessagesField = "can_post_messages"
|
const val canPostMessagesField = "can_post_messages"
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import dev.inmo.tgbotapi.utils.internal.boldMarkdownV2
|
|||||||
*/
|
*/
|
||||||
data class BoldTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class BoldTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.boldMarkdown() }
|
override val markdown: String by lazy { source.boldMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { boldMarkdownV2() }
|
override val markdownV2: String by lazy { boldMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { boldHTML() }
|
override val html: String by lazy { boldHTML() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ data class BotCommandTextSource @RiskFeature(DirectInvocationOfTextSourceConstru
|
|||||||
commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!"
|
commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!"
|
||||||
}
|
}
|
||||||
|
|
||||||
override val asMarkdownSource: String by lazy { source.commandMarkdown() }
|
override val markdown: String by lazy { source.commandMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { source.commandMarkdownV2() }
|
override val markdownV2: String by lazy { source.commandMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { source.commandHTML() }
|
override val html: String by lazy { source.commandHTML() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import dev.inmo.tgbotapi.utils.internal.cashTagMarkdownV2
|
|||||||
*/
|
*/
|
||||||
data class CashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class CashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.cashTagMarkdown() }
|
override val markdown: String by lazy { source.cashTagMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { cashTagMarkdownV2() }
|
override val markdownV2: String by lazy { cashTagMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { cashTagHTML() }
|
override val html: String by lazy { cashTagHTML() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ import dev.inmo.tgbotapi.utils.internal.codeMarkdownV2
|
|||||||
data class CodeTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class CodeTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String
|
override val source: String
|
||||||
) : TextSource {
|
) : TextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.codeMarkdown() }
|
override val markdown: String by lazy { source.codeMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { source.codeMarkdownV2() }
|
override val markdownV2: String by lazy { source.codeMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { source.codeHTML() }
|
override val html: String by lazy { source.codeHTML() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import dev.inmo.tgbotapi.utils.internal.emailMarkdownV2
|
|||||||
*/
|
*/
|
||||||
data class EMailTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class EMailTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.emailMarkdown() }
|
override val markdown: String by lazy { source.emailMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { emailMarkdownV2(source) }
|
override val markdownV2: String by lazy { emailMarkdownV2(source) }
|
||||||
override val asHtmlSource: String by lazy { emailHTML(source) }
|
override val html: String by lazy { emailHTML(source) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import dev.inmo.tgbotapi.utils.internal.hashTagMarkdownV2
|
|||||||
*/
|
*/
|
||||||
data class HashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class HashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.hashTagMarkdown() }
|
override val markdown: String by lazy { source.hashTagMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { hashTagMarkdownV2() }
|
override val markdownV2: String by lazy { hashTagMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { hashTagHTML() }
|
override val html: String by lazy { hashTagHTML() }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!source.startsWith("#")) {
|
if (!source.startsWith("#")) {
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import dev.inmo.tgbotapi.utils.internal.italicMarkdownV2
|
|||||||
*/
|
*/
|
||||||
data class ItalicTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class ItalicTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.italicMarkdown() }
|
override val markdown: String by lazy { source.italicMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { italicMarkdownV2() }
|
override val markdownV2: String by lazy { italicMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { italicHTML() }
|
override val html: String by lazy { italicHTML() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ private val String.withoutCommercialAt
|
|||||||
*/
|
*/
|
||||||
data class MentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class MentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.mentionMarkdown() }
|
override val markdown: String by lazy { source.mentionMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { mentionMarkdownV2() }
|
override val markdownV2: String by lazy { mentionMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { mentionHTML() }
|
override val html: String by lazy { mentionHTML() }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (!source.startsWith("@")) {
|
if (!source.startsWith("@")) {
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import dev.inmo.tgbotapi.utils.internal.phoneMarkdownV2
|
|||||||
*/
|
*/
|
||||||
data class PhoneNumberTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class PhoneNumberTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.phoneMarkdown() }
|
override val markdown: String by lazy { source.phoneMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { phoneMarkdownV2() }
|
override val markdownV2: String by lazy { phoneMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { phoneHTML() }
|
override val html: String by lazy { phoneHTML() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ data class PreTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) c
|
|||||||
override val source: String,
|
override val source: String,
|
||||||
val language: String? = null
|
val language: String? = null
|
||||||
) : TextSource {
|
) : TextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.preMarkdown(language) }
|
override val markdown: String by lazy { source.preMarkdown(language) }
|
||||||
override val asMarkdownV2Source: String by lazy { source.preMarkdownV2(language) }
|
override val markdownV2: String by lazy { source.preMarkdownV2(language) }
|
||||||
override val asHtmlSource: String by lazy { source.preHTML(language) }
|
override val html: String by lazy { source.preHTML(language) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import dev.inmo.tgbotapi.utils.internal.regularMarkdownV2
|
|||||||
data class RegularTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class RegularTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String
|
override val source: String
|
||||||
) : TextSource {
|
) : TextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.regularMarkdown() }
|
override val markdown: String by lazy { source.regularMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { source.regularMarkdownV2() }
|
override val markdownV2: String by lazy { source.regularMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { source.regularHtml() }
|
override val html: String by lazy { source.regularHtml() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import dev.inmo.tgbotapi.utils.internal.strikethroughMarkdownV2
|
|||||||
*/
|
*/
|
||||||
data class StrikethroughTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class StrikethroughTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asHtmlSource: String by lazy { strikethroughHTML() }
|
override val html: String by lazy { strikethroughHTML() }
|
||||||
override val asMarkdownV2Source: String by lazy { strikethroughMarkdownV2() }
|
override val markdownV2: String by lazy { strikethroughMarkdownV2() }
|
||||||
override val asMarkdownSource: String by lazy { source.strikethroughMarkdown() }
|
override val markdown: String by lazy { source.strikethroughMarkdown() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ data class TextLinkTextSource @RiskFeature(DirectInvocationOfTextSourceConstruct
|
|||||||
override val source: String,
|
override val source: String,
|
||||||
val url: String
|
val url: String
|
||||||
) : TextSource {
|
) : TextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.linkMarkdown(url) }
|
override val markdown: String by lazy { source.linkMarkdown(url) }
|
||||||
override val asMarkdownV2Source: String by lazy { source.linkMarkdownV2(url) }
|
override val markdownV2: String by lazy { source.linkMarkdownV2(url) }
|
||||||
override val asHtmlSource: String by lazy { source.linkHTML(url) }
|
override val html: String by lazy { source.linkHTML(url) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ import dev.inmo.tgbotapi.utils.internal.textMentionMarkdownV2
|
|||||||
data class TextMentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class TextMentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
val user: User,
|
val user: User,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.textMentionMarkdown(user.id) }
|
override val markdown: String by lazy { source.textMentionMarkdown(user.id) }
|
||||||
override val asMarkdownV2Source: String by lazy { textMentionMarkdownV2(user.id) }
|
override val markdownV2: String by lazy { textMentionMarkdownV2(user.id) }
|
||||||
override val asHtmlSource: String by lazy { textMentionHTML(user.id) }
|
override val html: String by lazy { textMentionHTML(user.id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import dev.inmo.tgbotapi.utils.internal.linkMarkdownV2
|
|||||||
data class URLTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class URLTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String
|
override val source: String
|
||||||
) : TextSource {
|
) : TextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.linkMarkdown(source) }
|
override val markdown: String by lazy { source.linkMarkdown(source) }
|
||||||
override val asMarkdownV2Source: String by lazy { source.linkMarkdownV2(source) }
|
override val markdownV2: String by lazy { source.linkMarkdownV2(source) }
|
||||||
override val asHtmlSource: String by lazy { source.linkHTML(source) }
|
override val html: String by lazy { source.linkHTML(source) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import dev.inmo.tgbotapi.utils.internal.underlineMarkdownV2
|
|||||||
*/
|
*/
|
||||||
data class UnderlineTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
data class UnderlineTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
|
||||||
override val source: String,
|
override val source: String,
|
||||||
override val textSources: List<TextSource>
|
override val subsources: List<TextSource>
|
||||||
) : MultilevelTextSource {
|
) : MultilevelTextSource {
|
||||||
override val asMarkdownSource: String by lazy { source.underlineMarkdown() }
|
override val markdown: String by lazy { source.underlineMarkdown() }
|
||||||
override val asMarkdownV2Source: String by lazy { underlineMarkdownV2() }
|
override val markdownV2: String by lazy { underlineMarkdownV2() }
|
||||||
override val asHtmlSource: String by lazy { underlineHTML() }
|
override val html: String by lazy { underlineHTML() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import com.soywiz.klock.DateTime
|
|||||||
sealed class RequestError
|
sealed class RequestError
|
||||||
|
|
||||||
data class RetryAfterError(
|
data class RetryAfterError(
|
||||||
val seconds: Long,
|
val seconds: Seconds,
|
||||||
val startCountingMillis: Long
|
val startCountingMillis: Long
|
||||||
) : RequestError() {
|
) : RequestError() {
|
||||||
val canContinue = (seconds * 1000L) + startCountingMillis
|
val canContinue = (seconds * 1000L) + startCountingMillis
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ data class ResponseParametersRaw(
|
|||||||
@SerialName("migrate_to_chat_id")
|
@SerialName("migrate_to_chat_id")
|
||||||
private val migrateToChatId: ChatId? = null,
|
private val migrateToChatId: ChatId? = null,
|
||||||
@SerialName("retry_after")
|
@SerialName("retry_after")
|
||||||
private val retryAfter: Long? = null
|
private val retryAfter: Seconds? = null
|
||||||
) {
|
) {
|
||||||
@Transient
|
@Transient
|
||||||
private val createTime: Long = DateTime.now().unixMillisLong
|
private val createTime: Long = DateTime.now().unixMillisLong
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ sealed class User : PrivateChat
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class CommonUser(
|
data class CommonUser(
|
||||||
override val id: ChatId,
|
override val id: UserId,
|
||||||
@SerialName(firstNameField)
|
@SerialName(firstNameField)
|
||||||
override val firstName: String,
|
override val firstName: String,
|
||||||
@SerialName(lastNameField)
|
@SerialName(lastNameField)
|
||||||
@@ -35,7 +35,7 @@ sealed class Bot : User() {
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class CommonBot(
|
data class CommonBot(
|
||||||
override val id: ChatId,
|
override val id: UserId,
|
||||||
@SerialName(usernameField)
|
@SerialName(usernameField)
|
||||||
override val username: Username,
|
override val username: Username,
|
||||||
@SerialName(firstNameField)
|
@SerialName(firstNameField)
|
||||||
@@ -49,7 +49,7 @@ data class CommonBot(
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ExtendedBot(
|
data class ExtendedBot(
|
||||||
override val id: ChatId,
|
override val id: UserId,
|
||||||
@SerialName(usernameField)
|
@SerialName(usernameField)
|
||||||
override val username: Username,
|
override val username: Username,
|
||||||
@SerialName(firstNameField)
|
@SerialName(firstNameField)
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package dev.inmo.tgbotapi.types.chat.abstracts
|
package dev.inmo.tgbotapi.types.chat.abstracts
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.types.ChatId
|
||||||
|
import dev.inmo.tgbotapi.types.UserId
|
||||||
import dev.inmo.tgbotapi.types.chat.PreviewChatSerializer
|
import dev.inmo.tgbotapi.types.chat.PreviewChatSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable(PreviewChatSerializer::class)
|
@Serializable(PreviewChatSerializer::class)
|
||||||
interface PrivateChat : Chat, UsernameChat {
|
interface PrivateChat : Chat, UsernameChat {
|
||||||
|
override val id: UserId
|
||||||
val firstName: String
|
val firstName: String
|
||||||
val lastName: String
|
val lastName: String
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ sealed class DiceAnimationType {
|
|||||||
object CubeDiceAnimationType : DiceAnimationType() {
|
object CubeDiceAnimationType : DiceAnimationType() {
|
||||||
override val emoji: String = "\uD83C\uDFB2"
|
override val emoji: String = "\uD83C\uDFB2"
|
||||||
override val valueLimits: IntRange
|
override val valueLimits: IntRange
|
||||||
get() = dartsAndCubeDiceResultLimit
|
get() = dartsCubeAndBowlingDiceResultLimit
|
||||||
}
|
}
|
||||||
@Serializable(DiceAnimationTypeSerializer::class)
|
@Serializable(DiceAnimationTypeSerializer::class)
|
||||||
object DartsDiceAnimationType : DiceAnimationType() {
|
object DartsDiceAnimationType : DiceAnimationType() {
|
||||||
override val emoji: String = "\uD83C\uDFAF"
|
override val emoji: String = "\uD83C\uDFAF"
|
||||||
override val valueLimits: IntRange
|
override val valueLimits: IntRange
|
||||||
get() = dartsAndCubeDiceResultLimit
|
get() = dartsCubeAndBowlingDiceResultLimit
|
||||||
}
|
}
|
||||||
@Serializable(DiceAnimationTypeSerializer::class)
|
@Serializable(DiceAnimationTypeSerializer::class)
|
||||||
object BasketballDiceAnimationType : DiceAnimationType() {
|
object BasketballDiceAnimationType : DiceAnimationType() {
|
||||||
@@ -36,6 +36,12 @@ object FootballDiceAnimationType : DiceAnimationType() {
|
|||||||
get() = basketballAndFootballDiceResultLimit
|
get() = basketballAndFootballDiceResultLimit
|
||||||
}
|
}
|
||||||
@Serializable(DiceAnimationTypeSerializer::class)
|
@Serializable(DiceAnimationTypeSerializer::class)
|
||||||
|
object BowlingDiceAnimationType : DiceAnimationType() {
|
||||||
|
override val emoji: String = "\uD83C\uDFB3"
|
||||||
|
override val valueLimits: IntRange
|
||||||
|
get() = dartsCubeAndBowlingDiceResultLimit
|
||||||
|
}
|
||||||
|
@Serializable(DiceAnimationTypeSerializer::class)
|
||||||
object SlotMachineDiceAnimationType : DiceAnimationType() {
|
object SlotMachineDiceAnimationType : DiceAnimationType() {
|
||||||
override val emoji: String = "\uD83C\uDFB0"
|
override val emoji: String = "\uD83C\uDFB0"
|
||||||
override val valueLimits: IntRange
|
override val valueLimits: IntRange
|
||||||
@@ -59,6 +65,7 @@ internal object DiceAnimationTypeSerializer : KSerializer<DiceAnimationType> {
|
|||||||
BasketballDiceAnimationType.emoji -> BasketballDiceAnimationType
|
BasketballDiceAnimationType.emoji -> BasketballDiceAnimationType
|
||||||
SlotMachineDiceAnimationType.emoji -> SlotMachineDiceAnimationType
|
SlotMachineDiceAnimationType.emoji -> SlotMachineDiceAnimationType
|
||||||
FootballDiceAnimationType.emoji -> FootballDiceAnimationType
|
FootballDiceAnimationType.emoji -> FootballDiceAnimationType
|
||||||
|
BowlingDiceAnimationType.emoji -> BowlingDiceAnimationType
|
||||||
else -> CustomDiceAnimationType(type)
|
else -> CustomDiceAnimationType(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import com.soywiz.klock.DateTime
|
|||||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||||
import dev.inmo.tgbotapi.types.chat.abstracts.ChannelChat
|
import dev.inmo.tgbotapi.types.chat.abstracts.ChannelChat
|
||||||
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ChannelEvent
|
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ChannelEvent
|
||||||
|
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.GroupEvent
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
|
||||||
|
|
||||||
data class ChannelEventMessage(
|
data class ChannelEventMessage<T : ChannelEvent>(
|
||||||
override val messageId: MessageIdentifier,
|
override val messageId: MessageIdentifier,
|
||||||
override val chat: ChannelChat,
|
override val chat: ChannelChat,
|
||||||
override val chatEvent: ChannelEvent,
|
override val chatEvent: T,
|
||||||
override val date: DateTime
|
override val date: DateTime
|
||||||
) : ChatEventMessage
|
) : ChatEventMessage<T>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package dev.inmo.tgbotapi.types.message.ChatEvents.abstracts
|
package dev.inmo.tgbotapi.types.message.ChatEvents.abstracts
|
||||||
|
|
||||||
interface SupergroupEvent: ChatEvent
|
interface SupergroupEvent: GroupEvent
|
||||||
@@ -8,12 +8,12 @@ import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.GroupEvent
|
|||||||
import dev.inmo.tgbotapi.types.message.abstracts.GroupEventMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.GroupEventMessage
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("CommonGroupEventMessage"))
|
@Deprecated("Renamed", ReplaceWith("CommonGroupEventMessage"))
|
||||||
typealias GroupEventMessage = CommonGroupEventMessage
|
typealias GroupEventMessage = CommonGroupEventMessage<*>
|
||||||
|
|
||||||
data class CommonGroupEventMessage(
|
data class CommonGroupEventMessage<T : GroupEvent>(
|
||||||
override val messageId: MessageIdentifier,
|
override val messageId: MessageIdentifier,
|
||||||
override val user: User,
|
override val user: User,
|
||||||
override val chat: GroupChat,
|
override val chat: GroupChat,
|
||||||
override val chatEvent: GroupEvent,
|
override val chatEvent: T,
|
||||||
override val date: DateTime
|
override val date: DateTime
|
||||||
) : GroupEventMessage
|
) : GroupEventMessage<T>
|
||||||
|
|||||||
@@ -4,16 +4,17 @@ import com.soywiz.klock.DateTime
|
|||||||
import dev.inmo.tgbotapi.types.MessageIdentifier
|
import dev.inmo.tgbotapi.types.MessageIdentifier
|
||||||
import dev.inmo.tgbotapi.types.User
|
import dev.inmo.tgbotapi.types.User
|
||||||
import dev.inmo.tgbotapi.types.chat.abstracts.SupergroupChat
|
import dev.inmo.tgbotapi.types.chat.abstracts.SupergroupChat
|
||||||
|
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.GroupEvent
|
||||||
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.SupergroupEvent
|
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.SupergroupEvent
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.SupergroupEventMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.SupergroupEventMessage
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("CommonSupergroupEventMessage"))
|
@Deprecated("Renamed", ReplaceWith("CommonSupergroupEventMessage"))
|
||||||
typealias SupergroupEventMessage = CommonSupergroupEventMessage
|
typealias SupergroupEventMessage = CommonSupergroupEventMessage<*>
|
||||||
|
|
||||||
data class CommonSupergroupEventMessage(
|
data class CommonSupergroupEventMessage<T : SupergroupEvent>(
|
||||||
override val messageId: MessageIdentifier,
|
override val messageId: MessageIdentifier,
|
||||||
override val user: User,
|
override val user: User,
|
||||||
override val chat: SupergroupChat,
|
override val chat: SupergroupChat,
|
||||||
override val chatEvent: SupergroupEvent,
|
override val chatEvent: T,
|
||||||
override val date: DateTime
|
override val date: DateTime
|
||||||
) : SupergroupEventMessage
|
) : SupergroupEventMessage<T>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ data class AnonymousGroupMessageImpl<T : MessageContent>(
|
|||||||
data class CommonGroupMessageImpl<T : MessageContent>(
|
data class CommonGroupMessageImpl<T : MessageContent>(
|
||||||
override val chat: GroupChat,
|
override val chat: GroupChat,
|
||||||
override val messageId: MessageIdentifier,
|
override val messageId: MessageIdentifier,
|
||||||
|
override val user: User,
|
||||||
override val date: DateTime,
|
override val date: DateTime,
|
||||||
override val forwardInfo: ForwardInfo?,
|
override val forwardInfo: ForwardInfo?,
|
||||||
override val editDate: DateTime?,
|
override val editDate: DateTime?,
|
||||||
|
|||||||
@@ -296,6 +296,7 @@ internal data class RawMessage(
|
|||||||
null -> CommonGroupMessageImpl(
|
null -> CommonGroupMessageImpl(
|
||||||
chat,
|
chat,
|
||||||
messageId,
|
messageId,
|
||||||
|
from ?: error("It is expected that in messages from non anonymous users and channels user must be specified"),
|
||||||
date.asDate,
|
date.asDate,
|
||||||
forwarded,
|
forwarded,
|
||||||
edit_date ?.asDate,
|
edit_date ?.asDate,
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ package dev.inmo.tgbotapi.types.message.abstracts
|
|||||||
|
|
||||||
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ChatEvent
|
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.ChatEvent
|
||||||
|
|
||||||
interface ChatEventMessage : Message {
|
interface ChatEventMessage<T : ChatEvent> : Message {
|
||||||
val chatEvent: ChatEvent
|
val chatEvent: T
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
package dev.inmo.tgbotapi.types.message.abstracts
|
package dev.inmo.tgbotapi.types.message.abstracts
|
||||||
|
|
||||||
interface GroupEventMessage : ChatEventMessage, FromUserMessage
|
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.GroupEvent
|
||||||
|
|
||||||
|
interface GroupEventMessage<T : GroupEvent> : ChatEventMessage<T>, FromUserMessage
|
||||||
|
|||||||
@@ -17,4 +17,4 @@ interface AnonymousGroupMessage<T : MessageContent> : GroupMessage<T>, SignedMes
|
|||||||
override val senderChat: GroupChat
|
override val senderChat: GroupChat
|
||||||
get() = chat
|
get() = chat
|
||||||
}
|
}
|
||||||
interface CommonGroupMessage<T : MessageContent> : GroupMessage<T>
|
interface CommonGroupMessage<T : MessageContent> : GroupMessage<T>, FromUserMessage
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
package dev.inmo.tgbotapi.types.message.abstracts
|
package dev.inmo.tgbotapi.types.message.abstracts
|
||||||
|
|
||||||
interface SupergroupEventMessage : GroupEventMessage
|
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.SupergroupEvent
|
||||||
|
|
||||||
|
interface SupergroupEventMessage<T : SupergroupEvent> : GroupEventMessage<T>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package dev.inmo.tgbotapi.types.message.content
|
package dev.inmo.tgbotapi.types.message.content
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
|
import dev.inmo.tgbotapi.CommonAbstracts.*
|
||||||
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
|
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
import dev.inmo.tgbotapi.requests.send.SendTextMessage
|
import dev.inmo.tgbotapi.requests.send.SendTextMessage
|
||||||
import dev.inmo.tgbotapi.types.ChatIdentifier
|
import dev.inmo.tgbotapi.types.ChatIdentifier
|
||||||
@@ -15,13 +14,13 @@ import dev.inmo.tgbotapi.utils.internal.fullListOfSubSource
|
|||||||
import dev.inmo.tgbotapi.utils.internal.toMarkdownTexts
|
import dev.inmo.tgbotapi.utils.internal.toMarkdownTexts
|
||||||
|
|
||||||
data class TextContent(
|
data class TextContent(
|
||||||
val text: String,
|
override val text: String,
|
||||||
/**
|
override val textEntities: List<TextPart> = emptyList()
|
||||||
* Not full list of entities. This list WILL NOT contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
|
) : MessageContent, TextedInput {
|
||||||
* @see [TextContent.fullEntitiesList]
|
@Deprecated("Has been renamed", ReplaceWith("textEntities"))
|
||||||
*/
|
val entities: List<TextPart>
|
||||||
val entities: List<TextPart> = emptyList()
|
get() = textEntities
|
||||||
) : MessageContent {
|
|
||||||
override fun createResend(
|
override fun createResend(
|
||||||
chatId: ChatIdentifier,
|
chatId: ChatIdentifier,
|
||||||
disableNotification: Boolean,
|
disableNotification: Boolean,
|
||||||
@@ -83,4 +82,5 @@ data class TextContent(
|
|||||||
* Convert its [TextContent.entities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
|
* Convert its [TextContent.entities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
|
||||||
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
|
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Useless due to the fact that currently every message contains full list of sources")
|
||||||
fun TextContent.fullEntitiesList(): TextSourcesList = text.fullListOfSubSource(entities).map { it.source }
|
fun TextContent.fullEntitiesList(): TextSourcesList = text.fullListOfSubSource(entities).map { it.source }
|
||||||
|
|||||||
@@ -2,10 +2,28 @@ package dev.inmo.tgbotapi.utils
|
|||||||
|
|
||||||
const val telegramBotAPIDefaultUrl = "https://api.telegram.org"
|
const val telegramBotAPIDefaultUrl = "https://api.telegram.org"
|
||||||
|
|
||||||
|
private inline val String.withoutLastSlash: String
|
||||||
|
get() {
|
||||||
|
var correctedUrl = this
|
||||||
|
while (true) {
|
||||||
|
val withoutSuffix = correctedUrl.removeSuffix("/")
|
||||||
|
if (withoutSuffix == correctedUrl) {
|
||||||
|
return correctedUrl
|
||||||
|
}
|
||||||
|
correctedUrl = withoutSuffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class TelegramAPIUrlsKeeper(
|
class TelegramAPIUrlsKeeper(
|
||||||
token: String,
|
token: String,
|
||||||
hostUrl: String = telegramBotAPIDefaultUrl
|
hostUrl: String = telegramBotAPIDefaultUrl
|
||||||
) {
|
) {
|
||||||
val commonAPIUrl = "$hostUrl/bot$token"
|
val commonAPIUrl: String
|
||||||
val fileBaseUrl = "$hostUrl/file/bot$token"
|
val fileBaseUrl: String
|
||||||
|
|
||||||
|
init {
|
||||||
|
val correctedHost = hostUrl.withoutLastSlash
|
||||||
|
commonAPIUrl = "$correctedHost/bot$token"
|
||||||
|
fileBaseUrl = "$correctedHost/file/bot$token"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ internal fun createFormattedText(
|
|||||||
val textBuilder = StringBuilder(partLength)
|
val textBuilder = StringBuilder(partLength)
|
||||||
for (entity in entities) {
|
for (entity in entities) {
|
||||||
val string = when (mode) {
|
val string = when (mode) {
|
||||||
is MarkdownParseMode -> entity.asMarkdownSource
|
is MarkdownParseMode -> entity.markdown
|
||||||
is MarkdownV2ParseMode -> entity.asMarkdownV2Source
|
is MarkdownV2ParseMode -> entity.markdownV2
|
||||||
is HTMLParseMode -> entity.asHtmlSource
|
is HTMLParseMode -> entity.html
|
||||||
}
|
}
|
||||||
if (textBuilder.length + string.length > partLength) {
|
if (textBuilder.length + string.length > partLength) {
|
||||||
if (textBuilder.isNotEmpty()) {
|
if (textBuilder.isNotEmpty()) {
|
||||||
|
|||||||
@@ -73,29 +73,29 @@ internal fun List<TextPart>.shiftSourcesToTheLeft(shiftCount: Int = 1): List<Tex
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun List<TextSource>.joinSubSourcesMarkdownV2() = joinToString("") {
|
private fun List<TextSource>.joinSubSourcesMarkdownV2() = joinToString("") {
|
||||||
it.asMarkdownV2Source
|
it.markdownV2
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<TextSource>.joinSubSourcesHtml() = joinToString("") {
|
private fun List<TextSource>.joinSubSourcesHtml() = joinToString("") {
|
||||||
it.asHtmlSource
|
it.html
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun MultilevelTextSource.markdownV2Default(
|
internal fun MultilevelTextSource.markdownV2Default(
|
||||||
openControlSymbol: String,
|
openControlSymbol: String,
|
||||||
closeControlSymbol: String = openControlSymbol
|
closeControlSymbol: String = openControlSymbol
|
||||||
) = "$openControlSymbol${textSources.joinSubSourcesMarkdownV2()}$closeControlSymbol"
|
) = "$openControlSymbol${subsources.joinSubSourcesMarkdownV2()}$closeControlSymbol"
|
||||||
internal fun MultilevelTextSource.htmlDefault(
|
internal fun MultilevelTextSource.htmlDefault(
|
||||||
openControlSymbol: String,
|
openControlSymbol: String,
|
||||||
closeControlSymbol: String = openControlSymbol
|
closeControlSymbol: String = openControlSymbol
|
||||||
) = "<$openControlSymbol>${textSources.joinSubSourcesHtml()}</$closeControlSymbol>"
|
) = "<$openControlSymbol>${subsources.joinSubSourcesHtml()}</$closeControlSymbol>"
|
||||||
|
|
||||||
|
|
||||||
internal fun MultilevelTextSource.linkMarkdownV2(
|
internal fun MultilevelTextSource.linkMarkdownV2(
|
||||||
link: String
|
link: String
|
||||||
) = "[${textSources.joinSubSourcesMarkdownV2()}](${link.escapeMarkdownV2Link()})"
|
) = "[${subsources.joinSubSourcesMarkdownV2()}](${link.escapeMarkdownV2Link()})"
|
||||||
internal fun MultilevelTextSource.linkHTML(
|
internal fun MultilevelTextSource.linkHTML(
|
||||||
link: String
|
link: String
|
||||||
) = "<a href=\"${link.toHtml()}\">${textSources.joinSubSourcesHtml()}</a>"
|
) = "<a href=\"${link.toHtml()}\">${subsources.joinSubSourcesHtml()}</a>"
|
||||||
|
|
||||||
|
|
||||||
internal fun MultilevelTextSource.optionalPrefix(
|
internal fun MultilevelTextSource.optionalPrefix(
|
||||||
@@ -116,8 +116,8 @@ internal fun MultilevelTextSource.boldMarkdownV2(): String = markdownV2Default(m
|
|||||||
internal fun MultilevelTextSource.boldHTML(): String = htmlDefault(htmlBoldControl)
|
internal fun MultilevelTextSource.boldHTML(): String = htmlDefault(htmlBoldControl)
|
||||||
|
|
||||||
|
|
||||||
internal fun MultilevelTextSource.cashTagMarkdownV2(): String = textSources.joinSubSourcesMarkdownV2()
|
internal fun MultilevelTextSource.cashTagMarkdownV2(): String = subsources.joinSubSourcesMarkdownV2()
|
||||||
internal fun MultilevelTextSource.cashTagHTML(): String = textSources.joinSubSourcesHtml()
|
internal fun MultilevelTextSource.cashTagHTML(): String = subsources.joinSubSourcesHtml()
|
||||||
|
|
||||||
|
|
||||||
internal fun MultilevelTextSource.italicMarkdownV2(): String = markdownV2Default(markdownItalicControl)
|
internal fun MultilevelTextSource.italicMarkdownV2(): String = markdownV2Default(markdownItalicControl)
|
||||||
@@ -135,21 +135,21 @@ internal fun MultilevelTextSource.underlineHTML(): String = htmlDefault(htmlUnde
|
|||||||
internal fun MultilevelTextSource.textMentionMarkdownV2(userId: UserId): String = linkMarkdownV2(userId.link)
|
internal fun MultilevelTextSource.textMentionMarkdownV2(userId: UserId): String = linkMarkdownV2(userId.link)
|
||||||
internal fun MultilevelTextSource.textMentionHTML(userId: UserId): String = linkHTML(userId.link)
|
internal fun MultilevelTextSource.textMentionHTML(userId: UserId): String = linkHTML(userId.link)
|
||||||
|
|
||||||
internal fun MultilevelTextSource.mentionMarkdownV2(): String = optionalPrefix("@") + textSources.joinSubSourcesMarkdownV2()
|
internal fun MultilevelTextSource.mentionMarkdownV2(): String = optionalPrefix("@") + subsources.joinSubSourcesMarkdownV2()
|
||||||
internal fun MultilevelTextSource.mentionHTML(): String = optionalPrefix("@") + textSources.joinSubSourcesHtml()
|
internal fun MultilevelTextSource.mentionHTML(): String = optionalPrefix("@") + subsources.joinSubSourcesHtml()
|
||||||
|
|
||||||
|
|
||||||
internal fun MultilevelTextSource.hashTagMarkdownV2(): String = when {
|
internal fun MultilevelTextSource.hashTagMarkdownV2(): String = when {
|
||||||
source.startsWith("\\#") || source.startsWith("#") -> ""
|
source.startsWith("\\#") || source.startsWith("#") -> ""
|
||||||
else -> "\\#"
|
else -> "\\#"
|
||||||
} + textSources.joinSubSourcesMarkdownV2()
|
} + subsources.joinSubSourcesMarkdownV2()
|
||||||
internal fun MultilevelTextSource.hashTagHTML(): String = optionalPrefix("#") + textSources.joinSubSourcesHtml()
|
internal fun MultilevelTextSource.hashTagHTML(): String = optionalPrefix("#") + subsources.joinSubSourcesHtml()
|
||||||
|
|
||||||
|
|
||||||
internal fun MultilevelTextSource.phoneMarkdownV2(): String = textSources.joinSubSourcesMarkdownV2()
|
internal fun MultilevelTextSource.phoneMarkdownV2(): String = subsources.joinSubSourcesMarkdownV2()
|
||||||
internal fun MultilevelTextSource.phoneHTML(): String = textSources.joinSubSourcesHtml()
|
internal fun MultilevelTextSource.phoneHTML(): String = subsources.joinSubSourcesHtml()
|
||||||
|
|
||||||
|
|
||||||
internal fun MultilevelTextSource.commandMarkdownV2(): String = optionalPrefix("/") + textSources.joinSubSourcesMarkdownV2()
|
internal fun MultilevelTextSource.commandMarkdownV2(): String = optionalPrefix("/") + subsources.joinSubSourcesMarkdownV2()
|
||||||
internal fun MultilevelTextSource.commandHTML(): String = optionalPrefix("/") + textSources.joinSubSourcesHtml()
|
internal fun MultilevelTextSource.commandHTML(): String = optionalPrefix("/") + subsources.joinSubSourcesHtml()
|
||||||
|
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ fun List<TextPart>.testTextParts() {
|
|||||||
assertTrue (get(5).source is MentionTextSource)
|
assertTrue (get(5).source is MentionTextSource)
|
||||||
|
|
||||||
val boldSource = get(1).source as BoldTextSource
|
val boldSource = get(1).source as BoldTextSource
|
||||||
assertTrue (boldSource.textSources.first() is ItalicTextSource)
|
assertTrue (boldSource.subsources.first() is ItalicTextSource)
|
||||||
assertTrue (boldSource.textSources[1] is RegularTextSource)
|
assertTrue (boldSource.subsources[1] is RegularTextSource)
|
||||||
assertTrue (boldSource.textSources[2] is StrikethroughTextSource)
|
assertTrue (boldSource.subsources[2] is StrikethroughTextSource)
|
||||||
assertTrue ((boldSource.textSources[2] as StrikethroughTextSource).textSources.first() is UnderlineTextSource)
|
assertTrue ((boldSource.subsources[2] as StrikethroughTextSource).subsources.first() is UnderlineTextSource)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,11 +39,7 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation kotlin('stdlib')
|
implementation kotlin('stdlib')
|
||||||
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
api project(":tgbotapi.core")
|
||||||
api "${project.group}:tgbotapi.core:$library_version"
|
|
||||||
} else {
|
|
||||||
api project(":tgbotapi.core")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
apply plugin: 'maven-publish'
|
|
||||||
|
|
||||||
task javadocsJar(type: Jar) {
|
|
||||||
classifier = 'javadoc'
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
project.publishing.publications.all {
|
|
||||||
// rename artifacts
|
|
||||||
groupId "${project.group}"
|
|
||||||
if (it.name.contains('kotlinMultiplatform')) {
|
|
||||||
artifactId = "${project.name}"
|
|
||||||
} else {
|
|
||||||
artifactId = "${project.name}-$name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications.all {
|
|
||||||
artifact javadocsJar
|
|
||||||
|
|
||||||
pom {
|
|
||||||
description = "API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference"
|
|
||||||
name = "Telegram Bot API Extensions for API"
|
|
||||||
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-api"
|
|
||||||
|
|
||||||
scm {
|
|
||||||
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
}
|
|
||||||
|
|
||||||
developers {
|
|
||||||
|
|
||||||
developer {
|
|
||||||
id = "InsanusMokrassar"
|
|
||||||
name = "Ovsiannikov Aleksei"
|
|
||||||
email = "ovsyannikov.alexey95@gmail.com"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
|
|
||||||
license {
|
|
||||||
name = "Apache Software License 2.0"
|
|
||||||
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +1,65 @@
|
|||||||
apply plugin: 'com.jfrog.bintray'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
apply from: "maven.publish.gradle"
|
task javadocsJar(type: Jar) {
|
||||||
|
classifier = 'javadoc'
|
||||||
bintray {
|
|
||||||
user = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
|
||||||
key = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
|
||||||
filesSpec {
|
|
||||||
from "${buildDir}/publications/"
|
|
||||||
eachFile {
|
|
||||||
String directorySubname = it.getFile().parentFile.name
|
|
||||||
if (it.getName() == "module.json") {
|
|
||||||
if (directorySubname == "kotlinMultiplatform") {
|
|
||||||
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module")
|
|
||||||
} else {
|
|
||||||
it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") {
|
|
||||||
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom")
|
|
||||||
} else {
|
|
||||||
it.exclude()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
into "${project.group}".replace(".", "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
publish = true
|
|
||||||
override = true
|
|
||||||
|
|
||||||
pkg {
|
|
||||||
repo = "TelegramBotAPI"
|
|
||||||
name = "${project.name}"
|
|
||||||
vcsUrl = "https://github.com/InsanusMokrassar/TelegramBotAPI"
|
|
||||||
licenses = ["Apache-2.0"]
|
|
||||||
version {
|
|
||||||
name = "${project.version}"
|
|
||||||
released = new Date()
|
|
||||||
vcsTag = "${project.version}"
|
|
||||||
gpg {
|
|
||||||
sign = true
|
|
||||||
passphrase = project.hasProperty('signing.gnupg.passphrase') ? project.property('signing.gnupg.passphrase') : System.getenv('signing.gnupg.passphrase')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bintrayUpload.doFirst {
|
afterEvaluate {
|
||||||
publications = publishing.publications.collect {
|
project.publishing.publications.all {
|
||||||
|
// rename artifacts
|
||||||
|
groupId "${project.group}"
|
||||||
if (it.name.contains('kotlinMultiplatform')) {
|
if (it.name.contains('kotlinMultiplatform')) {
|
||||||
null
|
artifactId = "${project.name}"
|
||||||
} else {
|
} else {
|
||||||
it.name
|
artifactId = "${project.name}-$name"
|
||||||
}
|
}
|
||||||
} - null
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bintrayUpload.dependsOn publishToMavenLocal
|
publishing {
|
||||||
|
publications.all {
|
||||||
|
artifact javadocsJar
|
||||||
|
|
||||||
|
pom {
|
||||||
|
description = "API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference"
|
||||||
|
name = "Telegram Bot API Extensions for API"
|
||||||
|
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-api"
|
||||||
|
|
||||||
|
scm {
|
||||||
|
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
}
|
||||||
|
|
||||||
|
developers {
|
||||||
|
|
||||||
|
developer {
|
||||||
|
id = "InsanusMokrassar"
|
||||||
|
name = "Ovsiannikov Aleksei"
|
||||||
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
|
||||||
|
license {
|
||||||
|
name = "Apache Software License 2.0"
|
||||||
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "bintray"
|
||||||
|
url = uri("https://api.bintray.com/maven/${project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')}/TelegramBotAPI/${project.name}/;publish=1;override=1")
|
||||||
|
credentials {
|
||||||
|
username = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
||||||
|
password = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.api
|
package dev.inmo.tgbotapi.extensions.api
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.bot.Ktor.KtorRequestsExecutor
|
import dev.inmo.tgbotapi.bot.Ktor.KtorRequestsExecutorBuilder
|
||||||
import dev.inmo.tgbotapi.bot.TelegramBot
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
||||||
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
|
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
|
||||||
@@ -11,11 +11,11 @@ import io.ktor.client.engine.*
|
|||||||
/**
|
/**
|
||||||
* Allows to create bot using bot [urlsKeeper]
|
* Allows to create bot using bot [urlsKeeper]
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Replaced in core", ReplaceWith("telegramBot", "dev.inmo.tgbotapi.bot.Ktor.telegramBot"))
|
||||||
fun telegramBot(
|
fun telegramBot(
|
||||||
urlsKeeper: TelegramAPIUrlsKeeper
|
urlsKeeper: TelegramAPIUrlsKeeper
|
||||||
): TelegramBot = KtorRequestsExecutor(
|
): TelegramBot = dev.inmo.tgbotapi.bot.Ktor.telegramBot(
|
||||||
urlsKeeper,
|
urlsKeeper
|
||||||
HttpClient()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,10 +24,9 @@ fun telegramBot(
|
|||||||
fun telegramBot(
|
fun telegramBot(
|
||||||
urlsKeeper: TelegramAPIUrlsKeeper,
|
urlsKeeper: TelegramAPIUrlsKeeper,
|
||||||
client: HttpClient
|
client: HttpClient
|
||||||
): TelegramBot = KtorRequestsExecutor(
|
): TelegramBot = dev.inmo.tgbotapi.bot.Ktor.telegramBot(urlsKeeper) {
|
||||||
urlsKeeper,
|
this.client = client
|
||||||
client
|
}
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to create bot using bot [urlsKeeper] and specify [HttpClientEngineFactory] by passing [clientFactory] param and optionally
|
* Allows to create bot using bot [urlsKeeper] and specify [HttpClientEngineFactory] by passing [clientFactory] param and optionally
|
||||||
@@ -73,11 +72,12 @@ inline fun telegramBot(
|
|||||||
/**
|
/**
|
||||||
* Allows to create bot using bot [token], [apiUrl] (for custom api servers) and already prepared [client]
|
* Allows to create bot using bot [token], [apiUrl] (for custom api servers) and already prepared [client]
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Replaced in core", ReplaceWith("telegramBot", "dev.inmo.tgbotapi.bot.Ktor.telegramBot"))
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun telegramBot(
|
inline fun telegramBot(
|
||||||
token: String,
|
token: String,
|
||||||
apiUrl: String = telegramBotAPIDefaultUrl
|
apiUrl: String = telegramBotAPIDefaultUrl
|
||||||
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, apiUrl))
|
): TelegramBot = dev.inmo.tgbotapi.bot.Ktor.telegramBot(token, apiUrl)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to create bot using bot [token], [apiUrl] (for custom api servers) and already prepared [client]
|
* Allows to create bot using bot [token], [apiUrl] (for custom api servers) and already prepared [client]
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,11 +39,7 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation kotlin('stdlib')
|
implementation kotlin('stdlib')
|
||||||
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
api project(":tgbotapi.core")
|
||||||
api "${project.group}:tgbotapi.core:$library_version"
|
|
||||||
} else {
|
|
||||||
api project(":tgbotapi.core")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
apply plugin: 'maven-publish'
|
|
||||||
|
|
||||||
task javadocsJar(type: Jar) {
|
|
||||||
classifier = 'javadoc'
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
project.publishing.publications.all {
|
|
||||||
// rename artifacts
|
|
||||||
groupId "${project.group}"
|
|
||||||
if (it.name.contains('kotlinMultiplatform')) {
|
|
||||||
artifactId = "${project.name}"
|
|
||||||
} else {
|
|
||||||
artifactId = "${project.name}-$name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications.all {
|
|
||||||
artifact javadocsJar
|
|
||||||
|
|
||||||
pom {
|
|
||||||
description = "Util extensions for more useful work with updates and other things"
|
|
||||||
name = "Telegram Bot API Utility Extensions"
|
|
||||||
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-utils"
|
|
||||||
|
|
||||||
scm {
|
|
||||||
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
}
|
|
||||||
|
|
||||||
developers {
|
|
||||||
|
|
||||||
developer {
|
|
||||||
id = "InsanusMokrassar"
|
|
||||||
name = "Ovsiannikov Aleksei"
|
|
||||||
email = "ovsyannikov.alexey95@gmail.com"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
|
|
||||||
license {
|
|
||||||
name = "Apache Software License 2.0"
|
|
||||||
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +1,65 @@
|
|||||||
apply plugin: 'com.jfrog.bintray'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
apply from: "maven.publish.gradle"
|
task javadocsJar(type: Jar) {
|
||||||
|
classifier = 'javadoc'
|
||||||
bintray {
|
|
||||||
user = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
|
||||||
key = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
|
||||||
filesSpec {
|
|
||||||
from "${buildDir}/publications/"
|
|
||||||
eachFile {
|
|
||||||
String directorySubname = it.getFile().parentFile.name
|
|
||||||
if (it.getName() == "module.json") {
|
|
||||||
if (directorySubname == "kotlinMultiplatform") {
|
|
||||||
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module")
|
|
||||||
} else {
|
|
||||||
it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") {
|
|
||||||
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom")
|
|
||||||
} else {
|
|
||||||
it.exclude()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
into "${project.group}".replace(".", "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
publish = true
|
|
||||||
override = true
|
|
||||||
|
|
||||||
pkg {
|
|
||||||
repo = "TelegramBotAPI"
|
|
||||||
name = "${project.name}"
|
|
||||||
vcsUrl = "https://github.com/InsanusMokrassar/TelegramBotAPI"
|
|
||||||
licenses = ["Apache-2.0"]
|
|
||||||
version {
|
|
||||||
name = "${project.version}"
|
|
||||||
released = new Date()
|
|
||||||
vcsTag = "${project.version}"
|
|
||||||
gpg {
|
|
||||||
sign = true
|
|
||||||
passphrase = project.hasProperty('signing.gnupg.passphrase') ? project.property('signing.gnupg.passphrase') : System.getenv('signing.gnupg.passphrase')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bintrayUpload.doFirst {
|
afterEvaluate {
|
||||||
publications = publishing.publications.collect {
|
project.publishing.publications.all {
|
||||||
|
// rename artifacts
|
||||||
|
groupId "${project.group}"
|
||||||
if (it.name.contains('kotlinMultiplatform')) {
|
if (it.name.contains('kotlinMultiplatform')) {
|
||||||
null
|
artifactId = "${project.name}"
|
||||||
} else {
|
} else {
|
||||||
it.name
|
artifactId = "${project.name}-$name"
|
||||||
}
|
}
|
||||||
} - null
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bintrayUpload.dependsOn publishToMavenLocal
|
publishing {
|
||||||
|
publications.all {
|
||||||
|
artifact javadocsJar
|
||||||
|
|
||||||
|
pom {
|
||||||
|
description = "Util extensions for more useful work with updates and other things"
|
||||||
|
name = "Telegram Bot API Utility Extensions"
|
||||||
|
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-utils"
|
||||||
|
|
||||||
|
scm {
|
||||||
|
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
}
|
||||||
|
|
||||||
|
developers {
|
||||||
|
|
||||||
|
developer {
|
||||||
|
id = "InsanusMokrassar"
|
||||||
|
name = "Ovsiannikov Aleksei"
|
||||||
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
|
||||||
|
license {
|
||||||
|
name = "Apache Software License 2.0"
|
||||||
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "bintray"
|
||||||
|
url = uri("https://api.bintray.com/maven/${project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')}/TelegramBotAPI/${project.name}/;publish=1;override=1")
|
||||||
|
credentials {
|
||||||
|
username = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
||||||
|
password = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
/**
|
/**
|
||||||
* Shortcut for [dev.inmo.micro_utils.coroutines.safely]. It was created for more comfortable way of handling different things
|
* Shortcut for [dev.inmo.micro_utils.coroutines.safely]. It was created for more comfortable way of handling different things
|
||||||
*/
|
*/
|
||||||
@PreviewFeature
|
|
||||||
@Deprecated("In future will be used typealias from micro_utils", ReplaceWith("safely", "dev.inmo.micro_utils.coroutines.safely"))
|
@Deprecated("In future will be used typealias from micro_utils", ReplaceWith("safely", "dev.inmo.micro_utils.coroutines.safely"))
|
||||||
suspend inline fun <T> safely(
|
suspend inline fun <T> safely(
|
||||||
noinline onException: ExceptionHandler<T> = { throw it },
|
noinline onException: ExceptionHandler<T> = { throw it },
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.utils.chat_events
|
package dev.inmo.tgbotapi.extensions.utils.chat_events
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.message.*
|
import dev.inmo.tgbotapi.extensions.utils.shortcuts.*
|
||||||
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
|
import dev.inmo.tgbotapi.types.message.abstracts.ChatEventMessage
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@Deprecated("Refactored, replaced and renamed", ReplaceWith("filterByChatEvent", "dev.inmo.tgbotapi.extensions.utils.shortcuts.filterByChatEvent"))
|
||||||
fun <T : ChatEventMessage> Flow<ChatEventMessage>.divideBySource(contentType: KClass<T>) = mapNotNull {
|
fun <T : ChatEventMessage<*>> Flow<ChatEventMessage<*>>.divideBySource(contentType: KClass<T>) = mapNotNull {
|
||||||
if (contentType.isInstance(it)) {
|
if (contentType.isInstance(it)) {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
it as T
|
it as T
|
||||||
@@ -16,6 +16,9 @@ fun <T : ChatEventMessage> Flow<ChatEventMessage>.divideBySource(contentType: KC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Flow<ChatEventMessage>.onlyChannelEvents() = divideBySource(ChannelEventMessage::class)
|
@Deprecated("Replaced and renamed", ReplaceWith("channelEvents", "dev.inmo.tgbotapi.extensions.utils.shortcuts.channelEvents"))
|
||||||
fun Flow<ChatEventMessage>.onlyGroupEvents() = divideBySource(CommonGroupEventMessage::class)
|
fun Flow<ChatEventMessage<*>>.onlyChannelEvents() = channelEvents()
|
||||||
fun Flow<ChatEventMessage>.onlySupergroupEvents() = divideBySource(CommonSupergroupEventMessage::class)
|
@Deprecated("Replaced and renamed", ReplaceWith("groupEvents", "dev.inmo.tgbotapi.extensions.utils.shortcuts.groupEvents"))
|
||||||
|
fun Flow<ChatEventMessage<*>>.onlyGroupEvents() = groupEvents()
|
||||||
|
@Deprecated("Replaced and renamed", ReplaceWith("supergroupEvents", "dev.inmo.tgbotapi.extensions.utils.shortcuts.supergroupEvents"))
|
||||||
|
fun Flow<ChatEventMessage<*>>.onlySupergroupEvents() = supergroupEvents()
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.utils.formatting
|
package dev.inmo.tgbotapi.extensions.utils.formatting
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.types.*
|
import dev.inmo.tgbotapi.types.*
|
||||||
|
import dev.inmo.tgbotapi.types.MessageEntity.textsources.link
|
||||||
import dev.inmo.tgbotapi.types.ParseMode.*
|
import dev.inmo.tgbotapi.types.ParseMode.*
|
||||||
import dev.inmo.tgbotapi.types.chat.abstracts.PrivateChat
|
import dev.inmo.tgbotapi.types.chat.abstracts.*
|
||||||
import dev.inmo.tgbotapi.types.chat.abstracts.UsernameChat
|
import dev.inmo.tgbotapi.types.chat.abstracts.extended.ExtendedPublicChat
|
||||||
import dev.inmo.tgbotapi.types.chat.abstracts.extended.ExtendedChat
|
import dev.inmo.tgbotapi.types.message.abstracts.Message
|
||||||
|
|
||||||
private const val internalLinkBeginning = "https://t.me"
|
private const val internalLinkBeginning = "https://t.me"
|
||||||
|
|
||||||
|
fun makeUsernameLink(username: String) = "$internalLinkBeginning/$username"
|
||||||
|
inline val Username.link
|
||||||
|
get() = makeUsernameLink(username)
|
||||||
|
inline fun makeLink(username: Username) = username.link
|
||||||
|
|
||||||
fun makeLinkToMessage(
|
fun makeLinkToMessage(
|
||||||
username: String,
|
username: String,
|
||||||
messageId: MessageIdentifier
|
messageId: MessageIdentifier
|
||||||
@@ -24,8 +30,12 @@ fun makeLinkToMessage(
|
|||||||
private val linkIdRedundantPartRegex = Regex("^-100")
|
private val linkIdRedundantPartRegex = Regex("^-100")
|
||||||
private val usernameBeginSymbolRegex = Regex("^@")
|
private val usernameBeginSymbolRegex = Regex("^@")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link which can be used as by any user to get access to [Message]. Returns null in case when there are no
|
||||||
|
* known way to build link (for [PrivateChat]s, for example)
|
||||||
|
*/
|
||||||
fun makeLinkToMessage(
|
fun makeLinkToMessage(
|
||||||
chat: ExtendedChat,
|
chat: Chat,
|
||||||
messageId: MessageIdentifier
|
messageId: MessageIdentifier
|
||||||
): String? {
|
): String? {
|
||||||
return when {
|
return when {
|
||||||
@@ -43,8 +53,55 @@ fun makeLinkToMessage(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see makeLinkToMessage
|
||||||
|
*/
|
||||||
|
val Message.link: String?
|
||||||
|
get() = makeLinkToMessage(
|
||||||
|
chat,
|
||||||
|
messageId
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link which can be used as by any user to get access to [Chat]. Returns null in case when there are no
|
||||||
|
* known way to build link
|
||||||
|
*/
|
||||||
|
val Chat.link: String?
|
||||||
|
get() {
|
||||||
|
if (this is UsernameChat) {
|
||||||
|
username ?.username ?.let { return it }
|
||||||
|
}
|
||||||
|
if (this is ExtendedPublicChat) {
|
||||||
|
inviteLink ?.let { return it }
|
||||||
|
}
|
||||||
|
if (this is PrivateChat) {
|
||||||
|
return id.link
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
private const val stickerSetAddingLinkPrefix = "$internalLinkBeginning/addstickers"
|
private const val stickerSetAddingLinkPrefix = "$internalLinkBeginning/addstickers"
|
||||||
|
|
||||||
|
val StickerSetName.stickerSetLink
|
||||||
|
get() = link(this, "$stickerSetAddingLinkPrefix/$this")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [MarkdownV2]
|
||||||
|
*/
|
||||||
|
@Deprecated("Use extension `stickerSetLink` + getting of `asMarkdownV2Source` property")
|
||||||
|
fun makeLinkToAddStickerSetInMarkdownV2(
|
||||||
|
stickerSetName: StickerSetName
|
||||||
|
) = stickerSetName.stickerSetLink.markdownV2
|
||||||
|
/**
|
||||||
|
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [Markdown]
|
||||||
|
*/
|
||||||
|
@Deprecated("Use extension `stickerSetLink` + getting of `asMarkdownSource` property")
|
||||||
|
fun makeLinkToAddStickerSetInMarkdown(stickerSetName: StickerSetName) = stickerSetName.stickerSetLink.markdown
|
||||||
|
/**
|
||||||
|
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [HTML]
|
||||||
|
*/
|
||||||
|
@Deprecated("Use extension `stickerSetLink` + getting of `asHtmlSource` property")
|
||||||
|
fun makeLinkToAddStickerSetInHtml(stickerSetName: StickerSetName) = stickerSetName.stickerSetLink.html
|
||||||
/**
|
/**
|
||||||
* Create a link for adding of sticker set with name [stickerSetName]. Was added thanks to user Djaler and based on
|
* Create a link for adding of sticker set with name [stickerSetName]. Was added thanks to user Djaler and based on
|
||||||
* https://github.com/Djaler/evil-bot/blob/master/src/main/kotlin/com/github/djaler/evilbot/utils/StickerUtils.kt#L6-L8
|
* https://github.com/Djaler/evil-bot/blob/master/src/main/kotlin/com/github/djaler/evilbot/utils/StickerUtils.kt#L6-L8
|
||||||
@@ -53,34 +110,12 @@ private const val stickerSetAddingLinkPrefix = "$internalLinkBeginning/addsticke
|
|||||||
* @see [makeLinkToAddStickerSetInMarkdown]
|
* @see [makeLinkToAddStickerSetInMarkdown]
|
||||||
* @see [makeLinkToAddStickerSetInHtml]
|
* @see [makeLinkToAddStickerSetInHtml]
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("Use extension `stickerSetLink` + getting of required property")
|
||||||
fun makeLinkToAddStickerSet(
|
fun makeLinkToAddStickerSet(
|
||||||
stickerSetName: StickerSetName,
|
stickerSetName: StickerSetName,
|
||||||
parseMode: ParseMode
|
parseMode: ParseMode
|
||||||
) = (stickerSetName to "$stickerSetAddingLinkPrefix/$stickerSetName").link(
|
) = when (parseMode) {
|
||||||
parseMode
|
MarkdownParseMode -> makeLinkToAddStickerSetInMarkdown(stickerSetName)
|
||||||
)
|
MarkdownV2ParseMode -> makeLinkToAddStickerSetInMarkdownV2(stickerSetName)
|
||||||
|
HTMLParseMode -> makeLinkToAddStickerSetInHtml(stickerSetName)
|
||||||
/**
|
}
|
||||||
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [MarkdownV2]
|
|
||||||
*/
|
|
||||||
fun makeLinkToAddStickerSetInMarkdownV2(stickerSetName: StickerSetName) =
|
|
||||||
makeLinkToAddStickerSet(
|
|
||||||
stickerSetName,
|
|
||||||
MarkdownV2
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [Markdown]
|
|
||||||
*/
|
|
||||||
fun makeLinkToAddStickerSetInMarkdown(stickerSetName: StickerSetName) =
|
|
||||||
makeLinkToAddStickerSet(
|
|
||||||
stickerSetName,
|
|
||||||
Markdown
|
|
||||||
)
|
|
||||||
/**
|
|
||||||
* @return Link for adding of sticker set with name [stickerSetName] with formatting for [HTML]
|
|
||||||
*/
|
|
||||||
fun makeLinkToAddStickerSetInHtml(stickerSetName: StickerSetName) =
|
|
||||||
makeLinkToAddStickerSet(
|
|
||||||
stickerSetName,
|
|
||||||
HTML
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ fun createFormattedText(
|
|||||||
val textBuilder = StringBuilder(partLength)
|
val textBuilder = StringBuilder(partLength)
|
||||||
for (entity in entities) {
|
for (entity in entities) {
|
||||||
val string = when (mode) {
|
val string = when (mode) {
|
||||||
is MarkdownParseMode -> entity.asMarkdownSource
|
is MarkdownParseMode -> entity.markdown
|
||||||
is MarkdownV2ParseMode -> entity.asMarkdownV2Source
|
is MarkdownV2ParseMode -> entity.markdownV2
|
||||||
is HTMLParseMode -> entity.asHtmlSource
|
is HTMLParseMode -> entity.html
|
||||||
}
|
}
|
||||||
if (textBuilder.length + string.length > partLength) {
|
if (textBuilder.length + string.length > partLength) {
|
||||||
if (textBuilder.isNotEmpty()) {
|
if (textBuilder.isNotEmpty()) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.inmo.tgbotapi.extensions.utils.shortcuts
|
package dev.inmo.tgbotapi.extensions.utils.shortcuts
|
||||||
|
|
||||||
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
|
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
|
||||||
|
import dev.inmo.tgbotapi.CommonAbstracts.textSources
|
||||||
import dev.inmo.tgbotapi.extensions.utils.onlyTextContentMessages
|
import dev.inmo.tgbotapi.extensions.utils.onlyTextContentMessages
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.asContentMessagesFlow
|
import dev.inmo.tgbotapi.extensions.utils.updates.asContentMessagesFlow
|
||||||
import dev.inmo.tgbotapi.types.MessageEntity.textsources.BotCommandTextSource
|
import dev.inmo.tgbotapi.types.MessageEntity.textsources.BotCommandTextSource
|
||||||
@@ -27,7 +28,7 @@ import kotlinx.coroutines.flow.*
|
|||||||
fun <T : ContentMessage<TextContent>> Flow<T>.filterExactCommands(
|
fun <T : ContentMessage<TextContent>> Flow<T>.filterExactCommands(
|
||||||
commandRegex: Regex
|
commandRegex: Regex
|
||||||
) = filter { contentMessage ->
|
) = filter { contentMessage ->
|
||||||
(contentMessage.content.fullEntitiesList().singleOrNull() as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
|
(contentMessage.content.textSources.singleOrNull() as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,7 +47,7 @@ fun <T : ContentMessage<TextContent>> Flow<T>.filterExactCommands(
|
|||||||
fun <T : ContentMessage<TextContent>> Flow<T>.filterCommandsInsideTextMessages(
|
fun <T : ContentMessage<TextContent>> Flow<T>.filterCommandsInsideTextMessages(
|
||||||
commandRegex: Regex
|
commandRegex: Regex
|
||||||
) = filter { contentMessage ->
|
) = filter { contentMessage ->
|
||||||
contentMessage.content.fullEntitiesList().any {
|
contentMessage.content.textSources.any {
|
||||||
(it as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
|
(it as? BotCommandTextSource) ?.let { commandRegex.matches(it.command) } == true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ fun <T : ContentMessage<TextContent>> Flow<T>.filterCommandsInsideTextMessages(
|
|||||||
fun <T : ContentMessage<TextContent>> Flow<T>.filterCommandsWithArgs(
|
fun <T : ContentMessage<TextContent>> Flow<T>.filterCommandsWithArgs(
|
||||||
commandRegex: Regex
|
commandRegex: Regex
|
||||||
) = mapNotNull { contentMessage ->
|
) = mapNotNull { contentMessage ->
|
||||||
val allEntities = contentMessage.content.fullEntitiesList()
|
val allEntities = contentMessage.content.textSources
|
||||||
(allEntities.firstOrNull() as? BotCommandTextSource) ?.let {
|
(allEntities.firstOrNull() as? BotCommandTextSource) ?.let {
|
||||||
if (commandRegex.matches(it.command)) {
|
if (commandRegex.matches(it.command)) {
|
||||||
contentMessage to allEntities.flatMap {
|
contentMessage to allEntities.flatMap {
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
@file:Suppress("NOTHING_TO_INLINE", "unused", "EXPERIMENTAL_API_USAGE")
|
||||||
|
|
||||||
|
package dev.inmo.tgbotapi.extensions.utils.shortcuts
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.coroutines.plus
|
||||||
|
import dev.inmo.tgbotapi.types.message.ChannelEventMessage
|
||||||
|
import dev.inmo.tgbotapi.types.message.ChatEvents.*
|
||||||
|
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
|
||||||
|
import dev.inmo.tgbotapi.types.message.abstracts.*
|
||||||
|
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
||||||
|
import dev.inmo.tgbotapi.utils.RiskFeature
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun FlowsUpdatesFilter.events(): Flow<ChatEventMessage<*>> {
|
||||||
|
return channelPostFlow.mapNotNull { it.data as? ChatEventMessage<*> } + messageFlow.mapNotNull { it.data as? ChatEventMessage<*> }
|
||||||
|
}
|
||||||
|
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun FlowsUpdatesFilter.channelEvents(): Flow<ChannelEventMessage<*>> = channelPostFlow.mapNotNull {
|
||||||
|
it.data as? ChannelEventMessage<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun FlowsUpdatesFilter.groupEvents(): Flow<GroupEventMessage<*>> = messageFlow.mapNotNull {
|
||||||
|
it.data as? GroupEventMessage<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun FlowsUpdatesFilter.supergroupEvents(): Flow<SupergroupEventMessage<*>> = messageFlow.mapNotNull {
|
||||||
|
it.data as? SupergroupEventMessage<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun <reified T: ChatEvent, reified O: ChatEventMessage<T>> Flow<ChatEventMessage<*>>.filterByChatEvent(): Flow<O> = mapNotNull {
|
||||||
|
if (it.chatEvent is T) it as? O else null
|
||||||
|
}
|
||||||
|
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun <reified T : ChannelEvent> Flow<ChatEventMessage<*>>.filterChannelEvents() = filterByChatEvent<T, ChannelEventMessage<T>>()
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun <reified T : ChannelEvent> FlowsUpdatesFilter.filterChannelEvents() = channelEvents().filterChannelEvents<T>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.channelCreatedEvents() = filterChannelEvents<ChannelChatCreated>()
|
||||||
|
inline fun FlowsUpdatesFilter.channelCreatedEvents() = filterChannelEvents<ChannelChatCreated>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.deletedChannelPhotoEvents() = filterChannelEvents<DeleteChatPhoto>()
|
||||||
|
inline fun FlowsUpdatesFilter.deletedChannelPhotoEvents() = filterChannelEvents<DeleteChatPhoto>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newChannelPhotoEvents() = filterChannelEvents<NewChatPhoto>()
|
||||||
|
inline fun FlowsUpdatesFilter.newChannelPhotoEvents() = filterChannelEvents<NewChatPhoto>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newChannelTitleEvents() = filterChannelEvents<NewChatTitle>()
|
||||||
|
inline fun FlowsUpdatesFilter.newChannelTitleEvents() = filterChannelEvents<NewChatTitle>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newChannelPinnedMessageEvents() = filterChannelEvents<PinnedMessage>()
|
||||||
|
inline fun FlowsUpdatesFilter.newChannelPinnedMessageEvents() = filterChannelEvents<PinnedMessage>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.channelEvents() = filterChannelEvents<ChannelEvent>()
|
||||||
|
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun <reified T : GroupEvent> Flow<ChatEventMessage<*>>.filterGroupEvents() = filterByChatEvent<T, GroupEventMessage<T>>()
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun <reified T : GroupEvent> FlowsUpdatesFilter.filterGroupEvents() = groupEvents().filterByChatEvent<T, GroupEventMessage<T>>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.groupCreatedEvents() = filterGroupEvents<GroupChatCreated>()
|
||||||
|
inline fun FlowsUpdatesFilter.groupCreatedEvents() = filterGroupEvents<GroupChatCreated>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.deletedGroupPhotoEvents() = filterGroupEvents<DeleteChatPhoto>()
|
||||||
|
inline fun FlowsUpdatesFilter.deletedGroupPhotoEvents() = filterGroupEvents<DeleteChatPhoto>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newGroupMembersEvents() = filterGroupEvents<NewChatMembers>()
|
||||||
|
inline fun FlowsUpdatesFilter.newGroupMembersEvents() = filterGroupEvents<NewChatMembers>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.leftGroupMemberEvents() = filterGroupEvents<LeftChatMember>()
|
||||||
|
inline fun FlowsUpdatesFilter.leftGroupMemberEvents() = filterGroupEvents<LeftChatMember>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newGroupPhotoEvents() = filterGroupEvents<NewChatPhoto>()
|
||||||
|
inline fun FlowsUpdatesFilter.newGroupPhotoEvents() = filterGroupEvents<NewChatPhoto>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newGroupTitleEvents() = filterGroupEvents<NewChatTitle>()
|
||||||
|
inline fun FlowsUpdatesFilter.newGroupTitleEvents() = filterGroupEvents<NewChatTitle>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newGroupPinnedMessageEvents() = filterGroupEvents<PinnedMessage>()
|
||||||
|
inline fun FlowsUpdatesFilter.newGroupPinnedMessageEvents() = filterGroupEvents<PinnedMessage>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.proximityAlertTriggeredInGroupEvents() = filterGroupEvents<ProximityAlertTriggered>()
|
||||||
|
inline fun FlowsUpdatesFilter.proximityAlertTriggeredInGroupEvents() = filterGroupEvents<ProximityAlertTriggered>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.groupEvents() = filterGroupEvents<GroupEvent>()
|
||||||
|
|
||||||
|
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun <reified T : SupergroupEvent> Flow<ChatEventMessage<*>>.filterSupergroupEvents() = filterByChatEvent<T, SupergroupEventMessage<T>>()
|
||||||
|
@RiskFeature("Use with caution")
|
||||||
|
inline fun <reified T : SupergroupEvent> FlowsUpdatesFilter.filterSupergroupEvents() = supergroupEvents().filterByChatEvent<T, SupergroupEventMessage<T>>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.supergroupCreatedEvents() = filterSupergroupEvents<SupergroupChatCreated>()
|
||||||
|
inline fun FlowsUpdatesFilter.supergroupCreatedEvents() = filterSupergroupEvents<SupergroupChatCreated>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.deletedSupergroupPhotoEvents() = filterSupergroupEvents<DeleteChatPhoto>()
|
||||||
|
inline fun FlowsUpdatesFilter.deletedSupergroupPhotoEvents() = filterSupergroupEvents<DeleteChatPhoto>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newSupergroupMembersEvents() = filterSupergroupEvents<NewChatMembers>()
|
||||||
|
inline fun FlowsUpdatesFilter.newSupergroupMembersEvents() = filterSupergroupEvents<NewChatMembers>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.leftSupergroupMemberEvents() = filterSupergroupEvents<LeftChatMember>()
|
||||||
|
inline fun FlowsUpdatesFilter.leftSupergroupMemberEvents() = filterSupergroupEvents<LeftChatMember>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newSupergroupPhotoEvents() = filterSupergroupEvents<NewChatPhoto>()
|
||||||
|
inline fun FlowsUpdatesFilter.newSupergroupPhotoEvents() = filterSupergroupEvents<NewChatPhoto>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newSupergroupTitleEvents() = filterSupergroupEvents<NewChatTitle>()
|
||||||
|
inline fun FlowsUpdatesFilter.newSupergroupTitleEvents() = filterSupergroupEvents<NewChatTitle>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.newSupergroupPinnedMessageEvents() = filterSupergroupEvents<PinnedMessage>()
|
||||||
|
inline fun FlowsUpdatesFilter.newSupergroupPinnedMessageEvents() = filterSupergroupEvents<PinnedMessage>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.proximityAlertTriggeredInSupergroupEvents() = filterSupergroupEvents<ProximityAlertTriggered>()
|
||||||
|
inline fun FlowsUpdatesFilter.proximityAlertTriggeredInSupergroupEvents() = filterSupergroupEvents<ProximityAlertTriggered>()
|
||||||
|
inline fun Flow<ChatEventMessage<*>>.supergroupEvents() = filterSupergroupEvents<SupergroupEvent>()
|
||||||
@@ -19,12 +19,15 @@ fun <T : BaseSentMessageUpdate> Flow<T>.asCommonMessagesFlow() = mapNotNull {
|
|||||||
it.data as? CommonMessage<*>
|
it.data as? CommonMessage<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <T : BaseSentMessageUpdate> Flow<T>.chatEvents() = mapNotNull {
|
||||||
|
it.data as? ChatEventMessage<*>
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Will map incoming [BaseSentMessageUpdate]s to [ChatEventMessage] from [BaseSentMessageUpdate.data]
|
* Will map incoming [BaseSentMessageUpdate]s to [ChatEventMessage] from [BaseSentMessageUpdate.data]
|
||||||
*/
|
*/
|
||||||
fun <T : BaseSentMessageUpdate> Flow<T>.asChatEventsFlow() = mapNotNull {
|
@Deprecated("Renamed", ReplaceWith("chatEvents", "dev.inmo.tgbotapi.extensions.utils.updates.chatEvents"))
|
||||||
it.data as? ChatEventMessage
|
fun <T : BaseSentMessageUpdate> Flow<T>.asChatEventsFlow() = chatEvents()
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will map incoming [BaseSentMessageUpdate]s to [UnknownMessageType] from [BaseSentMessageUpdate.data]
|
* Will map incoming [BaseSentMessageUpdate]s to [UnknownMessageType] from [BaseSentMessageUpdate.data]
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ fun RequestsExecutor.startGettingOfUpdatesByLongPolling(
|
|||||||
* [flowUpdatesPreset] lambda - it will be called BEFORE starting updates getting
|
* [flowUpdatesPreset] lambda - it will be called BEFORE starting updates getting
|
||||||
*/
|
*/
|
||||||
@FlowPreview
|
@FlowPreview
|
||||||
@PreviewFeature
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
fun RequestsExecutor.startGettingFlowsUpdatesByLongPolling(
|
fun RequestsExecutor.startGettingFlowsUpdatesByLongPolling(
|
||||||
timeoutSeconds: Seconds = 30,
|
timeoutSeconds: Seconds = 30,
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ import dev.inmo.micro_utils.coroutines.safely
|
|||||||
import dev.inmo.tgbotapi.bot.RequestsExecutor
|
import dev.inmo.tgbotapi.bot.RequestsExecutor
|
||||||
import dev.inmo.tgbotapi.extensions.utils.nonstrictJsonFormat
|
import dev.inmo.tgbotapi.extensions.utils.nonstrictJsonFormat
|
||||||
import dev.inmo.tgbotapi.extensions.utils.updates.flowsUpdatesFilter
|
import dev.inmo.tgbotapi.extensions.utils.updates.flowsUpdatesFilter
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.MultipartFile
|
import dev.inmo.tgbotapi.requests.webhook.SetWebhookRequest
|
||||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
|
||||||
import dev.inmo.tgbotapi.requests.send.media.base.MultipartRequestImpl
|
|
||||||
import dev.inmo.tgbotapi.requests.webhook.SetWebhook
|
|
||||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||||
import dev.inmo.tgbotapi.types.update.abstracts.UpdateDeserializationStrategy
|
import dev.inmo.tgbotapi.types.update.abstracts.UpdateDeserializationStrategy
|
||||||
import dev.inmo.tgbotapi.updateshandlers.*
|
import dev.inmo.tgbotapi.updateshandlers.*
|
||||||
@@ -67,7 +64,7 @@ fun Route.includeWebhookHandlingInRouteWithFlows(
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
* Setting up ktor server
|
||||||
*
|
*
|
||||||
* @param listenPort port which will be listen by bot
|
* @param listenPort port which will be listen by bot
|
||||||
* @param listenRoute address to listen by bot. If null - will be set up in root of host
|
* @param listenRoute address to listen by bot. If null - will be set up in root of host
|
||||||
@@ -119,27 +116,8 @@ fun startListenWebhooks(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun RequestsExecutor.internalSetWebhookInfoAndStartListenWebhooks(
|
|
||||||
listenPort: Int,
|
|
||||||
engineFactory: ApplicationEngineFactory<*, *>,
|
|
||||||
setWebhookRequest: Request<Boolean>,
|
|
||||||
exceptionsHandler: ExceptionHandler<Unit> = {},
|
|
||||||
listenHost: String = "0.0.0.0",
|
|
||||||
listenRoute: String? = null,
|
|
||||||
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
|
||||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
|
||||||
block: UpdateReceiver<Update>
|
|
||||||
): ApplicationEngine {
|
|
||||||
return try {
|
|
||||||
execute(setWebhookRequest)
|
|
||||||
startListenWebhooks(listenPort, engineFactory, exceptionsHandler, listenHost, listenRoute, privateKeyConfig, scope, block)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
* Setting up ktor server, set webhook info via [SetWebhookRequest] request.
|
||||||
*
|
*
|
||||||
* @param listenPort port which will be listen by bot
|
* @param listenPort port which will be listen by bot
|
||||||
* @param listenRoute address to listen by bot
|
* @param listenRoute address to listen by bot
|
||||||
@@ -153,55 +131,16 @@ private suspend fun RequestsExecutor.internalSetWebhookInfoAndStartListenWebhook
|
|||||||
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
||||||
listenPort: Int,
|
listenPort: Int,
|
||||||
engineFactory: ApplicationEngineFactory<*, *>,
|
engineFactory: ApplicationEngineFactory<*, *>,
|
||||||
setWebhookRequest: SetWebhook,
|
setWebhookRequest: SetWebhookRequest,
|
||||||
exceptionsHandler: ExceptionHandler<Unit> = {},
|
exceptionsHandler: ExceptionHandler<Unit> = {},
|
||||||
listenHost: String = "0.0.0.0",
|
listenHost: String = "0.0.0.0",
|
||||||
listenRoute: String = "/",
|
listenRoute: String = "/",
|
||||||
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
||||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
||||||
block: UpdateReceiver<Update>
|
block: UpdateReceiver<Update>
|
||||||
): ApplicationEngine = internalSetWebhookInfoAndStartListenWebhooks(
|
): ApplicationEngine = try {
|
||||||
listenPort,
|
execute(setWebhookRequest)
|
||||||
engineFactory,
|
startListenWebhooks(listenPort, engineFactory, exceptionsHandler, listenHost, listenRoute, privateKeyConfig, scope, block)
|
||||||
setWebhookRequest as Request<Boolean>,
|
} catch (e: Exception) {
|
||||||
exceptionsHandler,
|
throw e
|
||||||
listenHost,
|
}
|
||||||
listenRoute,
|
|
||||||
privateKeyConfig,
|
|
||||||
scope,
|
|
||||||
block
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setting up ktor server, set webhook info via [SetWebhook] request.
|
|
||||||
*
|
|
||||||
* @param listenPort port which will be listen by bot
|
|
||||||
* @param listenRoute address to listen by bot
|
|
||||||
* @param scope Scope which will be used for
|
|
||||||
*
|
|
||||||
* @see dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
|
|
||||||
* @see UpdatesFilter
|
|
||||||
* @see UpdatesFilter.asUpdateReceiver
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
suspend fun RequestsExecutor.setWebhookInfoAndStartListenWebhooks(
|
|
||||||
listenPort: Int,
|
|
||||||
engineFactory: ApplicationEngineFactory<*, *>,
|
|
||||||
setWebhookRequest: MultipartRequestImpl<SetWebhook, Map<String, MultipartFile>, Boolean>,
|
|
||||||
exceptionsHandler: ExceptionHandler<Unit> = {},
|
|
||||||
listenHost: String = "0.0.0.0",
|
|
||||||
listenRoute: String? = null,
|
|
||||||
privateKeyConfig: WebhookPrivateKeyConfig? = null,
|
|
||||||
scope: CoroutineScope = CoroutineScope(Executors.newFixedThreadPool(4).asCoroutineDispatcher()),
|
|
||||||
block: UpdateReceiver<Update>
|
|
||||||
): ApplicationEngine = internalSetWebhookInfoAndStartListenWebhooks(
|
|
||||||
listenPort,
|
|
||||||
engineFactory,
|
|
||||||
setWebhookRequest as Request<Boolean>,
|
|
||||||
exceptionsHandler,
|
|
||||||
listenHost,
|
|
||||||
listenRoute,
|
|
||||||
privateKeyConfig,
|
|
||||||
scope,
|
|
||||||
block
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,15 +39,9 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation kotlin('stdlib')
|
implementation kotlin('stdlib')
|
||||||
if ((project.hasProperty('RELEASE_MODE') && project.property('RELEASE_MODE') == "true") || System.getenv('RELEASE_MODE') == "true") {
|
api project(":tgbotapi.core")
|
||||||
api "${project.group}:tgbotapi.core:$library_version"
|
api project(":tgbotapi.extensions.api")
|
||||||
api "${project.group}:tgbotapi.extensions.api:$library_version"
|
api project(":tgbotapi.extensions.utils")
|
||||||
api "${project.group}:tgbotapi.extensions.utils:$library_version"
|
|
||||||
} else {
|
|
||||||
api project(":tgbotapi.core")
|
|
||||||
api project(":tgbotapi.extensions.api")
|
|
||||||
api project(":tgbotapi.extensions.utils")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
apply plugin: 'maven-publish'
|
|
||||||
|
|
||||||
task javadocsJar(type: Jar) {
|
|
||||||
classifier = 'javadoc'
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
project.publishing.publications.all {
|
|
||||||
// rename artifacts
|
|
||||||
groupId "${project.group}"
|
|
||||||
if (it.name.contains('kotlinMultiplatform')) {
|
|
||||||
artifactId = "${project.name}"
|
|
||||||
} else {
|
|
||||||
artifactId = "${project.name}-$name"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications.all {
|
|
||||||
artifact javadocsJar
|
|
||||||
|
|
||||||
pom {
|
|
||||||
description = "This project just include all subproject of TelegramBotAPI"
|
|
||||||
name = "Telegram Bot API"
|
|
||||||
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI"
|
|
||||||
|
|
||||||
scm {
|
|
||||||
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
|
||||||
}
|
|
||||||
|
|
||||||
developers {
|
|
||||||
|
|
||||||
developer {
|
|
||||||
id = "InsanusMokrassar"
|
|
||||||
name = "Ovsiannikov Aleksei"
|
|
||||||
email = "ovsyannikov.alexey95@gmail.com"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
licenses {
|
|
||||||
|
|
||||||
license {
|
|
||||||
name = "Apache Software License 2.0"
|
|
||||||
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +1,65 @@
|
|||||||
apply plugin: 'com.jfrog.bintray'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
apply from: "maven.publish.gradle"
|
task javadocsJar(type: Jar) {
|
||||||
|
classifier = 'javadoc'
|
||||||
bintray {
|
|
||||||
user = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
|
||||||
key = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
|
||||||
filesSpec {
|
|
||||||
from "${buildDir}/publications/"
|
|
||||||
eachFile {
|
|
||||||
String directorySubname = it.getFile().parentFile.name
|
|
||||||
if (it.getName() == "module.json") {
|
|
||||||
if (directorySubname == "kotlinMultiplatform") {
|
|
||||||
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module")
|
|
||||||
} else {
|
|
||||||
it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") {
|
|
||||||
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom")
|
|
||||||
} else {
|
|
||||||
it.exclude()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
into "${project.group}".replace(".", "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
publish = true
|
|
||||||
override = true
|
|
||||||
|
|
||||||
pkg {
|
|
||||||
repo = "TelegramBotAPI"
|
|
||||||
name = "${project.name}"
|
|
||||||
vcsUrl = "https://github.com/InsanusMokrassar/TelegramBotAPI"
|
|
||||||
licenses = ["Apache-2.0"]
|
|
||||||
version {
|
|
||||||
name = "${project.version}"
|
|
||||||
released = new Date()
|
|
||||||
vcsTag = "${project.version}"
|
|
||||||
gpg {
|
|
||||||
sign = true
|
|
||||||
passphrase = project.hasProperty('signing.gnupg.passphrase') ? project.property('signing.gnupg.passphrase') : System.getenv('signing.gnupg.passphrase')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bintrayUpload.doFirst {
|
afterEvaluate {
|
||||||
publications = publishing.publications.collect {
|
project.publishing.publications.all {
|
||||||
|
// rename artifacts
|
||||||
|
groupId "${project.group}"
|
||||||
if (it.name.contains('kotlinMultiplatform')) {
|
if (it.name.contains('kotlinMultiplatform')) {
|
||||||
null
|
artifactId = "${project.name}"
|
||||||
} else {
|
} else {
|
||||||
it.name
|
artifactId = "${project.name}-$name"
|
||||||
}
|
}
|
||||||
} - null
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bintrayUpload.dependsOn publishToMavenLocal
|
publishing {
|
||||||
|
publications.all {
|
||||||
|
artifact javadocsJar
|
||||||
|
|
||||||
|
pom {
|
||||||
|
description = "This project just include all subproject of TelegramBotAPI"
|
||||||
|
name = "Telegram Bot API"
|
||||||
|
url = "https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI"
|
||||||
|
|
||||||
|
scm {
|
||||||
|
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
|
||||||
|
}
|
||||||
|
|
||||||
|
developers {
|
||||||
|
|
||||||
|
developer {
|
||||||
|
id = "InsanusMokrassar"
|
||||||
|
name = "Ovsiannikov Aleksei"
|
||||||
|
email = "ovsyannikov.alexey95@gmail.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
licenses {
|
||||||
|
|
||||||
|
license {
|
||||||
|
name = "Apache Software License 2.0"
|
||||||
|
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "bintray"
|
||||||
|
url = uri("https://api.bintray.com/maven/${project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')}/TelegramBotAPI/${project.name}/;publish=1;override=1")
|
||||||
|
credentials {
|
||||||
|
username = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
|
||||||
|
password = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user