1
0
mirror of https://github.com/InsanusMokrassar/TelegramBotAPI.git synced 2025-11-16 12:00:18 +00:00

Compare commits

..

112 Commits

Author SHA1 Message Date
0b2f7a3899 update condition for ReplyMessageNotFoundException 2021-03-26 07:03:33 +06:00
112c86c9da remove caption based messages extension for parsing of commands 2021-03-24 13:56:51 +06:00
1ddd138ff7 update kdocs for new function 2021-03-24 13:44:27 +06:00
1a5d1cde78 add parseCommandsWithParams for text inputs 2021-03-24 13:43:32 +06:00
5b620014cb update kotlin version 2021-03-24 13:14:09 +06:00
9f8e8ee21b update dependencies 2021-03-19 20:20:07 +06:00
3de3bb6133 start 0.33.1 2021-03-19 20:18:32 +06:00
308fb9274b Update kdocs.yml 2021-03-17 21:14:05 +06:00
d14ca7bbdc Update kdocs.yml 2021-03-17 21:13:52 +06:00
dbdd9b5ad2 update dokka 2021-03-16 23:01:26 +06:00
6dd27cb0bf fixes in names of workflows 2021-03-16 22:41:45 +06:00
210a52485b add kdocs yml config 2021-03-16 22:39:54 +06:00
5c11b60ea6 fix dokka config 2021-03-16 22:33:53 +06:00
60c3a0d7af update core info about current version 2021-03-16 22:21:15 +06:00
8d777e1c0e Update dokka version 2021-03-16 16:30:13 +06:00
4e019eb8bb Update packages_publishing.yml 2021-03-12 20:11:26 +06:00
bd80562c2a Merge pull request #337 from InsanusMokrassar/0.33.0
0.33.0
2021-03-12 15:47:24 +06:00
9fc07f2ff3 fix build 2021-03-12 15:03:11 +06:00
a4bae5133a fill changelog 2021-03-12 14:58:13 +06:00
7bb272f2fa update compatibility note 2021-03-12 14:39:27 +06:00
72cf38d3bb fill Behaviour Builder for ChatMemberUpdated 2021-03-12 14:36:10 +06:00
0adee13cba remove deprecations 2021-03-11 22:28:56 +06:00
f9e3e57f24 migrate 0.32.10 -> 0.33.0 2021-03-11 21:44:08 +06:00
d7d4adc8e4 optimize imports 2021-03-11 21:39:34 +06:00
e9b074a36c updates of FlowsUpdatesFilter 2021-03-11 21:36:29 +06:00
65cba0f014 fill api of chat invite links 2021-03-11 21:25:11 +06:00
36202133a1 update classcasts 2021-03-11 21:06:25 +06:00
66f7801b32 fix ChatInviteLinkRequest 2021-03-11 20:41:47 +06:00
e7265829d1 include ChatMemberUpdated functionality 2021-03-11 20:17:08 +06:00
9ad5bfbc57 remove BotInviteChatLink 2021-03-11 16:36:15 +06:00
aba62ba930 chatmember serializers are public 2021-03-11 16:00:47 +06:00
40d702a311 add representations of all chat invite link functionality 2021-03-10 22:46:56 +06:00
233d893b5a add isOff extension for MessageAutoDeleteTimerChanged 2021-03-09 22:33:05 +06:00
0faca5838c fixes in events builder behaviours 2021-03-09 22:14:16 +06:00
838f62aa84 shortcuts seconds24Hours and seconds7Days are consts for now 2021-03-09 22:06:20 +06:00
bc21a680bc fixes for MessageAutoDeleteTimerChanged 2021-03-09 22:00:17 +06:00
8bb60bea34 now MessageAutoDeleteTimerChanged implementing ChannelEvent and GroupEvent 2021-03-09 21:37:25 +06:00
8daadcff95 now MessageAutoDeleteTimerChanged implementing ChannelEvent and GroupEvent 2021-03-09 21:35:53 +06:00
2a1e624641 VoiceChatParticipantsInvited type now is data class 2021-03-09 20:23:03 +06:00
696822db02 add behaviour builder events updates 2021-03-09 20:04:44 +06:00
ded501d963 remove regular build 2021-03-09 19:52:46 +06:00
86e506c33d include message_auto_delete_timer_change 2021-03-09 19:45:19 +06:00
9902b00e85 include revokeMessages in kickChatMember 2021-03-09 19:33:05 +06:00
53524abcbb include canManageChat 2021-03-09 19:26:30 +06:00
7639b15dc6 voice chats functionality included 2021-03-09 19:19:15 +06:00
61b720c61f fix of content waiters and expecters 2021-03-09 16:54:32 +06:00
baf4c74b69 update micro_utils 2021-03-09 16:46:08 +06:00
367cfff2cb start 0.32.10 2021-03-09 16:45:13 +06:00
75e8d0f62d Merge pull request #325 from InsanusMokrassar/0.32.9
0.32.9
2021-03-05 01:08:58 +06:00
c521a5f9a4 Update CHANGELOG.md 2021-03-03 22:32:44 +06:00
c5513365c2 Update gradle.properties 2021-03-03 22:31:29 +06:00
d184ce7a0f Update mpp_publish_template.kpsb 2021-03-03 01:39:18 +06:00
a3bff3f24d Update publish.gradle 2021-03-03 01:37:38 +06:00
a835b1dcbb Update mpp_publish_template.kpsb 2021-03-03 01:33:50 +06:00
ffed2b80a5 update publish scripts to avoid useless repos 2021-03-02 16:45:13 +06:00
ff24b9f35b add workflow for packages publication 2021-03-02 16:25:55 +06:00
1287852334 update microutils version 2021-03-02 15:26:52 +06:00
fc2f177e38 update dependencies 2021-02-28 22:24:34 +06:00
1efd4dce6e start 0.32.9 2021-02-28 22:21:57 +06:00
69b5a16b17 Update gradle-wrapper.properties 2021-02-23 09:53:45 +06:00
77b531ad06 Merge pull request #307 from InsanusMokrassar/0.32.8
0.32.8
2021-02-22 01:35:40 +06:00
a98d5d9abd update micro_utils 2021-02-21 22:50:47 +06:00
104653ac41 update serialization 2021-02-21 21:15:40 +06:00
63337b8285 start 0.32.8 2021-02-21 21:13:23 +06:00
5cc0bbb31b Merge pull request #303 from InsanusMokrassar/0.32.7
0.32.7
2021-02-18 00:34:46 +06:00
563d784603 RestrictionsChatPermissions 2021-02-18 00:28:36 +06:00
0d9f18f346 DiceAnimationType class casts 2021-02-17 22:29:29 +06:00
23ceaf8e97 LeftRestrictionsChatPermissions 2021-02-17 22:12:58 +06:00
fe2dffd8b5 BehaviourContext updates 2021-02-17 22:11:26 +06:00
eeb46817c3 start 0.32.7 2021-02-17 22:00:46 +06:00
5ab00da31d Merge pull request #300 from InsanusMokrassar/0.32.6
0.32.6
2021-02-17 17:15:40 +06:00
841ae73f7c replyWithDice 2021-02-17 17:10:21 +06:00
41b4d29917 updates in slot machine utils 2021-02-17 16:58:57 +06:00
f8b3c44146 update micro_utils 2021-02-16 13:48:32 +06:00
f0eb670c3f start 0.32.6 2021-02-16 13:47:31 +06:00
fe5d94f31e Update README.md 2021-02-13 10:09:33 +06:00
7901d0a223 Update README.md 2021-02-13 01:42:35 +06:00
799f9123ba Update README.md 2021-02-13 01:38:31 +06:00
f77f010e66 Update README.md 2021-02-11 13:38:55 +06:00
67ddf8d809 Update README.md 2021-02-11 13:37:24 +06:00
81afa46253 Update README.md 2021-02-11 13:36:53 +06:00
a5bba76f07 Update README.md 2021-02-11 13:35:06 +06:00
d882cf9c97 update readme 2021-02-11 12:06:34 +06:00
2e27b8b64d Merge pull request #295 from InsanusMokrassar/0.32.5
0.32.5
2021-02-09 19:13:42 +06:00
4df800eaa9 fix of #291 2021-02-09 19:07:31 +06:00
8d27349868 update content resends and different other things 2021-02-09 18:26:10 +06:00
2a89c41a58 fix of #292 2021-02-09 17:15:28 +06:00
098b5cc393 rewrite createAccumulatedUpdatesRetrieverFlow onto channelFlow 2021-02-09 16:33:48 +06:00
10f4817283 solution of #293 2021-02-08 19:35:32 +06:00
4449893608 fix of #294 2021-02-08 18:15:54 +06:00
3a53f41f66 start 0.32.5 2021-02-08 11:36:20 +06:00
7cd366d893 Update README.md 2021-02-07 18:02:20 +06:00
1309a4111c Merge pull request #290 from InsanusMokrassar/0.32.4
content messages renames
2021-02-07 16:59:51 +06:00
0ca815760b content messages renames 2021-02-07 16:54:48 +06:00
eca0680f2f update readme 2021-02-07 12:44:38 +06:00
d472d371ed Merge pull request #282 from InsanusMokrassar/0.32.4
0.32.4
2021-02-07 12:43:08 +06:00
4748b6813a ExceptionsOnlyLimiter now will not use Result to provide success/failure state of result 2021-02-07 12:40:05 +06:00
a2ea15d4b0 update wrapper version 2021-02-07 11:02:13 +06:00
27dc302f5d update for compiling 2021-02-06 11:53:30 +06:00
baf8ed3a77 now JVM part will be compiled with IR 2021-02-06 00:52:39 +06:00
18913af3c3 update publishing scripts 2021-02-06 00:50:51 +06:00
51871ea94c update micro_utils version 2021-02-05 16:08:45 +06:00
6a625d7b9f update publishing scripts 2021-02-05 16:08:28 +06:00
0b93b472a3 update klock 2021-02-05 14:22:42 +06:00
ff16f9a315 Update README.md 2021-02-05 01:18:38 +06:00
86bfe043a5 update dependencies 2021-02-03 23:05:17 +06:00
fa18e7299d 0.32.4 2021-02-03 22:59:37 +06:00
c986025075 Merge pull request #277 from InsanusMokrassar/0.32.3
0.32.3
2021-02-02 11:44:53 +06:00
e8a7ea9ce4 inline qieries expectators and waiters 2021-02-02 11:17:51 +06:00
30f35e5488 start 0.32.3 2021-02-02 11:07:30 +06:00
b626974ea7 Create dependabot.yml 2021-02-01 23:22:26 +06:00
128b782a27 Merge pull request #276 from InsanusMokrassar/0.32.2
0.32.2
2021-02-01 21:43:21 +06:00
126 changed files with 1920 additions and 800 deletions

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gradle" # See documentation for possible values
directory: "/tgbotapi.core" # Location of package manifests
schedule:
interval: "daily"

21
.github/workflows/kdocs.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: Publish KDocs
on:
push:
branches:
- master
jobs:
publishing:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build
run: ./gradlew dokkaGfm
- name: Publish KDocs
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/build/dokka/gfm
publish_branch: kdocs

View File

@@ -0,0 +1,23 @@
name: Publish package to GitHub Packages
on: [push]
jobs:
publishing:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Rewrite version
run: |
branch="`echo "${{ github.ref }}" | grep -o "[^/]*$"`"
cat gradle.properties | sed -e "s/^library_version=\([0-9\.]*\)/library_version=\1-branch_$branch-build${{ github.run_number }}/" > gradle.properties.tmp
rm gradle.properties
mv gradle.properties.tmp gradle.properties
- name: Build
run: ./gradlew build
- name: Publish
run: ./gradlew publishAllPublicationsToGithubPackagesRepository --no-parallel -x signJsPublication -x signJvmPublication -x signKotlinMultiplatformPublication -x signMetadataPublication
env:
GITHUBPACKAGES_USER: ${{ github.actor }}
GITHUBPACKAGES_PASSWORD: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,16 +0,0 @@
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Build with Gradle
run: ./gradlew build

View File

@@ -1,5 +1,124 @@
# TelegramBotAPI changelog
## 0.33.1
* `Common`:
* `Version`:
* `Kotlin`: `1.4.31` -> `1.4.32`
* `MicroUtils`: `0.4.29` -> `0.4.30`
* `Klocks`: `2.0.6` -> `2.0.7`
* `Utils Extensions`:
* Add extensions `parseCommandsWithParams`
## 0.33.0
**UPDATE UP TO Telegram Bot API 5.1**
_**ALL DEPRECATIONS WERE REMOVED**_
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.28` -> `0.4.29`
* `Core`:
* `AdministratorChatMemberSerializer` and `ChatMemberSerializer` has changed their visibility: they are public for now
* Add `ChatInviteLinkRequest` with subrequests like `KnownChatInviteLinkRequest`
* Add `CreateChatInviteLink`/`EditChatInviteLink`/`RevokeChatInviteLink` requests
* Update `KickChatMember` to include `revokeMessages` flag
* Update `PromoteChatMember` to include `canManageVoiceChats` and `canManageChat` flags
* Add `ChatInviteLink` object
* Add `PrimaryInviteLink` for `ChatInviteLink` with `isPrimary == true`
* Add `CommonInviteLink` for `ChatInviteLink` with `isPrimary == false`
* `AdministratorChatMemberSerializer` has been set as public for several versions
* `ChatMemberSerializer` has been set as public for several versions
* Add `ChatMemberUpdated`
* Add `MessageAutoDeleteTimerChanged`
* Add `VoiceChatEvent`
* Add `VoiceChatEnded`
* Add `VoiceChatParticipantsInvited`
* Add `VoiceChatStarted`
* Add `ChatMemberUpdatedUpdate`
* Add `CommonChatMemberUpdatedUpdate`
* Add `MyChatMemberUpdatedUpdate`
* `API`:
* All API extensions has been updated
* `Behaviour Builder`:
* Now content triggers and expectators will wait for channel posts too
* New waiters and triggers for `ChatMemberUpdated` and its variations
## 0.32.9
* `Common`:
* `Version`:
* `Kotlin`: `1.4.30` -> `1.4.31`
* `Ktor`: `1.5.1` -> `1.5.2`
* `MicroUtils`: `0.4.26` -> `0.4.28`
* `Coroutines`: `1.4.2` -> `1.4.3`
## 0.32.8
* `Common`:
* `Version`:
* `Serialization`: `1.1.0-RC` -> `1.1.0`
* `MicroUtils`: `0.4.25` -> `0.4.26`
## 0.32.7
* `Core`:
* New variable `LeftRestrictionsChatPermissions` and `RestrictionsChatPermissions`
* `Extensions Utils`:
* `DiceAnimationType` class casts
* `Behaviour Builder`:
* Now `doInSubContextWithUpdatesFilter` and `doInSubContext` will automatically subscribe on updates of parent
`BehaviourContext`
* `doInSubContextWithFlowsUpdatesFilterSetup`, `doInSubContextWithUpdatesFilter` and `doInSubContext` got new
parameter `stopOnCompletion` to be able to disable stopping of behaviour context on finishing
## 0.32.6
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.24` -> `0.4.25`
* `Extensions API`:
* New extension `TelegramBot#replyWithDice`
* `Extensions Utils`:
* `SlotMachineReelImages` has been renamed to `SlotMachineReelImage`
* `SlotMachineReelImage` got two built-in parameters: `text` and `number`
* New extension `String#asSlotMachineReelImage`
## 0.32.5
* `Core`:
* Add `mention` variants for user ids and receiver variants ([#294](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/294))
* Now `AbstractRequestCallFactory` will set up one-second delay for zero timeouts in `GetUpdate` requests
* Several extensions for `TelegramBotAPI` like `retrieveAccumulatedUpdates` have been added as a solution for
[#293](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/293)
* Links for `tg://user?id=<user_id>` have been updated ([#292](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/292))
* All usages of captions or texts in resends and same things have been replaced with `textSources`
* Global `defaultParseMode` has been added ([#291](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/291))
## 0.32.4
* `Common`:
* `Version`:
* `Kotlin`: `1.4.21` -> `1.4.30`
* `Klock`: `2.0.4` -> `2.0.6`
* `MicroUtils`: `0.4.23` -> `0.4.24`
* `Core`:
* Renames:
* `ChannelMessage` -> `ChannelContentMessage`
* `PublicMessage` -> `PublicContentMessage`
* `GroupMessage` -> `GroupContentMessage`
* `FromChannelGroupMessage` -> `FromChannelGroupContentMessage`
* `AnonymousGroupMessage` -> `AnonymousGroupContentMessage`
* `CommonGroupMessage` -> `CommonGroupContentMessage`
* `PrivateMessage` -> `PrivateContentMessage`
* `Extensions Utils`:
* Renames of extensions in `ClassCasts` according to changes in `Core`
## 0.32.3
* `Behaviour Builder`:
* Add expectators and waiters for inline queries
## 0.32.2
* `Core`:

223
README.md
View File

@@ -1,153 +1,118 @@
[Participate in our common survey ☺](https://forms.gle/q6Xf8K3fD1pPsYUw9)
# TelegramBotAPI
<details>
<summary><b>I do not wanna read a lot, just give me my bot</b></summary>
Hello! This is a set of libraries for working with Telegram Bot API.
You can simply use <a href="https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template">this template</a> (and button
<a href="https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate">Use template</a>) to get your copy of bot and start to code.
<p></p>
<b>P.S. Do not forget to look into our <a href="https://bookstack.inmo.dev/books/telegrambotapi/">minidocs</a> and
<a href="https://tgbotapi.inmo.dev/docs/index.html">kdocs</a></b>
</details>
| Common info | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Build Status](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI.svg?branch=master)](https://travis-ci.com/InsanusMokrassar/TelegramBotAPI) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
| Common info | [![Awesome Kotlin Badge](https://kotlin.link/awesome-kotlin.svg)](https://github.com/KotlinBy/awesome-kotlin) [![Build Status](https://github.com/InsanusMokrassar/TelegramBotAPI/workflows/Build/badge.svg)](https://github.com/InsanusMokrassar/TelegramBotAPI/actions) [Small survey](https://forms.gle/2Hex2ynbHWHhi1KY7)|
| -------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Useful links | [![Chat in Telegram](badges/chat.svg)](https://t.me/InMoTelegramBotAPI) [![Create bot](badges/template.svg)](https://github.com/InsanusMokrassar/TelegramBotAPI-bot_template/generate) [![KDocs](badges/kdocs.svg)](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 | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.core/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.core/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) |
| TelegramBotAPI API Extensions status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.api/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api) |
| TelegramBotAPI Util Extensions status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.utils/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils) |
| TelegramBotAPI Behaviour Builder Extensions status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.behaviour_builder/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi.extensions.behaviour_builder/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder) |
| TelegramBotAPI All status | [![Download](https://api.bintray.com/packages/insanusmokrassar/TelegramBotAPI/tgbotapi/images/download.svg)](https://bintray.com/insanusmokrassar/TelegramBotAPI/tgbotapi/_latestVersion) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) |
| TelegramBotAPI Core status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.core) |
| TelegramBotAPI API Extensions status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.api) |
| TelegramBotAPI Util Extensions status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.utils) |
| TelegramBotAPI Behaviour Builder Extensions status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi.extensions.behaviour_builder) |
| TelegramBotAPI All status | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi/badge.svg)](https://maven-badges.herokuapp.com/maven-central/dev.inmo/tgbotapi) |
**At the time of publication of version `0.28.0` there are errors in serialization plugins like
[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`**
## Examples
## What is it?
There are several things you need to do to launch examples below:
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:
* Add `mavenCentral()` to your project repositories
* [Maven variant](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/Including-in-your-project#pomxml)
* Add dependency `implementation "dev.inmo:tgbotapi:$tgbotapi_version"`
* Replace `tgbotapi_version` with exact version (see last one in the table above) or put variable with this name in project
* Alternative variant for maven [here](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/Including-in-your-project#telegrambotapi)
* [TelegramBotAPI Core](tgbotapi.core/README.md) - core of library. In fact it is independent library and can be used alone
without any additional library
* [TelegramBotAPI API Extensions](tgbotapi.extensions.api/README.md) - contains extensions (mostly for
`RequestsExecutor`), which allows to use the core library in more pleasant way
* [TelegramBotAPI Util Extensions](tgbotapi.extensions.utils/README.md) - contains extensions for more comfortable
work with commands, updates and other different things
* [TelegramBotAPI Behaviour Builder Extensions](tgbotapi.extensions.behaviour_builder/README.md) - builder for
step-by-step handling of bot behaviour in more comfortable manner
* [TelegramBotAPI](tgbotapi/README.md) - concentration of all previously mentioned libraries
More including instructions [available here](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/Including-in-your-project).
Other configuration examples:
Most part of some specific solves or unuseful
moments are describing by official [Telegram Bot API](https://core.telegram.org/bots/api).
* [For multiplatform](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/tree/master/ResenderBot)
* [For JVM](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/blob/master/GetMeBot/build.gradle)
## JavaScript notes
### Most common example
### Versions before `0.28.0`
```kotlin
suspend fun main() {
val bot = telegramBot(TOKEN)
In case if you are want to use this library inside of browser, you will need additional settings (thanks for help to [Alexander Nozik](https://research.jetbrains.org/researchers/altavir)):
<details>
<summary>Gradle build script help (for versions before 0.28.0)</summary>
```groovy
dependencies {
/* ... */
implementation "com.github.insanusmokrassar:TelegramBotAPI:$tgbot_api_version"
implementation "com.github.insanusmokrassar:TelegramBotAPI-extensions-api:$tgbot_api_version" // optional
implementation "com.github.insanusmokrassar:TelegramBotAPI-extensions-utils:$tgbot_api_version" // optional
/* Block of dependencies for correct building in browser */
implementation(npm("fs"))
implementation(npm("bufferutil"))
implementation(npm("utf-8-validate"))
implementation(npm("abort-controller"))
implementation(npm("text-encoding"))
}
/* ... */
kotlin {
target {
browser {
/* Block for fix of exception in absence of some functionality, https://github.com/ktorio/ktor/issues/1339 */
dceTask {
dceOptions {
keep("ktor-ktor-io.\$\$importsForInline\$\$.ktor-ktor-io.io.ktor.utils.io")
}
}
}
bot.buildBehaviour {
println(getMe())
onCommand("start") {
reply(it, "Hi:)")
}
}.join()
}
```
</details>
In this example you will see information about this bot at the moment of starting and answer with `Hi:)` every time it
gets message `/start`
## Ok, where should I start?
### Handling only last messages
![Libraries hierarchy](resources/TelegramBotAPI-libraries-hierarchy.svg)
```kotlin
suspend fun main() {
val bot = telegramBot(TOKEN)
In most cases, the most simple way will be to implement [TelegramBotAPI](tgbotapi/README.md) - it contains
all necessary tools for comfort usage of this library. If you want to exclude some libraries, you can implement just
[TelegramBotAPI BehaviourBuilder Extensions](tgbotapi.extensions.behaviour_builder/README.md),
[TelegramBotAPI API Extensions](tgbotapi.extensions.api/README.md),
[TelegramBotAPI Util Extensions](tgbotapi.extensions.utils/README.md) or even
[TelegramBotAPI Core](tgbotapi.core/README.md).
val flowsUpdatesFilter = FlowsUpdatesFilter()
bot.buildBehaviour(flowUpdatesFilter = flowsUpdatesFilter) {
println(getMe())
onCommand("start") {
reply(it, "Hi:)")
}
If you want to dive deeper in the core of library or develop something for it - welcome to learn more from
[TelegramBotAPI Core](tgbotapi.core/README.md) and our [Telegram Chat](https://teleg.one/InMoTelegramBotAPIChat).
Anyway, all libraries are very typical inside of them. Examples:
* In `TelegramBotAPI` common request look like `requestsExecutor.execute(SomeRequest())`
* `tgbotapi.extensions.api` typical syntax look like `requestsExecutor.someRequest()` (in most cases it would be
better to use `bot` name instead of `requestsExecutor`)
* `tgbotapi.extensions.utils` will look like `filter.filterBaseMessageUpdates(chatId).filterExactCommands(Regex("^.*$"))...`
## Build instruction
If you want to build this project or to contribute, there are several recommendations:
### Build
In case if you want to just build project, run next command:
```bash
./gradlew clean build
```
On windows:
```
gradlew.bat clean build
```
### Publishing for work with your version locally
In case, if you want to work in your other projects using your modification (or some state) of this library,
you can use next code:
```bash
./gradlew clean build publishToMavenLocal
```
On windows:
```
gradlew.bat clean build publishToMavenLocal
```
But you must remember, that in this case your local maven repo must be the first one from
your project retrieving libraries:
```groovy
repositories {
mavenLocal() // that must be the first one
jcenter()
mavenCentral()
retrieveAccumulatedUpdates(this).join()
}
}
```
Besides, for your own version you can change variable `library_version` in the file [gradle.properties](./gradle.properties).
The main difference with the previous example is that bot will get only last updates (accumulated before bot launch
and maybe some updates it got after launch)
### Build a little bit more complex behaviour
```kotlin
suspend fun main() {
val bot = telegramBot(TOKEN)
bot.buildBehaviour {
println(getMe())
val nameReplyMarkup = ReplyKeyboardMarkup(
matrix {
row {
+SimpleKeyboardButton("nope")
}
}
)
onCommand("start") {
val photo = waitPhoto(
SendTextMessage(it.chat.id, "Send me your photo please")
).first()
val name = waitText(
SendTextMessage(
it.chat.id,
"Send me your name or choose \"nope\"",
replyMarkup = nameReplyMarkup
)
).first().text.takeIf { it != "nope" }
sendPhoto(
it.chat,
photo.mediaCollection,
entities = buildEntities {
if (name != null) regular(name) // may be collapsed up to name ?.let(::regular)
}
)
}
}.join()
}
```
### More examples
You may find examples in [this project](https://github.com/InsanusMokrassar/TelegramBotAPI-examples). Besides, you are
always welcome in our [wiki](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/About-this-project) and
[chat](https://t.me/InMoTelegramBotAPIChat).

View File

@@ -36,7 +36,7 @@ kotlin {
dependencies {
implementation kotlin('stdlib')
project.parent.subprojects.forEach {
rootProject.subprojects.forEach {
if (it != project) {
api it
}
@@ -56,7 +56,7 @@ private List<SourceDirectorySet> findSourcesWithName(String... approximateNames)
}.collect { it.kotlin }
}
tasks.dokkaHtml {
Object callback = {
switch (true) {
case project.hasProperty("DOKKA_PATH"):
outputDirectory = project.property("DOKKA_PATH").toString()
@@ -82,11 +82,14 @@ tasks.dokkaHtml {
}
named("jsMain") {
sourceRoots.setFrom(findSourcesWithName("jsMain", "commonMain"))
sourceRoots.setFrom(findSourcesWithName("jsMain"))
}
named("jvmMain") {
sourceRoots.setFrom(findSourcesWithName("jvmMain", "commonMain"))
sourceRoots.setFrom(findSourcesWithName("jvmMain"))
}
}
}
tasks.dokkaGfm(callback)
tasks.dokkaHtml(callback)

View File

@@ -1,3 +1,3 @@
dokka_version=1.4.20
dokka_version=1.4.30
org.gradle.jvmargs=-Xmx1024m

View File

@@ -5,18 +5,18 @@ kotlin.js.generate.externals=true
kotlin.incremental=true
kotlin.incremental.js=true
kotlin_version=1.4.21
kotlin_coroutines_version=1.4.2
kotlin_serialisation_runtime_version=1.0.1
klock_version=2.0.4
kotlin_version=1.4.32
kotlin_coroutines_version=1.4.3
kotlin_serialisation_runtime_version=1.1.0
klock_version=2.0.7
uuid_version=0.2.3
ktor_version=1.5.1
ktor_version=1.5.2
micro_utils_version=0.4.23
micro_utils_version=0.4.30
javax_activation_version=1.1.1
library_group=dev.inmo
library_version=0.32.2
library_version=0.33.1
github_release_plugin_version=2.2.12

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip

View File

@@ -1,4 +1,11 @@
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.jetbrains.dokka") {
useModule("org.jetbrains.dokka:dokka-gradle-plugin:${requested.version}")
}
}
}
repositories {
gradlePluginPortal()
jcenter()

View File

@@ -10,7 +10,7 @@ moments are describing by official [Telegram Bot API](https://core.telegram.org/
## Compatibility
This version compatible with [4th of November 2020 update of TelegramBotAPI (version 5.0)](https://core.telegram.org/bots/api#november-4-2020).
This version compatible with [9th of March 2021 update of TelegramBotAPI (version 5.1)](https://core.telegram.org/bots/api-changelog#march-9-2021).
## How to implement library?

View File

@@ -29,7 +29,9 @@ repositories {
}
kotlin {
jvm()
jvm {
compilations.main.kotlinOptions.useIR = true
}
js(BOTH) {
browser()
nodejs()
@@ -58,6 +60,7 @@ kotlin {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
implementation project(":tgbotapi.extensions.utils")
}
}

View File

@@ -1 +1 @@
{"bintrayConfig":{"repo":"TelegramBotAPI","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/TelegramBotAPI","autoPublish":true,"overridePublish":true},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Core","description":"Library for Object-Oriented and type-safe work with Telegram Bot API","url":"https://insanusmokrassar.github.io/TelegramBotAPI","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]}}
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Core","description":"Library for Object-Oriented and type-safe work with Telegram Bot API","url":"https://insanusmokrassar.github.io/TelegramBotAPI","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI"},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}]}}

View File

@@ -4,22 +4,6 @@ apply plugin: 'signing'
task javadocsJar(type: Jar) {
classifier = 'javadoc'
}
task sourceJar (type : Jar) {
classifier = 'sources'
}
afterEvaluate {
project.publishing.publications.all {
// rename artifacts
groupId "${project.group}"
if (it.name.contains('kotlinMultiplatform')) {
artifactId = "${project.name}"
artifact sourceJar
} else {
artifactId = "${project.name}-$name"
}
}
}
publishing {
publications.all {
@@ -54,22 +38,32 @@ publishing {
}
}
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')
if ((project.hasProperty('GITHUBPACKAGES_USER') || System.getenv('GITHUBPACKAGES_USER') != null) && (project.hasProperty('GITHUBPACKAGES_PASSWORD') || System.getenv('GITHUBPACKAGES_PASSWORD') != null)) {
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI")
credentials {
username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven {
name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
}
}
signing {
useGpgCmd()
publishing.publications.forEach { sign it }
sign publishing.publications
}

View File

@@ -6,6 +6,7 @@ interface Captioned {
val caption: String?
}
@Deprecated("This interface is not used in library and will be removed soon")
interface CaptionedOutput : Captioned {
val parseMode: ParseMode?
}

View File

@@ -16,6 +16,8 @@ import io.ktor.http.ContentType
import kotlinx.serialization.json.Json
import kotlin.collections.set
var defaultUpdateTimeoutForZeroDelay = 1000L
abstract class AbstractRequestCallFactory : KtorCallFactory {
private val methodsCache: MutableMap<String, String> = mutableMapOf()
override suspend fun <T : Any> makeCall(
@@ -41,6 +43,11 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
requestTimeoutMillis = customTimeoutMillis
socketTimeoutMillis = customTimeoutMillis
}
} else {
timeout {
requestTimeoutMillis = defaultUpdateTimeoutForZeroDelay
socketTimeoutMillis = defaultUpdateTimeoutForZeroDelay
}
}
}
}

View File

@@ -12,7 +12,7 @@ fun newRequestException(
cause: Throwable? = null
) = response.description ?.let { description ->
when {
description == "Bad Request: reply message not found" -> ReplyMessageNotFoundException(response, plainAnswer, message, cause)
description == "Bad Request: reply message not found" || description == "Bad Request: replied message not found" -> ReplyMessageNotFoundException(response, plainAnswer, message, cause)
description == "Bad Request: message to edit not found" -> MessageToEditNotFoundException(response, plainAnswer, message, cause)
description.contains("Bad Request: message is not modified") -> MessageIsNotModifiedException(response, plainAnswer, message, cause)
description == "Unauthorized" -> UnauthorizedException(response, plainAnswer, message, cause)

View File

@@ -17,7 +17,9 @@ class CommonLimiter(
@Transient
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
) : RequestLimiter {
@Transient
private val quotaSemaphore = Semaphore(lockCount)
@Transient
private val counterRegeneratorJob = scope.launch {
val regenDelay: MilliSeconds = (regenTime.toDouble() / lockCount).roundToLong()
while (isActive) {

View File

@@ -37,11 +37,12 @@ class ExceptionsOnlyLimiter(
override suspend fun <T> limit(block: suspend () -> T): T {
while (true) {
lockState.first { !it }
var throwable: Throwable? = null
val result = safely({
when (it) {
throwable = when (it) {
is TooMuchRequestsException -> {
lock(it.retryAfter.leftToRetry)
Result.failure(it)
it
}
is ClientRequestException -> {
if (it.response.status == HttpStatusCode.TooManyRequests) {
@@ -49,15 +50,16 @@ class ExceptionsOnlyLimiter(
} else {
throw it
}
Result.failure(it)
it
}
else -> throw it
}
null
}) {
Result.success(block())
block()
}
if (result.isSuccess) {
return result.getOrNull()!!
if (throwable == null) {
return result!!
}
}
}

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.requests
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.PassportElementError

View File

@@ -0,0 +1,20 @@
package dev.inmo.tgbotapi.requests.chat.abstracts
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.DeserializationStrategy
interface ChatInviteLinkRequest : SimpleRequest<CommonInviteLink> {
val chatId: ChatIdentifier
override val resultDeserializer: DeserializationStrategy<CommonInviteLink>
get() = CommonInviteLink.serializer()
}
interface KnownChatInviteLinkRequest : ChatInviteLinkRequest {
val inviteLink: String
}
interface EditChatInviteLinkRequest : ChatInviteLinkRequest {
val expireDate: DateTime?
val membersLimit: MembersLimit?
}

View File

@@ -0,0 +1,31 @@
package dev.inmo.tgbotapi.requests.chat.invite_links
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.requests.chat.abstracts.EditChatInviteLinkRequest
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
@Serializable
data class CreateChatInviteLink(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(expireDateField)
private val expirationUnixTimeStamp: TelegramDate? = null,
@SerialName(memberLimitField)
override val membersLimit: MembersLimit? = null
) : EditChatInviteLinkRequest {
override val expireDate: DateTime?
get() = expirationUnixTimeStamp ?.asDate
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "createChatInviteLink"
}
fun CreateChatInviteLink(
chatId: ChatId,
expireDate: DateTime,
membersLimit: MembersLimit? = null
): CreateChatInviteLink = CreateChatInviteLink(
chatId, expireDate.toTelegramDate(), membersLimit
)

View File

@@ -0,0 +1,35 @@
package dev.inmo.tgbotapi.requests.chat.invite_links
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.requests.chat.abstracts.EditChatInviteLinkRequest
import dev.inmo.tgbotapi.requests.chat.abstracts.KnownChatInviteLinkRequest
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
@Serializable
data class EditChatInviteLink(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(inviteLinkField)
override val inviteLink: String,
@SerialName(expireDateField)
private val expirationUnixTimeStamp: TelegramDate? = null,
@SerialName(memberLimitField)
override val membersLimit: MembersLimit? = null
) : EditChatInviteLinkRequest, KnownChatInviteLinkRequest {
override val expireDate: DateTime?
get() = expirationUnixTimeStamp ?.asDate
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "editChatInviteLink"
}
fun EditChatInviteLink(
chatId: ChatIdentifier,
inviteLink: String,
expireDate: DateTime,
membersLimit: MembersLimit? = null
): EditChatInviteLink = EditChatInviteLink(
chatId, inviteLink, expireDate.toTelegramDate(), membersLimit
)

View File

@@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.requests.chat.invite_links
import dev.inmo.tgbotapi.requests.chat.abstracts.KnownChatInviteLinkRequest
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
@Serializable
data class RevokeChatInviteLink(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(inviteLinkField)
override val inviteLink: String
) : KnownChatInviteLinkRequest {
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "revokeChatInviteLink"
}

View File

@@ -13,7 +13,9 @@ data class KickChatMember(
@SerialName(userIdField)
override val userId: UserId,
@SerialName(untilDateField)
override val untilDate: TelegramDate? = null
override val untilDate: TelegramDate? = null,
@SerialName(revokeMessagesField)
val revokeMessages: Boolean? = null
) : ChatMemberRequest<Boolean>, UntilDate {
override fun method(): String = "kickChatMember"
override val resultDeserializer: DeserializationStrategy<Boolean>

View File

@@ -31,7 +31,11 @@ data class PromoteChatMember(
@SerialName(canPinMessagesField)
private val canPinMessages: Boolean? = null,
@SerialName(canPromoteMembersField)
private val canPromoteMembers: Boolean? = null
private val canPromoteMembers: Boolean? = null,
@SerialName(canManageVoiceChatsField)
private val canManageVoiceChats: Boolean? = null,
@SerialName(canManageChatField)
private val canManageChat: Boolean? = null
) : ChatMemberRequest<Boolean>, UntilDate {
override fun method(): String = "promoteChatMember"
override val resultDeserializer: DeserializationStrategy<Boolean>

View File

@@ -18,6 +18,8 @@ data class SetChatPhoto (
override fun method(): String = "setChatPhoto"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
@Transient
override val mediaMap: Map<String, MultipartFile> = mapOf(photoField to photo)
@Transient
override val paramsJson: JsonObject = toJson(serializer())
}

View File

@@ -16,6 +16,11 @@ import kotlinx.serialization.*
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<PollContent>> = TelegramBotAPIMessageDeserializationStrategyClass()
private inline val ApproximateScheduledCloseInfo.openPeriod
get() = openDuration.millisecondsLong.div(1000)
private inline val ExactScheduledCloseInfo.closeDate
get() = closeDateTime.unixMillisLong.div(1000)
private fun checkPollInfo(
question: String,
options: List<String>
@@ -138,12 +143,23 @@ sealed class SendPoll : SendMessageRequest<ContentMessage<PollContent>>,
abstract val options: List<String>
abstract val isAnonymous: Boolean
abstract val isClosed: Boolean
abstract val closeInfo: ScheduledCloseInfo?
abstract val type: String
internal abstract val openPeriod: LongSeconds?
internal abstract val closeDate: LongSeconds?
protected val creationDate = DateTime.now()
open val closeInfo: ScheduledCloseInfo?
get() {
val openPeriod = openPeriod
val closeDate = closeDate
return when {
openPeriod != null -> openPeriod.asApproximateScheduledCloseInfo(creationDate)
closeDate != null -> closeDate.asExactScheduledCloseInfo
else -> null
}
}
override fun method(): String = "sendPoll"
override val resultDeserializer: DeserializationStrategy<ContentMessage<PollContent>>
get() = commonResultDeserializer
@@ -163,8 +179,10 @@ data class SendRegularPoll(
override val isClosed: Boolean = false,
@SerialName(allowsMultipleAnswersField)
val allowMultipleAnswers: Boolean = false,
@Transient
override val closeInfo: ScheduledCloseInfo? = null,
@SerialName(openPeriodField)
override val openPeriod: LongSeconds?= null,
@SerialName(closeDateField)
override val closeDate: LongSeconds?,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
@@ -178,20 +196,39 @@ data class SendRegularPoll(
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
@SerialName(openPeriodField)
override val openPeriod: LongSeconds?
= (closeInfo as? ApproximateScheduledCloseInfo) ?.openDuration ?.millisecondsLong ?.div(1000)
@SerialName(closeDateField)
override val closeDate: LongSeconds?
= (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000)
init {
checkPollInfo(question, options)
closeInfo ?.checkSendData()
}
}
fun SendRegularPoll(
chatId: ChatIdentifier,
question: String,
options: List<String>,
isAnonymous: Boolean = true,
isClosed: Boolean = false,
allowMultipleAnswers: Boolean = false,
closeInfo: ScheduledCloseInfo? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendRegularPoll(
chatId,
question,
options,
isAnonymous,
isClosed,
allowMultipleAnswers,
(closeInfo as? ApproximateScheduledCloseInfo) ?.openPeriod,
(closeInfo as? ExactScheduledCloseInfo) ?.closeDate,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
fun SendQuizPoll(
chatId: ChatIdentifier,
question: String,
@@ -253,6 +290,39 @@ fun SendQuizPoll(
replyMarkup
)
internal fun SendQuizPoll(
chatId: ChatIdentifier,
question: String,
options: List<String>,
correctOptionId: Int,
isAnonymous: Boolean = true,
isClosed: Boolean = false,
explanation: String? = null,
parseMode: ParseMode? = null,
rawEntities: List<RawMessageEntity>? = null,
closeInfo: ScheduledCloseInfo? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendQuizPoll(
chatId,
question,
options,
correctOptionId,
isAnonymous,
isClosed,
explanation,
parseMode,
rawEntities,
(closeInfo as? ApproximateScheduledCloseInfo) ?.openPeriod,
(closeInfo as? ExactScheduledCloseInfo) ?.closeDate,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@Serializable
data class SendQuizPoll internal constructor(
@SerialName(chatIdField)
@@ -273,8 +343,10 @@ data class SendQuizPoll internal constructor(
override val parseMode: ParseMode? = null,
@SerialName(explanationEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@Transient
override val closeInfo: ScheduledCloseInfo? = null,
@SerialName(openPeriodField)
override val openPeriod: LongSeconds? = null,
@SerialName(closeDateField)
override val closeDate: LongSeconds? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
@@ -291,14 +363,6 @@ data class SendQuizPoll internal constructor(
rawEntities ?.asTextParts(explanation ?: return@lazy null) ?.justTextSources()
}
@SerialName(openPeriodField)
override val openPeriod: LongSeconds?
= (closeInfo as? ApproximateScheduledCloseInfo) ?.openDuration ?.millisecondsLong ?.div(1000)
@SerialName(closeDateField)
override val closeDate: LongSeconds?
= (closeInfo as? ExactScheduledCloseInfo) ?.closeDateTime ?.unixMillisLong ?.div(1000)
init {
checkPollInfo(question, options)
closeInfo ?.checkSendData()

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.types
import dev.inmo.micro_utils.common.Warning
import kotlinx.serialization.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@@ -17,9 +18,20 @@ data class ChatId(
val chatId: Identifier
) : ChatIdentifier()
val ChatId.link: String
get() = "tg://user?id=$chatId"
/**
* https://core.telegram.org/bots/api#formatting-options
*/
@Warning("This API have restrictions in Telegram System")
val Identifier.link: String
get() = "tg://user?id=$this"
/**
* https://core.telegram.org/bots/api#formatting-options
*/
@Warning("This API have restrictions in Telegram System")
val UserId.link: String
get() = chatId.link
val User.link: String
get() = id.link
typealias UserId = ChatId

View File

@@ -0,0 +1,104 @@
package dev.inmo.tgbotapi.types
import com.soywiz.klock.DateTime
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@Serializable
private data class RawChatInviteLink(
@SerialName(inviteLinkField)
val inviteLink: String,
@SerialName(creatorField)
val creator: User,
@SerialName(isPrimaryField)
val isPrimary: Boolean,
@SerialName(isRevokedField)
val isRevoked: Boolean,
@SerialName(expireDateField)
val expirationDateTime: TelegramDate? = null,
@SerialName(memberLimitField)
val membersLimit: MembersLimit ?= null
)
private fun ChatInviteLink.toRawChatInviteLink() = RawChatInviteLink(
inviteLink,
creator,
isPrimary,
isRevoked,
expirationDateTime ?.toTelegramDate(),
membersLimit
)
@Serializable(ChatInviteLinkSerializer::class)
sealed class ChatInviteLink {
abstract val inviteLink: String
abstract val creator: User
abstract val isPrimary: Boolean
abstract val isRevoked: Boolean
abstract val expirationDateTime: DateTime?
abstract val membersLimit: MembersLimit?
}
@Serializable
data class PrimaryInviteLink(
@SerialName(inviteLinkField)
override val inviteLink: String,
@SerialName(creatorField)
override val creator: User,
@SerialName(isRevokedField)
override val isRevoked: Boolean = false,
@SerialName(expireDateField)
private val expireDate: TelegramDate? = null,
@SerialName(memberLimitField)
override val membersLimit: MembersLimit? = null
) : ChatInviteLink() {
override val isPrimary: Boolean
get() = true
override val expirationDateTime: DateTime?
get() = expireDate ?.asDate
}
@Serializable
data class CommonInviteLink(
@SerialName(inviteLinkField)
override val inviteLink: String,
@SerialName(creatorField)
override val creator: User,
@SerialName(isRevokedField)
override val isRevoked: Boolean = false,
@SerialName(expireDateField)
private val expireDate: TelegramDate? = null,
@SerialName(memberLimitField)
override val membersLimit: MembersLimit? = null
) : ChatInviteLink() {
override val isPrimary: Boolean
get() = false
override val expirationDateTime: DateTime?
get() = expireDate ?.asDate
}
@Serializer(ChatInviteLink::class)
object ChatInviteLinkSerializer : KSerializer<ChatInviteLink> {
override val descriptor: SerialDescriptor
get() = RawChatInviteLink.serializer().descriptor
override fun deserialize(decoder: Decoder): ChatInviteLink {
val deserializedRaw = RawChatInviteLink.serializer().deserialize(decoder)
return deserializedRaw.run {
when {
deserializedRaw.isPrimary -> PrimaryInviteLink(
inviteLink, creator, isRevoked, expirationDateTime, membersLimit
)
else -> CommonInviteLink(
inviteLink, creator, isRevoked, expirationDateTime, membersLimit
)
}
}
}
override fun serialize(encoder: Encoder, value: ChatInviteLink) {
RawChatInviteLink.serializer().serialize(encoder, value.toRawChatInviteLink())
}
}

View File

@@ -26,6 +26,10 @@ data class AdministratorChatMemberImpl(
override val canPinMessages: Boolean = false,
@SerialName(canPromoteMembersField)
override val canPromoteMembers: Boolean = false,
@SerialName(canManageVoiceChatsField)
override val canManageVoiceChats: Boolean = false,
@SerialName(canManageChatField)
override val canManageChat: Boolean = false,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = false,
@SerialName(customTitleField)

View File

@@ -30,6 +30,10 @@ data class CreatorChatMember(
override val canPinMessages: Boolean = true
@Transient
override val canPromoteMembers: Boolean = true
@Transient
override val canManageVoiceChats: Boolean = true
@Transient
override val canManageChat: Boolean = true
@SerialName(statusField)
@Required
private val type: String = "creator"

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.types.ChatMember.abstracts
import dev.inmo.tgbotapi.utils.RiskFeature
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
@@ -13,12 +14,15 @@ interface AdministratorChatMember : SpecialRightsChatMember {
val canRemoveMessages: Boolean
val canRestrictMembers: Boolean
val canPromoteMembers: Boolean
val canManageVoiceChats: Boolean
val canManageChat: Boolean
val isAnonymous: Boolean
val customTitle: String?
}
@Serializer(AdministratorChatMember::class)
internal object AdministratorChatMemberSerializer : KSerializer<AdministratorChatMember> {
@RiskFeature
object AdministratorChatMemberSerializer : KSerializer<AdministratorChatMember> {
override val descriptor: SerialDescriptor = ChatMemberSerializer.descriptor
override fun deserialize(decoder: Decoder): AdministratorChatMember = ChatMemberSerializer.deserialize(decoder) as AdministratorChatMember

View File

@@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.types.ChatMember.abstracts
import dev.inmo.tgbotapi.types.ChatMember.*
import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.statusField
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor
@@ -17,7 +18,8 @@ interface ChatMember {
}
@Serializer(ChatMember::class)
internal object ChatMemberSerializer : KSerializer<ChatMember> {
@RiskFeature
object ChatMemberSerializer : KSerializer<ChatMember> {
override val descriptor: SerialDescriptor = JsonObject.serializer().descriptor
override fun deserialize(decoder: Decoder): ChatMember {

View File

@@ -0,0 +1,22 @@
package dev.inmo.tgbotapi.types
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ChatMemberUpdated(
@SerialName(chatField)
val chat: Chat,
@SerialName(fromField)
val user: User,
@SerialName(dateField)
val date: TelegramDate,
@SerialName(oldChatMemberField)
val oldChatMemberState: ChatMember,
@SerialName(newChatMemberField)
val newChatMemberState: ChatMember,
@SerialName(inviteLinkField)
val inviteLink: ChatInviteLink? = null
)

View File

@@ -26,10 +26,12 @@ typealias FoursquareId = String
typealias FoursquareType = String
typealias GooglePlaceId = String
typealias GooglePlaceType = String
typealias MembersLimit = Int
typealias Seconds = Int
typealias MilliSeconds = Long
typealias LongSeconds = Long
typealias UnixTimeStamp = LongSeconds
typealias Meters = Float
typealias Degrees = Int
@@ -76,6 +78,8 @@ val explanationLimit = 0 .. 200
val openPeriodPollSecondsLimit = 5 .. 600
val membersLimit = 1 .. 99999
// Made as lazy for correct work in K/JS
val telegramInlineModeGifPermittedMimeTypes by lazy {
listOf(
@@ -162,6 +166,12 @@ const val optionIdsField = "option_ids"
const val ipAddressField = "ip_address"
const val linkedChatIdField = "linked_chat_id"
const val horizontalAccuracyField = "horizontal_accuracy"
const val revokeMessagesField = "revoke_messages"
const val messageAutoDeleteTimeField = "message_auto_delete_time"
const val isPrimaryField = "is_primary"
const val isRevokedField = "is_revoked"
const val expireDateField = "expire_date"
const val memberLimitField = "member_limit"
const val requestContactField = "request_contact"
const val requestLocationField = "request_location"
@@ -239,8 +249,12 @@ const val canInviteUsersField = "can_invite_users"
const val canRestrictMembersField = "can_restrict_members"
const val canPinMessagesField = "can_pin_messages"
const val canPromoteMembersField = "can_promote_members"
const val canManageVoiceChatsField = "can_manage_voice_chats"
const val canManageChatField = "can_manage_chat"
const val pngStickerField = "png_sticker"
const val tgsStickerField = "tgs_sticker"
const val oldChatMemberField = "old_chat_member"
const val newChatMemberField = "new_chat_member"
const val okField = "ok"
const val captionField = "caption"
@@ -292,6 +306,7 @@ const val payField = "pay"
const val permissionsField = "permissions"
const val typeField = "type"
const val valueField = "value"
const val creatorField = "creator"
const val pointField = "point"
const val xShiftField = "x_shift"
@@ -331,6 +346,7 @@ const val telegramPaymentChargeIdField = "telegram_payment_charge_id"
const val providerPaymentChargeIdField = "provider_payment_charge_id"
const val providerTokenField = "provider_token"
const val providerDataField = "provider_data"
const val usersField = "users"
const val requireNameField = "need_name"
const val requirePhoneNumberField = "need_phone_number"

View File

@@ -74,3 +74,15 @@ fun AudioFile.toInputMediaAudio(
title,
thumb ?.fileId
)
fun AudioFile.toInputMediaAudio(
textSources: TextSourcesList = emptyList(),
title: String? = this.title
): InputMediaAudio = InputMediaAudio(
fileId,
textSources,
duration,
performer,
title,
thumb ?.fileId
)

View File

@@ -70,3 +70,11 @@ fun DocumentFile.toInputMediaDocument(
parseMode,
thumb ?.fileId
)
fun DocumentFile.toInputMediaDocument(
textSources: TextSourcesList = emptyList()
) = InputMediaDocument(
fileId,
textSources,
thumb ?.fileId
)

View File

@@ -53,3 +53,10 @@ fun PhotoSize.toInputMediaPhoto(
caption,
parseMode
)
fun PhotoSize.toInputMediaPhoto(
textSources: TextSourcesList = emptyList()
): InputMediaPhoto = InputMediaPhoto(
fileId,
textSources
)

View File

@@ -1,7 +1,7 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.*
@@ -21,6 +21,26 @@ data class TextMentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstr
@Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>, user: User) = TextMentionTextSource(parts.makeString(), user, parts)
@Suppress("NOTHING_TO_INLINE")
inline fun User.mention(parts: List<TextSource>) = mention(parts, this)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>, userId: UserId) = mention(parts, CommonUser(userId, ""))
@Suppress("NOTHING_TO_INLINE")
inline fun UserId.mention(parts: List<TextSource>) = mention(parts, this)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>, id: Identifier) = mention(parts, UserId(id))
@Suppress("NOTHING_TO_INLINE")
inline fun Identifier.mention(parts: List<TextSource>) = mention(parts, this)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(user: User, vararg parts: TextSource) = mention(parts.toList(), user)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(text: String, user: User) = mention(user, regular(text))
@Suppress("NOTHING_TO_INLINE")
inline fun User.mention(text: String) = mention(this, regular(text))
@Suppress("NOTHING_TO_INLINE")
inline fun mention(text: String, userId: UserId) = mention(text, CommonUser(userId, ""))
@Suppress("NOTHING_TO_INLINE")
inline fun UserId.mention(text: String) = mention(text, this)
@Suppress("NOTHING_TO_INLINE")
inline fun mention(text: String, id: Identifier) = mention(text, UserId(id))
@Suppress("NOTHING_TO_INLINE")
inline fun Identifier.mention(text: String) = mention(text, this)

View File

@@ -35,12 +35,21 @@ typealias Markdown = MarkdownParseMode
typealias MarkdownV2 = MarkdownV2ParseMode
typealias HTML = HTMLParseMode
/**
* This variable respects to default parse mode used in places like next:
*
* * [dev.inmo.tgbotapi.types.message.content.TextContent.createResends]
* *
*/
var defaultParseMode: ParseMode = HTML
@Serializer(ParseMode::class)
internal object ParseModeSerializerObject : KSerializer<ParseMode> {
override fun deserialize(decoder: Decoder): ParseMode {
return when (decoder.decodeString()) {
MarkdownParseMode.parseModeName -> MarkdownParseMode
HTMLParseMode.parseModeName -> HTMLParseMode
Markdown.parseModeName -> Markdown
MarkdownV2.parseModeName -> MarkdownV2
HTML.parseModeName -> HTML
else -> throw IllegalArgumentException("Unknown parse mode")
}
}

View File

@@ -11,6 +11,8 @@ const val UPDATE_SHIPPING_QUERY = "shipping_query"
const val UPDATE_PRE_CHECKOUT_QUERY = "pre_checkout_query"
const val UPDATE_POLL = "poll"
const val UPDATE_POLL_ANSWER = "poll_answer"
const val MY_CHAT_MEMBER = "my_chat_member"
const val CHAT_MEMBER = "chat_member"
val ALL_UPDATES_LIST = listOf(
UPDATE_MESSAGE,
@@ -23,5 +25,7 @@ val ALL_UPDATES_LIST = listOf(
UPDATE_SHIPPING_QUERY,
UPDATE_PRE_CHECKOUT_QUERY,
UPDATE_POLL,
UPDATE_POLL_ANSWER
UPDATE_POLL_ANSWER,
MY_CHAT_MEMBER,
CHAT_MEMBER
)

View File

@@ -23,3 +23,25 @@ data class ChatPermissions(
@SerialName(canPinMessagesField)
val canPinMessages: Boolean = false
)
val LeftRestrictionsChatPermissions = ChatPermissions(
canSendMessages = true,
canSendMediaMessages = true,
canSendPolls = true,
canSendOtherMessages = true,
canAddWebPagePreviews = true,
canChangeInfo = true,
canInviteUsers = true,
canPinMessages = true,
)
val RestrictionsChatPermissions = ChatPermissions(
canSendMessages = false,
canSendMediaMessages = false,
canSendPolls = false,
canSendOtherMessages = false,
canAddWebPagePreviews = false,
canChangeInfo = false,
canInviteUsers = false,
canPinMessages = false,
)

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.types.files
import dev.inmo.tgbotapi.CommonAbstracts.TextSourcesList
import dev.inmo.tgbotapi.requests.abstracts.FileId
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InputMedia.InputMediaVideo
@@ -44,3 +45,15 @@ inline fun VideoFile.toInputMediaVideo(
duration,
thumb ?.fileId
)
@Suppress("NOTHING_TO_INLINE")
inline fun VideoFile.toInputMediaVideo(
textSources: TextSourcesList
) = InputMediaVideo(
fileId,
textSources,
width,
height,
duration,
thumb ?.fileId
)

View File

@@ -4,11 +4,11 @@ import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.chat.abstracts.ChannelChat
import dev.inmo.tgbotapi.types.message.abstracts.ChannelMessage
import dev.inmo.tgbotapi.types.message.abstracts.ChannelContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
data class ChannelMessageImpl<T: MessageContent>(
data class ChannelContentMessageImpl<T: MessageContent>(
override val messageId: MessageIdentifier,
override val chat: ChannelChat,
override val content: T,
@@ -19,4 +19,4 @@ data class ChannelMessageImpl<T: MessageContent>(
override val replyMarkup: InlineKeyboardMarkup?,
override val senderBot: CommonBot?,
override val authorSignature: AuthorSignature?
) : ChannelMessage<T>
) : ChannelContentMessage<T>

View File

@@ -0,0 +1,25 @@
package dev.inmo.tgbotapi.types.message.ChatEvents
import dev.inmo.tgbotapi.types.Seconds
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
import dev.inmo.tgbotapi.types.messageAutoDeleteTimeField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
private const val seconds24Hours: Seconds = 60 * 60 * 24
private const val seconds7Days: Seconds = seconds24Hours * 7
@Serializable
data class MessageAutoDeleteTimerChanged(
@SerialName(messageAutoDeleteTimeField)
val newAutoDeleteTime: Seconds // TODO:: check that it is seconds
) : ChannelEvent, GroupEvent, SupergroupEvent
val MessageAutoDeleteTimerChanged.isOff
get() = newAutoDeleteTime == 0
val MessageAutoDeleteTimerChanged.is24Hours
get() = newAutoDeleteTime == seconds24Hours
val MessageAutoDeleteTimerChanged.is7Days
get() = newAutoDeleteTime == seconds7Days

View File

@@ -0,0 +1,3 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.abstracts
interface VoiceChatEvent : SupergroupEvent

View File

@@ -0,0 +1,18 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.voice
import com.soywiz.klock.TimeSpan
import com.soywiz.klock.seconds
import dev.inmo.tgbotapi.types.Seconds
import dev.inmo.tgbotapi.types.durationField
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.VoiceChatEvent
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class VoiceChatEnded(
@SerialName(durationField)
val duration: Seconds
) : VoiceChatEvent {
val timeSpan: TimeSpan
get() = TimeSpan(duration.seconds.milliseconds)
}

View File

@@ -0,0 +1,13 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.voice
import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.VoiceChatEvent
import dev.inmo.tgbotapi.types.usersField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class VoiceChatParticipantsInvited(
@SerialName(usersField)
val users: List<User> = emptyList()
) : VoiceChatEvent

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.message.ChatEvents.voice
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.VoiceChatEvent
import kotlinx.serialization.Serializable
@Serializable
object VoiceChatStarted : VoiceChatEvent

View File

@@ -8,7 +8,7 @@ import dev.inmo.tgbotapi.types.chat.abstracts.GroupChat
import dev.inmo.tgbotapi.types.message.abstracts.*
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
data class FromChannelGroupMessageImpl<T : MessageContent>(
data class FromChannelGroupContentMessageImpl<T : MessageContent>(
override val chat: GroupChat,
override val channel: ChannelChat,
override val messageId: MessageIdentifier,
@@ -20,9 +20,9 @@ data class FromChannelGroupMessageImpl<T : MessageContent>(
override val content: T,
override val senderBot: CommonBot?,
override val authorSignature: AuthorSignature?
) : FromChannelGroupMessage<T>
) : FromChannelGroupContentMessage<T>
data class AnonymousGroupMessageImpl<T : MessageContent>(
data class AnonymousGroupContentMessageImpl<T : MessageContent>(
override val chat: GroupChat,
override val messageId: MessageIdentifier,
override val date: DateTime,
@@ -33,9 +33,9 @@ data class AnonymousGroupMessageImpl<T : MessageContent>(
override val content: T,
override val senderBot: CommonBot?,
override val authorSignature: AuthorSignature?
) : AnonymousGroupMessage<T>
) : AnonymousGroupContentMessage<T>
data class CommonGroupMessageImpl<T : MessageContent>(
data class CommonGroupContentMessageImpl<T : MessageContent>(
override val chat: GroupChat,
override val messageId: MessageIdentifier,
override val user: User,
@@ -46,4 +46,4 @@ data class CommonGroupMessageImpl<T : MessageContent>(
override val replyMarkup: InlineKeyboardMarkup?,
override val content: T,
override val senderBot: CommonBot?
) : CommonGroupMessage<T>
) : CommonGroupContentMessage<T>

View File

@@ -5,11 +5,11 @@ import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.abstracts.PrivateMessage
import dev.inmo.tgbotapi.types.message.abstracts.PrivateContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
import dev.inmo.tgbotapi.types.message.payments.SuccessfulPaymentInfo
data class PrivateMessageImpl<T: MessageContent>(
data class PrivateContentMessageImpl<T: MessageContent>(
override val messageId: MessageIdentifier,
override val user: User,
override val chat: Chat,
@@ -21,4 +21,4 @@ data class PrivateMessageImpl<T: MessageContent>(
override val replyMarkup: InlineKeyboardMarkup?,
override val senderBot: CommonBot?,
val paymentInfo: SuccessfulPaymentInfo?
) : PrivateMessage<T>
) : PrivateContentMessage<T>

View File

@@ -11,6 +11,7 @@ import dev.inmo.tgbotapi.types.games.RawGame
import dev.inmo.tgbotapi.types.location.Location
import dev.inmo.tgbotapi.types.message.ChatEvents.*
import dev.inmo.tgbotapi.types.message.ChatEvents.abstracts.*
import dev.inmo.tgbotapi.types.message.ChatEvents.voice.*
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.abstracts.UnknownMessageType
import dev.inmo.tgbotapi.types.message.content.*
@@ -81,6 +82,14 @@ internal data class RawMessage(
private val dice: Dice? = null,
private val successful_payment: SuccessfulPayment? = null,
// Voice Chat Service Messages
private val voice_chat_started: VoiceChatStarted? = null,
private val voice_chat_ended: VoiceChatEnded? = null,
private val voice_chat_participants_invited: VoiceChatParticipantsInvited? = null,
// AutoDelete Message time changed
private val message_auto_delete_timer_changed: MessageAutoDeleteTimerChanged? = null,
// login property
private val connected_website: String? = null,
@@ -172,6 +181,10 @@ internal data class RawMessage(
left_chat_member != null -> LeftChatMember(left_chat_member)
new_chat_title != null -> NewChatTitle(new_chat_title)
new_chat_photo != null -> NewChatPhoto(new_chat_photo.toList())
voice_chat_started != null -> voice_chat_started
message_auto_delete_timer_changed != null -> message_auto_delete_timer_changed
voice_chat_ended != null -> voice_chat_ended
voice_chat_participants_invited != null -> voice_chat_participants_invited
delete_chat_photo -> DeleteChatPhoto()
group_chat_created -> GroupChatCreated(
migrate_to_chat_id
@@ -256,7 +269,7 @@ internal data class RawMessage(
}
} ?: when (chat) {
is PublicChat -> when (chat) {
is ChannelChat -> ChannelMessageImpl(
is ChannelChat -> ChannelContentMessageImpl(
messageId,
chat,
content,
@@ -269,7 +282,7 @@ internal data class RawMessage(
author_signature
)
is GroupChat -> when (sender_chat) {
is ChannelChat -> FromChannelGroupMessageImpl(
is ChannelChat -> FromChannelGroupContentMessageImpl(
chat,
sender_chat,
messageId,
@@ -282,7 +295,7 @@ internal data class RawMessage(
via_bot,
author_signature
)
is GroupChat -> AnonymousGroupMessageImpl(
is GroupChat -> AnonymousGroupContentMessageImpl(
chat,
messageId,
date.asDate,
@@ -294,7 +307,7 @@ internal data class RawMessage(
via_bot,
author_signature
)
null -> CommonGroupMessageImpl(
null -> CommonGroupContentMessageImpl(
chat,
messageId,
from ?: error("It is expected that in messages from non anonymous users and channels user must be specified"),
@@ -310,7 +323,7 @@ internal data class RawMessage(
}
else -> error("Unknown type of public chat: $chat")
}
is PrivateChat -> PrivateMessageImpl(
is PrivateChat -> PrivateContentMessageImpl(
messageId,
from ?: error("Was detected common message, but owner (sender) of the message was not found"),
chat,

View File

@@ -4,7 +4,7 @@ import dev.inmo.tgbotapi.types.chat.abstracts.ChannelChat
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
import dev.inmo.tgbotapi.types.message.content.abstracts.PossiblySentViaBotCommonMessage
interface ChannelMessage<T: MessageContent> : PossiblySentViaBotCommonMessage<T>, SignedMessage, WithSenderChatMessage {
interface ChannelContentMessage<T: MessageContent> : PossiblySentViaBotCommonMessage<T>, SignedMessage, WithSenderChatMessage {
override val chat: ChannelChat
override val senderChat: ChannelChat
get() = chat

View File

@@ -4,17 +4,20 @@ import dev.inmo.tgbotapi.types.chat.abstracts.ChannelChat
import dev.inmo.tgbotapi.types.chat.abstracts.GroupChat
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
interface GroupMessage<T : MessageContent> : PublicMessage<T> {
interface GroupContentMessage<T : MessageContent> : PublicContentMessage<T> {
override val chat: GroupChat
}
interface FromChannelGroupMessage<T : MessageContent> : GroupMessage<T>, SignedMessage, WithSenderChatMessage {
interface FromChannelGroupContentMessage<T : MessageContent> : GroupContentMessage<T>, SignedMessage, WithSenderChatMessage {
val channel: ChannelChat
override val senderChat: ChannelChat
get() = channel
}
interface AnonymousGroupMessage<T : MessageContent> : GroupMessage<T>, SignedMessage, WithSenderChatMessage {
interface AnonymousGroupContentMessage<T : MessageContent> : GroupContentMessage<T>, SignedMessage, WithSenderChatMessage {
override val senderChat: GroupChat
get() = chat
}
interface CommonGroupMessage<T : MessageContent> : GroupMessage<T>, FromUserMessage
interface CommonGroupContentMessage<T : MessageContent> : GroupContentMessage<T>, FromUserMessage

View File

@@ -3,4 +3,4 @@ package dev.inmo.tgbotapi.types.message.abstracts
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
import dev.inmo.tgbotapi.types.message.content.abstracts.PossiblySentViaBotCommonMessage
interface PrivateMessage<T: MessageContent> : PossiblySentViaBotCommonMessage<T>, FromUserMessage
interface PrivateContentMessage<T: MessageContent> : PossiblySentViaBotCommonMessage<T>, FromUserMessage

View File

@@ -4,6 +4,6 @@ import dev.inmo.tgbotapi.types.chat.abstracts.PublicChat
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
import dev.inmo.tgbotapi.types.message.content.abstracts.PossiblySentViaBotCommonMessage
interface PublicMessage<T: MessageContent> : PossiblySentViaBotCommonMessage<T> {
interface PublicContentMessage<T: MessageContent> : PossiblySentViaBotCommonMessage<T> {
override val chat: PublicChat
}

View File

@@ -1,16 +1,15 @@
package dev.inmo.tgbotapi.types.message.content
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.TextedInput
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.SendTextMessage
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.*
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.defaultParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
import dev.inmo.tgbotapi.utils.internal.*
data class TextContent(
override val text: String,
@@ -24,51 +23,11 @@ data class TextContent(
replyMarkup: KeyboardMarkup?
): Request<ContentMessage<TextContent>> = SendTextMessage(
chatId,
toHtmlTexts().first(),
HTMLParseMode,
textSources,
false,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
override fun createResends(
chatId: ChatIdentifier,
disableNotification: Boolean,
replyToMessageId: MessageIdentifier?,
allowSendingWithoutReply: Boolean?,
replyMarkup: KeyboardMarkup?
): List<Request<ContentMessage<TextContent>>> = createResends(
chatId,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup,
HTMLParseMode
)
fun createResends(
chatId: ChatIdentifier,
disableNotification: Boolean,
replyToMessageId: MessageIdentifier?,
allowSendingWithoutReply: Boolean?,
replyMarkup: KeyboardMarkup?,
parseMode: ParseMode = HTMLParseMode
): List<Request<ContentMessage<TextContent>>> = when (parseMode) {
is MarkdownParseMode -> toMarkdownTexts()
is MarkdownV2ParseMode -> toMarkdownV2Texts()
is HTMLParseMode -> toHtmlTexts()
}.map {
SendTextMessage(
chatId,
it,
parseMode,
false,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
}
}

View File

@@ -14,12 +14,4 @@ interface ResendableContent {
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<out Message>
fun createResends(
chatId: ChatIdentifier,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): List<Request<out Message>> = listOf(createResend(chatId, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup))
}

View File

@@ -1,21 +1,16 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendAnimation
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaAnimation
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.ParseMode.MarkdownV2
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.AnimationFile
import dev.inmo.tgbotapi.types.files.DocumentFile
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
import dev.inmo.tgbotapi.utils.internal.toMarkdownV2Captions
data class AnimationContent(
override val media: AnimationFile,
@@ -33,8 +28,7 @@ data class AnimationContent(
chatId,
media.fileId,
media.thumb ?.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
media.duration,
media.width,
media.height,
@@ -46,8 +40,7 @@ data class AnimationContent(
override fun asInputMedia(): InputMediaAnimation = InputMediaAnimation(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
textSources,
media.width,
media.height,
media.duration,

View File

@@ -1,18 +1,17 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendAudio
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaAudio
import dev.inmo.tgbotapi.types.InputMedia.toInputMediaAudio
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.AudioFile
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.AudioMediaGroupContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
data class AudioContent(
override val media: AudioFile,
@@ -29,8 +28,7 @@ data class AudioContent(
chatId,
media.fileId,
media.thumb ?.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
media.duration,
media.performer,
media.title,
@@ -42,8 +40,5 @@ data class AudioContent(
override fun toMediaGroupMemberInputMedia(): InputMediaAudio = asInputMedia()
override fun asInputMedia(): InputMediaAudio = media.toInputMediaAudio(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaAudio = media.toInputMediaAudio(textSources)
}

View File

@@ -1,21 +1,18 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendDocument
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaDocument
import dev.inmo.tgbotapi.types.InputMedia.toInputMediaDocument
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.DocumentFile
import dev.inmo.tgbotapi.types.files.asDocumentFile
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.DocumentMediaGroupContent
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
data class DocumentContent(
override val media: DocumentFile,
@@ -32,8 +29,7 @@ data class DocumentContent(
chatId,
media.fileId,
media.thumb ?.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
@@ -42,10 +38,7 @@ data class DocumentContent(
override fun toMediaGroupMemberInputMedia(): InputMediaDocument = asInputMedia()
override fun asInputMedia(): InputMediaDocument = media.toInputMediaDocument(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaDocument = media.toInputMediaDocument(textSources)
}
@Suppress("NOTHING_TO_INLINE")

View File

@@ -1,19 +1,18 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendPhoto
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaPhoto
import dev.inmo.tgbotapi.types.InputMedia.toInputMediaPhoto
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.*
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaCollectionContent
import dev.inmo.tgbotapi.types.message.content.abstracts.VisualMediaGroupContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
data class PhotoContent(
override val mediaCollection: Photo,
@@ -31,8 +30,7 @@ data class PhotoContent(
): Request<ContentMessage<PhotoContent>> = SendPhoto(
chatId,
media.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
@@ -41,8 +39,5 @@ data class PhotoContent(
override fun toMediaGroupMemberInputMedia(): InputMediaPhoto = asInputMedia()
override fun asInputMedia(): InputMediaPhoto = media.toInputMediaPhoto(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaPhoto = media.toInputMediaPhoto(textSources)
}

View File

@@ -1,18 +1,17 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.textSources
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendVideo
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaVideo
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.VideoFile
import dev.inmo.tgbotapi.types.files.toInputMediaVideo
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.VisualMediaGroupContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
data class VideoContent(
override val media: VideoFile,
@@ -29,8 +28,7 @@ data class VideoContent(
chatId,
media.fileId,
media.thumb ?.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
media.duration,
media.width,
media.height,
@@ -43,8 +41,5 @@ data class VideoContent(
override fun toMediaGroupMemberInputMedia(): InputMediaVideo = asInputMedia()
override fun asInputMedia(): InputMediaVideo = media.toInputMediaVideo(
toHtmlCaptions().firstOrNull(),
HTMLParseMode
)
override fun asInputMedia(): InputMediaVideo = media.toInputMediaVideo(textSources)
}

View File

@@ -1,20 +1,15 @@
package dev.inmo.tgbotapi.types.message.content.media
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedInput
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.requests.send.media.SendVoice
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.InputMedia.InputMediaAudio
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.ParseMode.HTMLParseMode
import dev.inmo.tgbotapi.types.ParseMode.MarkdownV2
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.files.VoiceFile
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.internal.toHtmlCaptions
import dev.inmo.tgbotapi.utils.internal.toMarkdownV2Captions
data class VoiceContent(
override val media: VoiceFile,
@@ -30,8 +25,7 @@ data class VoiceContent(
): Request<ContentMessage<VoiceContent>> = SendVoice(
chatId,
media.fileId,
toHtmlCaptions().firstOrNull(),
HTMLParseMode,
textSources,
media.duration,
disableNotification,
replyToMessageId,
@@ -41,8 +35,7 @@ data class VoiceContent(
override fun asInputMedia(): InputMediaAudio = InputMediaAudio(
media.fileId,
toMarkdownV2Captions().firstOrNull(),
MarkdownV2,
textSources,
media.duration
)
}

View File

@@ -4,13 +4,13 @@ import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.*
@Serializable
data class AddressSecureValue(
@SerialName(dataField)
override val data: DataCredentials
) : SecureValueWithData {
@Transient
override val credentials: List<EndDataCredentials> = listOf(data)
}

View File

@@ -4,13 +4,13 @@ import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.DataCredentials
import dev.inmo.tgbotapi.types.passport.credentials.EndDataCredentials
import dev.inmo.tgbotapi.types.passport.decrypted.abstracts.SecureValueWithData
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.*
@Serializable
data class PersonalDetailsSecureValue(
@SerialName(dataField)
override val data: DataCredentials
) : SecureValueWithData {
@Transient
override val credentials: List<EndDataCredentials> = listOf(data)
}

View File

@@ -3,8 +3,8 @@ package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.emailField
import dev.inmo.tgbotapi.types.hashField
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElementWithEmail
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

View File

@@ -3,8 +3,8 @@ package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElementWithData
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

View File

@@ -3,8 +3,8 @@ package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.dataField
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElementWithData
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

View File

@@ -2,8 +2,8 @@ package dev.inmo.tgbotapi.types.passport.encrypted
import dev.inmo.micro_utils.serialization.base64.Base64BytesToFromStringSerializer
import dev.inmo.tgbotapi.types.hashField
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.EncryptedPassportElementWithPhoneNumber
import dev.inmo.tgbotapi.types.passport.encrypted.abstracts.PassportElementHash
import dev.inmo.tgbotapi.types.phoneNumberField
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

View File

@@ -33,6 +33,9 @@ val LongSeconds.asApproximateScheduledCloseInfo
get() = ApproximateScheduledCloseInfo(
TimeSpan(this * 1000.0)
)
fun LongSeconds.asApproximateScheduledCloseInfo(startPoint: DateTime) = ApproximateScheduledCloseInfo(
TimeSpan(this * 1000.0), startPoint
)
val LongSeconds.asExactScheduledCloseInfo
get() = ExactScheduledCloseInfo(
DateTime(unixMillis = this * 1000.0)

View File

@@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.update
import dev.inmo.tgbotapi.types.ChatMemberUpdated
import dev.inmo.tgbotapi.types.UpdateIdentifier
import dev.inmo.tgbotapi.types.update.abstracts.ChatMemberUpdatedUpdate
data class CommonChatMemberUpdatedUpdate(
override val updateId: UpdateIdentifier,
override val data: ChatMemberUpdated
) : ChatMemberUpdatedUpdate

View File

@@ -0,0 +1,10 @@
package dev.inmo.tgbotapi.types.update
import dev.inmo.tgbotapi.types.ChatMemberUpdated
import dev.inmo.tgbotapi.types.UpdateIdentifier
import dev.inmo.tgbotapi.types.update.abstracts.ChatMemberUpdatedUpdate
data class MyChatMemberUpdatedUpdate(
override val updateId: UpdateIdentifier,
override val data: ChatMemberUpdated
) : ChatMemberUpdatedUpdate

View File

@@ -1,9 +1,9 @@
package dev.inmo.tgbotapi.types.update
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.CallbackQuery.RawCallbackQuery
import dev.inmo.tgbotapi.types.InlineQueries.ChosenInlineResult.RawChosenInlineResult
import dev.inmo.tgbotapi.types.InlineQueries.query.RawInlineQuery
import dev.inmo.tgbotapi.types.UpdateIdentifier
import dev.inmo.tgbotapi.types.message.abstracts.*
import dev.inmo.tgbotapi.types.payments.PreCheckoutQuery
import dev.inmo.tgbotapi.types.payments.ShippingQuery
@@ -11,7 +11,6 @@ import dev.inmo.tgbotapi.types.polls.Poll
import dev.inmo.tgbotapi.types.polls.PollAnswer
import dev.inmo.tgbotapi.types.update.abstracts.UnknownUpdate
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.types.updateIdField
import kotlinx.serialization.*
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonObject
@@ -34,7 +33,9 @@ internal data class RawUpdate constructor(
private val shipping_query: ShippingQuery? = null,
private val pre_checkout_query: PreCheckoutQuery? = null,
private val poll: Poll? = null,
private val poll_answer: PollAnswer? = null
private val poll_answer: PollAnswer? = null,
private val my_chat_member: ChatMemberUpdated? = null,
private val chat_member: ChatMemberUpdated? = null
) {
private var initedUpdate: Update? = null
/**
@@ -58,6 +59,8 @@ internal data class RawUpdate constructor(
pre_checkout_query != null -> PreCheckoutQueryUpdate(updateId, pre_checkout_query)
poll != null -> PollUpdate(updateId, poll)
poll_answer != null -> PollAnswerUpdate(updateId, poll_answer)
my_chat_member != null -> MyChatMemberUpdatedUpdate(updateId, my_chat_member)
chat_member != null -> CommonChatMemberUpdatedUpdate(updateId, chat_member)
else -> UnknownUpdate(
updateId,
raw.toString(),

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.types.update.abstracts
import dev.inmo.tgbotapi.types.ChatMemberUpdated
interface ChatMemberUpdatedUpdate : Update {
override val data: ChatMemberUpdated
}

View File

@@ -28,6 +28,8 @@ interface FlowsUpdatesFilter : UpdatesFilter {
val preCheckoutQueryFlow: Flow<PreCheckoutQueryUpdate>
val pollFlow: Flow<PollUpdate>
val pollAnswerFlow: Flow<PollAnswerUpdate>
val chatMemberUpdatedFlow: Flow<CommonChatMemberUpdatedUpdate>
val myChatMemberUpdatedFlow: Flow<MyChatMemberUpdatedUpdate>
val unknownUpdateTypeFlow: Flow<UnknownUpdate>
}
@@ -74,5 +76,7 @@ class DefaultFlowsUpdatesFilter(
override val preCheckoutQueryFlow: Flow<PreCheckoutQueryUpdate> = allUpdatesFlow.filterIsInstance()
override val pollFlow: Flow<PollUpdate> = allUpdatesFlow.filterIsInstance()
override val pollAnswerFlow: Flow<PollAnswerUpdate> = allUpdatesFlow.filterIsInstance()
override val chatMemberUpdatedFlow: Flow<CommonChatMemberUpdatedUpdate> = allUpdatesFlow.filterIsInstance()
override val myChatMemberUpdatedFlow: Flow<MyChatMemberUpdatedUpdate> = allUpdatesFlow.filterIsInstance()
override val unknownUpdateTypeFlow: Flow<UnknownUpdate> = allUpdatesFlow.filterIsInstance()
}

View File

@@ -35,4 +35,4 @@ const val lowLevelRiskFeatureMessage = "This method is low-level and not recomme
AnnotationTarget.TYPEALIAS,
AnnotationTarget.TYPE_PARAMETER
)
annotation class RiskFeature(val message: String)
annotation class RiskFeature(val message: String = lowLevelRiskFeatureMessage)

View File

@@ -37,8 +37,6 @@ data class StorageFile(
) {
val input: Input
get() = inputSource()
@Deprecated("This method will be fully replaced with input property", ReplaceWith("input"))
fun asInput() = input
}
@Suppress("NOTHING_TO_INLINE")

View File

@@ -1,97 +0,0 @@
package dev.inmo.tgbotapi.utils.internal
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.ParseMode.*
import dev.inmo.tgbotapi.types.captionLength
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.textLength
internal fun createFormattedText(
entities: TextSourcesList,
partLength: Int = textLength.last,
mode: ParseMode = MarkdownParseMode
): List<String> {
val texts = mutableListOf<String>()
val textBuilder = StringBuilder(partLength)
for (entity in entities) {
val string = when (mode) {
is MarkdownParseMode -> entity.markdown
is MarkdownV2ParseMode -> entity.markdownV2
is HTMLParseMode -> entity.html
}
if (textBuilder.length + string.length > partLength) {
if (textBuilder.isNotEmpty()) {
texts.add(textBuilder.toString())
textBuilder.clear()
}
val chunked = string.chunked(partLength)
val last = chunked.last()
textBuilder.append(last)
val listToAdd = if (chunked.size > 1) {
chunked.subList(0, chunked.size - 1)
} else {
emptyList()
}
listToAdd.forEach {
texts.add(it)
}
} else {
textBuilder.append(string)
}
}
if (textBuilder.isNotEmpty()) {
texts.add(textBuilder.toString())
textBuilder.clear()
}
return texts
}
internal fun createMarkdownText(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownParseMode)
internal fun TextSourcesList.toMarkdownTexts(): List<String> = createMarkdownText(
this,
textLength.last
)
internal fun TextContent.toMarkdownTexts(): List<String> = textSources.toMarkdownTexts()
internal fun createMarkdownV2Text(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, MarkdownV2ParseMode)
internal fun TextSourcesList.toMarkdownV2Captions(): List<String> = createMarkdownV2Text(
this,
captionLength.last
)
internal fun CaptionedInput.toMarkdownV2Captions(): List<String> = textSources.toMarkdownV2Captions()
internal fun TextSourcesList.toMarkdownV2Texts(): List<String> = createMarkdownV2Text(
this,
textLength.last
)
internal fun TextContent.toMarkdownV2Texts(): List<String> = textSources.toMarkdownV2Texts()
internal fun createHtmlText(
entities: TextSourcesList,
partLength: Int = textLength.last
): List<String> = createFormattedText(entities, partLength, HTMLParseMode)
internal fun TextSourcesList.toHtmlCaptions(): List<String> = createHtmlText(
this,
captionLength.last
)
internal fun CaptionedInput.toHtmlCaptions(): List<String> = textSources.toHtmlCaptions()
internal fun TextSourcesList.toHtmlTexts(): List<String> = createHtmlText(
this,
textLength.last
)
internal fun TextContent.toHtmlTexts(): List<String> = textSources.toHtmlTexts()

View File

@@ -1,14 +1,7 @@
package dev.inmo.tgbotapi.utils.passport
import dev.inmo.micro_utils.crypto.SourceBytes
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.get.GetFile
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedCredentials
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedData
import dev.inmo.tgbotapi.types.passport.encrypted.PassportFile
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.json.JsonObject
interface Decryptor {
fun decrypt(data: EncryptedData): SourceBytes

View File

@@ -2,8 +2,8 @@ package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.CommonAbstracts.plus
import dev.inmo.tgbotapi.extensions.utils.formatting.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.*
import dev.inmo.tgbotapi.utils.internal.*
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@@ -1,8 +1,8 @@
package dev.inmo.tgbotapi.types.MessageEntity
import dev.inmo.tgbotapi.CommonAbstracts.justTextSources
import dev.inmo.tgbotapi.utils.internal.toHtmlTexts
import dev.inmo.tgbotapi.utils.internal.toMarkdownV2Texts
import dev.inmo.tgbotapi.extensions.utils.formatting.toHtmlTexts
import dev.inmo.tgbotapi.extensions.utils.formatting.toMarkdownV2Texts
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@@ -4,11 +4,10 @@ import dev.inmo.micro_utils.crypto.decodeBase64
import dev.inmo.tgbotapi.types.passport.credentials.DecryptedCredentials
import dev.inmo.tgbotapi.types.passport.credentials.EncryptedCredentials
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import java.security.*
import java.security.KeyFactory
import java.security.PrivateKey
import java.security.spec.PKCS8EncodedKeySpec
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
private val regexToRemoveFromKey = Regex("(-----(BEGIN|END) ((?:.*? KEY)|CERTIFICATE)-----|[\\s])")

View File

@@ -29,7 +29,9 @@ repositories {
}
kotlin {
jvm()
jvm {
compilations.main.kotlinOptions.useIR = true
}
js(BOTH) {
browser()
nodejs()

View File

@@ -1 +1 @@
{"bintrayConfig":{"repo":"TelegramBotAPI","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/TelegramBotAPI","autoPublish":true,"overridePublish":true},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Extensions for API","description":"API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference","url":"https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-api","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]}}
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Extensions for API","description":"API extensions which provide work with RequestsExecutor of TelegramBotAPI almost like it is described in original Telegram Bot API reference","url":"https://insanusmokrassar.github.io/TelegramBotAPI/TelegramBotAPI-extensions-api","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI"},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}]}}

View File

@@ -4,22 +4,6 @@ apply plugin: 'signing'
task javadocsJar(type: Jar) {
classifier = 'javadoc'
}
task sourceJar (type : Jar) {
classifier = 'sources'
}
afterEvaluate {
project.publishing.publications.all {
// rename artifacts
groupId "${project.group}"
if (it.name.contains('kotlinMultiplatform')) {
artifactId = "${project.name}"
artifact sourceJar
} else {
artifactId = "${project.name}-$name"
}
}
}
publishing {
publications.all {
@@ -54,22 +38,32 @@ publishing {
}
}
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')
if ((project.hasProperty('GITHUBPACKAGES_USER') || System.getenv('GITHUBPACKAGES_USER') != null) && (project.hasProperty('GITHUBPACKAGES_PASSWORD') || System.getenv('GITHUBPACKAGES_PASSWORD') != null)) {
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI")
credentials {
username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven {
name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
}
}
signing {
useGpgCmd()
publishing.publications.forEach { sign it }
sign publishing.publications
}

View File

@@ -0,0 +1,31 @@
package dev.inmo.tgbotapi.extensions.api.chat.invite_links
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.chat.invite_links.CreateChatInviteLink
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.abstracts.PublicChat
suspend fun TelegramBot.createChatInviteLink(
chatId: ChatIdentifier,
expiration: TelegramDate? = null,
membersLimit: MembersLimit? = null
) = execute(CreateChatInviteLink(chatId, expiration, membersLimit))
suspend fun TelegramBot.createChatInviteLink(
chat: PublicChat,
expiration: TelegramDate? = null,
membersLimit: MembersLimit? = null
) = createChatInviteLink(chat.id, expiration, membersLimit)
suspend fun TelegramBot.createChatInviteLink(
chatId: ChatIdentifier,
expiration: DateTime,
membersLimit: MembersLimit? = null
) = createChatInviteLink(chatId, expiration.toTelegramDate(), membersLimit)
suspend fun TelegramBot.createChatInviteLink(
chat: PublicChat,
expiration: DateTime,
membersLimit: MembersLimit? = null
) = createChatInviteLink(chat.id, expiration.toTelegramDate(), membersLimit)

View File

@@ -0,0 +1,63 @@
package dev.inmo.tgbotapi.extensions.api.chat.invite_links
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.chat.invite_links.EditChatInviteLink
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.abstracts.PublicChat
suspend fun TelegramBot.editChatInviteLink(
chatId: ChatIdentifier,
previousLink: String,
expiration: TelegramDate? = null,
membersLimit: MembersLimit? = null
) = execute(EditChatInviteLink(chatId, previousLink, expiration, membersLimit))
suspend fun TelegramBot.editChatInviteLink(
chat: PublicChat,
previousLink: String,
expiration: TelegramDate? = null,
membersLimit: MembersLimit? = null
) = editChatInviteLink(chat.id, previousLink, expiration, membersLimit)
suspend fun TelegramBot.editChatInviteLink(
chatId: ChatIdentifier,
previousLink: String,
expiration: DateTime,
membersLimit: MembersLimit? = null
) = editChatInviteLink(chatId, previousLink, expiration.toTelegramDate(), membersLimit)
suspend fun TelegramBot.editChatInviteLink(
chat: PublicChat,
previousLink: String,
expiration: DateTime,
membersLimit: MembersLimit? = null
) = editChatInviteLink(chat.id, previousLink, expiration.toTelegramDate(), membersLimit)
suspend fun TelegramBot.editChatInviteLink(
chat: ChatIdentifier,
previousLink: ChatInviteLink,
expiration: TelegramDate? = previousLink.expirationDateTime ?.toTelegramDate(),
membersLimit: MembersLimit? = previousLink.membersLimit
) = editChatInviteLink(chat, previousLink.inviteLink, expiration, membersLimit)
suspend fun TelegramBot.editChatInviteLink(
chat: ChatIdentifier,
previousLink: ChatInviteLink,
expiration: DateTime,
membersLimit: MembersLimit? = previousLink.membersLimit
) = editChatInviteLink(chat, previousLink.inviteLink, expiration, membersLimit)
suspend fun TelegramBot.editChatInviteLink(
chat: PublicChat,
previousLink: ChatInviteLink,
expiration: TelegramDate? = previousLink.expirationDateTime ?.toTelegramDate(),
membersLimit: MembersLimit? = previousLink.membersLimit
) = editChatInviteLink(chat, previousLink.inviteLink, expiration, membersLimit)
suspend fun TelegramBot.editChatInviteLink(
chat: PublicChat,
previousLink: ChatInviteLink,
expiration: DateTime,
membersLimit: MembersLimit? = previousLink.membersLimit
) = editChatInviteLink(chat, previousLink.inviteLink, expiration, membersLimit)

View File

@@ -0,0 +1,27 @@
package dev.inmo.tgbotapi.extensions.api.chat.invite_links
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.requests.chat.invite_links.RevokeChatInviteLink
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.ChatInviteLink
import dev.inmo.tgbotapi.types.chat.abstracts.PublicChat
suspend fun TelegramBot.revokeChatInviteLink(
chatId: ChatIdentifier,
previousLink: String
) = execute(RevokeChatInviteLink(chatId, previousLink))
suspend fun TelegramBot.revokeChatInviteLink(
chat: PublicChat,
previousLink: String
) = revokeChatInviteLink(chat.id, previousLink)
suspend fun TelegramBot.revokeChatInviteLink(
chatId: ChatIdentifier,
previousLink: ChatInviteLink
) = revokeChatInviteLink(chatId, previousLink.inviteLink)
suspend fun TelegramBot.revokeChatInviteLink(
chat: PublicChat,
previousLink: ChatInviteLink
) = revokeChatInviteLink(chat, previousLink.inviteLink)

View File

@@ -8,23 +8,27 @@ import dev.inmo.tgbotapi.types.chat.abstracts.PublicChat
suspend fun TelegramBot.kickChatMember(
chatId: ChatIdentifier,
userId: UserId,
untilDate: TelegramDate? = null
) = execute(KickChatMember(chatId, userId, untilDate))
untilDate: TelegramDate? = null,
revokeMessages: Boolean? = null
) = execute(KickChatMember(chatId, userId, untilDate, revokeMessages))
suspend fun TelegramBot.kickChatMember(
chat: PublicChat,
userId: UserId,
untilDate: TelegramDate? = null
) = kickChatMember(chat.id, userId, untilDate)
untilDate: TelegramDate? = null,
revokeMessages: Boolean? = null
) = kickChatMember(chat.id, userId, untilDate, revokeMessages)
suspend fun TelegramBot.kickChatMember(
chatId: ChatId,
user: User,
untilDate: TelegramDate? = null
) = kickChatMember(chatId, user.id, untilDate)
untilDate: TelegramDate? = null,
revokeMessages: Boolean? = null
) = kickChatMember(chatId, user.id, untilDate, revokeMessages)
suspend fun TelegramBot.kickChatMember(
chat: PublicChat,
user: User,
untilDate: TelegramDate? = null
) = kickChatMember(chat.id, user.id, untilDate)
untilDate: TelegramDate? = null,
revokeMessages: Boolean? = null
) = kickChatMember(chat.id, user.id, untilDate, revokeMessages)

View File

@@ -17,7 +17,9 @@ suspend fun TelegramBot.promoteChatMember(
canInviteUsers: Boolean? = null,
canRestrictMembers: Boolean? = null,
canPinMessages: Boolean? = null,
canPromoteMembers: Boolean? = null
canPromoteMembers: Boolean? = null,
canManageVoiceChats: Boolean? = null,
canManageChat: Boolean?
) = execute(
PromoteChatMember(
chatId,
@@ -31,7 +33,9 @@ suspend fun TelegramBot.promoteChatMember(
canInviteUsers,
canRestrictMembers,
canPinMessages,
canPromoteMembers
canPromoteMembers,
canManageVoiceChats,
canManageChat
)
)
@@ -47,7 +51,9 @@ suspend fun TelegramBot.promoteChatMember(
canInviteUsers: Boolean? = null,
canRestrictMembers: Boolean? = null,
canPinMessages: Boolean? = null,
canPromoteMembers: Boolean? = null
canPromoteMembers: Boolean? = null,
canManageVoiceChats: Boolean? = null,
canManageChat: Boolean? = null
) = promoteChatMember(
chat.id,
userId,
@@ -60,7 +66,9 @@ suspend fun TelegramBot.promoteChatMember(
canInviteUsers,
canRestrictMembers,
canPinMessages,
canPromoteMembers
canPromoteMembers,
canManageVoiceChats,
canManageChat
)
suspend fun TelegramBot.promoteChatMember(
@@ -75,7 +83,9 @@ suspend fun TelegramBot.promoteChatMember(
canInviteUsers: Boolean? = null,
canRestrictMembers: Boolean? = null,
canPinMessages: Boolean? = null,
canPromoteMembers: Boolean? = null
canPromoteMembers: Boolean? = null,
canManageVoiceChats: Boolean? = null,
canManageChat: Boolean? = null
) = promoteChatMember(
chatId,
user.id,
@@ -88,7 +98,9 @@ suspend fun TelegramBot.promoteChatMember(
canInviteUsers,
canRestrictMembers,
canPinMessages,
canPromoteMembers
canPromoteMembers,
canManageVoiceChats,
canManageChat
)
suspend fun TelegramBot.promoteChatMember(
@@ -103,7 +115,9 @@ suspend fun TelegramBot.promoteChatMember(
canInviteUsers: Boolean? = null,
canRestrictMembers: Boolean? = null,
canPinMessages: Boolean? = null,
canPromoteMembers: Boolean? = null
canPromoteMembers: Boolean? = null,
canManageVoiceChats: Boolean? = null,
canManageChat: Boolean? = null
) = promoteChatMember(
chat.id,
user.id,
@@ -116,5 +130,7 @@ suspend fun TelegramBot.promoteChatMember(
canInviteUsers,
canRestrictMembers,
canPinMessages,
canPromoteMembers
canPromoteMembers,
canManageVoiceChats,
canManageChat
)

View File

@@ -29,10 +29,18 @@ suspend fun TelegramBot.sendDice(
replyMarkup: KeyboardMarkup? = null
) = sendDice(chat.id, animationType, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
suspend inline fun TelegramBot.replyWithDice(
to: Message,
animationType: DiceAnimationType? = null,
disableNotification: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = sendDice(to.chat, animationType, disableNotification, to.messageId, allowSendingWithoutReply, replyMarkup)
suspend inline fun TelegramBot.reply(
to: Message,
animationType: DiceAnimationType? = null,
disableNotification: Boolean = false,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = replyWithDice(to, animationType, disableNotification, allowSendingWithoutReply, replyMarkup)

View File

@@ -8,7 +8,6 @@ import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
import dev.inmo.tgbotapi.types.message.abstracts.Message
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaGroupContent
import dev.inmo.tgbotapi.types.message.content.abstracts.VisualMediaGroupContent
import dev.inmo.tgbotapi.utils.RiskFeature
/**

View File

@@ -29,7 +29,9 @@ repositories {
}
kotlin {
jvm()
jvm {
compilations.main.kotlinOptions.useIR = true
}
js(BOTH) {
browser()
nodejs()

View File

@@ -1 +1 @@
{"bintrayConfig":{"repo":"TelegramBotAPI","packageName":"${project.name}","packageVcs":"https://github.com/InsanusMokrassar/TelegramBotAPI","autoPublish":true,"overridePublish":true},"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Steps Extensions","description":"This extensions project contains tools for simple interaction with chats","url":"https://insanusmokrassar.github.io/TelegramBotAPI/tgbotapi.extensions.steps","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}]}}
{"licenses":[{"id":"Apache-2.0","title":"Apache Software License 2.0","url":"https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"}],"mavenConfig":{"name":"Telegram Bot API Steps Extensions","description":"This extensions project contains tools for simple interaction with chats","url":"https://insanusmokrassar.github.io/TelegramBotAPI/tgbotapi.extensions.steps","vcsUrl":"https://github.com/insanusmokrassar/TelegramBotAPI.git","includeGpgSigning":true,"developers":[{"id":"InsanusMokrassar","name":"Ovsiannikov Aleksei","eMail":"ovsyannikov.alexey95@gmail.com"}],"repositories":[{"name":"GithubPackages","url":"https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI"},{"name":"sonatype","url":"https://oss.sonatype.org/service/local/staging/deploy/maven2/"}]}}

View File

@@ -4,22 +4,6 @@ apply plugin: 'signing'
task javadocsJar(type: Jar) {
classifier = 'javadoc'
}
task sourceJar (type : Jar) {
classifier = 'sources'
}
afterEvaluate {
project.publishing.publications.all {
// rename artifacts
groupId "${project.group}"
if (it.name.contains('kotlinMultiplatform')) {
artifactId = "${project.name}"
artifact sourceJar
} else {
artifactId = "${project.name}-$name"
}
}
}
publishing {
publications.all {
@@ -54,22 +38,32 @@ publishing {
}
}
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')
if ((project.hasProperty('GITHUBPACKAGES_USER') || System.getenv('GITHUBPACKAGES_USER') != null) && (project.hasProperty('GITHUBPACKAGES_PASSWORD') || System.getenv('GITHUBPACKAGES_PASSWORD') != null)) {
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI")
credentials {
username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven {
name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
}
}
signing {
useGpgCmd()
publishing.publications.forEach { sign it }
sign publishing.publications
}

View File

@@ -4,6 +4,7 @@ import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.utils.RiskFeature
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.filter
@@ -25,12 +26,15 @@ data class BehaviourContext(
/**
* Creates new one [BehaviourContext], adding subsequent [FlowsUpdatesFilter] in case [newFlowsUpdatesFilterSetUp] is provided and
* [CoroutineScope] as new [BehaviourContext.scope]
* [CoroutineScope] as new [BehaviourContext.scope]. You must do all subscription/running of longPolling manually.
*
* @param newFlowsUpdatesFilterSetUp As a parameter receives [FlowsUpdatesFilter] from old [this] [BehaviourContext.flowsUpdatesFilter]
*/
@RiskFeature("It is recommended to use doInSubContextWithUpdatesFilter instead. " +
"This method is low level and should not be used in case you are not pretty sure you need it.")
suspend fun <T> BehaviourContext.doInSubContextWithFlowsUpdatesFilterSetup(
newFlowsUpdatesFilterSetUp: BehaviourContextAndTypeReceiver<Unit, FlowsUpdatesFilter>?,
stopOnCompletion: Boolean = true,
behaviourContextReceiver: BehaviourContextReceiver<T>
) = copy(
flowsUpdatesFilter = FlowsUpdatesFilter(),
@@ -39,7 +43,7 @@ suspend fun <T> BehaviourContext.doInSubContextWithFlowsUpdatesFilterSetup(
newFlowsUpdatesFilterSetUp ?.let {
it.apply { invoke(this@run, this@doInSubContextWithFlowsUpdatesFilterSetup.flowsUpdatesFilter) }
}
behaviourContextReceiver().also { stop() }
behaviourContextReceiver().also { if (stopOnCompletion) stop() }
}
/**
@@ -48,19 +52,24 @@ suspend fun <T> BehaviourContext.doInSubContextWithFlowsUpdatesFilterSetup(
*/
suspend fun <T> BehaviourContext.doInSubContextWithUpdatesFilter(
updatesFilter: BehaviourContextAndTypeReceiver<Boolean, Update>?,
stopOnCompletion: Boolean = true,
behaviourContextReceiver: BehaviourContextReceiver<T>
) = doInSubContextWithFlowsUpdatesFilterSetup(
newFlowsUpdatesFilterSetUp = updatesFilter ?.let {
{ oldOne ->
oldOne.allUpdatesFlow.filter { updatesFilter(it) }.subscribeSafelyWithoutExceptions(scope, asUpdateReceiver)
}
} ?: { oldOne ->
oldOne.allUpdatesFlow.subscribeSafelyWithoutExceptions(scope, asUpdateReceiver)
},
stopOnCompletion,
behaviourContextReceiver
)
suspend fun <T> BehaviourContext.doInSubContext(
stopOnCompletion: Boolean = true,
behaviourContextReceiver: BehaviourContextReceiver<T>
) = doInSubContextWithFlowsUpdatesFilterSetup(newFlowsUpdatesFilterSetUp = null, behaviourContextReceiver)
) = doInSubContextWithUpdatesFilter(updatesFilter = null, stopOnCompletion, behaviourContextReceiver)
/**
* This method will cancel ALL subsequent contexts, expectations and waiters

View File

@@ -24,7 +24,7 @@ private suspend fun <O> BehaviourContext.waitCallbackQueries(
}.toList().toList()
private suspend inline fun <reified T : CallbackQuery> BehaviourContext.waitEvents(
private suspend inline fun <reified T : CallbackQuery> BehaviourContext.waitCallbacks(
count: Int = 1,
initRequest: Request<*>? = null,
noinline errorFactory: NullableRequestBuilder<*> = { null },
@@ -51,52 +51,52 @@ suspend fun BehaviourContext.waitDataCallbackQuery(
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<DataCallbackQuery>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)
suspend fun BehaviourContext.waitGameShortNameCallbackQuery(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<GameShortNameCallbackQuery>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)
suspend fun BehaviourContext.waitInlineMessageIdCallbackQuery(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<InlineMessageIdCallbackQuery>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)
suspend fun BehaviourContext.waitInlineMessageIdDataCallbackQuery(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<InlineMessageIdDataCallbackQuery>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)
suspend fun BehaviourContext.waitInlineMessageIdGameShortNameCallbackQuery(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<InlineMessageIdGameShortNameCallbackQuery>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)
suspend fun BehaviourContext.waitMessageCallbackQuery(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<MessageCallbackQuery>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)
suspend fun BehaviourContext.waitMessageDataCallbackQuery(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<MessageDataCallbackQuery>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)
suspend fun BehaviourContext.waitMessageGameShortNameCallbackQuery(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<MessageGameShortNameCallbackQuery>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)
suspend fun BehaviourContext.waitUnknownCallbackQuery(
initRequest: Request<*>? = null,
errorFactory: NullableRequestBuilder<*> = { null },
count: Int = 1,
filter: CallbackQueryMapper<UnknownCallbackQueryType>? = null
) = waitEvents(count, initRequest, errorFactory, filter)
) = waitCallbacks(count, initRequest, errorFactory, filter)

Some files were not shown because too many files have changed in this diff Show More