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

Compare commits

..

265 Commits

Author SHA1 Message Date
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
dc83b8d77a fix of #275 and several other internal problems 2021-02-01 21:09:11 +06:00
2aac6c0bde start 0.32.2 2021-02-01 21:04:54 +06:00
b637d0d2a6 Merge pull request #274 from InsanusMokrassar/0.32.1
0.32.1
2021-01-30 21:06:15 +06:00
d12cba2343 replacing of withContent and requireWithContent and extending of extensions receivers types 2021-01-30 20:59:26 +06:00
450c7e6474 fix of #273 2021-01-30 20:05:07 +06:00
a35fb40a66 fix of #272 2021-01-30 19:35:53 +06:00
8731aa2c26 start 0.32.1 2021-01-30 19:33:38 +06:00
32e305537d Merge pull request #260 from InsanusMokrassar/0.32.0
0.32.0
2021-01-29 17:00:06 +06:00
ec0a10e36e fillup changelog 2021-01-29 13:28:18 +06:00
131ec4d6d5 renames of EncryptedPassportElements 2021-01-29 12:44:13 +06:00
ecc608f51a add additional variant of doInDecryptionContextWithPKCS8Key 2021-01-29 10:44:11 +06:00
040654f131 refill readme 2021-01-29 01:18:44 +06:00
9e73d0c461 add opportunity to manually set up delay for media groups webhooks 2021-01-29 00:56:47 +06:00
d67c80bc99 ClassCasts update for SecureValue 2021-01-28 22:21:21 +06:00
b0eef4f82d update ktor 2021-01-28 22:06:52 +06:00
fbe91a6321 complete preview tools for passport 2021-01-28 22:03:14 +06:00
15066c9d63 add SecureData and DecryptedCredentials 2021-01-28 17:08:25 +06:00
e0bf67d8f9 global update of passport 2021-01-28 16:03:30 +06:00
1dc3ce2fb5 add passport in API 2021-01-25 10:43:51 +06:00
0c71133969 add expectations and triggers for passport 2021-01-25 10:29:11 +06:00
1359dd549f Create regular-build.yml 2021-01-25 04:42:23 +06:00
c425e2ecc3 update classcasts 2021-01-23 21:10:57 +06:00
4d63e3a17d complete tools for handling of encrypted data 2021-01-23 20:50:46 +06:00
d34deade0d temporal state (currently tools for files decryption in JS do work 2021-01-23 18:49:41 +06:00
2f52ad45a4 add tools for passport files hashes calculation 2021-01-23 12:21:57 +06:00
1d99e632a4 fix of SetPassportDataErrors request parent interface 2021-01-22 23:40:33 +06:00
cdcfaf5a29 fixes in passport errors serialization and replacing of PassportElementError 2021-01-22 23:14:24 +06:00
f3590762f3 add PassportElementError realization 2021-01-22 23:01:37 +06:00
e0ff14b7fe update gradle wrapper 2021-01-22 21:57:23 +06:00
9983e111ec update EncryptedElementSerializer 2021-01-22 21:53:37 +06:00
08b8710772 add asAction and several variants of oneOf 2021-01-19 20:19:28 +06:00
fc71e028c4 improving work of behaviour_builder 2021-01-19 18:50:45 +06:00
30a4a7bd8b update micro_utils dependency 2021-01-19 13:52:06 +06:00
b973278b0a add note about breaking changes 2021-01-19 11:00:12 +06:00
ae2f4579e2 start 0.32.0 as a migration from 0.31.1 due to breaking changes in MediaGroupMessage type 2021-01-19 10:52:30 +06:00
a4bf6911c7 Update micro_utils version note 2021-01-19 00:40:29 +06:00
73b3daa68b Update micro_utils dependency 2021-01-19 00:39:46 +06:00
09748615ae optimize imports 2021-01-18 23:43:21 +06:00
2dc8521aed now all data field are predecrypted with Base64StringSerializer 2021-01-17 16:44:56 +06:00
81de59f37c fix of translations in UtilityBill 2021-01-17 16:34:05 +06:00
fb61a94c5e fix defaults in encrypted passport data 2021-01-17 16:30:25 +06:00
26fd5e51bf filesSize in PassportFile is nullable for now 2021-01-17 16:24:33 +06:00
c1ab9da4c4 fix error with deserialization of passport data 2021-01-17 16:11:38 +06:00
6b414d64b0 remove redundant imports 2021-01-17 15:45:20 +06:00
5a3edc2b44 add passportMessages extension 2021-01-17 15:43:08 +06:00
6dcdc2ab7f now PassportMessage contains user too 2021-01-17 15:35:25 +06:00
a2ae4f71de new PassportMessage type 2021-01-15 16:27:22 +06:00
5d87b86afe update passport data to use Base64StringSerializer 2021-01-15 16:02:16 +06:00
ef22735894 add base64 serialization dependency and update micro_utils up to 0.4.17 2021-01-14 21:27:58 +06:00
c0ea479fe3 add primitives for Telegram Passport API 2021-01-14 14:03:25 +06:00
0846e816e9 start 0.31.1 2021-01-14 12:37:31 +06:00
d837c9d605 update publication scripts 2021-01-13 14:21:35 +06:00
d1993842c3 Merge pull request #257 from InsanusMokrassar/0.31.0
0.31.0
2021-01-10 13:08:00 +06:00
4e8a9dcff0 update changelog 2021-01-09 22:35:41 +06:00
10eb15e172 several RiskFeature updates 2021-01-09 22:18:31 +06:00
0320da7614 updates in long polling methods 2021-01-09 22:10:38 +06:00
7aa3ff180e several refactoring things and docs appending 2021-01-09 21:50:02 +06:00
a882a212c2 remove different internal strings things 2021-01-09 21:24:13 +06:00
1b15748f65 optimize imports 2021-01-09 20:59:37 +06:00
044fe5eadf full removing of old redundant "fullEntitiesList" 2021-01-09 20:52:21 +06:00
9453ec37e7 update gradle wrapper 2021-01-09 19:01:14 +06:00
3d0cbc2d2b small refactor 2021-01-09 19:00:41 +06:00
198b551ebf deprecations removing 2021-01-09 18:25:11 +06:00
1452e32293 behaviours documentatio and changing of buildBehaviour signature 2021-01-09 18:04:45 +06:00
946b7abcae start 0.31.0 2021-01-08 16:58:25 +06:00
879943622a Merge pull request #254 from InsanusMokrassar/0.30.13
0.30.13
2021-01-08 16:50:14 +06:00
c0b4b523cf update micro_utils version 2021-01-08 16:41:08 +06:00
49e6e9cfe3 fix in new project publication scripts 2021-01-08 16:39:29 +06:00
ffadb6355b fixes in readme 2021-01-08 16:37:03 +06:00
9cc402b42d ContentMessage -> CommonMessage in behaviour_builder, fill readme of behaviour_builder and update projects schema 2021-01-08 16:28:00 +06:00
b9341f89ac add media groups triggers and waiters 2021-01-08 11:02:18 +06:00
ac07f44c81 change public signature of waiters 2021-01-08 10:29:29 +06:00
2e53247726 now content waiters and triggers may have set up manually parameter "includeMediaGroups" 2021-01-08 10:22:29 +06:00
e2dddf96a1 several small additions 2021-01-08 00:30:29 +06:00
ce0fceb240 include media groups 2021-01-08 00:22:19 +06:00
633239961a update FlowsUsh 2021-01-07 19:02:35 +06:00
8b79b15777 FlowsUpdatesFilter#allUpdatesWithoutMediaGroupsGroupingFlow 2021-01-07 19:01:02 +06:00
a28cf5ddff now BehaviourContext is UpdateFilterm TelegramBot and CoroutineScope 2021-01-07 18:20:23 +06:00
8c2cffc8e3 rename steps subproject to behaviour_builder 2021-01-07 18:17:50 +06:00
b933361258 optimize imports in steps 2021-01-07 18:12:37 +06:00
383e722d07 rename scenario to behaviour context 2021-01-07 18:11:24 +06:00
3125c2fc1b add callback query expectations and triggers 2021-01-07 17:57:08 +06:00
965b8c3c50 add chat event triggers and expectations in steps 2021-01-07 17:24:58 +06:00
94745ef373 add docs to base expectations 2021-01-07 16:01:25 +06:00
aee5ab564b optimize imports 2021-01-07 12:45:54 +06:00
c70f0b65dd add content triggers and update command 2021-01-07 12:45:30 +06:00
30e6f68228 small update of scenarios 2021-01-06 23:21:33 +06:00
00873a255c preview state of steps 2021-01-06 23:06:48 +06:00
6bd423dc11 class casts for ResendableContent and TextSource 2021-01-06 20:49:55 +06:00
c5ada8cea0 start 0.30.13 2021-01-06 15:41:27 +06:00
0cb3df4d1a Merge pull request #251 from InsanusMokrassar/0.3.12
0.3.12
2021-01-05 23:06:35 +06:00
b22118b400 add suppressing of unchecked casts 2021-01-05 23:04:09 +06:00
2006e45b57 last update of classcasts 2021-01-05 23:02:00 +06:00
c091098feb remove *Impl casts 2021-01-05 22:37:52 +06:00
6cf8d47cbf update classcasts 2021-01-05 22:27:42 +06:00
3dc4e9dda4 preview of solution for #145 2021-01-05 11:54:02 +06:00
6407ad1a93 Revert "one more update of klassindex"
This reverts commit f974e5787f.
2021-01-05 11:11:50 +06:00
f974e5787f one more update of klassindex 2021-01-05 11:11:37 +06:00
28a9bbd310 Revert "add klassindex"
This reverts commit 599d5a51e3.
2021-01-05 01:37:01 +06:00
599d5a51e3 add klassindex 2021-01-05 01:36:52 +06:00
25f8d15a4b start 0.3.12 2021-01-05 00:16:11 +06:00
66c2cb2d30 Merge pull request #243 from InsanusMokrassar/0.30.11
0.30.11
2021-01-04 14:35:56 +06:00
74fb448378 update klock 2021-01-04 14:29:06 +06:00
3417ec060f Update README.md 2021-01-03 15:22:19 +06:00
4f54a00003 Update README.md 2021-01-03 15:20:42 +06:00
4fb187da30 Update README.md 2021-01-03 15:19:35 +06:00
7637b6f69a Update README.md 2021-01-03 15:17:58 +06:00
9df9af193c bot actions got class-cast shortcuts 2021-01-02 16:06:00 +06:00
ba4b4c4b64 bot actions shortcut 2021-01-02 15:51:26 +06:00
fa0861b8bc update micro_utils 2020-12-23 13:42:00 +06:00
20494e1d4a Update CHANGELOG.md 2020-12-22 17:34:14 +06:00
a404008dee Update dependencies 2020-12-22 17:33:20 +06:00
881205dd80 update dependencies 2020-12-16 14:25:09 +06:00
2096c44811 start 0.30.11 2020-12-13 22:25:57 +06:00
1a3da33589 Merge pull request #237 from InsanusMokrassar/0.30.10
0.30.10
2020-12-08 14:25:00 +06:00
be28c9bd5d update dependencies 2020-12-08 12:03:45 +06:00
a193ef5fd5 buildBot 2020-12-04 16:29:50 +06:00
7c43d3aaa5 update dependencies 2020-12-04 16:13:02 +06:00
e034afc75c start 0.30.10 2020-12-04 16:06:14 +06:00
08e3326d1a Merge pull request #226 from InsanusMokrassar/0.30.9
0.30.9
2020-11-27 00:59:33 +06:00
6dd1825b98 update dependencies 2020-11-27 00:44:29 +06:00
bd4eb29fc1 update limits of dices 2020-11-26 19:37:35 +06:00
2cc66ef13c BowlingDiceAnimationType 2020-11-25 23:09:49 +06:00
9a8175d1c8 update dependencies 2020-11-25 23:02:54 +06:00
25285b2e8a start 0.30.9 2020-11-25 23:01:19 +06:00
bb09f05d7b Merge pull request #223 from InsanusMokrassar/0.30.8
0.30.8
2020-11-21 16:37:47 +06:00
da5e46e59f remove several PreviewFeature 2020-11-21 15:19:31 +06:00
a3f315a73a update micro_utils 2020-11-21 15:15:07 +06:00
43583a885a update versions 2020-11-21 14:40:34 +06:00
ec02257ecd start 0.30.8 2020-11-21 14:32:32 +06:00
29ee4a9396 update publishing urls 2020-11-18 17:51:53 +06:00
2717cb4fc6 exprimentally update publishing scripts 2020-11-18 17:18:51 +06:00
1ce2526401 Merge pull request #217 from InsanusMokrassar/0.30.7
0.30.7
2020-11-17 16:32:19 +06:00
74c480b07e one new telegramBot function 2020-11-17 16:18:58 +06:00
657e9aa770 add KtorRequestsExecutorBuilder 2020-11-17 16:06:25 +06:00
0d19952ba7 PowLimiter and CommonLimiter rewriting (#210) 2020-11-17 15:48:58 +06:00
f8cccc3e17 update gradle 2020-11-17 14:41:53 +06:00
bc1b7c3f25 fix ending of host url in TelegramAPIUrlsKeeper 2020-11-17 13:18:11 +06:00
ec74111a9d update micro_utils version 2020-11-17 12:51:55 +06:00
2dadeb7eb7 start 0.30.7 2020-11-17 12:50:54 +06:00
24bd65501b Update README.md 2020-11-16 21:59:25 +06:00
574ca803fa Update README.md 2020-11-16 21:56:31 +06:00
947e3bf34e add fast start 2020-11-16 21:55:22 +06:00
488158d8fb Merge pull request #214 from InsanusMokrassar/0.30.6
0.30.6
2020-11-16 16:29:46 +06:00
41bf3c7f0b filling of changelog and renaming of new function makeLink -> makeUsernameLink 2020-11-16 16:25:10 +06:00
c2032d21cd TextSource properties has been renamed 2020-11-16 13:32:20 +06:00
6650dd9cfe reworking of links extension 2020-11-16 13:22:08 +06:00
af1d6d6f1a start 0.30.6 2020-11-15 23:05:19 +06:00
a5861d659d Merge pull request #212 from InsanusMokrassar/0.30.5
0.30.5
2020-11-14 19:44:26 +06:00
b36f80a6d3 update micro_utils 2020-11-14 19:41:26 +06:00
7c4f034a6c fixes in imports 2020-11-14 14:41:16 +06:00
3b08bc6dd2 serialization of ChatMember and changing of id type in User 2020-11-14 14:38:54 +06:00
ed87c0ad95 start 0.30.5 2020-11-14 11:19:53 +06:00
c8c0fc2ce8 Merge pull request #211 from InsanusMokrassar/0.30.4
0.30.4
2020-11-12 23:05:49 +06:00
1f40ce1a81 add a lot of shortcuts for events 2020-11-12 22:35:27 +06:00
b0219389fc add several functions and changelog notes 2020-11-12 22:23:10 +06:00
f6ec82b449 deprecate old asChatEventsFlow 2020-11-12 22:04:46 +06:00
71dac70635 deprecations in old functions 2020-11-12 22:02:06 +06:00
98f68a9e1e filling of changelog 2020-11-12 21:54:14 +06:00
e7199e7451 fix use user in group messages 2020-11-12 21:46:33 +06:00
33b50c6c68 events filters 2020-11-12 21:17:11 +06:00
e4ce6f8fc7 fixes in events 2020-11-12 17:44:33 +06:00
8764f18ca8 TextContent now implements TextedInput 2020-11-12 16:57:32 +06:00
b2fa7fee9d rename MultilevelTextSource#textSources 2020-11-12 16:37:17 +06:00
0121e3a104 update micro_utils 2020-11-12 16:33:48 +06:00
f6e5664632 start 0.30.4 2020-11-12 16:31:02 +06:00
c5b7c4e1f5 Merge pull request #209 from InsanusMokrassar/0.30.3
0.30.3
2020-11-11 11:25:25 +06:00
53800d49bf small rework in ExceptionsOnlyLimiter 2020-11-11 11:23:24 +06:00
d83e3eb10a add handling of 429 status 2020-11-11 11:15:19 +06:00
66b4d06064 limiter rework 2020-11-11 10:23:20 +06:00
4fab01b2a2 update micro_utils 2020-11-11 10:15:06 +06:00
b81086c4bb start 0.30.3 2020-11-11 10:14:10 +06:00
d776071cac Update build.gradle 2020-11-11 01:32:25 +06:00
5f33d05deb Update extensions utils dependencies 2020-11-11 01:31:28 +06:00
912cc7217c Update extensions api dependencies 2020-11-11 01:30:31 +06:00
96e00f6e31 Merge pull request #207 from InsanusMokrassar/0.30.2
0.30.2
2020-11-10 21:52:37 +06:00
273 changed files with 7934 additions and 2281 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"

View File

@@ -0,0 +1,22 @@
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 and publish
run: ./gradlew clean build publishAllPublicationsToGithubPackagesRepository -x signJsPublication -x signJvmPublication -x signKotlinMultiplatformPublication -x signMetadataPublication
env:
GITHUBPACKAGES_USER: ${{ github.actor }}
GITHUBPACKAGES_PASSWORD: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,5 +1,316 @@
# TelegramBotAPI changelog # TelegramBotAPI changelog
## 0.32.10
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.28` -> `0.4.29`
* `Core`:
* `AdministratorChatMemberSerializer` and `ChatMemberSerializer` has changed their visibility: they are public for now
* `Behaviour Builder`:
* Now content triggers and expectators will wait for channel posts too
## 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`:
* Fix of [#275](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/275)
## 0.32.1
* `Core`:
* Fix of [#272](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/272)
* `Utils`:
* Fix of [#273](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/273)
## 0.32.0
**THIS UPDATE CONTAINS BREAKING CHANGES**
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.16` -> `0.4.23`
* `Klock`: `0.2.3` -> `0.2.4`
* `Ktor`: `1.5.0` -> `1.5.1`
* `Core`:
* **BREAKING CHANGE** Now `MediaGroupMessage` have a generic type related to `MediaGroupContent`
* Methods and types related to `MediaGroupMessage` have been modified according to their meanings
* **Important Change** `FlowsUpdatesFilter` now is an interface. Old class has been renamed to
`DefaultFlowsUpdatesFilter` and factory method `FlowsUpdatesFilter` has been added
* **PASSPORT** Full support of `Telegram Passport API`
* `PassportData`
* All variants of `EncryptedPassportElement`
* All variants of `SecureValue`
* All variants of `PassportElementError`
* New request `SetPassportDataErrors`
* `Credentials`:
* `EncryptedCredentials`
* `DeryptedCredentials`
* `EndDataCredentials`
* `Behaviour Builder`:
* Trigger and expectation extensions for `MessageContent` (`onContentMessage` and `waitContentMessage`)
* `onMediaGroup` has been replaced
* `waitMediaGroup` has been added
* `onVisualMediaGroup` now is just an alternative to `onVisualGallery`
* `command` and `onCommand` expectations has been added for commands `String` variant
* New extensions `BehaviourContext#oneOf`, `BehaviourContext#parallel` and `Deferred<T>#withAction`
* Several renames:
* `waitAudioMediaGroup` -> `waitAudioMediaGroupContent`
* `waitDocumentMediaGroup` -> `waitDocumentMediaGroupContent`
* `waitMediaGroup` -> `waitAnyMediaGroupContent`
* `waitVisualMediaGroup` -> `waitVisualMediaGroupContent`
* New extensions `BehaviourContext#waitPassportMessagesWith` and `BehaviourContext#waitAnyPassportMessages`
* New extensions `BehaviourContext#onPassportMessage` and `BehaviourContext#onPassportMessageWith`
* `Utils`:
* New `ClassCasts` for
* `Message`
* **PASSPORT** `EncryptedPassportElement`
* **PASSPORT** `PassportElementError`
* **PASSPORT** `SecureValue`
* Several tools for decryption have been added:
* `AESDecryptor` is available for `JVM` platform
* Extensions `EncryptedCredentials#decryptWithPKCS8PrivateKey` are available for `JVM`
platform
* Extensions `EndDataCredentials#decryptData` and `FileCredentials#decryptFile` have been added
* Several extensions `createDecryptor`
* Several extensions `doInDecryptionContextWithPKCS8Key`
* New extension `Flow#passportMessages`
* In most of webhook setting up functions/methods now available parameter `mediaGroupsDebounceTimeMillis`
* `API`:
* **PASSPORT** New extensions `TelegramBot#setPassportDataErrors`
## 0.31.0
**THIS UPDATE CONTAINS BREAKING CHANGES**
* `Common`:
* **ALL DEPRECATIONS CREATED SINCE 0.30.0 WERE REMOVED**
* `Behaviour Builder`:
* Extension `TelegramBot#buildBehaviour` have changed its return value: now it is `Job` instead of
`FlowsUpdatesFilter`
* `Utils`
* New extensions `TelegramBot#longPolling` were added as new recommended way to start getting updates via long
polling
* Old extensions `RequestsExecutor#startGettingFlowsUpdatesByLongPolling` has been deprecated
## 0.30.13
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.15` -> `0.4.16`
* `Core`:
* New variable `FlowsUpdatesFilter#allUpdatesWithoutMediaGroupsGroupingFlow` which will contains updates without
`SentMediaGroupUpdate`
* `Utils`:
* Extensions for `ResendableContent` has been added
* Extensions for `TextSource` has been added
* `Behaviour Builder`:
* Project has been created :)
## 0.30.12
* `Utils`:
* Class casts has been added. Now you can write something like `message.asGroupMessage() ?.let { ... }` instead of
`(message as? GroupMessage<*>) ?.let { ... }`
## 0.30.11
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.11` -> `0.4.15`
* `Klock`: `2.0.1` -> `2.0.3`
* `Ktor`: `1.4.3` -> `1.5.0`
* `Core`:
* All bot actions got functions for short calling, like `recordVideo` for `RecordVideoNote`
* All bot actions got class-cast shortcuts
## 0.30.10
* `Common`:
* `Version`:
* `Kotlin`: `1.4.20` -> `1.4.21`
* `Klock`: `2.0.0` -> `2.0.1`
* `Ktor`: `1.4.2` -> `1.4.3`
* `MicroUtils`: `0.4.6` -> `0.4.11`
* `API Extensions`:
* New function `buildBot`
## 0.30.9
* `Common`:
* `Version`:
* `UUID`: `0.2.2` -> `0.2.3`
* `Coroutines`: `1.4.1` -> `1.4.2`
* `MicroUtils`: `0.4.3` -> `0.4.6`
* `Core`:
* Add `BowlingDiceAnimationType`
## 0.30.8
* `Common`:
* `Version`:
* `Kotlin`: `1.4.10` -> `1.4.20`
* `Klock`: `1.12.1` -> `2.0.0`
* `MicroUtils`: `0.4.1` -> `0.4.3`
## 0.30.7
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.0` -> `0.4.1`
* `Core`:
* `TelegramAPIUrlsKeeper` will fix ending of host url since this version
* New mechanisms in`PowLimiter` and `CommonLimiter` has been added
* New builder `KtorRequestsExecutorBuilder`
* New function `telegramBot`
* `Utils`:
* Simple function `telegramBot(TelegramAPIUrlsKeeper)` has been deprecated with replacement by almost the same
function in `Core`
## 0.30.6
* `Core`
* `TextSource` properties has been renamed:
* `asMarkdownSource` -> `markdown`
* `asMarkdownV2Source` -> `markdownV2`
* `asHtmlSource` -> `html`
* `PrivateChat` override `id` property with type `UserId`
* Several new extensions and functions in links creation:
* New function `makeUsernameLink` with parameter `String`
* New extension `Username#link` and function `makeLink(Username)`
* Function `makeLinkToMessage` now able to get any type of chat
* New extension `Message#link`
* Old functions `makeLinkToAddStickerSet...` has been deprecated:
* `makeLinkToAddStickerSet`
* `makeLinkToAddStickerSetInMarkdownV2`
* `makeLinkToAddStickerSetInMarkdown`
* `makeLinkToAddStickerSetInHtml`
## 0.30.5
* `Common`:
* `Version`:
* `MicroUtils`: `0.3.3` -> `0.4.0`
* `Core`:
* Mechanism of `ChatMember` serialization has been changed
* Since this version any `ChatMember` can be serialized (even outside in case it marked by `@Serializable`)
* Since this version any `ChatMember` (included in this project) can be deserialized in common way
* `User` property `id` has changed its type: now it is `UserId` (under the hood it is the same as `ChatId`)
## 0.30.4
* `Common`:
* `Version`:
* `MicroUtils`: `0.3.1` -> `0.3.3`
* `Core`:
* `MultilevelTextSource#textSources` has been safely renamed to `subsources`
* `TextContent#fullEntitiesList` has been deprecated
* Now `TextContent` implements `TextedInput`
* `TextContent#entities` has been deprecated
* `GroupEventMessage` now overrides `chatEvent` with type `GroupEvent`
* `SupergroupEventMessage` now overrides `chatEvent` with type `SupergroupEvent`
* Any `ChatEventMessage` now have generic type of its `chatEvent` (just like messages)
* `Utils`:
* Old extensions related to chat events are deprecated:
* `Flow<ChatEventMessage<*>>#divideBySource`
* `Flow<ChatEventMessage<*>>#onlyChannelEvents`
* `Flow<ChatEventMessage<*>>#onlyGroupEvents`
* `Flow<ChatEventMessage<*>>#onlySupergroupEvents`
* A lot of extensions for `Flow<ChatEventMessage>` has been added:
* `FlowsUpdatesFilter#events`
* `FlowsUpdatesFilter#channelEvents`
* `FlowsUpdatesFilter#groupEvents`
* `FlowsUpdatesFilter#supergroupEvents`
* And a lot of other filters with specific types
## 0.30.3
* `Common`:
* `Version`:
* `MicroUtils`: `0.3.0` -> `0.3.1`
* `Core`:
* New type of requests exceptions `TooMuchRequestsException`. In fact it will be rare case when you will get this
exception
* `EmptyLimiter` has been renamed to `ExceptionsOnlyLimiter` and currently will stop requests after
`TooMuchRequestsException` happen until retry time is actual
* Now `ExceptionsOnlyLimiter` (previously `EmptyLimiter`) is a class
* `AbstractRequestCallFactory` currently will not look at the response and wait if it have `RetryAfter` error. New
behaviour aimed on delegating of this work to `RequestsLimiter`
## 0.30.2 ## 0.30.2
* `Common`: * `Common`:

209
README.md
View File

@@ -1,137 +1,118 @@
[Participate in our common survey ☺](https://forms.gle/q6Xf8K3fD1pPsYUw9)
# TelegramBotAPI # TelegramBotAPI
| 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)| Hello! This is a set of libraries for working with Telegram Bot API.
| 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) | | 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 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 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 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 | [![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 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 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 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 ## Examples
[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`**
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 * Add `mavenCentral()` to your project repositories
the list of this complex currently next projects: * [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 More including instructions [available here](https://github.com/InsanusMokrassar/TelegramBotAPI/wiki/Including-in-your-project).
without any additional library Other configuration examples:
* [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](tgbotapi/README.md) - concentration of all previously mentioned libraries
Most part of some specific solves or unuseful * [For multiplatform](https://github.com/InsanusMokrassar/TelegramBotAPI-examples/tree/master/ResenderBot)
moments are describing by official [Telegram Bot API](https://core.telegram.org/bots/api). * [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)): bot.buildBehaviour {
println(getMe())
<details>
<summary>Gradle build script help (for versions before 0.28.0)</summary> onCommand("start") {
reply(it, "Hi:)")
```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")
}
}
}
} }
}.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 val flowsUpdatesFilter = FlowsUpdatesFilter()
all necessary tools for comfort usage of this library. If you want to exclude some libraries, you can implement just bot.buildBehaviour(flowUpdatesFilter = flowsUpdatesFilter) {
[TelegramBotAPI API Extensions](tgbotapi.extensions.api/README.md), println(getMe())
[TelegramBotAPI Util Extensions](tgbotapi.extensions.utils/README.md) or even
[TelegramBotAPI Core](tgbotapi.core/README.md). 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 retrieveAccumulatedUpdates(this).join()
[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()
} }
``` ```
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

@@ -1,5 +1,5 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<minder version="1.11.1"> <minder version="1.11.3">
<theme name="default" label="Default" index="-1"/> <theme name="default" label="Default" index="-1"/>
<styles> <styles>
<style level="0" isset="true" branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/> <style level="0" isset="true" branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
@@ -14,45 +14,54 @@
<style level="9" isset="true" branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/> <style level="9" isset="true" branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
<style level="10" isset="true" branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/> <style level="10" isset="true" branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="200" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true" connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
</styles> </styles>
<drawarea x="-320.56697591145837" y="-10.028254191080691" scale="0.75"/> <drawarea x="-950.47548925255796" y="-49.650554065281653" scale="0.5"/>
<images/> <images/>
<nodes> <nodes>
<node id="0" posx="748.88964843749955" posy="119.42341613769531" width="472" height="168" side="top" fold="false" treesize="603" layout="Downwards" group="false"> <node id="0" posx="1378.798161778599" posy="159.04571601189673" width="472" height="168" side="top" fold="false" treesize="743" layout="Downwards" group="false">
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="439" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/> <style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="439" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
<nodename posx="764.88964843749955" posy="135.42341613769531" maxwidth="488.96484375"> <nodename posx="1394.798161778599" posy="175.04571601189673" maxwidth="488.96484375">
<text data="tgbotapi.core&#10;&#10;Root project with API. It is not recommended to use its requests directly and better to use at least tgbotapi.extensions.api"/> <text data="tgbotapi.core&#10;&#10;Root project with API. It is not recommended to use its requests directly and better to use at least tgbotapi.extensions.api"/>
</nodename> </nodename>
<nodenote></nodenote> <nodenote></nodenote>
<nodes> <nodes>
<node id="1" posx="781.88964843749955" posy="387.42341613769531" width="406" height="145" side="bottom" fold="false" treesize="603" color="#68b723" colorroot="true" layout="Downwards" group="false"> <node id="1" posx="1411.798161778599" posy="427.04571601189673" width="406" height="145" side="bottom" fold="false" treesize="743" color="#68b723" colorroot="true" layout="Downwards" group="false">
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="none" nodewidth="394" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/> <style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="none" nodewidth="394" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
<nodename posx="797.88964843749955" posy="403.42341613769531" maxwidth="419.451171875"> <nodename posx="1427.798161778599" posy="443.04571601189673" maxwidth="419.451171875">
<text data="TelegramBotAPI extensions&#10;&#10;Family of projects which are fully based on TelegramBotAPI and extend its functionality"/> <text data="TelegramBotAPI extensions&#10;&#10;Family of projects which are fully based on TelegramBotAPI and extend its functionality"/>
</nodename> </nodename>
<nodenote></nodenote> <nodenote></nodenote>
<nodes> <nodes>
<node id="2" posx="683.38964843749955" posy="632.42341613769531" width="296" height="191" side="bottom" fold="false" treesize="296" color="#68b723" colorroot="true" layout="Downwards" group="false"> <node id="2" posx="1247.298161778599" posy="672.04571601189673" width="296" height="191" side="bottom" fold="false" treesize="296" color="#68b723" colorroot="true" layout="Downwards" group="false">
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="203" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/> <style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="203" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
<nodename posx="699.38964843749955" posy="648.42341613769531" maxwidth="295.90315755208337"> <nodename posx="1263.298161778599" posy="688.04571601189673" maxwidth="295.90315755208337">
<text data="tgbotapi.extensions.api&#10;&#10;Extensions project for make requests more look like in the Telegram Bot API and give opportunity to use it's easier"/> <text data="tgbotapi.extensions.api&#10;&#10;Extensions project for make requests more look like in the Telegram Bot API and give opportunity to use it's easier"/>
</nodename> </nodename>
<nodenote></nodenote> <nodenote></nodenote>
</node> </node>
<node id="3" posx="979.38964843749955" posy="632.42341613769531" width="307" height="168" side="bottom" fold="false" treesize="307" color="#68b723" colorroot="true" layout="Downwards" group="false"> <node id="3" posx="1609.298161778599" posy="672.04571601189673" width="307" height="168" side="bottom" fold="false" treesize="439" color="#68b723" colorroot="true" layout="Downwards" group="false">
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="286" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/> <style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="286" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
<nodename posx="995.38964843749955" posy="648.42341613769531" maxwidth="299.252197265625"> <nodename posx="1625.298161778599" posy="688.04571601189673" maxwidth="299.252197265625">
<text data="tgbotapi.extensions.utils&#10;&#10;Extensions project with utils things which will make easier different operations"/> <text data="tgbotapi.extensions.utils&#10;&#10;Extensions project with utils things which will make easier different operations"/>
</nodename> </nodename>
<nodenote></nodenote> <nodenote></nodenote>
<nodes>
<node id="4" posx="1543.298161778599" posy="940.04571601189673" width="439" height="122" side="bottom" fold="false" treesize="439" color="#68b723" colorroot="false" layout="Downwards" group="false">
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="387" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
<nodename posx="1559.298161778599" posy="956.04571601189673" maxwidth="408.97932942708348">
<text data="tgbotapi.extensions.behaviour_builder&#10;&#10;Extension project for building bot behaviour via special dsl"/>
</nodename>
<nodenote></nodenote>
</node>
</nodes>
</node> </node>
</nodes> </nodes>
</node> </node>
</nodes> </nodes>
</node> </node>
<node id="4" posx="815.52319335937455" posy="948.04447937011719" width="329" height="213" side="top" fold="false" treesize="329" layout="Downwards" group="false"> <node id="5" posx="1391.8445078072455" posy="1155.6062730594231" width="461" height="236" side="bottom" fold="false" treesize="461" layout="Downwards" group="false">
<style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="388" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/> <style branchmargin="100" linktype="curved" linkwidth="5" linkarrow="true" linkdash="solid" nodeborder="bracket" nodewidth="430" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
<nodename posx="831.52319335937455" posy="964.04447937011719" maxwidth="394.3671875"> <nodename posx="1407.8445078072455" posy="1171.6062730594231" maxwidth="453.885498046875">
<text data="tgbotapi&#10;&#10;Here included all available TelegramBotAPI libraries:&#13;&#10;&#13;&#10;* tgbotapi.core&#13;&#10;* tgbotapi.extensions.api&#13;&#10;* tgbotapi.extensions.utils"> <text data="tgbotapi&#10;&#10;Here included all available TelegramBotAPI libraries:&#13;&#10;&#13;&#10;* tgbotapi.core&#13;&#10;* tgbotapi.extensions.api&#13;&#10;* tgbotapi.extensions.utils&#10;* tgbotapi.extensions.behaviour_builder">
<color> <color>
<range start="67" end="68" extra="rgb(255,0,0)"/> <range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/> <range start="67" end="68" extra="rgb(255,0,0)"/>
@@ -70,6 +79,94 @@
<range start="67" end="68" extra="rgb(255,0,0)"/> <range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/> <range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/> <range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="67" end="68" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/> <range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/> <range start="84" end="85" extra="rgb(255,0,0)"/>
<range start="84" end="85" extra="rgb(255,0,0)"/> <range start="84" end="85" extra="rgb(255,0,0)"/>
@@ -102,6 +199,90 @@
<range start="111" end="112" extra="rgb(255,0,0)"/> <range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/> <range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/> <range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="111" end="112" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
<range start="139" end="140" extra="rgb(255,0,0)"/>
</color> </color>
</text> </text>
</nodename> </nodename>
@@ -110,12 +291,17 @@
</nodes> </nodes>
<groups/> <groups/>
<connections> <connections>
<connection from_id="2" to_id="4" drag_x="905.70642089843705" drag_y="891.23394775390625" color="#777777"> <connection from_id="2" to_id="5" drag_x="1475.8213347929195" drag_y="1014.8259945356604" color="#777777">
<style connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/> <style connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
<title></title> <title></title>
<note></note> <note></note>
</connection> </connection>
<connection from_id="3" to_id="4" drag_x="1056.456420898437" drag_y="885.48394775390625" color="#777777"> <connection from_id="4" to_id="5" drag_x="1691.5447998046875" drag_y="1107.00439453125" color="#777777">
<style connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
<title></title>
<note></note>
</connection>
<connection from_id="3" to_id="5" drag_x="1483.48876953125" drag_y="896.18115234375">
<style connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/> <style connectiondash="dotted" connectionlwidth="2" connectionarrow="fromto" connectionpadding="3" connectionfont="Sans 10" connectiontwidth="100"/>
<title></title> <title></title>
<note></note> <note></note>

View File

@@ -9,7 +9,6 @@ buildscript {
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
classpath "com.github.breadmoirai:github-release:$github_release_plugin_version" classpath "com.github.breadmoirai:github-release:$github_release_plugin_version"
} }
} }

View File

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

View File

@@ -5,19 +5,18 @@ kotlin.js.generate.externals=true
kotlin.incremental=true kotlin.incremental=true
kotlin.incremental.js=true kotlin.incremental.js=true
kotlin_version=1.4.10 kotlin_version=1.4.31
kotlin_coroutines_version=1.4.1 kotlin_coroutines_version=1.4.3
kotlin_serialisation_runtime_version=1.0.1 kotlin_serialisation_runtime_version=1.1.0
klock_version=1.12.1 klock_version=2.0.6
uuid_version=0.2.2 uuid_version=0.2.3
ktor_version=1.4.2 ktor_version=1.5.2
micro_utils_version=0.3.0 micro_utils_version=0.4.29
javax_activation_version=1.1.1 javax_activation_version=1.1.1
library_group=dev.inmo library_group=dev.inmo
library_version=0.30.2 library_version=0.32.10
gradle_bintray_plugin_version=1.8.5
github_release_plugin_version=2.2.12 github_release_plugin_version=2.2.12

View File

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

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 89 KiB

View File

@@ -8,5 +8,6 @@ pluginManagement {
include ":tgbotapi.core" include ":tgbotapi.core"
include ":tgbotapi.extensions.api" include ":tgbotapi.extensions.api"
include ":tgbotapi.extensions.utils" include ":tgbotapi.extensions.utils"
include ":tgbotapi.extensions.behaviour_builder"
include ":tgbotapi" include ":tgbotapi"
include ":docs" include ":docs"

View File

@@ -11,9 +11,6 @@ moments are describing by official [Telegram Bot API](https://core.telegram.org/
## Compatibility ## 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 [4th of November 2020 update of TelegramBotAPI (version 5.0)](https://core.telegram.org/bots/api#november-4-2020).
There is only one exception of implemented functionality - Telegram Passport API, which was presented in
[August 2018 update of TelegramBotAPI](https://core.telegram.org/bots/api-changelog#august-27-2018) update. It will be implemented
as soon as possible.
## How to implement library? ## How to implement library?
@@ -149,3 +146,18 @@ Here was used `okhttp` realisation of client, but there are several others engin
available on ktor.io site for [client](https://ktor.io/clients/http-client/engines.html) and [server](https://ktor.io/quickstart/artifacts.html) available on ktor.io site for [client](https://ktor.io/clients/http-client/engines.html) and [server](https://ktor.io/quickstart/artifacts.html)
engines. engines.
### Passport
In case you wish to work with `Telegram Passport`, currently there are several useful things, but most part of working
with decryption and handling is available only on JVM. Next snippet contains example of data decryption on JVM platform:
```kotlin
passportMessage.passportData.doInDecryptionContextWithPKCS8Key(privateKey) {
val passportDataSecureValue = passport ?.data ?: return@doInDecryptionContextWithPKCS8Key
val passportData = (passportMessage.passportData.data.firstOrNull { it is CommonPassport } ?: return@doInDecryptionContextWithPKCS8Key) as CommonPassport
val decrypted = passportDataSecureValue.decrypt(
passportData.data
) ?.decodeToString() ?: return@doInDecryptionContextWithPKCS8Key
println(decrypted)
}
```

View File

@@ -8,7 +8,6 @@ buildscript {
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
} }
} }
@@ -30,7 +29,9 @@ repositories {
} }
kotlin { kotlin {
jvm() jvm {
compilations.main.kotlinOptions.useIR = true
}
js(BOTH) { js(BOTH) {
browser() browser()
nodejs() nodejs()
@@ -47,7 +48,10 @@ kotlin {
api "com.soywiz.korlibs.klock:klock:$klock_version" api "com.soywiz.korlibs.klock:klock:$klock_version"
api "com.benasher44:uuid:$uuid_version" api "com.benasher44:uuid:$uuid_version"
api "dev.inmo:micro_utils.crypto:$micro_utils_version"
api "dev.inmo:micro_utils.coroutines:$micro_utils_version" api "dev.inmo:micro_utils.coroutines:$micro_utils_version"
api "dev.inmo:micro_utils.serialization.base64:$micro_utils_version"
api "dev.inmo:micro_utils.serialization.encapsulator:$micro_utils_version"
api "io.ktor:ktor-client-core:$ktor_version" api "io.ktor:ktor-client-core:$ktor_version"
} }
@@ -56,6 +60,7 @@ kotlin {
dependencies { dependencies {
implementation kotlin('test-common') implementation kotlin('test-common')
implementation kotlin('test-annotations-common') implementation kotlin('test-annotations-common')
implementation project(":tgbotapi.extensions.utils")
} }
} }
@@ -74,7 +79,6 @@ kotlin {
implementation kotlin('test-junit') implementation kotlin('test-junit')
} }
} }
jsTest { jsTest {
dependencies { dependencies {
implementation kotlin('test-junit') implementation kotlin('test-junit')

View File

@@ -1,53 +0,0 @@
apply plugin: 'maven-publish'
task javadocsJar(type: Jar) {
classifier = 'javadoc'
}
afterEvaluate {
project.publishing.publications.all {
// rename artifacts
groupId "${project.group}"
if (it.name.contains('kotlinMultiplatform')) {
artifactId = "${project.name}"
} else {
artifactId = "${project.name}-$name"
}
}
}
publishing {
publications.all {
artifact javadocsJar
pom {
description = "Library for Object-Oriented and type-safe work with Telegram Bot API"
name = "Telegram Bot API Core"
url = "https://insanusmokrassar.github.io/TelegramBotAPI"
scm {
developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
}
developers {
developer {
id = "InsanusMokrassar"
name = "Ovsiannikov Aleksei"
email = "ovsyannikov.alexey95@gmail.com"
}
}
licenses {
license {
name = "Apache Software License 2.0"
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
}
}
}
}

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","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

@@ -1,59 +1,69 @@
apply plugin: 'com.jfrog.bintray' apply plugin: 'maven-publish'
apply plugin: 'signing'
apply from: "maven.publish.gradle" task javadocsJar(type: Jar) {
classifier = 'javadoc'
}
bintray { publishing {
user = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER') publications.all {
key = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY') artifact javadocsJar
filesSpec {
from "${buildDir}/publications/" pom {
eachFile { description = "Library for Object-Oriented and type-safe work with Telegram Bot API"
String directorySubname = it.getFile().parentFile.name name = "Telegram Bot API Core"
if (it.getName() == "module.json") { url = "https://insanusmokrassar.github.io/TelegramBotAPI"
if (directorySubname == "kotlinMultiplatform") {
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module") scm {
} else { developerConnection = "scm:git:[fetch=]https://github.com/insanusmokrassar/TelegramBotAPI.git[push=]https://github.com/insanusmokrassar/TelegramBotAPI.git"
it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module") url = "https://github.com/insanusmokrassar/TelegramBotAPI.git"
} }
} else {
if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") { developers {
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom")
} else { developer {
it.exclude() id = "InsanusMokrassar"
} name = "Ovsiannikov Aleksei"
email = "ovsyannikov.alexey95@gmail.com"
}
}
licenses {
license {
name = "Apache Software License 2.0"
url = "https://github.com/InsanusMokrassar/TelegramBotAPI/blob/master/LICENSE"
}
} }
} }
into "${project.group}".replace(".", "/") repositories {
} if ((project.hasProperty('GITHUBPACKAGES_USER') || System.getenv('GITHUBPACKAGES_USER') != null) && (project.hasProperty('GITHUBPACKAGES_PASSWORD') || System.getenv('GITHUBPACKAGES_PASSWORD') != null)) {
maven {
publish = true name = "GithubPackages"
override = true url = uri("https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI")
credentials {
pkg { username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
repo = "TelegramBotAPI" password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
name = "${project.name}" }
vcsUrl = "https://github.com/InsanusMokrassar/TelegramBotAPI" }
licenses = ["Apache-2.0"] }
version { if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
name = "${project.version}" maven {
released = new Date() name = "sonatype"
vcsTag = "${project.version}" url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
gpg { credentials {
sign = true username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
passphrase = project.hasProperty('signing.gnupg.passphrase') ? project.property('signing.gnupg.passphrase') : System.getenv('signing.gnupg.passphrase') password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
} }
} }
} }
} }
bintrayUpload.doFirst { signing {
publications = publishing.publications.collect { useGpgCmd()
if (it.name.contains('kotlinMultiplatform')) { sign publishing.publications
null
} else {
it.name
}
} - null
} }
bintrayUpload.dependsOn publishToMavenLocal

View File

@@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.CommonAbstracts package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.utils.internal.fullListOfSubSource
interface Captioned { interface Captioned {
val caption: String? val caption: String?
@@ -13,8 +12,7 @@ interface CaptionedOutput : Captioned {
interface CaptionedInput : Captioned { interface CaptionedInput : Captioned {
/** /**
* Not full list of entities. This list WILL NOT contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource] * Full list of entities. This list WILL contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
* @see [CaptionedInput.fullEntitiesList]
*/ */
val captionEntities: List<TextPart> val captionEntities: List<TextPart>
} }
@@ -25,10 +23,3 @@ interface CaptionedInput : Captioned {
*/ */
val CaptionedInput.textSources val CaptionedInput.textSources
get() = captionEntities.justTextSources() get() = captionEntities.justTextSources()
/**
* Convert its [CaptionedInput.captionEntities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
@Deprecated("Currently list of entities already full. This method is redundant")
fun CaptionedInput.fullEntitiesList(): TextSourcesList = caption ?.fullListOfSubSource(captionEntities) ?.map { it.source } ?: emptyList()

View File

@@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.CommonAbstracts package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.utils.internal.fullListOfSubSource
interface Explained { interface Explained {
val explanation: String? val explanation: String?
@@ -19,8 +18,7 @@ interface ExplainedOutput : ParsableExplainedOutput, EntitiesExplainedOutput
interface ExplainedInput : Explained { interface ExplainedInput : Explained {
/** /**
* Not full list of entities. This list WILL NOT contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource] * Full list of entities. This list WILL contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
* @see [ExplainedInput.fullEntitiesList]
*/ */
val explanationEntities: List<TextPart> val explanationEntities: List<TextPart>
} }
@@ -31,10 +29,3 @@ interface ExplainedInput : Explained {
*/ */
val ExplainedInput.textSources val ExplainedInput.textSources
get() = explanationEntities.justTextSources() get() = explanationEntities.justTextSources()
/**
* Convert its [ExplainedInput.explanationEntities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
@Deprecated("Currently list of entities already full. This method is redundant")
fun ExplainedInput.fullEntitiesList(): TextSourcesList = explanation ?.fullListOfSubSource(explanationEntities) ?.map { it.source } ?: emptyList()

View File

@@ -8,15 +8,11 @@ import dev.inmo.tgbotapi.types.textLength
const val DirectInvocationOfTextSourceConstructor = "It is strongly not recommended to use constructors directly instead of factory methods" const val DirectInvocationOfTextSourceConstructor = "It is strongly not recommended to use constructors directly instead of factory methods"
typealias TextSourcesList = List<TextSource> typealias TextSourcesList = List<TextSource>
@Deprecated("All lists of TextSource in public API now are full. So, this typealias is redundant")
typealias FullTextSourcesList = List<TextSource>
@Deprecated("All lists of TextPart in public API now are full. So, this typealias is redundant")
typealias FullTextPartsList = List<TextPart>
interface TextSource { interface TextSource {
val asMarkdownSource: String val markdown: String
val asMarkdownV2Source: String val markdownV2: String
val asHtmlSource: String val html: String
val source: String val source: String
val asText: String val asText: String
@@ -33,10 +29,7 @@ inline operator fun TextSource.plus(text: String) = listOf(this, regular(text))
inline operator fun List<TextSource>.plus(text: String) = this + regular(text) inline operator fun List<TextSource>.plus(text: String) = this + regular(text)
interface MultilevelTextSource : TextSource { interface MultilevelTextSource : TextSource {
@Deprecated("Will be removed in near major release") val subsources: List<TextSource>
val textParts: List<TextPart>
get() = textParts(0)
val textSources: List<TextSource>
} }
data class TextPart( data class TextPart(
@@ -46,7 +39,7 @@ data class TextPart(
fun List<TextPart>.justTextSources() = map { it.source } fun List<TextPart>.justTextSources() = map { it.source }
fun List<TextSource>.makeString() = joinToString("") { it.source } fun List<TextSource>.makeString() = joinToString("") { it.source }
internal fun MultilevelTextSource.textParts(offset: Int): List<TextPart> = textSources.toTextParts(offset) internal fun MultilevelTextSource.textParts(offset: Int): List<TextPart> = subsources.toTextParts(offset)
fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> { fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null): List<List<TextSource>> {
if (isEmpty()) { if (isEmpty()) {
return emptyList() return emptyList()

View File

@@ -1,7 +1,6 @@
package dev.inmo.tgbotapi.CommonAbstracts package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.utils.internal.fullListOfSubSource
interface Texted { interface Texted {
val text: String? val text: String?
@@ -19,22 +18,18 @@ interface TextedOutput : ParsableOutput, EntitiesOutput
interface TextedInput : Texted { interface TextedInput : Texted {
/** /**
* Not full list of entities. This list WILL NOT contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource] * Here must be full list of entities. This list must contains [TextPart]s with
* @see [CaptionedInput.fullEntitiesList] * [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource] in case if source text contains parts of
* regular text
*/ */
val textEntities: List<TextPart> val textEntities: List<TextPart>
} }
/** /**
* Full list of [TextSource] built from source[TextedInput.textEntities]
*
* @see TextedInput.textEntities * @see TextedInput.textEntities
* @see justTextSources * @see justTextSources
*/ */
val TextedInput.textSources val TextedInput.textSources
get() = textEntities.justTextSources() get() = textEntities.justTextSources()
/**
* Convert its [TextedInput.textEntities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
@Deprecated("Currently list of entities already full. This method is redundant")
fun TextedInput.fullEntitiesList(): TextSourcesList = text ?.fullListOfSubSource(textEntities) ?.map { it.source } ?: emptyList()

View File

@@ -3,8 +3,9 @@ package dev.inmo.tgbotapi.bot.Ktor
import dev.inmo.micro_utils.coroutines.safely import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
import dev.inmo.tgbotapi.bot.Ktor.base.* import dev.inmo.tgbotapi.bot.Ktor.base.*
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.bot.exceptions.newRequestException import dev.inmo.tgbotapi.bot.exceptions.newRequestException
import dev.inmo.tgbotapi.bot.settings.limiters.EmptyLimiter import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.Response import dev.inmo.tgbotapi.types.Response
@@ -14,12 +15,39 @@ import io.ktor.client.features.*
import io.ktor.client.statement.readText import io.ktor.client.statement.readText
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
class KtorRequestsExecutorBuilder(
var telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper
) {
var client: HttpClient = HttpClient()
var callsFactories: List<KtorCallFactory> = emptyList()
var excludeDefaultFactories: Boolean = false
var requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter()
var jsonFormatter: Json = nonstrictJsonFormat
fun build() = KtorRequestsExecutor(telegramAPIUrlsKeeper, client, callsFactories, excludeDefaultFactories, requestsLimiter, jsonFormatter)
}
inline fun telegramBot(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
crossinline builder: KtorRequestsExecutorBuilder.() -> Unit = {}
): TelegramBot = KtorRequestsExecutorBuilder(telegramAPIUrlsKeeper).apply(builder).build()
/**
* Shortcut for [telegramBot]
*/
@Suppress("NOTHING_TO_INLINE")
inline fun telegramBot(
token: String,
apiUrl: String = telegramBotAPIDefaultUrl,
crossinline builder: KtorRequestsExecutorBuilder.() -> Unit = {}
): TelegramBot = telegramBot(TelegramAPIUrlsKeeper(token, apiUrl), builder)
class KtorRequestsExecutor( class KtorRequestsExecutor(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper, telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
client: HttpClient = HttpClient(), client: HttpClient = HttpClient(),
callsFactories: List<KtorCallFactory> = emptyList(), callsFactories: List<KtorCallFactory> = emptyList(),
excludeDefaultFactories: Boolean = false, excludeDefaultFactories: Boolean = false,
private val requestsLimiter: RequestLimiter = EmptyLimiter, private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter(),
private val jsonFormatter: Json = nonstrictJsonFormat private val jsonFormatter: Json = nonstrictJsonFormat
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) { ) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
private val callsFactories: List<KtorCallFactory> = callsFactories.run { private val callsFactories: List<KtorCallFactory> = callsFactories.run {
@@ -40,7 +68,7 @@ class KtorRequestsExecutor(
return safely( return safely(
{ e -> { e ->
throw if (e is ClientRequestException) { throw if (e is ClientRequestException) {
val content = e.response ?.readText() ?: throw e val content = e.response.readText()
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
newRequestException( newRequestException(
responseObject, responseObject,

View File

@@ -1,11 +1,11 @@
package dev.inmo.tgbotapi.bot.Ktor.base package dev.inmo.tgbotapi.bot.Ktor.base
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
import dev.inmo.tgbotapi.bot.exceptions.newRequestException import dev.inmo.tgbotapi.bot.exceptions.newRequestException
import dev.inmo.tgbotapi.requests.GetUpdates import dev.inmo.tgbotapi.requests.GetUpdates
import dev.inmo.tgbotapi.requests.abstracts.Request import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.Response import dev.inmo.tgbotapi.types.Response
import dev.inmo.tgbotapi.types.RetryAfterError
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.receive import io.ktor.client.call.receive
@@ -13,10 +13,11 @@ import io.ktor.client.features.timeout
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.client.statement.HttpResponse import io.ktor.client.statement.HttpResponse
import io.ktor.http.ContentType import io.ktor.http.ContentType
import kotlinx.coroutines.delay
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlin.collections.set import kotlin.collections.set
var defaultUpdateTimeoutForZeroDelay = 1000L
abstract class AbstractRequestCallFactory : KtorCallFactory { abstract class AbstractRequestCallFactory : KtorCallFactory {
private val methodsCache: MutableMap<String, String> = mutableMapOf() private val methodsCache: MutableMap<String, String> = mutableMapOf()
override suspend fun <T : Any> makeCall( override suspend fun <T : Any> makeCall(
@@ -42,6 +43,11 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
requestTimeoutMillis = customTimeoutMillis requestTimeoutMillis = customTimeoutMillis
socketTimeoutMillis = customTimeoutMillis socketTimeoutMillis = customTimeoutMillis
} }
} else {
timeout {
requestTimeoutMillis = defaultUpdateTimeoutForZeroDelay
socketTimeoutMillis = defaultUpdateTimeoutForZeroDelay
}
} }
} }
} }
@@ -51,23 +57,17 @@ abstract class AbstractRequestCallFactory : KtorCallFactory {
val content = response.receive<String>() val content = response.receive<String>()
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content) val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
return (responseObject.result?.let { return safely {
jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it) (responseObject.result?.let {
} ?: responseObject.parameters?.let { jsonFormatter.decodeFromJsonElement(request.resultDeserializer, it)
val error = it.error } ?: response.let {
if (error is RetryAfterError) { throw newRequestException(
delay(error.leftToRetry) responseObject,
makeCall(client, urlsKeeper, request, jsonFormatter) content,
} else { "Can't get result object from $content"
null )
} })
} ?: response.let { }
throw newRequestException(
responseObject,
content,
"Can't get result object from $content"
)
})
} }
} }

View File

@@ -25,10 +25,9 @@ object MultipartRequestCallFactory : AbstractRequestCallFactory() {
Headers.build { Headers.build {
append(HttpHeaders.ContentType, value.mimeType) append(HttpHeaders.ContentType, value.mimeType)
append(HttpHeaders.ContentDisposition, "filename=${value.fileId}") append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
} },
) { block = value.file::input
value.file.asInput() )
}
is FileId -> append(key, value.fileId) is FileId -> append(key, value.fileId)
else -> append(key, value.toString()) else -> append(key, value.toString())
} }

View File

@@ -1,6 +1,8 @@
package dev.inmo.tgbotapi.bot.exceptions package dev.inmo.tgbotapi.bot.exceptions
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.types.Response import dev.inmo.tgbotapi.types.Response
import dev.inmo.tgbotapi.types.RetryAfterError
import io.ktor.utils.io.errors.IOException import io.ktor.utils.io.errors.IOException
fun newRequestException( fun newRequestException(
@@ -16,6 +18,13 @@ fun newRequestException(
description == "Unauthorized" -> UnauthorizedException(response, plainAnswer, message, cause) description == "Unauthorized" -> UnauthorizedException(response, plainAnswer, message, cause)
description.contains("PHOTO_INVALID_DIMENSIONS") -> InvalidPhotoDimensionsException(response, plainAnswer, message, cause) description.contains("PHOTO_INVALID_DIMENSIONS") -> InvalidPhotoDimensionsException(response, plainAnswer, message, cause)
description.contains("wrong file identifier") -> WrongFileIdentifierException(response, plainAnswer, message, cause) description.contains("wrong file identifier") -> WrongFileIdentifierException(response, plainAnswer, message, cause)
description.contains("Too Many Requests") -> TooMuchRequestsException(
(response.parameters ?.error as? RetryAfterError) ?: RetryAfterError(60, DateTime.now().unixMillisLong),
response,
plainAnswer,
message,
cause
)
else -> null else -> null
} }
} ?: CommonRequestException(response, plainAnswer, message, cause) } ?: CommonRequestException(response, plainAnswer, message, cause)
@@ -49,3 +58,6 @@ class InvalidPhotoDimensionsException(response: Response, plainAnswer: String, m
class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) : class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
RequestException(response, plainAnswer, message, cause) RequestException(response, plainAnswer, message, cause)
class TooMuchRequestsException(val retryAfter: RetryAfterError, response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
RequestException(response, plainAnswer, message, cause)

View File

@@ -1,67 +1,41 @@
package dev.inmo.tgbotapi.bot.settings.limiters package dev.inmo.tgbotapi.bot.settings.limiters
import com.soywiz.klock.DateTime import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.types.MilliSeconds
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.sync.Semaphore
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import kotlin.math.roundToLong
private fun now(): Long = DateTime.nowUnixLong() private fun now(): Long = DateTime.nowUnixLong()
@Serializable
class CommonLimiter( class CommonLimiter(
private val lockCount: Int = 10, private val lockCount: Int = 10,
private val regenTime: Long = 20 * 1000L // 20 seconds for full regen of opportunity to send message private val regenTime: MilliSeconds = 15 * 1000, // 15 seconds for full regen of opportunity to send message
@Transient
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
) : RequestLimiter { ) : RequestLimiter {
private var doLimit: Boolean = false @Transient
private val quotaSemaphore = Semaphore(lockCount)
private val counterChannel = Channel<Unit>(Channel.UNLIMITED) @Transient
private val scope = CoroutineScope(Dispatchers.Default) private val counterRegeneratorJob = scope.launch {
private val counterJob = scope.launch { val regenDelay: MilliSeconds = (regenTime.toDouble() / lockCount).roundToLong()
var wasLastSecond = 0 while (isActive) {
var lastCountTime = now() delay(regenDelay)
var limitManagementJob: Job? = null if (quotaSemaphore.availablePermits < lockCount) {
var removeLimitTime: Long = lastCountTime try {
for (counter in counterChannel) { quotaSemaphore.release()
val now = now() } catch (_: IllegalStateException) {
if (now - lastCountTime > 1000) { // Skip IllegalStateException due to the fact that this exception may happens in release method
lastCountTime = now
wasLastSecond = 1
} else {
wasLastSecond++
}
if (wasLastSecond >= lockCount) {
removeLimitTime = now + regenTime
if (limitManagementJob == null) {
limitManagementJob = launch {
doLimit = true
var internalNow = now()
while (internalNow < removeLimitTime) {
delay(removeLimitTime - internalNow)
internalNow = now()
}
doLimit = false
}
} }
} }
if (now > removeLimitTime) {
limitManagementJob = null
}
}
}
private val quoterChannel = Channel<Unit>(Channel.CONFLATED)
private val tickerJob = scope.launch {
while (isActive) {
quoterChannel.send(Unit)
delay(1000L)
} }
} }
override suspend fun <T> limit(block: suspend () -> T): T { override suspend fun <T> limit(block: suspend () -> T): T {
counterChannel.send(Unit) quotaSemaphore.acquire()
return if (!doLimit) { return block()
block()
} else {
quoterChannel.receive()
block()
}
} }
} }

View File

@@ -1,5 +0,0 @@
package dev.inmo.tgbotapi.bot.settings.limiters
object EmptyLimiter : RequestLimiter {
override suspend fun <T> limit(block: suspend () -> T): T = block()
}

View File

@@ -0,0 +1,66 @@
package dev.inmo.tgbotapi.bot.settings.limiters
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.exceptions.TooMuchRequestsException
import dev.inmo.tgbotapi.types.MilliSeconds
import dev.inmo.tgbotapi.types.RetryAfterError
import io.ktor.client.features.ClientRequestException
import io.ktor.http.HttpStatusCode
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
/**
* This limiter will limit requests only after getting a [RetryAfterError] or [ClientRequestException] with
* [HttpStatusCode.TooManyRequests] status code. Important thing is that in case if some of block has been blocked, all
* the others will wait until it will be possible to be called
*
* @param defaultTooManyRequestsDelay This parameter will be used in case of getting [ClientRequestException] with
* [HttpStatusCode.TooManyRequests] as a parameter for delay like it would be [TooMuchRequestsException]. The reason of
* it is that in [ClientRequestException] there is no information about required delay between requests
*/
class ExceptionsOnlyLimiter(
private val defaultTooManyRequestsDelay: MilliSeconds = 1000L
) : RequestLimiter {
private val lockState = MutableStateFlow(false)
private suspend fun lock(timeMillis: MilliSeconds) {
try {
safely {
lockState.emit(true)
delay(timeMillis)
}
} finally {
lockState.emit(false)
}
}
override suspend fun <T> limit(block: suspend () -> T): T {
while (true) {
lockState.first { !it }
var throwable: Throwable? = null
val result = safely({
throwable = when (it) {
is TooMuchRequestsException -> {
lock(it.retryAfter.leftToRetry)
it
}
is ClientRequestException -> {
if (it.response.status == HttpStatusCode.TooManyRequests) {
lock(defaultTooManyRequestsDelay)
} else {
throw it
}
it
}
else -> throw it
}
null
}) {
block()
}
if (throwable == null) {
return result!!
}
}
}
}

View File

@@ -1,7 +1,9 @@
package dev.inmo.tgbotapi.bot.settings.limiters package dev.inmo.tgbotapi.bot.settings.limiters
import dev.inmo.micro_utils.coroutines.actor
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.types.MilliSeconds
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
import kotlin.coroutines.* import kotlin.coroutines.*
@@ -9,62 +11,60 @@ import kotlin.math.pow
private sealed class RequestEvent private sealed class RequestEvent
private class AddRequest( private class AddRequest(
val continuation: Continuation<Long> val continuation: Continuation<MilliSeconds>
) : RequestEvent() ) : RequestEvent()
private object CompleteRequest : RequestEvent() private object CompleteRequest : RequestEvent()
@Serializable @Serializable
data class PowLimiter( data class PowLimiter(
private val minAwaitTime: Long = 0L, private val minAwaitTime: MilliSeconds = 0L,
private val maxAwaitTime: Long = 10000L, private val maxAwaitTime: MilliSeconds = 10000L,
private val powValue: Double = 4.0, private val powValue: Double = 4.0,
private val powK: Double = 0.0016 private val powK: Double = 1.6,
@Transient
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
) : RequestLimiter { ) : RequestLimiter {
@Transient
private val scope = CoroutineScope(Dispatchers.Default)
@Transient
private val eventsChannel = Channel<RequestEvent>(Channel.UNLIMITED)
@Transient @Transient
private val awaitTimeRange = minAwaitTime .. maxAwaitTime private val awaitTimeRange = minAwaitTime .. maxAwaitTime
@Transient
private val eventsChannel = let {
var requestsInWork = 0.0
scope.actor<RequestEvent> {
when (it) {
is AddRequest -> {
val awaitTime = (requestsInWork.pow(powValue) * powK).toLong()
requestsInWork++
init { it.continuation.resume(
scope.launch { when {
var requestsInWork: Double = 0.0 awaitTime in awaitTimeRange -> awaitTime
for (event in eventsChannel) { awaitTime < awaitTimeRange.first -> awaitTimeRange.first
when (event) { else -> awaitTimeRange.last
is AddRequest -> { }
val awaitTime = (((requestsInWork.pow(powValue) * powK) * 1000L).toLong()) )
requestsInWork++
event.continuation.resume(
if (awaitTime in awaitTimeRange) {
awaitTime
} else {
if (awaitTime < minAwaitTime) {
minAwaitTime
} else {
maxAwaitTime
}
}
)
}
is CompleteRequest -> requestsInWork--
} }
is CompleteRequest -> requestsInWork--
} }
} }
} }
override suspend fun <T> limit( private suspend inline fun <T> withDelay(
block: suspend () -> T crossinline block: suspend () -> T
): T { ): T {
val delayMillis = suspendCoroutine<Long> { val delayMillis = suspendCoroutine<Long> {
scope.launch { eventsChannel.send(AddRequest(it)) } scope.launch { eventsChannel.send(AddRequest(it)) }
} }
delay(delayMillis) delay(delayMillis)
return try { return try {
block() safely { block() }
} finally { } finally {
eventsChannel.send(CompleteRequest) eventsChannel.send(CompleteRequest)
} }
} }
override suspend fun <T> limit(
block: suspend () -> T
): T {
return withDelay(block)
}
} }

View File

@@ -0,0 +1,21 @@
package dev.inmo.tgbotapi.requests
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.passport.PassportElementError
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class SetPassportDataErrors(
@SerialName(userIdField)
val user: UserId,
@SerialName(errorsField)
val errors: List<PassportElementError>
) : SimpleRequest<Boolean> {
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override fun method(): String = "setPassportDataErrors"
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -16,7 +16,7 @@ data class AnswerCallbackQuery(
val showAlert: Boolean? = null, val showAlert: Boolean? = null,
@SerialName(urlField) @SerialName(urlField)
val url: String? = null, val url: String? = null,
@SerialName(cachedTimeField) @SerialName(cacheTimeField)
val cachedTimeSeconds: Int? = null val cachedTimeSeconds: Int? = null
) : SimpleRequest<Boolean> { ) : SimpleRequest<Boolean> {
override fun method(): String = "answerCallbackQuery" override fun method(): String = "answerCallbackQuery"

View File

@@ -16,7 +16,7 @@ data class AnswerInlineQuery(
@Serializable(InlineQueryAnswersResultsSerializer::class) @Serializable(InlineQueryAnswersResultsSerializer::class)
@SerialName(resultsField) @SerialName(resultsField)
val results: List<InlineQueryResult> = emptyList(), val results: List<InlineQueryResult> = emptyList(),
@SerialName(cachedTimeField) @SerialName(cacheTimeField)
val cachedTime: Int? = null, val cachedTime: Int? = null,
@SerialName(isPersonalField) @SerialName(isPersonalField)
val isPersonal: Boolean? = null, val isPersonal: Boolean? = null,

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

@@ -4,13 +4,13 @@ import dev.inmo.tgbotapi.CommonAbstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMemberSerializerWithoutDeserialization import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMemberSerializer
import dev.inmo.tgbotapi.types.chatIdField import dev.inmo.tgbotapi.types.chatIdField
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.ListSerializer
private val chatMembersListSerializer = ListSerializer( private val chatMembersListSerializer = ListSerializer(
AdministratorChatMemberSerializerWithoutDeserialization AdministratorChatMemberSerializer
) )
@Serializable @Serializable

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

@@ -3,7 +3,7 @@ package dev.inmo.tgbotapi.requests.chat.members
import dev.inmo.tgbotapi.requests.chat.abstracts.ChatMemberRequest import dev.inmo.tgbotapi.requests.chat.abstracts.ChatMemberRequest
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMemberDeserializationStrategy import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMemberSerializer
import kotlinx.serialization.* import kotlinx.serialization.*
@Serializable @Serializable
@@ -15,7 +15,7 @@ data class GetChatMember(
) : ChatMemberRequest<ChatMember> { ) : ChatMemberRequest<ChatMember> {
override fun method(): String = "getChatMember" override fun method(): String = "getChatMember"
override val resultDeserializer: DeserializationStrategy<ChatMember> override val resultDeserializer: DeserializationStrategy<ChatMember>
get() = ChatMemberDeserializationStrategy get() = ChatMemberSerializer
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
} }

View File

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

View File

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

View File

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

View File

@@ -2,10 +2,7 @@ package dev.inmo.tgbotapi.requests.chat.modify
import dev.inmo.tgbotapi.CommonAbstracts.types.ChatRequest import dev.inmo.tgbotapi.CommonAbstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.ChatIdentifier import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageIdentifier
import dev.inmo.tgbotapi.types.chatIdField
import dev.inmo.tgbotapi.types.messageIdField
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer

View File

@@ -10,6 +10,7 @@ import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.* import kotlinx.serialization.*
private val commonResultDeserializer = TelegramBotAPIMessageDeserializationStrategyClass<ContentMessage<LocationContent>>() private val commonResultDeserializer = TelegramBotAPIMessageDeserializationStrategyClass<ContentMessage<LocationContent>>()
const val editMessageLiveLocationMethod = "editMessageLiveLocation"
@Serializable @Serializable
data class EditChatMessageLiveLocation( data class EditChatMessageLiveLocation(
@@ -30,7 +31,7 @@ data class EditChatMessageLiveLocation(
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditChatMessage<LocationContent>, EditReplyMessage, EditLocationMessage { ) : EditChatMessage<LocationContent>, EditReplyMessage, EditLocationMessage {
override fun method(): String = "editMessageLiveLocation" override fun method(): String = editMessageLiveLocationMethod
override val resultDeserializer: DeserializationStrategy<ContentMessage<LocationContent>> override val resultDeserializer: DeserializationStrategy<ContentMessage<LocationContent>>
get() = commonResultDeserializer get() = commonResultDeserializer
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>

View File

@@ -23,7 +23,7 @@ data class EditInlineMessageLiveLocation(
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditInlineMessage, EditReplyMessage, EditLocationMessage { ) : EditInlineMessage, EditReplyMessage, EditLocationMessage {
override fun method(): String = "editMessageLiveLocation" override fun method(): String = editMessageLiveLocationMethod
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()

View File

@@ -10,6 +10,7 @@ import dev.inmo.tgbotapi.types.message.content.LocationContent
import kotlinx.serialization.* import kotlinx.serialization.*
private val commonResultDeserializer = TelegramBotAPIMessageDeserializationStrategyClass<ContentMessage<LocationContent>>() private val commonResultDeserializer = TelegramBotAPIMessageDeserializationStrategyClass<ContentMessage<LocationContent>>()
const val stopMessageLiveLocationMethod = "stopMessageLiveLocation"
@Serializable @Serializable
data class StopChatMessageLiveLocation( data class StopChatMessageLiveLocation(
@@ -20,7 +21,7 @@ data class StopChatMessageLiveLocation(
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditChatMessage<LocationContent>, EditReplyMessage { ) : EditChatMessage<LocationContent>, EditReplyMessage {
override fun method(): String = "stopMessageLiveLocation" override fun method(): String = stopMessageLiveLocationMethod
override val resultDeserializer: DeserializationStrategy<ContentMessage<LocationContent>> override val resultDeserializer: DeserializationStrategy<ContentMessage<LocationContent>>
get() = commonResultDeserializer get() = commonResultDeserializer
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>

View File

@@ -13,7 +13,7 @@ data class StopInlineMessageLiveLocation(
@SerialName(replyMarkupField) @SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditInlineMessage, EditReplyMessage { ) : EditInlineMessage, EditReplyMessage {
override fun method(): String = "stopMessageLiveLocation" override fun method(): String = stopMessageLiveLocationMethod
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
} }

View File

@@ -2,7 +2,6 @@ package dev.inmo.tgbotapi.requests.edit.text
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.edit.abstracts.* import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.requests.edit.media.editMessageMediaMethod
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.* import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.ParseMode.ParseMode import dev.inmo.tgbotapi.types.ParseMode.ParseMode
@@ -55,10 +54,10 @@ data class EditInlineMessageText internal constructor(
override val replyMarkup: InlineKeyboardMarkup? = null override val replyMarkup: InlineKeyboardMarkup? = null
) : EditInlineMessage, EditTextChatMessage, EditReplyMessage, EditDisableWebPagePreviewMessage { ) : EditInlineMessage, EditTextChatMessage, EditReplyMessage, EditDisableWebPagePreviewMessage {
override val entities: List<TextSource>? by lazy { override val entities: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextParts(text) ?.justTextSources()
} }
override fun method(): String = editMessageMediaMethod override fun method(): String = editMessageTextMethod
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
} }

View File

@@ -9,8 +9,6 @@ import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.ParseMode.ParseMode import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import kotlinx.serialization.* import kotlinx.serialization.*
fun CopyMessage( fun CopyMessage(

View File

@@ -8,6 +8,10 @@ import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InputMedia.* import dev.inmo.tgbotapi.types.InputMedia.*
import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializerClass import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializeOnlySerializerClass
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaGroupContent
import dev.inmo.tgbotapi.types.message.content.abstracts.VisualMediaGroupContent
import dev.inmo.tgbotapi.types.message.content.media.AudioContent
import dev.inmo.tgbotapi.types.message.content.media.DocumentContent
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.*
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer import kotlinx.serialization.builtins.ListSerializer
@@ -17,13 +21,13 @@ const val rawSendingMediaGroupsWarning = "Media groups contains restrictions rel
" types. Currently it is possible to combine photo + video OR audio OR documents" " types. Currently it is possible to combine photo + video OR audio OR documents"
@RiskFeature(rawSendingMediaGroupsWarning) @RiskFeature(rawSendingMediaGroupsWarning)
fun SendMediaGroup( fun <T : MediaGroupContent> SendMediaGroup(
chatId: ChatIdentifier, chatId: ChatIdentifier,
media: List<MediaGroupMemberInputMedia>, media: List<MediaGroupMemberInputMedia>,
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null
): Request<List<MediaGroupMessage>> { ): Request<List<MediaGroupMessage<T>>> {
if (media.size !in mediaCountInMediaGroup) { if (media.size !in mediaCountInMediaGroup) {
throwRangeError("Count of members in media group", mediaCountInMediaGroup, media.size) throwRangeError("Count of members in media group", mediaCountInMediaGroup, media.size)
} }
@@ -47,14 +51,14 @@ fun SendMediaGroup(
allowSendingWithoutReply allowSendingWithoutReply
) )
return if (files.isEmpty()) { return (if (files.isEmpty()) {
data data
} else { } else {
MultipartRequestImpl( MultipartRequestImpl(
data, data,
SendMediaGroupFiles(files) SendMediaGroupFiles(files)
) )
} }) as Request<List<MediaGroupMessage<T>>>
} }
/** /**
@@ -69,7 +73,7 @@ inline fun SendPlaylist(
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null
) = SendMediaGroup(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply) ) = SendMediaGroup<AudioContent>(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply)
/** /**
* Use this method to be sure that you are correctly sending documents media group * Use this method to be sure that you are correctly sending documents media group
@@ -83,7 +87,7 @@ inline fun SendDocumentsGroup(
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null
) = SendMediaGroup(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply) ) = SendMediaGroup<DocumentContent>(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply)
/** /**
* Use this method to be sure that you are correctly sending visual media group * Use this method to be sure that you are correctly sending visual media group
@@ -98,9 +102,9 @@ inline fun SendVisualMediaGroup(
disableNotification: Boolean = false, disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null, replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null allowSendingWithoutReply: Boolean? = null
) = SendMediaGroup(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply) ) = SendMediaGroup<VisualMediaGroupContent>(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply)
private val messagesListSerializer: KSerializer<List<MediaGroupMessage>> private val messagesListSerializer: KSerializer<List<MediaGroupMessage<MediaGroupContent>>>
= ListSerializer(TelegramBotAPIMessageDeserializeOnlySerializerClass()) = ListSerializer(TelegramBotAPIMessageDeserializeOnlySerializerClass())
@Serializable @Serializable
@@ -114,7 +118,7 @@ data class SendMediaGroupData internal constructor(
override val replyToMessageId: MessageIdentifier? = null, override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField) @SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null override val allowSendingWithoutReply: Boolean? = null
) : DataRequest<List<MediaGroupMessage>>, SendMessageRequest<List<MediaGroupMessage>> { ) : DataRequest<List<MediaGroupMessage<MediaGroupContent>>>, SendMessageRequest<List<MediaGroupMessage<MediaGroupContent>>> {
@SerialName(mediaField) @SerialName(mediaField)
private val convertedMedia: String private val convertedMedia: String
get() = buildJsonArray { get() = buildJsonArray {
@@ -127,7 +131,7 @@ data class SendMediaGroupData internal constructor(
override fun method(): String = "sendMediaGroup" override fun method(): String = "sendMediaGroup"
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() get() = serializer()
override val resultDeserializer: DeserializationStrategy<List<MediaGroupMessage>> override val resultDeserializer: DeserializationStrategy<List<MediaGroupMessage<MediaGroupContent>>>
get() = messagesListSerializer get() = messagesListSerializer
} }

View File

@@ -16,6 +16,11 @@ import kotlinx.serialization.*
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<PollContent>> = TelegramBotAPIMessageDeserializationStrategyClass() 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( private fun checkPollInfo(
question: String, question: String,
options: List<String> options: List<String>
@@ -87,7 +92,7 @@ fun Poll.createRequest(
correctOptionId, correctOptionId,
isAnonymous, isAnonymous,
isClosed, isClosed,
fullEntitiesList(), textSources,
scheduledCloseInfo, scheduledCloseInfo,
disableNotification, disableNotification,
replyToMessageId, replyToMessageId,
@@ -138,12 +143,23 @@ sealed class SendPoll : SendMessageRequest<ContentMessage<PollContent>>,
abstract val options: List<String> abstract val options: List<String>
abstract val isAnonymous: Boolean abstract val isAnonymous: Boolean
abstract val isClosed: Boolean abstract val isClosed: Boolean
abstract val closeInfo: ScheduledCloseInfo?
abstract val type: String abstract val type: String
internal abstract val openPeriod: LongSeconds? internal abstract val openPeriod: LongSeconds?
internal abstract val closeDate: 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 fun method(): String = "sendPoll"
override val resultDeserializer: DeserializationStrategy<ContentMessage<PollContent>> override val resultDeserializer: DeserializationStrategy<ContentMessage<PollContent>>
get() = commonResultDeserializer get() = commonResultDeserializer
@@ -163,8 +179,10 @@ data class SendRegularPoll(
override val isClosed: Boolean = false, override val isClosed: Boolean = false,
@SerialName(allowsMultipleAnswersField) @SerialName(allowsMultipleAnswersField)
val allowMultipleAnswers: Boolean = false, val allowMultipleAnswers: Boolean = false,
@Transient @SerialName(openPeriodField)
override val closeInfo: ScheduledCloseInfo? = null, override val openPeriod: LongSeconds?= null,
@SerialName(closeDateField)
override val closeDate: LongSeconds?,
@SerialName(disableNotificationField) @SerialName(disableNotificationField)
override val disableNotification: Boolean = false, override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField) @SerialName(replyToMessageIdField)
@@ -178,20 +196,39 @@ data class SendRegularPoll(
override val requestSerializer: SerializationStrategy<*> override val requestSerializer: SerializationStrategy<*>
get() = serializer() 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 { init {
checkPollInfo(question, options) checkPollInfo(question, options)
closeInfo ?.checkSendData() 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( fun SendQuizPoll(
chatId: ChatIdentifier, chatId: ChatIdentifier,
question: String, question: String,
@@ -253,6 +290,39 @@ fun SendQuizPoll(
replyMarkup 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 @Serializable
data class SendQuizPoll internal constructor( data class SendQuizPoll internal constructor(
@SerialName(chatIdField) @SerialName(chatIdField)
@@ -273,8 +343,10 @@ data class SendQuizPoll internal constructor(
override val parseMode: ParseMode? = null, override val parseMode: ParseMode? = null,
@SerialName(explanationEntitiesField) @SerialName(explanationEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null, private val rawEntities: List<RawMessageEntity>? = null,
@Transient @SerialName(openPeriodField)
override val closeInfo: ScheduledCloseInfo? = null, override val openPeriod: LongSeconds? = null,
@SerialName(closeDateField)
override val closeDate: LongSeconds? = null,
@SerialName(disableNotificationField) @SerialName(disableNotificationField)
override val disableNotification: Boolean = false, override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField) @SerialName(replyToMessageIdField)
@@ -291,14 +363,6 @@ data class SendQuizPoll internal constructor(
rawEntities ?.asTextParts(explanation ?: return@lazy null) ?.justTextSources() 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 { init {
checkPollInfo(question, options) checkPollInfo(question, options)
closeInfo ?.checkSendData() closeInfo ?.checkSendData()

View File

@@ -1,7 +1,8 @@
package dev.inmo.tgbotapi.requests.webhook package dev.inmo.tgbotapi.requests.webhook
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.* import dev.inmo.tgbotapi.requests.send.media.base.DataRequest
import dev.inmo.tgbotapi.requests.send.media.base.MultipartRequestImpl
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.types package dev.inmo.tgbotapi.types
import dev.inmo.micro_utils.common.Warning
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
@@ -17,9 +18,20 @@ data class ChatId(
val chatId: Identifier val chatId: Identifier
) : ChatIdentifier() ) : ChatIdentifier()
/**
val ChatId.link: String * https://core.telegram.org/bots/api#formatting-options
get() = "tg://user?id=$chatId" */
@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 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

@@ -1,19 +1,41 @@
package dev.inmo.tgbotapi.types.ChatMember package dev.inmo.tgbotapi.types.ChatMember
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
import dev.inmo.tgbotapi.types.User import kotlinx.serialization.*
@Serializable
data class AdministratorChatMemberImpl( data class AdministratorChatMemberImpl(
@SerialName(userField)
override val user: User, override val user: User,
override val canBeEdited: Boolean, @SerialName(canBeEditedField)
override val canChangeInfo: Boolean, override val canBeEdited: Boolean = false,
override val canPostMessages: Boolean, @SerialName(canChangeInfoField)
override val canEditMessages: Boolean, override val canChangeInfo: Boolean = false,
override val canRemoveMessages: Boolean, @SerialName(canPostMessagesField)
override val canInviteUsers: Boolean, override val canPostMessages: Boolean = false,
override val canRestrictMembers: Boolean, @SerialName(canEditMessagesField)
override val canPinMessages: Boolean, override val canEditMessages: Boolean = false,
override val canPromoteMembers: Boolean, @SerialName(canDeleteMessagesField)
override val isAnonymous: Boolean, override val canRemoveMessages: Boolean = false,
override val customTitle: String? @SerialName(canInviteUsersField)
) : AdministratorChatMember override val canInviteUsers: Boolean = false,
@SerialName(canRestrictMembersField)
override val canRestrictMembers: Boolean = false,
@SerialName(canPinMessagesField)
override val canPinMessages: Boolean = false,
@SerialName(canPromoteMembersField)
override val canPromoteMembers: Boolean = false,
@SerialName(canManageVoiceChatsField)
override val canManageVoiceChats: Boolean = false,
@SerialName(canManageChatField)
override val canManageChat: Boolean = false,
@SerialName(isAnonymousField)
override val isAnonymous: Boolean = false,
@SerialName(customTitleField)
override val customTitle: String? = null
) : AdministratorChatMember {
@SerialName(statusField)
@Required
private val type: String = "administrator"
}

View File

@@ -1,20 +1,40 @@
package dev.inmo.tgbotapi.types.ChatMember package dev.inmo.tgbotapi.types.ChatMember
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.AdministratorChatMember
import dev.inmo.tgbotapi.types.User import kotlinx.serialization.*
@Serializable
data class CreatorChatMember( data class CreatorChatMember(
override val user: User, override val user: User,
override val isAnonymous: Boolean, @SerialName(isAnonymousField)
override val customTitle: String? override val isAnonymous: Boolean = false,
@SerialName(customTitleField)
override val customTitle: String? = null
) : AdministratorChatMember { ) : AdministratorChatMember {
@Transient
override val canBeEdited: Boolean = true override val canBeEdited: Boolean = true
@Transient
override val canChangeInfo: Boolean = true override val canChangeInfo: Boolean = true
@Transient
override val canPostMessages: Boolean = true override val canPostMessages: Boolean = true
@Transient
override val canEditMessages: Boolean = true override val canEditMessages: Boolean = true
@Transient
override val canRemoveMessages: Boolean = true override val canRemoveMessages: Boolean = true
@Transient
override val canInviteUsers: Boolean = true override val canInviteUsers: Boolean = true
@Transient
override val canRestrictMembers: Boolean = true override val canRestrictMembers: Boolean = true
@Transient
override val canPinMessages: Boolean = true override val canPinMessages: Boolean = true
@Transient
override val canPromoteMembers: Boolean = true override val canPromoteMembers: Boolean = true
@Transient
override val canManageVoiceChats: Boolean = true
@Transient
override val canManageChat: Boolean = true
@SerialName(statusField)
@Required
private val type: String = "creator"
} }

View File

@@ -1,10 +1,17 @@
package dev.inmo.tgbotapi.types.ChatMember package dev.inmo.tgbotapi.types.ChatMember
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ChatMember.abstracts.BannedChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.BannedChatMember
import dev.inmo.tgbotapi.types.TelegramDate import kotlinx.serialization.*
import dev.inmo.tgbotapi.types.User
@Serializable
data class KickedChatMember( data class KickedChatMember(
@SerialName(userField)
override val user: User, override val user: User,
override val untilDate: TelegramDate? @SerialName(untilDateField)
) : BannedChatMember override val untilDate: TelegramDate? = null
) : BannedChatMember {
@SerialName(statusField)
@Required
private val type: String = "kicked"
}

View File

@@ -1,7 +1,12 @@
package dev.inmo.tgbotapi.types.ChatMember package dev.inmo.tgbotapi.types.ChatMember
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
import dev.inmo.tgbotapi.types.User import kotlinx.serialization.*
data class LeftChatMember(override val user: User) : @Serializable
ChatMember data class LeftChatMember(@SerialName(userField) override val user: User) : ChatMember {
@SerialName(statusField)
@Required
private val type: String = "left"
}

View File

@@ -1,7 +1,12 @@
package dev.inmo.tgbotapi.types.ChatMember package dev.inmo.tgbotapi.types.ChatMember
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
import dev.inmo.tgbotapi.types.User import kotlinx.serialization.*
data class MemberChatMember(override val user: User) : @Serializable
ChatMember data class MemberChatMember(@SerialName(userField) override val user: User) : ChatMember {
@SerialName(statusField)
@Required
private val type: String = "member"
}

View File

@@ -1,87 +0,0 @@
package dev.inmo.tgbotapi.types.ChatMember
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ChatMember.abstracts.ChatMember
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
internal data class RawChatMember(
val user: User,
private val status: String,
private val until_date: TelegramDate? = null,
@SerialName(canBeEditedField)
private val canBeEdited: Boolean = false,
@SerialName(canChangeInfoField)
private val canChangeInfo: Boolean = false,
@SerialName(canPostMessagesField)
private val canPostMessages: Boolean = false,
@SerialName(canEditMessagesField)
private val canEditMessages: Boolean = false,
@SerialName(canDeleteMessagesField)
private val canDeleteMessages: Boolean = false,
@SerialName(canInviteUsersField)
private val canInviteUsers: Boolean = false,
@SerialName(canRestrictMembersField)
private val canRestrictMembers: Boolean = false,
@SerialName(canPinMessagesField)
private val canPinMessages: Boolean = false,
@SerialName(canPromoteMembersField)
private val canPromoteMembers: Boolean = false,
@SerialName(isMemberField)
private val isMember: Boolean = false,
@SerialName(canSendMessagesField)
private val canSendMessages: Boolean = false,
@SerialName(canSendMediaMessagesField)
private val canSendMediaMessages: Boolean = false,
@SerialName(canSendPollsField)
private val canSendPolls: Boolean = false,
@SerialName(canSendOtherMessagesField)
private val canSendOtherMessages: Boolean = false,
@SerialName(canAddWebPagePreviewsField)
private val canAddWebPagePreviews: Boolean = false,
@SerialName(isAnonymousField)
private val isAnonymous: Boolean = false,
@SerialName(customTitleField)
private val customTitle: String? = null
) {
val asChatMember: ChatMember by lazy {
when (status) {
"creator" -> CreatorChatMember(user, isAnonymous, customTitle)
"administrator" -> AdministratorChatMemberImpl(
user,
canBeEdited,
canChangeInfo,
canPostMessages,
canEditMessages,
canDeleteMessages,
canInviteUsers,
canRestrictMembers,
canPinMessages,
canPromoteMembers,
isAnonymous,
customTitle
)
"member" -> MemberChatMember(user)
"restricted" -> RestrictedChatMember(
user,
until_date,
isMember,
canSendMessages,
canSendMediaMessages,
canSendPolls,
canSendOtherMessages,
canAddWebPagePreviews,
canChangeInfo,
canInviteUsers,
canPinMessages
)
"left" -> LeftChatMember(user)
"kicked" -> KickedChatMember(
user,
until_date
)
else -> throw IllegalStateException("Can't understand type of user: $status")
}
}
}

View File

@@ -1,20 +1,36 @@
package dev.inmo.tgbotapi.types.ChatMember package dev.inmo.tgbotapi.types.ChatMember
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ChatMember.abstracts.BannedChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.BannedChatMember
import dev.inmo.tgbotapi.types.ChatMember.abstracts.SpecialRightsChatMember import dev.inmo.tgbotapi.types.ChatMember.abstracts.SpecialRightsChatMember
import dev.inmo.tgbotapi.types.TelegramDate import kotlinx.serialization.*
import dev.inmo.tgbotapi.types.User
@Serializable
data class RestrictedChatMember( data class RestrictedChatMember(
@SerialName(userField)
override val user: User, override val user: User,
override val untilDate: TelegramDate?, @SerialName(untilDateField)
val isMember: Boolean, override val untilDate: TelegramDate? = null,
val canSendMessages: Boolean, @SerialName(isMemberField)
val canSendMediaMessages: Boolean, val isMember: Boolean = false,
val canSendPolls: Boolean, @SerialName(canSendMessagesField)
val canSendOtherMessages: Boolean, val canSendMessages: Boolean = false,
val canAddWebpagePreviews: Boolean, @SerialName(canSendMediaMessagesField)
override val canChangeInfo: Boolean, val canSendMediaMessages: Boolean = false,
override val canInviteUsers: Boolean, @SerialName(canSendPollsField)
override val canPinMessages: Boolean val canSendPolls: Boolean = false,
) : BannedChatMember, SpecialRightsChatMember @SerialName(canSendOtherMessagesField)
val canSendOtherMessages: Boolean = false,
@SerialName(canAddWebPagePreviewsField)
val canAddWebpagePreviews: Boolean = false,
@SerialName(canChangeInfoField)
override val canChangeInfo: Boolean = false,
@SerialName(canInviteUsersField)
override val canInviteUsers: Boolean = false,
@SerialName(canPinMessagesField)
override val canPinMessages: Boolean = false
) : BannedChatMember, SpecialRightsChatMember {
@SerialName(statusField)
@Required
private val type: String = "restricted"
}

View File

@@ -1,5 +1,12 @@
package dev.inmo.tgbotapi.types.ChatMember.abstracts 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
import kotlinx.serialization.encoding.Encoder
@Serializable(AdministratorChatMemberSerializer::class)
interface AdministratorChatMember : SpecialRightsChatMember { interface AdministratorChatMember : SpecialRightsChatMember {
val canBeEdited: Boolean val canBeEdited: Boolean
val canPostMessages: Boolean val canPostMessages: Boolean
@@ -7,6 +14,17 @@ interface AdministratorChatMember : SpecialRightsChatMember {
val canRemoveMessages: Boolean val canRemoveMessages: Boolean
val canRestrictMembers: Boolean val canRestrictMembers: Boolean
val canPromoteMembers: Boolean val canPromoteMembers: Boolean
val canManageVoiceChats: Boolean
val canManageChat: Boolean
val isAnonymous: Boolean val isAnonymous: Boolean
val customTitle: String? val customTitle: String?
} }
@Serializer(AdministratorChatMember::class)
@RiskFeature
object AdministratorChatMemberSerializer : KSerializer<AdministratorChatMember> {
override val descriptor: SerialDescriptor = ChatMemberSerializer.descriptor
override fun deserialize(decoder: Decoder): AdministratorChatMember = ChatMemberSerializer.deserialize(decoder) as AdministratorChatMember
override fun serialize(encoder: Encoder, value: AdministratorChatMember) = ChatMemberSerializer.serialize(encoder, value)
}

View File

@@ -1,5 +1,7 @@
package dev.inmo.tgbotapi.types.ChatMember.abstracts package dev.inmo.tgbotapi.types.ChatMember.abstracts
import dev.inmo.tgbotapi.CommonAbstracts.types.UntilDate import dev.inmo.tgbotapi.CommonAbstracts.types.UntilDate
import kotlinx.serialization.Serializable
@Serializable(ChatMemberSerializer::class)
interface BannedChatMember : ChatMember, UntilDate interface BannedChatMember : ChatMember, UntilDate

View File

@@ -1,27 +1,48 @@
package dev.inmo.tgbotapi.types.ChatMember.abstracts package dev.inmo.tgbotapi.types.ChatMember.abstracts
import dev.inmo.tgbotapi.types.ChatMember.RawChatMember import dev.inmo.tgbotapi.types.ChatMember.*
import dev.inmo.tgbotapi.types.User import dev.inmo.tgbotapi.types.User
import kotlinx.serialization.DeserializationStrategy import dev.inmo.tgbotapi.types.statusField
import kotlinx.serialization.KSerializer import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.nonstrictJsonFormat
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive
@Serializable(ChatMemberSerializer::class)
interface ChatMember { interface ChatMember {
val user: User val user: User
} }
internal object AdministratorChatMemberSerializerWithoutDeserialization : KSerializer<AdministratorChatMember> { @Serializer(ChatMember::class)
override val descriptor: SerialDescriptor = ChatMemberDeserializationStrategy.descriptor @RiskFeature
object ChatMemberSerializer : KSerializer<ChatMember> {
override val descriptor: SerialDescriptor = JsonObject.serializer().descriptor
override fun deserialize(decoder: Decoder): AdministratorChatMember override fun deserialize(decoder: Decoder): ChatMember {
= ChatMemberDeserializationStrategy.deserialize(decoder) as AdministratorChatMember val json = JsonObject.serializer().deserialize(decoder)
override fun serialize(encoder: Encoder, value: AdministratorChatMember) = throw UnsupportedOperationException() return when (json[statusField] ?.jsonPrimitive ?.content ?: error("Status field of chat member must be specified, but incoming json contains next: $json")) {
} "creator" -> nonstrictJsonFormat.decodeFromJsonElement(CreatorChatMember.serializer(), json)
"administrator" -> nonstrictJsonFormat.decodeFromJsonElement(AdministratorChatMemberImpl.serializer(), json)
internal object ChatMemberDeserializationStrategy : DeserializationStrategy<ChatMember> { "member" -> nonstrictJsonFormat.decodeFromJsonElement(MemberChatMember.serializer(), json)
override val descriptor: SerialDescriptor = RawChatMember.serializer().descriptor "restricted" -> nonstrictJsonFormat.decodeFromJsonElement(RestrictedChatMember.serializer(), json)
"left" -> nonstrictJsonFormat.decodeFromJsonElement(LeftChatMember.serializer(), json)
override fun deserialize(decoder: Decoder): ChatMember = RawChatMember.serializer().deserialize(decoder).asChatMember "kicked" -> nonstrictJsonFormat.decodeFromJsonElement(KickedChatMember.serializer(), json)
else -> error("Unknown type of chat member in json: $json")
}
}
override fun serialize(encoder: Encoder, value: ChatMember) {
when (value) {
is CreatorChatMember -> CreatorChatMember.serializer()
is AdministratorChatMemberImpl -> AdministratorChatMemberImpl.serializer()
is MemberChatMember -> MemberChatMember.serializer()
is RestrictedChatMember -> RestrictedChatMember.serializer()
is LeftChatMember -> LeftChatMember.serializer()
is KickedChatMember -> KickedChatMember.serializer()
}
}
} }

View File

@@ -1,5 +1,8 @@
package dev.inmo.tgbotapi.types.ChatMember.abstracts package dev.inmo.tgbotapi.types.ChatMember.abstracts
import kotlinx.serialization.Serializable
@Serializable(ChatMemberSerializer::class)
interface SpecialRightsChatMember : ChatMember { interface SpecialRightsChatMember : ChatMember {
val canChangeInfo: Boolean val canChangeInfo: Boolean
val canInviteUsers: Boolean val canInviteUsers: Boolean

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,9 +26,12 @@ typealias FoursquareId = String
typealias FoursquareType = String typealias FoursquareType = String
typealias GooglePlaceId = String typealias GooglePlaceId = String
typealias GooglePlaceType = String typealias GooglePlaceType = String
typealias MembersLimit = Int
typealias Seconds = Int typealias Seconds = Int
typealias MilliSeconds = Long
typealias LongSeconds = Long typealias LongSeconds = Long
typealias UnixTimeStamp = LongSeconds
typealias Meters = Float typealias Meters = Float
typealias Degrees = Int typealias Degrees = Int
@@ -60,10 +63,7 @@ val inlineQueryAnswerResultsLimit = 0 .. 50
val customTitleLength = 0 .. 16 val customTitleLength = 0 .. 16
val dartsAndCubeDiceResultLimit = 1 .. 6 val dartsCubeAndBowlingDiceResultLimit = 1 .. 6
@Deprecated("Renamed", ReplaceWith("dartsAndCubeDiceResultLimit", "dev.inmo.tgbotapi.types.dartsAndCubeDiceResultLimit"))
val diceResultLimit
get() = dartsAndCubeDiceResultLimit
val basketballAndFootballDiceResultLimit = 1 .. 5 val basketballAndFootballDiceResultLimit = 1 .. 5
val slotMachineDiceResultLimit = 1 .. 64 val slotMachineDiceResultLimit = 1 .. 64
@@ -78,6 +78,8 @@ val explanationLimit = 0 .. 200
val openPeriodPollSecondsLimit = 5 .. 600 val openPeriodPollSecondsLimit = 5 .. 600
val membersLimit = 1 .. 99999
// Made as lazy for correct work in K/JS // Made as lazy for correct work in K/JS
val telegramInlineModeGifPermittedMimeTypes by lazy { val telegramInlineModeGifPermittedMimeTypes by lazy {
listOf( listOf(
@@ -125,7 +127,7 @@ const val callbackQueryIdField = "callback_query_id"
const val inlineQueryIdField = "inline_query_id" const val inlineQueryIdField = "inline_query_id"
const val inlineKeyboardField = "inline_keyboard" const val inlineKeyboardField = "inline_keyboard"
const val showAlertField = "show_alert" const val showAlertField = "show_alert"
const val cachedTimeField = "cached_time" const val cacheTimeField = "cache_time"
const val foursquareIdField = "foursquare_id" const val foursquareIdField = "foursquare_id"
const val foursquareTypeField = "foursquare_type" const val foursquareTypeField = "foursquare_type"
const val googlePlaceIdField = "google_place_id" const val googlePlaceIdField = "google_place_id"
@@ -164,6 +166,12 @@ const val optionIdsField = "option_ids"
const val ipAddressField = "ip_address" const val ipAddressField = "ip_address"
const val linkedChatIdField = "linked_chat_id" const val linkedChatIdField = "linked_chat_id"
const val horizontalAccuracyField = "horizontal_accuracy" 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 requestContactField = "request_contact"
const val requestLocationField = "request_location" const val requestLocationField = "request_location"
@@ -231,6 +239,7 @@ const val canSendPollsField = "can_send_polls"
const val canAddWebPagePreviewsField = "can_add_web_page_previews" const val canAddWebPagePreviewsField = "can_add_web_page_previews"
const val canSetStickerSetField = "can_set_sticker_set" const val canSetStickerSetField = "can_set_sticker_set"
const val statusField = "status"
const val canBeEditedField = "can_be_edited" const val canBeEditedField = "can_be_edited"
const val canChangeInfoField = "can_change_info" const val canChangeInfoField = "can_change_info"
const val canPostMessagesField = "can_post_messages" const val canPostMessagesField = "can_post_messages"
@@ -240,8 +249,12 @@ const val canInviteUsersField = "can_invite_users"
const val canRestrictMembersField = "can_restrict_members" const val canRestrictMembersField = "can_restrict_members"
const val canPinMessagesField = "can_pin_messages" const val canPinMessagesField = "can_pin_messages"
const val canPromoteMembersField = "can_promote_members" 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 pngStickerField = "png_sticker"
const val tgsStickerField = "tgs_sticker" const val tgsStickerField = "tgs_sticker"
const val oldChatMemberField = "old_chat_member"
const val newChatMemberField = "new_chat_member"
const val okField = "ok" const val okField = "ok"
const val captionField = "caption" const val captionField = "caption"
@@ -293,6 +306,7 @@ const val payField = "pay"
const val permissionsField = "permissions" const val permissionsField = "permissions"
const val typeField = "type" const val typeField = "type"
const val valueField = "value" const val valueField = "value"
const val creatorField = "creator"
const val pointField = "point" const val pointField = "point"
const val xShiftField = "x_shift" const val xShiftField = "x_shift"
@@ -332,6 +346,7 @@ const val telegramPaymentChargeIdField = "telegram_payment_charge_id"
const val providerPaymentChargeIdField = "provider_payment_charge_id" const val providerPaymentChargeIdField = "provider_payment_charge_id"
const val providerTokenField = "provider_token" const val providerTokenField = "provider_token"
const val providerDataField = "provider_data" const val providerDataField = "provider_data"
const val usersField = "users"
const val requireNameField = "need_name" const val requireNameField = "need_name"
const val requirePhoneNumberField = "need_phone_number" const val requirePhoneNumberField = "need_phone_number"
@@ -358,3 +373,39 @@ const val forceField = "force"
const val regularPollType = "regular" const val regularPollType = "regular"
const val quizPollType = "quiz" const val quizPollType = "quiz"
const val dataField = "data"
const val credentialsField = "credentials"
const val hashField = "hash"
const val translationField = "translation"
const val translationFileField = "translation_file"
const val fileField = "file"
const val filesField = "files"
const val translationFilesField = "translation_files"
const val frontSideField = "front_side"
const val reverseSideField = "reverse_side"
const val selfieField = "selfie"
const val secretField = "secret"
const val errorsField = "errors"
const val sourceField = "source"
const val fieldNameField = "field_name"
const val dataHashField = "data_hash"
const val fileHashField = "file_hash"
const val fileHashesField = "file_hashes"
const val messageField = "message"
const val unspecifiedField = "unspecified"
const val secureDataField = "secure_data"
const val nonceField = "nonce"
const val personalDetailsField = "personal_details"
const val passportField = "passport"
const val internalPassportField = "internal_passport"
const val driverLicenseField = "driver_license"
const val identityCardField = "identity_card"
const val utilityBillField = "utility_bill"
const val bankStatementField = "bank_statement"
const val rentalAgreementField = "rental_agreement"
const val passportRegistrationField = "passport_registration"
const val temporaryRegistrationField = "temporary_registration"

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.audio package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.audio
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedOutput
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.WithInputMessageContentInlineQueryResult import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.WithInputMessageContentInlineQueryResult
@@ -8,10 +7,5 @@ import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.WithInp
const val inlineQueryResultAudioType = "audio" const val inlineQueryResultAudioType = "audio"
interface InlineQueryResultAudioCommon : InlineQueryResult, interface InlineQueryResultAudioCommon : InlineQueryResult,
CaptionedOutput,
TextedOutput, TextedOutput,
WithInputMessageContentInlineQueryResult { WithInputMessageContentInlineQueryResult
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
}

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.document package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.document
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedOutput
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.* import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.*
@@ -9,10 +8,5 @@ const val inlineQueryResultDocumentType = "document"
interface InlineQueryResultDocumentCommon : InlineQueryResult, interface InlineQueryResultDocumentCommon : InlineQueryResult,
TitledInlineQueryResult, TitledInlineQueryResult,
DescribedInlineQueryResult, DescribedInlineQueryResult,
CaptionedOutput,
TextedOutput, TextedOutput,
WithInputMessageContentInlineQueryResult { WithInputMessageContentInlineQueryResult
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
}

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.gif package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.gif
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedOutput
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.* import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.*
@@ -8,10 +7,5 @@ const val inlineQueryResultGifType = "gif"
interface InlineQueryResultGifCommon : InlineQueryResult, interface InlineQueryResultGifCommon : InlineQueryResult,
OptionallyTitledInlineQueryResult, OptionallyTitledInlineQueryResult,
CaptionedOutput,
TextedOutput, TextedOutput,
WithInputMessageContentInlineQueryResult { WithInputMessageContentInlineQueryResult
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
}

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.mpeg4gif package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.mpeg4gif
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedOutput
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.* import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.*
@@ -8,10 +7,5 @@ const val inlineQueryResultMpeg4GifType = "mpeg4_gif"
interface InlineQueryResultMpeg4GifCommon : InlineQueryResult, interface InlineQueryResultMpeg4GifCommon : InlineQueryResult,
OptionallyTitledInlineQueryResult, OptionallyTitledInlineQueryResult,
CaptionedOutput,
TextedOutput, TextedOutput,
WithInputMessageContentInlineQueryResult { WithInputMessageContentInlineQueryResult
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
}

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.photo package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.photo
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedOutput
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.* import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.*
@@ -9,10 +8,5 @@ const val inlineQueryResultPhotoType = "photo"
interface InlineQueryResultPhotoCommon : InlineQueryResult, interface InlineQueryResultPhotoCommon : InlineQueryResult,
OptionallyTitledInlineQueryResult, OptionallyTitledInlineQueryResult,
DescribedInlineQueryResult, DescribedInlineQueryResult,
CaptionedOutput,
TextedOutput, TextedOutput,
WithInputMessageContentInlineQueryResult { WithInputMessageContentInlineQueryResult
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
}

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.video package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.video
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedOutput
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.* import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.*
@@ -9,10 +8,5 @@ const val inlineQueryResultVideoType = "video"
interface InlineQueryResultVideoCommon : InlineQueryResult, interface InlineQueryResultVideoCommon : InlineQueryResult,
TitledInlineQueryResult, TitledInlineQueryResult,
DescribedInlineQueryResult, DescribedInlineQueryResult,
CaptionedOutput,
TextedOutput, TextedOutput,
WithInputMessageContentInlineQueryResult { WithInputMessageContentInlineQueryResult
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
}

View File

@@ -1,17 +1,11 @@
package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.voice package dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.results.voice
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedOutput
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.* import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.*
const val inlineQueryResultVoiceType = "voice" const val inlineQueryResultVoiceType = "voice"
interface InlineQueryResultVoiceCommon : InlineQueryResult, interface InlineQueryResultVoiceCommon : InlineQueryResult,
CaptionedOutput,
TextedOutput, TextedOutput,
WithInputMessageContentInlineQueryResult, WithInputMessageContentInlineQueryResult,
TitledInlineQueryResult { TitledInlineQueryResult
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
}

View File

@@ -37,10 +37,7 @@ data class InputTextMessageContent internal constructor(
private val rawEntities: List<RawMessageEntity>? = null, private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(disableWebPagePreviewField) @SerialName(disableWebPagePreviewField)
override val disableWebPagePreview: Boolean? = null override val disableWebPagePreview: Boolean? = null
) : CaptionedOutput, TextedOutput, DisableWebPagePreview, InputMessageContent { ) : TextedOutput, DisableWebPagePreview, InputMessageContent {
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
override val entities: List<TextSource>? by lazy { override val entities: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text) ?.justTextSources() rawEntities ?.asTextParts(text) ?.justTextSources()
} }

View File

@@ -3,9 +3,6 @@ package dev.inmo.tgbotapi.types.InputMedia
import dev.inmo.tgbotapi.requests.abstracts.InputFile import dev.inmo.tgbotapi.requests.abstracts.InputFile
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Deprecated("Will be removed due to redundancy for end-side users")
fun String.toInputMediaFileAttachmentName() = "attach://$this"
@Serializable(InputMediaSerializer::class) @Serializable(InputMediaSerializer::class)
interface InputMedia { interface InputMedia {
val type: String val type: String

View File

@@ -42,16 +42,12 @@ data class InputMediaAnimation internal constructor(
override val height: Int? = null, override val height: Int? = null,
override val duration: Long? = null, override val duration: Long? = null,
override val thumb: InputFile? = null override val thumb: InputFile? = null
) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, TextedOutput, CaptionedOutput { ) : InputMedia, SizedInputMedia, DuratedInputMedia, ThumbedInputMedia, TextedOutput {
override val type: String = "animation" override val type: String = "animation"
override val entities: List<TextSource>? by lazy { override val entities: List<TextSource>? by lazy {
rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources() rawEntities ?.asTextParts(text ?: return@lazy null) ?.justTextSources()
} }
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
@SerialName(mediaField) @SerialName(mediaField)
override val media: String override val media: String
init { media = file.fileIdToSend } // crutch until js compiling will be fixed init { media = file.fileIdToSend } // crutch until js compiling will be fixed

View File

@@ -74,3 +74,15 @@ fun AudioFile.toInputMediaAudio(
title, title,
thumb ?.fileId 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, parseMode,
thumb ?.fileId thumb ?.fileId
) )
fun DocumentFile.toInputMediaDocument(
textSources: TextSourcesList = emptyList()
) = InputMediaDocument(
fileId,
textSources,
thumb ?.fileId
)

View File

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

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.types.InputMedia package dev.inmo.tgbotapi.types.InputMedia
import dev.inmo.tgbotapi.CommonAbstracts.CaptionedOutput
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
@@ -16,10 +15,7 @@ internal fun <T> T.buildArguments(withSerializer: SerializationStrategy<T>) = ar
) )
@Serializable(MediaGroupMemberInputMediaSerializer::class) @Serializable(MediaGroupMemberInputMediaSerializer::class)
interface MediaGroupMemberInputMedia : InputMedia, CaptionedOutput, TextedOutput { interface MediaGroupMemberInputMedia : InputMedia, TextedOutput {
@Deprecated("Will be removed in next major release")
override val caption: String?
get() = text
fun serialize(format: StringFormat): String fun serialize(format: StringFormat): String
} }

View File

@@ -1,6 +1,6 @@
package dev.inmo.tgbotapi.types.InputMedia package dev.inmo.tgbotapi.types.InputMedia
import dev.inmo.tgbotapi.requests.abstracts.* import dev.inmo.tgbotapi.requests.abstracts.InputFile
interface ThumbedInputMedia : InputMedia { interface ThumbedInputMedia : InputMedia {
val thumb: InputFile? val thumb: InputFile?

View File

@@ -1,21 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.boldMarkdown
import dev.inmo.tgbotapi.utils.internal.boldMarkdownV2
/** /**
* @see bold * @see bold
*/ */
data class BoldTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class BoldTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.boldMarkdown() } override val markdown: String by lazy { source.boldMarkdown() }
override val asMarkdownV2Source: String by lazy { boldMarkdownV2() } override val markdownV2: String by lazy { boldMarkdownV2() }
override val asHtmlSource: String by lazy { boldHTML() } override val html: String by lazy { boldHTML() }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,10 +1,9 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.DirectInvocationOfTextSourceConstructor
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.commandMarkdown
import dev.inmo.tgbotapi.utils.internal.commandMarkdownV2
private val commandRegex = Regex("[/!][^@\\s]*") private val commandRegex = Regex("[/!][^@\\s]*")
@@ -18,9 +17,9 @@ data class BotCommandTextSource @RiskFeature(DirectInvocationOfTextSourceConstru
commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!" commandRegex.find(source) ?.value ?.substring(1) ?: source.substring(1)// skip first symbol like "/" or "!"
} }
override val asMarkdownSource: String by lazy { source.commandMarkdown() } override val markdown: String by lazy { source.commandMarkdown() }
override val asMarkdownV2Source: String by lazy { source.commandMarkdownV2() } override val markdownV2: String by lazy { source.commandMarkdownV2() }
override val asHtmlSource: String by lazy { source.commandHTML() } override val html: String by lazy { source.commandHTML() }
} }
/** /**

View File

@@ -1,21 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.cashTagMarkdown
import dev.inmo.tgbotapi.utils.internal.cashTagMarkdownV2
/** /**
* @see cashTag * @see cashTag
*/ */
data class CashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class CashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.cashTagMarkdown() } override val markdown: String by lazy { source.cashTagMarkdown() }
override val asMarkdownV2Source: String by lazy { cashTagMarkdownV2() } override val markdownV2: String by lazy { cashTagMarkdownV2() }
override val asHtmlSource: String by lazy { cashTagHTML() } override val html: String by lazy { cashTagHTML() }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -2,10 +2,8 @@ package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.DirectInvocationOfTextSourceConstructor import dev.inmo.tgbotapi.CommonAbstracts.DirectInvocationOfTextSourceConstructor
import dev.inmo.tgbotapi.CommonAbstracts.TextSource import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.codeMarkdown
import dev.inmo.tgbotapi.utils.internal.codeMarkdownV2
/** /**
* @see code * @see code
@@ -13,9 +11,9 @@ import dev.inmo.tgbotapi.utils.internal.codeMarkdownV2
data class CodeTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class CodeTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String override val source: String
) : TextSource { ) : TextSource {
override val asMarkdownSource: String by lazy { source.codeMarkdown() } override val markdown: String by lazy { source.codeMarkdown() }
override val asMarkdownV2Source: String by lazy { source.codeMarkdownV2() } override val markdownV2: String by lazy { source.codeMarkdownV2() }
override val asHtmlSource: String by lazy { source.codeHTML() } override val html: String by lazy { source.codeHTML() }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,21 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.emailMarkdown
import dev.inmo.tgbotapi.utils.internal.emailMarkdownV2
/** /**
* @see email * @see email
*/ */
data class EMailTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class EMailTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.emailMarkdown() } override val markdown: String by lazy { source.emailMarkdown() }
override val asMarkdownV2Source: String by lazy { emailMarkdownV2(source) } override val markdownV2: String by lazy { emailMarkdownV2(source) }
override val asHtmlSource: String by lazy { emailHTML(source) } override val html: String by lazy { emailHTML(source) }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,21 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.hashTagMarkdown
import dev.inmo.tgbotapi.utils.internal.hashTagMarkdownV2
/** /**
* @see hashtag * @see hashtag
*/ */
data class HashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class HashTagTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.hashTagMarkdown() } override val markdown: String by lazy { source.hashTagMarkdown() }
override val asMarkdownV2Source: String by lazy { hashTagMarkdownV2() } override val markdownV2: String by lazy { hashTagMarkdownV2() }
override val asHtmlSource: String by lazy { hashTagHTML() } override val html: String by lazy { hashTagHTML() }
init { init {
if (!source.startsWith("#")) { if (!source.startsWith("#")) {

View File

@@ -1,21 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.italicMarkdown
import dev.inmo.tgbotapi.utils.internal.italicMarkdownV2
/** /**
* @see italic * @see italic
*/ */
data class ItalicTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class ItalicTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.italicMarkdown() } override val markdown: String by lazy { source.italicMarkdown() }
override val asMarkdownV2Source: String by lazy { italicMarkdownV2() } override val markdownV2: String by lazy { italicMarkdownV2() }
override val asHtmlSource: String by lazy { italicHTML() } override val html: String by lazy { italicHTML() }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,10 +1,8 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.mentionMarkdown
import dev.inmo.tgbotapi.utils.internal.mentionMarkdownV2
private val String.withoutCommercialAt private val String.withoutCommercialAt
get() = if (startsWith("@")) { get() = if (startsWith("@")) {
@@ -18,11 +16,11 @@ private val String.withoutCommercialAt
*/ */
data class MentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class MentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.mentionMarkdown() } override val markdown: String by lazy { source.mentionMarkdown() }
override val asMarkdownV2Source: String by lazy { mentionMarkdownV2() } override val markdownV2: String by lazy { mentionMarkdownV2() }
override val asHtmlSource: String by lazy { mentionHTML() } override val html: String by lazy { mentionHTML() }
init { init {
if (!source.startsWith("@")) { if (!source.startsWith("@")) {

View File

@@ -1,21 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.phoneMarkdown
import dev.inmo.tgbotapi.utils.internal.phoneMarkdownV2
/** /**
* @see phone * @see phone
*/ */
data class PhoneNumberTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class PhoneNumberTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.phoneMarkdown() } override val markdown: String by lazy { source.phoneMarkdown() }
override val asMarkdownV2Source: String by lazy { phoneMarkdownV2() } override val markdownV2: String by lazy { phoneMarkdownV2() }
override val asHtmlSource: String by lazy { phoneHTML() } override val html: String by lazy { phoneHTML() }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,10 +1,9 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.DirectInvocationOfTextSourceConstructor
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.preMarkdown
import dev.inmo.tgbotapi.utils.internal.preMarkdownV2
/** /**
* @see pre * @see pre
@@ -13,9 +12,9 @@ data class PreTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) c
override val source: String, override val source: String,
val language: String? = null val language: String? = null
) : TextSource { ) : TextSource {
override val asMarkdownSource: String by lazy { source.preMarkdown(language) } override val markdown: String by lazy { source.preMarkdown(language) }
override val asMarkdownV2Source: String by lazy { source.preMarkdownV2(language) } override val markdownV2: String by lazy { source.preMarkdownV2(language) }
override val asHtmlSource: String by lazy { source.preHTML(language) } override val html: String by lazy { source.preHTML(language) }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,10 +1,9 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.DirectInvocationOfTextSourceConstructor
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.regularMarkdown
import dev.inmo.tgbotapi.utils.internal.regularMarkdownV2
/** /**
* @see regular * @see regular
@@ -12,9 +11,9 @@ import dev.inmo.tgbotapi.utils.internal.regularMarkdownV2
data class RegularTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class RegularTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String override val source: String
) : TextSource { ) : TextSource {
override val asMarkdownSource: String by lazy { source.regularMarkdown() } override val markdown: String by lazy { source.regularMarkdown() }
override val asMarkdownV2Source: String by lazy { source.regularMarkdownV2() } override val markdownV2: String by lazy { source.regularMarkdownV2() }
override val asHtmlSource: String by lazy { source.regularHtml() } override val html: String by lazy { source.regularHtml() }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,21 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.strikethroughMarkdown
import dev.inmo.tgbotapi.utils.internal.strikethroughMarkdownV2
/** /**
* @see strikethrough * @see strikethrough
*/ */
data class StrikethroughTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class StrikethroughTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asHtmlSource: String by lazy { strikethroughHTML() } override val html: String by lazy { strikethroughHTML() }
override val asMarkdownV2Source: String by lazy { strikethroughMarkdownV2() } override val markdownV2: String by lazy { strikethroughMarkdownV2() }
override val asMarkdownSource: String by lazy { source.strikethroughMarkdown() } override val markdown: String by lazy { source.strikethroughMarkdown() }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,10 +1,9 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.DirectInvocationOfTextSourceConstructor
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.linkMarkdown
import dev.inmo.tgbotapi.utils.internal.linkMarkdownV2
/** /**
* @see link * @see link
@@ -13,9 +12,9 @@ data class TextLinkTextSource @RiskFeature(DirectInvocationOfTextSourceConstruct
override val source: String, override val source: String,
val url: String val url: String
) : TextSource { ) : TextSource {
override val asMarkdownSource: String by lazy { source.linkMarkdown(url) } override val markdown: String by lazy { source.linkMarkdown(url) }
override val asMarkdownV2Source: String by lazy { source.linkMarkdownV2(url) } override val markdownV2: String by lazy { source.linkMarkdownV2(url) }
override val asHtmlSource: String by lazy { source.linkHTML(url) } override val html: String by lazy { source.linkHTML(url) }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,11 +1,9 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.types.User import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.textMentionMarkdown
import dev.inmo.tgbotapi.utils.internal.textMentionMarkdownV2
/** /**
* @see mention * @see mention
@@ -13,16 +11,36 @@ import dev.inmo.tgbotapi.utils.internal.textMentionMarkdownV2
data class TextMentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class TextMentionTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
val user: User, val user: User,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.textMentionMarkdown(user.id) } override val markdown: String by lazy { source.textMentionMarkdown(user.id) }
override val asMarkdownV2Source: String by lazy { textMentionMarkdownV2(user.id) } override val markdownV2: String by lazy { textMentionMarkdownV2(user.id) }
override val asHtmlSource: String by lazy { textMentionHTML(user.id) } override val html: String by lazy { textMentionHTML(user.id) }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline fun mention(parts: List<TextSource>, user: User) = TextMentionTextSource(parts.makeString(), user, parts) inline fun mention(parts: List<TextSource>, user: User) = TextMentionTextSource(parts.makeString(), user, parts)
@Suppress("NOTHING_TO_INLINE") @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) inline fun mention(user: User, vararg parts: TextSource) = mention(parts.toList(), user)
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline fun mention(text: String, user: User) = mention(user, regular(text)) 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

@@ -1,10 +1,9 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.DirectInvocationOfTextSourceConstructor
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.CommonAbstracts.TextSource
import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.linkMarkdown
import dev.inmo.tgbotapi.utils.internal.linkMarkdownV2
/** /**
* @see link * @see link
@@ -12,9 +11,9 @@ import dev.inmo.tgbotapi.utils.internal.linkMarkdownV2
data class URLTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class URLTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String override val source: String
) : TextSource { ) : TextSource {
override val asMarkdownSource: String by lazy { source.linkMarkdown(source) } override val markdown: String by lazy { source.linkMarkdown(source) }
override val asMarkdownV2Source: String by lazy { source.linkMarkdownV2(source) } override val markdownV2: String by lazy { source.linkMarkdownV2(source) }
override val asHtmlSource: String by lazy { source.linkHTML(source) } override val html: String by lazy { source.linkHTML(source) }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -1,21 +1,19 @@
package dev.inmo.tgbotapi.types.MessageEntity.textsources package dev.inmo.tgbotapi.types.MessageEntity.textsources
import dev.inmo.tgbotapi.CommonAbstracts.* import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.utils.* import dev.inmo.tgbotapi.utils.RiskFeature
import dev.inmo.tgbotapi.utils.internal.* import dev.inmo.tgbotapi.utils.internal.*
import dev.inmo.tgbotapi.utils.internal.underlineMarkdown
import dev.inmo.tgbotapi.utils.internal.underlineMarkdownV2
/** /**
* @see underline * @see underline
*/ */
data class UnderlineTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor ( data class UnderlineTextSource @RiskFeature(DirectInvocationOfTextSourceConstructor) constructor (
override val source: String, override val source: String,
override val textSources: List<TextSource> override val subsources: List<TextSource>
) : MultilevelTextSource { ) : MultilevelTextSource {
override val asMarkdownSource: String by lazy { source.underlineMarkdown() } override val markdown: String by lazy { source.underlineMarkdown() }
override val asMarkdownV2Source: String by lazy { underlineMarkdownV2() } override val markdownV2: String by lazy { underlineMarkdownV2() }
override val asHtmlSource: String by lazy { underlineHTML() } override val html: String by lazy { underlineHTML() }
} }
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")

View File

@@ -35,12 +35,21 @@ typealias Markdown = MarkdownParseMode
typealias MarkdownV2 = MarkdownV2ParseMode typealias MarkdownV2 = MarkdownV2ParseMode
typealias HTML = HTMLParseMode 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) @Serializer(ParseMode::class)
internal object ParseModeSerializerObject : KSerializer<ParseMode> { internal object ParseModeSerializerObject : KSerializer<ParseMode> {
override fun deserialize(decoder: Decoder): ParseMode { override fun deserialize(decoder: Decoder): ParseMode {
return when (decoder.decodeString()) { return when (decoder.decodeString()) {
MarkdownParseMode.parseModeName -> MarkdownParseMode Markdown.parseModeName -> Markdown
HTMLParseMode.parseModeName -> HTMLParseMode MarkdownV2.parseModeName -> MarkdownV2
HTML.parseModeName -> HTML
else -> throw IllegalArgumentException("Unknown parse mode") else -> throw IllegalArgumentException("Unknown parse mode")
} }
} }

View File

@@ -5,7 +5,7 @@ import com.soywiz.klock.DateTime
sealed class RequestError sealed class RequestError
data class RetryAfterError( data class RetryAfterError(
val seconds: Long, val seconds: Seconds,
val startCountingMillis: Long val startCountingMillis: Long
) : RequestError() { ) : RequestError() {
val canContinue = (seconds * 1000L) + startCountingMillis val canContinue = (seconds * 1000L) + startCountingMillis

View File

@@ -8,7 +8,7 @@ data class ResponseParametersRaw(
@SerialName("migrate_to_chat_id") @SerialName("migrate_to_chat_id")
private val migrateToChatId: ChatId? = null, private val migrateToChatId: ChatId? = null,
@SerialName("retry_after") @SerialName("retry_after")
private val retryAfter: Long? = null private val retryAfter: Seconds? = null
) { ) {
@Transient @Transient
private val createTime: Long = DateTime.now().unixMillisLong private val createTime: Long = DateTime.now().unixMillisLong

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_PRE_CHECKOUT_QUERY = "pre_checkout_query"
const val UPDATE_POLL = "poll" const val UPDATE_POLL = "poll"
const val UPDATE_POLL_ANSWER = "poll_answer" 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( val ALL_UPDATES_LIST = listOf(
UPDATE_MESSAGE, UPDATE_MESSAGE,
@@ -23,5 +25,7 @@ val ALL_UPDATES_LIST = listOf(
UPDATE_SHIPPING_QUERY, UPDATE_SHIPPING_QUERY,
UPDATE_PRE_CHECKOUT_QUERY, UPDATE_PRE_CHECKOUT_QUERY,
UPDATE_POLL, UPDATE_POLL,
UPDATE_POLL_ANSWER UPDATE_POLL_ANSWER,
MY_CHAT_MEMBER,
CHAT_MEMBER
) )

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