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

Compare commits

..

540 Commits

Author SHA1 Message Date
c4fbd2f1c6 revert type of BuiltinMimeTypes 2021-08-13 18:39:46 +06:00
c90bcea42c add additional mime types 2021-08-13 18:39:08 +06:00
e75c93d626 remove mime types from requests 2021-08-13 14:02:39 +06:00
58dcbe8751 StorageFile#asMultipartFile 2021-08-13 11:45:36 +06:00
17806cde25 add calculation of mimed type from TelegramMediaFile when it is MimedFile 2021-08-13 11:43:36 +06:00
f147a3d620 fix of package for AdditionalContentAsStorageFile 2021-08-13 11:41:57 +06:00
9eb6008a73 convertToStorageFile 2021-08-13 11:37:01 +06:00
f7d2c8bbd2 hotfix 2021-08-10 16:54:15 +06:00
f42cf78969 fixes 2021-08-10 16:50:50 +06:00
9a14932511 small improvement of DownloadFileRequestCallFactory 2021-08-10 11:32:22 +06:00
149ecf175b small improvement of DownloadFileChannelRequestCallFactory 2021-08-10 11:29:46 +06:00
2049fea82a new asStorageFile 2021-08-10 11:08:08 +06:00
40d94cca70 improvements in files downloading api 2021-08-10 10:34:59 +06:00
c8ad68ea69 make ByteReadChannelAllocatorSerializer -> ByteReadChannelAllocatorDeserializationStrategy 2021-08-10 10:12:22 +06:00
c66d64adbc renames 2021-08-09 23:24:12 +06:00
b475976ff1 add streaming file downloading feature 2021-08-09 23:22:08 +06:00
ea8db5b851 rename JVM DownloadFile file 2021-08-09 20:01:26 +06:00
af2fabf1ca fix changelog 2021-08-09 19:55:51 +06:00
abc0457a36 files downloading improvements 2021-08-09 19:55:08 +06:00
8dbdbdee13 start 0.35.5 2021-08-09 19:39:03 +06:00
0c31379ff5 Merge pull request #439 from InsanusMokrassar/0.35.4
0.35.4
2021-08-09 14:18:19 +06:00
3b3cf81aaa Update CHANGELOG.md 2021-08-09 12:26:37 +06:00
1642075a75 Update microutils 2021-08-09 12:21:51 +06:00
760c9f2916 start 0.35.4 2021-08-09 12:21:27 +06:00
219238cf19 Merge pull request #436 from InsanusMokrassar/0.35.3
0.35.3
2021-08-08 18:48:45 +06:00
762087fc09 optimize imports 2021-08-08 18:00:42 +06:00
142fae1ede remove WithLanguageCode 2021-08-08 17:55:27 +06:00
95abc72bf3 WithOptionalLanguageCode?.javaLocale 2021-08-08 17:47:18 +06:00
1d37a7446c add companions for SimpleRequestCallFactory and MultipartRequestCallFactory 2021-08-08 17:44:20 +06:00
7d35114b5d classcasts fill for WithOptionalLanguageCode 2021-08-08 16:43:49 +06:00
75f4226772 base ktor request call factories became classes to avoid sharing of their cache between bots 2021-08-08 16:14:43 +06:00
96d980cb8a fix build 2021-08-06 12:02:26 +06:00
ed077ae1bc filters in waiters 2021-08-06 10:32:31 +06:00
9540797ffc Revert "update classcasts"
This reverts commit 217b01994e.
2021-08-06 09:15:30 +06:00
217b01994e update classcasts 2021-08-05 23:54:30 +06:00
6b89c94ef1 include support of ietf language codes 2021-08-05 23:36:01 +06:00
e25ce57f6a update microutils version 2021-08-05 23:12:17 +06:00
530394fd15 SimpleFilter 2021-08-03 11:46:23 +06:00
3e891d50fd downloadFile for MediaContent 2021-08-03 11:33:52 +06:00
adf5fd6288 improvements in buildBehaviour 2021-08-03 11:27:39 +06:00
e7a2dc51aa update dependencies 2021-08-03 11:18:30 +06:00
399793243b start 0.35.3 2021-08-03 11:14:21 +06:00
3801025ff1 Merge pull request #428 from InsanusMokrassar/0.35.2
0.35.2
2021-07-17 13:43:02 +06:00
0ad2d9afc4 Fill changelog with versions updates 2021-07-17 13:40:05 +06:00
a303700b56 Update gradle.properties 2021-07-15 23:00:08 +06:00
42bf896f7a Update gradle.properties 2021-07-10 00:42:04 +06:00
0bce522101 Update gradle.properties 2021-07-10 00:03:20 +06:00
3c75d6a2c7 Update dependencies 2021-07-09 11:23:33 +06:00
93eebe37ce Update CHANGELOG.md 2021-07-09 11:20:33 +06:00
f893803939 start 0.35.2 2021-07-09 11:18:54 +06:00
0b92edc05e Update gradle-wrapper.properties 2021-07-03 23:41:48 +06:00
190d83b22b Merge pull request #421 from InsanusMokrassar/0.35.1
0.35.1
2021-06-30 14:51:30 +06:00
7ec4fc460a fix build 2021-06-30 14:01:59 +06:00
75cebf5aa3 add GetUpdatesConflict 2021-06-30 13:57:20 +06:00
a241c91adf waitContentMessage with includeMediaGroups 2021-06-30 11:45:56 +06:00
4f920abb61 upfixes 2021-06-30 11:26:31 +06:00
6ba9a31fb9 seal of MediaGroupUpdates 2021-06-30 11:12:09 +06:00
65801f5104 Update CHANGELOG.md 2021-06-30 10:40:23 +06:00
9e82211473 Merge pull request #422 from eboshare/0.35.1
Add Update#sourceUser method
2021-06-30 10:39:00 +06:00
Vasya
560179a574 simplify Update#sourceUser 2021-06-29 21:47:15 +03:00
Vasya
cffcf2277e add asFromUser, whenFromUser, requireFromUser to ClassCasts.kt 2021-06-29 21:35:46 +03:00
Vasya
cb9a20a9d1 Merge remote-tracking branch 'upstream/0.35.1' into 0.35.1
# Conflicts:
#	tgbotapi.core/src/commonMain/kotlin/dev/inmo/tgbotapi/types/InlineQueries/abstracts/ChosenInlineResult.kt
2021-06-29 21:23:20 +03:00
vasya
45ea103c9a bring back strange InsanusMokrassar's space :) 2021-06-29 21:08:41 +03:00
vasya
c00adb0784 remove redundant import in LeftChatMember.kt 2021-06-29 21:07:18 +03:00
vasya
38826a5e7e remove FromUser interface from RawChosenInlineResult 2021-06-29 21:06:46 +03:00
b2915857d7 remove usages of deprecated ChosenInlineResult 2021-06-29 11:55:46 +06:00
067e36adc6 ChosenInlineResult now is sealed 2021-06-29 11:53:36 +06:00
vasya
12a35da4b6 remove unnecessary FromUser usages 2021-06-29 03:34:27 +03:00
vasya
022e6f623a add FromUser interface to objects where field user is present 2021-06-29 00:57:32 +03:00
vasya
30c138029e add asFromUserMessage calls to Update#sourceUser 2021-06-29 00:37:53 +03:00
732e2a3906 serializable subclasses of MessageContent 2021-06-29 00:06:07 +06:00
c5e089a45d make*String extensions 2021-06-29 00:01:40 +06:00
vasya
919b1590e3 add Update#sourceUser method 2021-06-28 20:30:12 +03:00
0c1017901f optimize imports 2021-06-28 11:12:51 +06:00
fd6e4b0522 final refactor, fixes and upfilling of changelog 2021-06-28 11:10:09 +06:00
21c5d42dc2 BehaviourContext now is interface 2021-06-28 10:29:45 +06:00
77dff639f0 updates 2021-06-28 01:00:20 +06:00
47fe048b10 refactor and fixes in ContentTriggers 2021-06-27 19:28:21 +06:00
ee8cc2aa46 defaultExceptionsHandler in behaviour builder 2021-06-26 17:05:34 +06:00
b9de002517 rewrite to use subscribeSafelyWithoutExceptionsAsync in triggers of behaviour builder 2021-06-26 12:15:52 +06:00
449f2727c4 update dependencies 2021-06-26 02:04:08 +06:00
8712914126 update actuality of core 2021-06-26 01:59:25 +06:00
69b64e9908 and more... :) 2021-06-26 01:58:20 +06:00
656bb68739 add support of input_field_placeholder 2021-06-26 01:48:41 +06:00
7f69052dea *MyCommands actualization 2021-06-26 01:42:35 +06:00
b60fab4871 BotCommandScope 2021-06-26 01:27:28 +06:00
bf28a8b0a6 add performInParallel for behaviour builder 2021-06-25 12:45:20 +06:00
85270dd12d update micro_utils 2021-06-24 14:34:58 +06:00
e39dd2d086 remove redundant fsm module 2021-06-24 12:56:40 +06:00
e10d47b7e4 fill changelog 2021-06-24 12:56:15 +06:00
1e181bc042 fixes 2021-06-24 12:54:50 +06:00
61cf9936fb complete migration of replies 2021-06-24 12:49:47 +06:00
65fd3ced36 start replacement of reply methods 2021-06-24 11:21:02 +06:00
66d37b72eb add when* syntax 2021-06-23 22:14:45 +06:00
55b1d3734d telegramBotWithBehaviour 2021-06-23 21:51:30 +06:00
45b32fd6f7 start 0.35.1 2021-06-23 21:20:28 +06:00
fcd8f20a90 Update README.md 2021-06-17 15:34:53 +06:00
18e6b9e471 Merge pull request #395 from InsanusMokrassar/0.35.0
0.35.0
2021-06-06 09:05:09 +06:00
f5b248f534 update micro_utils 2021-06-05 15:48:38 +06:00
3ebcbe2860 builder extending 2021-06-04 01:07:53 +06:00
3829e04b0c Update CHANGELOG.md 2021-06-04 00:32:42 +06:00
39fa36426f Update CHANGELOG.md 2021-06-03 23:25:19 +06:00
a265e5ecbf Update CHANGELOG.md 2021-06-03 23:09:46 +06:00
86e78c4ba0 Update packages_publishing.yml 2021-05-30 01:20:25 +06:00
a6451ca394 update workflows to separate build and publishing 2021-05-29 17:05:18 +06:00
521a3a8c35 fix internal deprecations 2021-05-29 16:02:55 +06:00
173839c677 small refactoring 2021-05-29 15:51:45 +06:00
bb7d47a33b fix build 2021-05-29 15:46:13 +06:00
5c0e58caec buildable except of jvm tests 2021-05-29 15:34:14 +06:00
72c3623d30 small fillup of changelog 2021-05-29 14:32:45 +06:00
fe1831fc19 deprecations removed 2021-05-29 14:31:44 +06:00
7825ec3010 a lot of types has been converted to sealed 2021-05-29 14:23:25 +06:00
12184cd2be InlineKeyboardButton now is an interface 2021-05-29 13:40:48 +06:00
e90e25ab01 BotAction now is an interface 2021-05-29 13:39:43 +06:00
004ff0b490 update dependencies and changelog 2021-05-29 13:29:01 +06:00
07faba7d38 Update CHANGELOG.md 2021-05-27 00:04:42 +06:00
e5584cd8b4 Update gradle.properties 2021-05-27 00:04:11 +06:00
6acc9ef2b0 update klock 2021-05-26 22:00:57 +06:00
169fc0401a update dependencies 2021-05-26 21:55:09 +06:00
dcfcea65cb start 0.35.0 2021-05-26 21:51:29 +06:00
eedb36ede7 Merge pull request #383 from InsanusMokrassar/gradle-wrapper/6.9
Update gradle-wrapper
2021-05-08 17:19:21 +06:00
eaee334ff6 Update gradle-wrapper.properties 2021-05-08 16:44:14 +06:00
5c694e8625 Update CHANGELOG.md 2021-05-06 13:24:23 +06:00
0306c40fb2 Update CHANGELOG.md 2021-05-06 13:24:11 +06:00
fd915553e3 Merge pull request #381 from InsanusMokrassar/0.34.1
0.34.1
2021-05-05 19:37:32 +06:00
ec1c0ba8bb update microutils 2021-05-05 19:20:51 +06:00
12a64ec1d1 update ktor 2021-05-05 19:12:59 +06:00
59d7a7c781 fix in text sources list creating 2021-05-05 19:02:22 +06:00
cabfd7c76b start 0.34.1 2021-05-05 18:53:26 +06:00
f12f52899c Merge pull request #369 from InsanusMokrassar/renovate/org.jetbrains.dokka-gfm-plugin-1.x
Update dependency org.jetbrains.dokka:gfm-plugin to v1.4.32
2021-04-30 09:55:54 +06:00
Renovate Bot
ed067db20f Update dependency org.jetbrains.dokka:gfm-plugin to v1.4.32 2021-04-29 13:36:31 +00:00
b055268979 Merge pull request #362 from InsanusMokrassar/0.34.0
0.34.0
2021-04-29 19:03:29 +06:00
2584839d66 update core readme 2021-04-29 19:02:51 +06:00
63946e860d note about UnknownExtendedChat 2021-04-29 17:45:19 +06:00
90df436c63 small refactor of usage TextedInput 2021-04-29 17:40:01 +06:00
d3c8b49b10 Update CHANGELOG.md 2021-04-29 17:33:27 +06:00
c1372b55bc Note about ChatType in CHANGRLOG 2021-04-29 15:26:08 +06:00
b6c7ece995 small hotfix 2021-04-29 15:09:45 +06:00
44e7c80f43 remove redundant extensions for parseCommandsWithParams 2021-04-29 15:08:05 +06:00
1e41e95333 fixes in parseCommandsWithParams 2021-04-29 15:07:16 +06:00
03d4d715c0 hotfix 2021-04-29 11:59:44 +06:00
ab060d02ea deprecate Explained 2021-04-29 11:59:44 +06:00
f447be02dc Update InlineKeyboardMarkup.kt 2021-04-29 01:18:07 +06:00
eb923a6338 fixes 2021-04-28 23:22:13 +06:00
0914710cc7 update voice chats 2021-04-28 20:08:02 +06:00
1f7450844f optimize imports 2021-04-28 19:59:30 +06:00
167c214e35 migration to avoid using of TextPart 2021-04-28 19:54:57 +06:00
42a8d649cd Update CHANGELOG.md 2021-04-27 23:43:04 +06:00
eb3f180cc6 textSources now is main property 2021-04-27 16:08:36 +06:00
70f96ac8fa completing of captioned input deprecation 2021-04-26 21:34:13 +06:00
d69b2e09d5 migration from CaptionedInput 2021-04-26 21:25:52 +06:00
946b0222df fix botaction tests 2021-04-26 21:10:38 +06:00
7da315dbaf fix botaction tests 2021-04-26 21:08:52 +06:00
87071ca52c deprecation of an old record audio and upload audio bot actions 2021-04-26 21:02:11 +06:00
b2770e3ecc record_voice and upload_voice 2021-04-26 20:52:20 +06:00
df63ccfe07 VoiceChatScheduled 2021-04-26 20:47:03 +06:00
694bec22a2 include chat_type 2021-04-26 20:42:26 +06:00
6a3588bb8d InputInvoiceMessageContent 2021-04-26 20:23:26 +06:00
a26568aa29 maxTipAmounts and suggestedTipAmounts support in SendInvoice 2021-04-26 20:01:14 +06:00
cd30660256 update SendInvoice 2021-04-26 19:28:19 +06:00
1846d20b0d start 0.34.0 2021-04-26 19:15:55 +06:00
f13207064e Merge pull request #361 from InsanusMokrassar/0.33.4
0.33.4
2021-04-17 16:02:14 +06:00
61be689aca fix of build 2021-04-17 14:36:23 +06:00
03f8d65bb6 fix of build 2021-04-17 11:14:35 +06:00
2dc8beba8a update classcasts 2021-04-16 22:00:45 +06:00
5451adf4ac FromUserMessage extends Message 2021-04-16 18:07:27 +06:00
9982534001 updates in TextSourceSerializer 2021-04-15 14:34:05 +06:00
c0451d4c8f Update gradle-wrapper.properties 2021-04-15 13:56:52 +06:00
a9d65944e6 update MicroUtils 2021-04-13 15:53:35 +06:00
39598dcb69 fill CHANGELOG 2021-04-13 01:54:45 +06:00
3069a6084c fixes in parseCommandsWithParams 2021-04-13 01:50:41 +06:00
e7bbce3fa7 update uuid dependency 2021-04-12 23:32:50 +06:00
0b361163f2 TextSourceSerializer 2021-04-12 23:23:18 +06:00
6aba2ff641 start 0.33.4 2021-04-12 20:57:12 +06:00
6b761ab37d Update gradle wrapper 2021-04-11 04:06:30 +06:00
b9c8a89af9 Merge pull request #357 from InsanusMokrassar/0.33.3
0.33.3
2021-04-05 19:41:52 +06:00
a42c5c63c4 fillup changelog 2021-04-05 19:08:12 +06:00
fc1a029acb fix of #358 2021-04-05 19:06:49 +06:00
f90ae2f918 include weakLaunch in behaviour builder 2021-04-05 18:15:10 +06:00
019b260888 update ktor 2021-04-05 18:11:29 +06:00
0831f2fa75 update microutils 2021-04-05 17:21:59 +06:00
32ae9d2b16 hotfix 2021-04-05 16:50:31 +06:00
b975a1b036 updates in behaviour builder 2021-04-05 16:41:27 +06:00
f4b1e4a150 start 0.33.3 2021-04-05 13:42:48 +06:00
97031512d4 Merge pull request #356 from InsanusMokrassar/0.33.2
0.33.2
2021-04-03 15:39:14 +06:00
353df43109 update microutils 2021-04-03 15:13:20 +06:00
4e55460834 fix in doInSubContext 2021-04-03 15:05:25 +06:00
e2e235bd6c behaviour builder updates 2021-04-03 14:51:21 +06:00
8ced95bc2f start 0.33.2 2021-04-03 14:24:24 +06:00
685e4af8f5 Merge pull request #345 from InsanusMokrassar/0.33.1
0.33.1
2021-03-26 09:13:15 +06:00
0b2f7a3899 update condition for ReplyMessageNotFoundException 2021-03-26 07:03:33 +06:00
112c86c9da remove caption based messages extension for parsing of commands 2021-03-24 13:56:51 +06:00
1ddd138ff7 update kdocs for new function 2021-03-24 13:44:27 +06:00
1a5d1cde78 add parseCommandsWithParams for text inputs 2021-03-24 13:43:32 +06:00
5b620014cb update kotlin version 2021-03-24 13:14:09 +06:00
80093cb5a9 Update kdocs.yml 2021-03-21 23:22:16 +06:00
9f8e8ee21b update dependencies 2021-03-19 20:20:07 +06:00
3de3bb6133 start 0.33.1 2021-03-19 20:18:32 +06:00
308fb9274b Update kdocs.yml 2021-03-17 21:14:05 +06:00
d14ca7bbdc Update kdocs.yml 2021-03-17 21:13:52 +06:00
dbdd9b5ad2 update dokka 2021-03-16 23:01:26 +06:00
6dd27cb0bf fixes in names of workflows 2021-03-16 22:41:45 +06:00
210a52485b add kdocs yml config 2021-03-16 22:39:54 +06:00
5c11b60ea6 fix dokka config 2021-03-16 22:33:53 +06:00
60c3a0d7af update core info about current version 2021-03-16 22:21:15 +06:00
8d777e1c0e Update dokka version 2021-03-16 16:30:13 +06:00
4e019eb8bb Update packages_publishing.yml 2021-03-12 20:11:26 +06:00
bd80562c2a Merge pull request #337 from InsanusMokrassar/0.33.0
0.33.0
2021-03-12 15:47:24 +06:00
9fc07f2ff3 fix build 2021-03-12 15:03:11 +06:00
a4bae5133a fill changelog 2021-03-12 14:58:13 +06:00
7bb272f2fa update compatibility note 2021-03-12 14:39:27 +06:00
72cf38d3bb fill Behaviour Builder for ChatMemberUpdated 2021-03-12 14:36:10 +06:00
0adee13cba remove deprecations 2021-03-11 22:28:56 +06:00
f9e3e57f24 migrate 0.32.10 -> 0.33.0 2021-03-11 21:44:08 +06:00
d7d4adc8e4 optimize imports 2021-03-11 21:39:34 +06:00
e9b074a36c updates of FlowsUpdatesFilter 2021-03-11 21:36:29 +06:00
65cba0f014 fill api of chat invite links 2021-03-11 21:25:11 +06:00
36202133a1 update classcasts 2021-03-11 21:06:25 +06:00
66f7801b32 fix ChatInviteLinkRequest 2021-03-11 20:41:47 +06:00
e7265829d1 include ChatMemberUpdated functionality 2021-03-11 20:17:08 +06:00
9ad5bfbc57 remove BotInviteChatLink 2021-03-11 16:36:15 +06:00
aba62ba930 chatmember serializers are public 2021-03-11 16:00:47 +06:00
40d702a311 add representations of all chat invite link functionality 2021-03-10 22:46:56 +06:00
233d893b5a add isOff extension for MessageAutoDeleteTimerChanged 2021-03-09 22:33:05 +06:00
0faca5838c fixes in events builder behaviours 2021-03-09 22:14:16 +06:00
838f62aa84 shortcuts seconds24Hours and seconds7Days are consts for now 2021-03-09 22:06:20 +06:00
bc21a680bc fixes for MessageAutoDeleteTimerChanged 2021-03-09 22:00:17 +06:00
8bb60bea34 now MessageAutoDeleteTimerChanged implementing ChannelEvent and GroupEvent 2021-03-09 21:37:25 +06:00
8daadcff95 now MessageAutoDeleteTimerChanged implementing ChannelEvent and GroupEvent 2021-03-09 21:35:53 +06:00
2a1e624641 VoiceChatParticipantsInvited type now is data class 2021-03-09 20:23:03 +06:00
696822db02 add behaviour builder events updates 2021-03-09 20:04:44 +06:00
ded501d963 remove regular build 2021-03-09 19:52:46 +06:00
86e506c33d include message_auto_delete_timer_change 2021-03-09 19:45:19 +06:00
9902b00e85 include revokeMessages in kickChatMember 2021-03-09 19:33:05 +06:00
53524abcbb include canManageChat 2021-03-09 19:26:30 +06:00
7639b15dc6 voice chats functionality included 2021-03-09 19:19:15 +06:00
61b720c61f fix of content waiters and expecters 2021-03-09 16:54:32 +06:00
baf4c74b69 update micro_utils 2021-03-09 16:46:08 +06:00
367cfff2cb start 0.32.10 2021-03-09 16:45:13 +06:00
75e8d0f62d Merge pull request #325 from InsanusMokrassar/0.32.9
0.32.9
2021-03-05 01:08:58 +06:00
c521a5f9a4 Update CHANGELOG.md 2021-03-03 22:32:44 +06:00
c5513365c2 Update gradle.properties 2021-03-03 22:31:29 +06:00
d184ce7a0f Update mpp_publish_template.kpsb 2021-03-03 01:39:18 +06:00
a3bff3f24d Update publish.gradle 2021-03-03 01:37:38 +06:00
a835b1dcbb Update mpp_publish_template.kpsb 2021-03-03 01:33:50 +06:00
ffed2b80a5 update publish scripts to avoid useless repos 2021-03-02 16:45:13 +06:00
ff24b9f35b add workflow for packages publication 2021-03-02 16:25:55 +06:00
1287852334 update microutils version 2021-03-02 15:26:52 +06:00
fc2f177e38 update dependencies 2021-02-28 22:24:34 +06:00
1efd4dce6e start 0.32.9 2021-02-28 22:21:57 +06:00
69b5a16b17 Update gradle-wrapper.properties 2021-02-23 09:53:45 +06:00
77b531ad06 Merge pull request #307 from InsanusMokrassar/0.32.8
0.32.8
2021-02-22 01:35:40 +06:00
a98d5d9abd update micro_utils 2021-02-21 22:50:47 +06:00
104653ac41 update serialization 2021-02-21 21:15:40 +06:00
63337b8285 start 0.32.8 2021-02-21 21:13:23 +06:00
5cc0bbb31b Merge pull request #303 from InsanusMokrassar/0.32.7
0.32.7
2021-02-18 00:34:46 +06:00
563d784603 RestrictionsChatPermissions 2021-02-18 00:28:36 +06:00
0d9f18f346 DiceAnimationType class casts 2021-02-17 22:29:29 +06:00
23ceaf8e97 LeftRestrictionsChatPermissions 2021-02-17 22:12:58 +06:00
fe2dffd8b5 BehaviourContext updates 2021-02-17 22:11:26 +06:00
eeb46817c3 start 0.32.7 2021-02-17 22:00:46 +06:00
5ab00da31d Merge pull request #300 from InsanusMokrassar/0.32.6
0.32.6
2021-02-17 17:15:40 +06:00
841ae73f7c replyWithDice 2021-02-17 17:10:21 +06:00
41b4d29917 updates in slot machine utils 2021-02-17 16:58:57 +06:00
f8b3c44146 update micro_utils 2021-02-16 13:48:32 +06:00
f0eb670c3f start 0.32.6 2021-02-16 13:47:31 +06:00
fe5d94f31e Update README.md 2021-02-13 10:09:33 +06:00
7901d0a223 Update README.md 2021-02-13 01:42:35 +06:00
799f9123ba Update README.md 2021-02-13 01:38:31 +06:00
f77f010e66 Update README.md 2021-02-11 13:38:55 +06:00
67ddf8d809 Update README.md 2021-02-11 13:37:24 +06:00
81afa46253 Update README.md 2021-02-11 13:36:53 +06:00
a5bba76f07 Update README.md 2021-02-11 13:35:06 +06:00
d882cf9c97 update readme 2021-02-11 12:06:34 +06:00
2e27b8b64d Merge pull request #295 from InsanusMokrassar/0.32.5
0.32.5
2021-02-09 19:13:42 +06:00
4df800eaa9 fix of #291 2021-02-09 19:07:31 +06:00
8d27349868 update content resends and different other things 2021-02-09 18:26:10 +06:00
2a89c41a58 fix of #292 2021-02-09 17:15:28 +06:00
098b5cc393 rewrite createAccumulatedUpdatesRetrieverFlow onto channelFlow 2021-02-09 16:33:48 +06:00
10f4817283 solution of #293 2021-02-08 19:35:32 +06:00
4449893608 fix of #294 2021-02-08 18:15:54 +06:00
3a53f41f66 start 0.32.5 2021-02-08 11:36:20 +06:00
7cd366d893 Update README.md 2021-02-07 18:02:20 +06:00
1309a4111c Merge pull request #290 from InsanusMokrassar/0.32.4
content messages renames
2021-02-07 16:59:51 +06:00
0ca815760b content messages renames 2021-02-07 16:54:48 +06:00
eca0680f2f update readme 2021-02-07 12:44:38 +06:00
d472d371ed Merge pull request #282 from InsanusMokrassar/0.32.4
0.32.4
2021-02-07 12:43:08 +06:00
4748b6813a ExceptionsOnlyLimiter now will not use Result to provide success/failure state of result 2021-02-07 12:40:05 +06:00
a2ea15d4b0 update wrapper version 2021-02-07 11:02:13 +06:00
27dc302f5d update for compiling 2021-02-06 11:53:30 +06:00
baf8ed3a77 now JVM part will be compiled with IR 2021-02-06 00:52:39 +06:00
18913af3c3 update publishing scripts 2021-02-06 00:50:51 +06:00
51871ea94c update micro_utils version 2021-02-05 16:08:45 +06:00
6a625d7b9f update publishing scripts 2021-02-05 16:08:28 +06:00
0b93b472a3 update klock 2021-02-05 14:22:42 +06:00
ff16f9a315 Update README.md 2021-02-05 01:18:38 +06:00
86bfe043a5 update dependencies 2021-02-03 23:05:17 +06:00
fa18e7299d 0.32.4 2021-02-03 22:59:37 +06:00
c986025075 Merge pull request #277 from InsanusMokrassar/0.32.3
0.32.3
2021-02-02 11:44:53 +06:00
e8a7ea9ce4 inline qieries expectators and waiters 2021-02-02 11:17:51 +06:00
30f35e5488 start 0.32.3 2021-02-02 11:07:30 +06:00
b626974ea7 Create dependabot.yml 2021-02-01 23:22:26 +06:00
128b782a27 Merge pull request #276 from InsanusMokrassar/0.32.2
0.32.2
2021-02-01 21:43:21 +06:00
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
f8ea5f9515 fix in changelog 2020-11-10 21:45:07 +06:00
9f11c4f1c4 update ktor 2020-11-10 20:56:11 +06:00
9c91980d5d webhook fixes 2020-11-10 20:44:39 +06:00
7376eb5b10 start 0.30.2 2020-11-10 20:01:22 +06:00
6654f27f9d Merge pull request #202 from InsanusMokrassar/0.30.1
0.30.1
2020-11-09 15:16:26 +06:00
d29acce417 add suppressing of unused in EntitiesBuilder 2020-11-09 15:14:48 +06:00
f0f18209f3 a little bit improve EntitiesBuilder 2020-11-09 15:12:57 +06:00
324018a0f6 update publication scripts 2020-11-09 14:45:29 +06:00
b621325e92 update version of microutils and changelog 2020-11-09 08:37:30 +06:00
43e92555c2 Merge pull request #203 from Djaler/entities-dsl
Add builder-style dsl for text sources
2020-11-09 08:26:44 +06:00
Kirill Romanov
5f1ca51e60 Add builder-style dsl for text sources 2020-11-08 23:12:32 +03:00
83edda2dfe add link to bot template 2020-11-08 18:58:52 +06:00
1974c20229 start 0.30.1 2020-11-08 12:07:14 +06:00
499d9b1791 Update README.md 2020-11-08 00:03:41 +06:00
6caa7dd428 Merge pull request #163 from InsanusMokrassar/0.30.0
0.30.0
2020-11-07 23:00:35 +06:00
e8ded44562 rename StorageFile in jvm of common 2020-11-07 22:28:20 +06:00
1e6b0381ee StorageFile factories 2020-11-07 14:44:05 +06:00
1cf7ae7438 add micro_utils and deprecate old coroutine methods 2020-11-07 13:42:10 +06:00
311512b5db fix chat interfaces serializers 2020-11-07 01:34:22 +06:00
d73fa4076f add several extension properties to texted/captioned/explained interfaces 2020-11-06 19:13:59 +06:00
3620350cc0 add simple text dsl for textsources 2020-11-06 18:52:59 +06:00
54cfea9adf fill changelog 2020-11-06 14:42:30 +06:00
6665b6ef03 reorganize text sources and text parts 2020-11-06 14:37:13 +06:00
ee6f0f3d5d add separation of text sources 2020-11-06 12:59:55 +06:00
6ec0fcadd2 rewrite telegramBot functions 2020-11-06 12:29:51 +06:00
c89aa7b9ba telegramBot improvements 2020-11-06 12:07:46 +06:00
cf47cee36a Merge pull request #198 from madhead/issues/190
Fix #190: Support for Google Places values in venue-related methods and types
2020-11-06 11:23:29 +06:00
madhead
824fa9ba09 Fix #190: Support for Google Places values in venue-related methods and types 2020-11-06 00:06:33 +03:00
654d84b1b4 Merge pull request #197 from madhead/issues/175
Fix #175: Support for message_id field in unpinChatMessage method
2020-11-06 02:17:11 +06:00
madhead
c7259e7699 Fix #175: Support for message_id field in unpinChatMessage method 2020-11-05 23:15:23 +03:00
00a75801a8 fixes 2020-11-06 01:14:48 +06:00
e45f9cf46a return serialname for messageId in RawMessage 2020-11-06 00:37:56 +06:00
3b1803e851 remove deprecations 2020-11-06 00:12:14 +06:00
bf1e353615 fix build 2020-11-06 00:05:05 +06:00
99bb8d6e0d update extnsions.api 2020-11-05 23:48:23 +06:00
98d7b9c651 update coroutines :) 2020-11-05 21:42:31 +06:00
765caefc32 implementation of allow sending without reply (#191) 2020-11-05 21:33:11 +06:00
6bdefb6f8f new request CopyMessage (#187) 2020-11-05 20:27:45 +06:00
d5e283e7ba Update all classes which must have "entities"/"caption_entities" fields (#189) 2020-11-05 20:18:16 +06:00
a5982ac881 partially restructurize InlineQueryResult and several its implementators 2020-11-05 18:00:40 +06:00
c0e81b1d6d partially complete rewriting of things according to #189 2020-11-05 16:53:26 +06:00
eb879963f8 isAnonymous support in api 2020-11-05 12:48:44 +06:00
f835167f66 isAnonymous support 2020-11-05 12:47:14 +06:00
ff34b23777 implementation of sender_chat and author_signature 2020-11-05 12:39:59 +06:00
ec806dfd83 Merge pull request #195 from madhead/issues/184
Fix #184: Anonymous Admins: support for is_anonymous flag
2020-11-05 11:38:24 +06:00
madhead
0a73dfb799 Fix #184: Anonymous Admins: support for is_anonymous flag 2020-11-05 01:57:26 +03:00
53b8cc4625 update pollQuestionTextLength 2020-11-05 01:15:03 +06:00
201def826e locations updates 2020-11-05 01:12:14 +06:00
609a959b99 DiceAnimationType#valueLimits 2020-11-04 23:52:22 +06:00
6a05a7ecab add footbal dice animation type 2020-11-04 23:47:01 +06:00
159ea6f1cc UnpinAllChatMessages 2020-11-04 23:44:13 +06:00
0886781d61 add docs for PinChatMessage 2020-11-04 23:41:19 +06:00
60d5581ec6 supporting of private chats in pinChatMessage 2020-11-04 23:38:40 +06:00
2a33216006 disableContentTypeDetection 2020-11-04 23:33:48 +06:00
179bb66183 return SetWebhook without certificate 2020-11-04 23:21:25 +06:00
7a2ecd2dbf getChat updates completing 2020-11-04 23:10:39 +06:00
fd1a15cb5d ExtendedPrivateChat#bio 2020-11-04 22:46:08 +06:00
86a472e814 SetWebhook updates 2020-11-04 22:43:26 +06:00
6d6c544aaf logout and close 2020-11-04 22:17:17 +06:00
dd4d5cd15d start 0.30.0 2020-11-04 22:06:44 +06:00
23dfa4f69d Merge pull request #162 from InsanusMokrassar/0.29.4
0.29.4
2020-11-02 21:51:23 +06:00
531 changed files with 18639 additions and 3937 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"

12
.github/workflows/build.yml vendored Normal file
View File

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

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

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

View File

@@ -0,0 +1,21 @@
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: Publish
run: ./gradlew publishAllPublicationsToGithubPackagesRepository --no-parallel -x signJsPublication -x signJvmPublication -x signKotlinMultiplatformPublication
env:
GITHUBPACKAGES_USER: ${{ github.actor }}
GITHUBPACKAGES_PASSWORD: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1 +0,0 @@
spellchecker: true

View File

@@ -1,5 +1,663 @@
# TelegramBotAPI changelog
## 0.35.5
**MIME TYPES FOR REQUESTS HAVE BEEN DEPRECATED DUE TO REDUNDANCY OF MIME TYPES IN FILES SENDING**
* `Core`:
* Several new extensions `ByteReadChannel#asStorageFile` and `ByteReadChannelAllocator#asStorageFile`
* Several new extensions `ByteArray#asMultipartFile`, `ByteReadChannel#asMultipartFile` and
`ByteReadChannelAllocator#asMultipartFile`
* New extension `StorageFile#asMultipartFile`
* `API`:
* New extensions `TelegramBot#downloadFile` for writing of incoming bytes to the file
* New extensions `TelegramBot#downloadFileStream` and `TelegramBot#downloadFileStreamAllocator` for getting of input
streams instead of whole bytes arrays
* Old extensions `TelegramBot#downloadFile` has been replaced to the new package. Migration: replace in your project
`import dev.inmo.tgbotapi.extensions.api.downloadFile` with `import dev.inmo.tgbotapi.extensions.api.files.downloadFile`
* `PathedFile#filename` extension has been deprecated, and new property `PathedFile#fileName` has been included
directly in `PathedFile`
* `Utils`:
* Add several functions `convertToStorageFile` and extensions `TelegramBot#convertToStorageFile`
## 0.35.4 Hotfix
* `Common`:
* `Version`:
* `MicroUtils`: `0.5.18` -> `0.5.19`
## 0.35.3
* `Common`:
* `Version`:
* `Klock`: `2.2.0` -> `2.3.1`
* `Ktor`: `1.6.1` -> `1.6.2`
* `MicroUtils`: `0.5.16` -> `0.5.18`
* `Core`:
* **`SimpleRequestCallFactory` and `MultipartRequestCallFactory` became a classes instead of objects to avoid
collisions in different bots**
* Support of strongly-typed ietf language codes has been added
* `API`:
* New extension `TelegramBot#downloadFile` for any `MediaContent`
* `Behaviour Builder`:
* New provider `defaultCoroutineScopeProvider`
* Now it is not necessary to provide `CoroutineScope` to `TelegramBot#buildBehaviour`
extension
* New `TelegramBot#buildBehaviour` extension with `FlowUpdatesFilter` and `CoroutineScope` with
default `CoroutineScope`
* New typealias `SimpleFilter` for unifying triggers filter signatures
* All waiters got real filters (`SimpleFilter`) and rename old filters as mappers
* New extensions for `Any`: `as`/`when`/`require` for `WithOptionalLanguageCode` and `WithLanguageCode`
## 0.35.2
* `Common`:
* `Version`:
* `Kotlin`: `1.5.20` -> `1.5.21`
* `Coroutines`: `1.5.0` -> `1.5.1`
* `Serialization`: `1.2.1` -> `1.2.2`
* `Klock`: `2.1.2` -> `2.2.0`
* `Ktor`: `1.6.0` -> `1.6.1`
* `MicroUtils`: `0.5.15` -> `0.5.16`
## 0.35.1
* `Common`:
* `Version`:
* `Kotlin`: `1.5.10` -> `1.5.20`
* `MicroUtils`: `0.5.6` -> `0.5.15`
* `Core`:
* New interface `MyCommandsRequest` (also see `Bot API 5.3` below)
* New extensions `TextSourcesList#make*String` for all parse modes
* All `MessageContent` subclasses now serializable
* `ChosenInlineResult` was replaced and modified to be sealed
* `ChosenInlineResult` now extends `FromUser`
* Added `Update#sourceUser` method
* More types assumed as sent by user types now implements `FromUser` interface
* Added `Any#whenFromUser`, `Any#asFromUser` and`Any#requireFromUser` extensions
* `MedaGroupUpdate` and its direct extenders `SentMediaGroupUpdate` and `EditMediaGroupUpdate` became
`sealed interface`s
* New built-in `RequestException` implementator `GetUpdatesConflict` has been added
* `Behaviour Builder`:
* ❗️ All triggers (`on*` extensions) have been modified to work in parallel by some marker by default (new parameter
`markerFactory`, in most cases will work async for different chats)
* New extensions `telegramBotWithBehaviour`
* All behaviour builder extensions got new parameter `defaultExceptionsHandler`
* Class `BehaviourContext` was rewritten as an interface with default realization `DefaultBehaviourContext` and
factory `BehaviourContext(TelegramBot, CoroutineScope, FlowsUpdatesFilter)`
* Extension `buildBehaviour` (and all related extensions/functions) for opportunity to pass
`defaultExceptionsHandler`
* Trigger `onContentMessage` and waiter `waitContentMessage` now may include media groups
* `API`:
* All `reply` and subsequent extensions have been replaced in send package
* `Utils`:
* With class casts like `as*` and `require*` now you may use `when*` with parameter callback
* Methods of `EntitiesBuilder` now will return builder itself, so you may create sequences like
`buildEntities { bold("Hello,") + italic(" world") }` directly in `buildEntities` body
* New extension `TelegramBot#longPollingFlow` has been added with returning value `Flow` with updates
* `Bot API 5.3`:
* Add type `BotCommandScope`, its serializer `BotCommandScopeSerializer` and all its children
* New request `DeleteMyCommands` and updates in `GetMyCommands` and `SetMyCommands`
* Renames according to `And more` of [June 25, 2021](https://core.telegram.org/bots/api-changelog#june-25-2021) update
## 0.35.0
**ALL PREVIOUS DEPRECATIONS HAVE BEEN REMOVED**
**JS PART NOW USE IR COMPILER ONLY**
* `Common`:
* `Version`:
* `Kotlin`: `1.4.72` -> `1.5.10`
* `MicroUtils`: `0.4.36` -> `0.5.6`
* `Coroutines`: `1.4.3` -> `1.5.0`
* `Serialization`: `1.1.0` -> `1.2.1`
* `Klock`: `2.0.7` -> `2.1.2`
* `UUID`: `0.2.3` -> `0.3.0`
* `Ktor`: `1.5.4` -> `1.6.0`
* `Core`:
* `ForceReply` has been renamed to `ReplyForce`
* `Captioned` and `Explained` interfaces have been removed
* `RecordAudioAction` and `UploadAudioAction` (and all related to these actions functionality) have been removed
* `TextSource` interface and all related things have been replaced
* `CallbackQuery` interface and all its extenders/implementers become `sealed`
* `InputMedia` interface and all its extenders/implementers become `sealed`
* `ParseMode` interface and all its extenders/implementers become `sealed`
* `ChatMember` becomes `sealed`
* `KeyboardMarkup` becomes `sealed`
* `LeftChatMember` and `MemberChatMember` become interfaces. All their code were replaced to the `*Impl` classes
* Most of `sealed` classes have been modified to be interfaces
* Most serializers becomes public, but they are still `RistFeature`
* For `EntitiesBuilder` multilevel text sources builders with callback have been added
## 0.34.1
* `Common`:
* `Version`:
* `ktor`: `1.5.3` -> `1.5.4`
* `MicroUtils`: `0.4.35` -> `0.4.36`
* `Core`
* Fix in creating of text sources list
## 0.34.0
_**It is recommended to use [0.34.1](https://github.com/InsanusMokrassar/TelegramBotAPI/releases/tag/0.34.1) version due to the bug in 0.34.0 related to rewriting of `TextSource`s creating mechanism.**_
**UPDATE UP TO Telegram Bot API 5.2**
_**ALL OLD DEPRECATIONS WERE REMOVED**_
* `Core`:
* Type `ChatType` has been added
* New `ExtendedChat` for unknown messages `UnknownExtendedChat` has been added
* `SendInvoice#startParameter` becomes optional and replaced in `SendInvoice` constructor
* New interface `CommonSendInvoiceData` has been added
* Fields `CommonSendInvoiceData#maxTipAmount` and `CommonSendInvoiceData#suggestedTipAmounts` have been added
* New type `InputInvoiceMessageContent` has been added
* New interface `TextedWithTextSources` on top of `Texted` interface
* Interface `TextedInput` now extends `TextedWithTextSources` with overriding of `textSources` field as not
nullable
* `textSources` become main field in `TextedInput`
* **MIGRATION** Remove all `import dev.inmo.tgbotapi.CommonAbstracts.textSources` in your project
* `textEntities` become are calculable property in `TextedInput`
* Interface `Captioned` and `CaptionedInput` now is deprecated
* Most of captions usages were replaced with texts
* Interface `Explained` and `ExplainedInput` now is deprecated
* Most of captions usages were replaced with texts
* Interface `VoiceChatEvent` now is `CommonEvent`
* Mechanism of `RawMessageEntity` converting were fully rewritten
## 0.33.4
* `Common`:
* `Version`:
* `uuid`: `0.2.3` -> `0.2.4`
* `MicroUtils`: `0.4.33` -> `0.4.35`
* `Core`:
* All `TextSource` implementators have become `Serializable`
* New serializer `TextSourceSerializer`
* Interface`FromUserMessage` now extends `Message`
* New interface `FromUser`
* Interface `FromUserMessage` now extends `FromUser`
* `Extensions Utils`
* Fixes in `parseCommandsWithParams`
## 0.33.3
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.32` -> `0.4.33`
* `Ktor`: `1.5.2` -> `1.5.3`
* `API`:
* Bot actions DSL (fix for [#358](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/358))
* `Behaviour Builder`:
* Rewrite logic of `doInSubContextWithUpdatesFilter` and `doInSubContextWithFlowsUpdatesFilterSetup` extensions
* All triggers now work with `stopOnCompletion` set up to `false`
## 0.33.2
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.30` -> `0.4.32`
* `Behaviour Builder`:
* New typealias `MediaGroupFilter` has been added for `MediaGroup` expectators
* Several typealiases became `suspend`:
* `CallbackQueryMapper`
* `ChatMemberUpdatedMapper`
* `InlineQueryMapper`
* Commands got an additional parameter - `additionalFilter`. It will be called when all command filters were passed
## 0.33.1
* `Common`:
* `Version`:
* `Kotlin`: `1.4.31` -> `1.4.32`
* `MicroUtils`: `0.4.29` -> `0.4.30`
* `Klocks`: `2.0.6` -> `2.0.7`
* `Utils Extensions`:
* Add extensions `parseCommandsWithParams`
## 0.33.0
**UPDATE UP TO Telegram Bot API 5.1**
_**ALL DEPRECATIONS WERE REMOVED**_
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.28` -> `0.4.29`
* `Core`:
* `AdministratorChatMemberSerializer` and `ChatMemberSerializer` has changed their visibility: they are public for now
* Add `ChatInviteLinkRequest` with subrequests like `KnownChatInviteLinkRequest`
* Add `CreateChatInviteLink`/`EditChatInviteLink`/`RevokeChatInviteLink` requests
* Update `KickChatMember` to include `revokeMessages` flag
* Update `PromoteChatMember` to include `canManageVoiceChats` and `canManageChat` flags
* Add `ChatInviteLink` object
* Add `PrimaryInviteLink` for `ChatInviteLink` with `isPrimary == true`
* Add `CommonInviteLink` for `ChatInviteLink` with `isPrimary == false`
* `AdministratorChatMemberSerializer` has been set as public for several versions
* `ChatMemberSerializer` has been set as public for several versions
* Add `ChatMemberUpdated`
* Add `MessageAutoDeleteTimerChanged`
* Add `VoiceChatEvent`
* Add `VoiceChatEnded`
* Add `VoiceChatParticipantsInvited`
* Add `VoiceChatStarted`
* Add `ChatMemberUpdatedUpdate`
* Add `CommonChatMemberUpdatedUpdate`
* Add `MyChatMemberUpdatedUpdate`
* `API`:
* All API extensions has been updated
* `Behaviour Builder`:
* Now content triggers and expectators will wait for channel posts too
* New waiters and triggers for `ChatMemberUpdated` and its variations
## 0.32.9
* `Common`:
* `Version`:
* `Kotlin`: `1.4.30` -> `1.4.31`
* `Ktor`: `1.5.1` -> `1.5.2`
* `MicroUtils`: `0.4.26` -> `0.4.28`
* `Coroutines`: `1.4.2` -> `1.4.3`
## 0.32.8
* `Common`:
* `Version`:
* `Serialization`: `1.1.0-RC` -> `1.1.0`
* `MicroUtils`: `0.4.25` -> `0.4.26`
## 0.32.7
* `Core`:
* New variable `LeftRestrictionsChatPermissions` and `RestrictionsChatPermissions`
* `Extensions Utils`:
* `DiceAnimationType` class casts
* `Behaviour Builder`:
* Now `doInSubContextWithUpdatesFilter` and `doInSubContext` will automatically subscribe on updates of parent
`BehaviourContext`
* `doInSubContextWithFlowsUpdatesFilterSetup`, `doInSubContextWithUpdatesFilter` and `doInSubContext` got new
parameter `stopOnCompletion` to be able to disable stopping of behaviour context on finishing
## 0.32.6
* `Common`:
* `Version`:
* `MicroUtils`: `0.4.24` -> `0.4.25`
* `Extensions API`:
* New extension `TelegramBot#replyWithDice`
* `Extensions Utils`:
* `SlotMachineReelImages` has been renamed to `SlotMachineReelImage`
* `SlotMachineReelImage` got two built-in parameters: `text` and `number`
* New extension `String#asSlotMachineReelImage`
## 0.32.5
* `Core`:
* Add `mention` variants for user ids and receiver variants ([#294](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/294))
* Now `AbstractRequestCallFactory` will set up one-second delay for zero timeouts in `GetUpdate` requests
* Several extensions for `TelegramBotAPI` like `retrieveAccumulatedUpdates` have been added as a solution for
[#293](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/293)
* Links for `tg://user?id=<user_id>` have been updated ([#292](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/292))
* All usages of captions or texts in resends and same things have been replaced with `textSources`
* Global `defaultParseMode` has been added ([#291](https://github.com/InsanusMokrassar/TelegramBotAPI/issues/291))
## 0.32.4
* `Common`:
* `Version`:
* `Kotlin`: `1.4.21` -> `1.4.30`
* `Klock`: `2.0.4` -> `2.0.6`
* `MicroUtils`: `0.4.23` -> `0.4.24`
* `Core`:
* Renames:
* `ChannelMessage` -> `ChannelContentMessage`
* `PublicMessage` -> `PublicContentMessage`
* `GroupMessage` -> `GroupContentMessage`
* `FromChannelGroupMessage` -> `FromChannelGroupContentMessage`
* `AnonymousGroupMessage` -> `AnonymousGroupContentMessage`
* `CommonGroupMessage` -> `CommonGroupContentMessage`
* `PrivateMessage` -> `PrivateContentMessage`
* `Extensions Utils`:
* Renames of extensions in `ClassCasts` according to changes in `Core`
## 0.32.3
* `Behaviour Builder`:
* Add expectators and waiters for inline queries
## 0.32.2
* `Core`:
* 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
* `Common`:
* `Version`:
* `Ktor`: `1.4.1` -> `1.4.2`
* `Core`:
* New sealed class `SetWebhookRequest` which can be used in `SetWebhook` requests
* `Utils`:
* Extensions `setWebhookInfoAndStartListenWebhooks` has been united in one extension with `SetWebhookRequest`
incoming parameter
## 0.30.1
* `Common`:
* `Version`:
* `MicroUtils`: `0.2.7` -> `0.3.0`
* `Utils`:
* Builder-style DSL for text sources - `buildEntities` (thanks to [djaler](https://github.com/djaler))
## 0.30.0 Bot API 5.0
**THIS UPDATE CONTAINS A LOT OF BREAKING CHANGES. PLEASE, BE CAREFUL ON UPGRADING OF YOUR PROJECT**
* `Common`:
* `Version`:
* `Coroutine`: `1.4.0` -> `1.4.1`
* **NEW** `MicroUtils`: `0.2.7`
* `Core`:
* Support of `logOut` method (`LogOut` object as a `Request`)
* Support of `close` method (`Close` object as a `Request`)
* `SetWebhook` updates:
* New field `ipAddress`. It works the same as `ip_address` in [setWebhook](https://core.telegram.org/bots/api#setwebhook)
section
* New field `dropPendingUpdates`. It works the same as `drop_pending_updates` in [setWebhook](https://core.telegram.org/bots/api#setwebhook)
section
* New field `ExtendedPrivateChat#bio`
* New data class `ChatLocation`
* New field `UnbanChatMember#onlyIfBanned`
* New fields `ExtendedChannelChat#linkedGroupChatId` and `ExtendedSupergroupChat#linkedChannelChatId`
* New fields `ExtendedSupergroupChat#location`
* New fields `AudioFile#fileName` and `VideoFile#fileName`
* New fields `SendDocument#disableContentTypeDetection` and `InputMediaDocument#disableContentTypeDetection`
* New request `UnpinAllChatMessages`
* New parameter for `unpinChatMessage` method: `messageId`
* New dice type `FootballDiceAnimationType`
* Limits for dices has been changed
* `commonDiceResultLimit` has been deprecated
* New field `DiceAnimationType#valueLimits`
* Locations updates:
* New interface `Headed` with property `heading`
* New interface `HorizontallyAccured` with property `horizontalAccuracy`
* New interface `ProximityAlertable` with property `proximityAlertRadius`
* `Location` class has been separated:
* `StaticLocation` for static locations
* `LiveLocation` for live locations
* Property `Livable#livePeriod` now use typealias type `Seconds` (the same by meaning - `Int`)
* `EditLocationMessage` now extends `Locationed`, `HorizontallyAccured`, `ProximityAlertable` and `Headed` interfaces
* New properties in `EditChatMessageLiveLocation`: `horizontalAccuracy`, `heading`, `proximityAlertRadius`
* New properties in `EditInlineMessageLiveLocation`: `horizontalAccuracy`, `heading`, `proximityAlertRadius`
* Main constructor of `SendLocation` now is internal. Instead of that currently available next factories:
* `SendLocation` - sending of static location without live parameters
* `SendStaticLocation` - sending of static location without live parameters
* `SendLiveLocation` - sending of live location with live parameters
* `PositionedSendMessageRequest` now extends `Locationed`
* `LocationContent#createResend` now can create `LiveLocation`
* Support of `ProximityAlertTriggered`. It is `CommonEvent`
* Property `pollQuestionTextLength` now have maximum up to `300`
* Anonymous Admins:
* New field `AdministratorChatMember#isAnonymous`
* Several new interfaces of messages:
* `SignedMessage` - any message which possibly have `authorSignature`
* `WithSenderChatMessage` - any message which have `senderChat`. Property `senderChat` is not-nullable due to
separation of implementators
* `PublicMessage` - all channel messages have property `val chat: PublicChat` instead of common `val chat: Chat`
* `ChannelMessage` - all channel messages have property `val chat: ChannelChat` instead of common `val chat: Chat`
* Old `ChannelMessage` was safely renamed to `ChannelMessageImpl` (old name was set as typealias and deprecated)
* `GroupMessage` - all group messages have property `val chat: GroupChat` instead of common `val chat: Chat`
* `FromChannelGroupMessage` - instances should have property `val channel: ChannelChat`
* `AnonymousGroupMessage` - instances may have setup property `authorSignature`
* `CommonGroupMessage` - just common message
* `PrivateMessage` - works like previous `CommonMessageImpl`
* Previous `CommonMessageImpl` safely renamed to `PrivateMessageImpl`
* New property `PromoteChatMember#isAnonymous`
* Update all classes which must have `entities`/`caption_entities` fields
* New request `CopyMessage`
* New extension `List<TextSource>#makeString` for more comfortable work with new api with entities
* Support for Google Places identifiers for venues
* New extensions for text sources separating:
* `List<TextSource>#separateForMessage`
* `List<TextSource>#separateForCaption`
* `List<TextSource>#separateForText`
* Rewritten work with text sources and text parts:
* Now any `Message` type with entities will have full list of entities. That means that parts without any
formatter entities will use `RegularTextSource`
* `MultilevelTextSource#textParts` has been deprecated. Now each `MultilevelTextSource` have its own
`textSources` list
* New dsl for creating of `TextSource` lists
* Built-in `handleSafely` and `ExceptionHandler` is deprecated
* New common factories for `StorageFile`
* `API`:
* Extensions `TelegramBot#pinChatMessage` now support any `Chat` and `Message`s from any `Chat`
* New extensions `TelegramBot#unpinAllChatMessages`
* Extensions `TelegramBot#promoteChatMember` got `isAnonymous` parameter
* All old api methods has been actualized to their analogs in `Core`
* All `telegramBot` with `token: String` got `apiUrl` parameter
* Factory `telegramBotWithCustomClientConfig` has been renamed to `telegramBot`
## 0.29.4
* `Core`:

211
README.md
View File

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

View File

@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<minder version="1.11.1">
<minder version="1.11.3">
<theme name="default" label="Default" index="-1"/>
<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"/>
@@ -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="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>
<drawarea x="-320.56697591145837" y="-10.028254191080691" scale="0.75"/>
<drawarea x="-950.47548925255796" y="-49.650554065281653" scale="0.5"/>
<images/>
<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"/>
<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"/>
</nodename>
<nodenote></nodenote>
<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"/>
<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"/>
</nodename>
<nodenote></nodenote>
<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"/>
<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"/>
</nodename>
<nodenote></nodenote>
</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"/>
<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"/>
</nodename>
<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>
</nodes>
</node>
</nodes>
</node>
<node id="4" posx="815.52319335937455" posy="948.04447937011719" width="329" height="213" side="top" fold="false" treesize="329" 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"/>
<nodename posx="831.52319335937455" posy="964.04447937011719" maxwidth="394.3671875">
<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">
<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="430" nodeborderwidth="3" nodefill="false" nodemargin="11" nodepadding="5" nodefont="Roboto Mono 14" nodemarkup="true"/>
<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&#10;* tgbotapi.extensions.behaviour_builder">
<color>
<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="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="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>
</text>
</nodename>
@@ -110,12 +291,17 @@
</nodes>
<groups/>
<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"/>
<title></title>
<note></note>
</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"/>
<title></title>
<note></note>

20
badges/template.svg Normal file
View File

@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="104" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="a">
<rect width="104" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#a)">
<path fill="#555" d="M0 0h65v20H0z"/>
<path fill="#007ec6" d="M35 0h69v20H35z"/>
<path fill="url(#b)" d="M0 0h104v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110">
<text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">Bot</text>
<text x="175" y="140" transform="scale(.1)">Bot</text>
<text x="690" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)">Template</text>
<text x="690" y="140" transform="scale(.1)">Template</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1016 B

View File

@@ -9,7 +9,6 @@ buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$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"
}
}
@@ -19,6 +18,17 @@ plugins {
id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version" apply false
}
// temporal crutch until legacy tests will be stabled or legacy target will be removed
allprojects {
if (it != rootProject.findProject("docs")) {
tasks.whenTaskAdded { task ->
if(task.name == "jsLegacyBrowserTest" || task.name == "jsLegacyNodeTest") {
task.enabled = false
}
}
}
}
private String getCurrentVersionChangelog() {
OutputStream changelogDataOS = new ByteArrayOutputStream()
exec {

View File

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

View File

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

View File

@@ -5,17 +5,18 @@ kotlin.js.generate.externals=true
kotlin.incremental=true
kotlin.incremental.js=true
kotlin_version=1.4.10
kotlin_coroutines_version=1.4.0
kotlin_serialisation_runtime_version=1.0.1
klock_version=1.12.1
uuid_version=0.2.2
ktor_version=1.4.1
kotlin_version=1.5.21
kotlin_coroutines_version=1.5.1
kotlin_serialisation_runtime_version=1.2.2
klock_version=2.3.1
uuid_version=0.3.0
ktor_version=1.6.2
micro_utils_version=0.5.19
javax_activation_version=1.1.1
library_group=dev.inmo
library_version=0.29.4
library_version=0.35.5
gradle_bintray_plugin_version=1.8.5
github_release_plugin_version=2.2.12

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-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

@@ -1,4 +1,11 @@
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.jetbrains.dokka") {
useModule("org.jetbrains.dokka:dokka-gradle-plugin:${requested.version}")
}
}
}
repositories {
gradlePluginPortal()
jcenter()
@@ -8,5 +15,6 @@ pluginManagement {
include ":tgbotapi.core"
include ":tgbotapi.extensions.api"
include ":tgbotapi.extensions.utils"
include ":tgbotapi.extensions.behaviour_builder"
include ":tgbotapi"
include ":docs"

View File

@@ -1,6 +1,5 @@
# TelegramBotAPI Core
[![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)
## What is it?
@@ -10,10 +9,7 @@ moments are describing by official [Telegram Bot API](https://core.telegram.org/
## Compatibility
This version compatible with [4th of June 2020 update of TelegramBotAPI (version 4.9)](https://core.telegram.org/bots/api#june-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.
This version compatible with [25th of June 2021 update of TelegramBotAPI (version 5.3)](https://core.telegram.org/bots/api-changelog#june-25-2021).
## How to implement library?
@@ -149,3 +145,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)
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 {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:$gradle_bintray_plugin_version"
}
}
@@ -31,7 +30,7 @@ repositories {
kotlin {
jvm()
js(BOTH) {
js(IR) {
browser()
nodejs()
}
@@ -47,6 +46,13 @@ kotlin {
api "com.soywiz.korlibs.klock:klock:$klock_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.serialization.base64:$micro_utils_version"
api "dev.inmo:micro_utils.serialization.encapsulator:$micro_utils_version"
api "dev.inmo:micro_utils.serialization.typed_serializer:$micro_utils_version"
api "dev.inmo:micro_utils.language_codes:$micro_utils_version"
api "io.ktor:ktor-client-core:$ktor_version"
}
}
@@ -54,6 +60,7 @@ kotlin {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
implementation project(":tgbotapi.extensions.utils")
}
}
@@ -72,7 +79,6 @@ kotlin {
implementation kotlin('test-junit')
}
}
jsTest {
dependencies {
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},"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"}]},"type":"Multiplatform"}
{"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,58 +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 {
user = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : System.getenv('BINTRAY_USER')
key = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : System.getenv('BINTRAY_KEY')
filesSpec {
from "${buildDir}/publications/"
eachFile {
String directorySubname = it.getFile().parentFile.name
if (it.getName() == "module.json") {
if (directorySubname == "kotlinMultiplatform") {
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.module")
} else {
it.setPath("${project.name}-${directorySubname}/${project.version}/${project.name}-${directorySubname}-${project.version}.module")
}
} else {
if (directorySubname == "kotlinMultiplatform" && it.getName() == "pom-default.xml") {
it.setPath("${project.name}/${project.version}/${project.name}-${project.version}.pom")
} else {
it.exclude()
}
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"
}
}
}
into "${project.group}".replace(".", "/")
}
publish = true
pkg {
repo = "TelegramBotAPI"
name = "${project.name}"
vcsUrl = "https://github.com/InsanusMokrassar/TelegramBotAPI"
licenses = ["Apache-2.0"]
version {
name = "${project.version}"
released = new Date()
vcsTag = "${project.version}"
gpg {
sign = true
passphrase = project.hasProperty('signing.gnupg.passphrase') ? project.property('signing.gnupg.passphrase') : System.getenv('signing.gnupg.passphrase')
repositories {
if ((project.hasProperty('GITHUBPACKAGES_USER') || System.getenv('GITHUBPACKAGES_USER') != null) && (project.hasProperty('GITHUBPACKAGES_PASSWORD') || System.getenv('GITHUBPACKAGES_PASSWORD') != null)) {
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/InsanusMokrassar/TelegramBotAPI")
credentials {
username = project.hasProperty('GITHUBPACKAGES_USER') ? project.property('GITHUBPACKAGES_USER') : System.getenv('GITHUBPACKAGES_USER')
password = project.hasProperty('GITHUBPACKAGES_PASSWORD') ? project.property('GITHUBPACKAGES_PASSWORD') : System.getenv('GITHUBPACKAGES_PASSWORD')
}
}
}
if ((project.hasProperty('SONATYPE_USER') || System.getenv('SONATYPE_USER') != null) && (project.hasProperty('SONATYPE_PASSWORD') || System.getenv('SONATYPE_PASSWORD') != null)) {
maven {
name = "sonatype"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/")
credentials {
username = project.hasProperty('SONATYPE_USER') ? project.property('SONATYPE_USER') : System.getenv('SONATYPE_USER')
password = project.hasProperty('SONATYPE_PASSWORD') ? project.property('SONATYPE_PASSWORD') : System.getenv('SONATYPE_PASSWORD')
}
}
}
}
}
}
bintrayUpload.doFirst {
publications = publishing.publications.collect {
if (it.name.contains('kotlinMultiplatform')) {
null
} else {
it.name
}
} - null
signing {
useGpgCmd()
sign publishing.publications
}
bintrayUpload.dependsOn publishToMavenLocal

View File

@@ -1,26 +0,0 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.utils.fullListOfSubSource
interface Captioned {
val caption: String?
}
interface CaptionedOutput : Captioned {
val parseMode: ParseMode?
}
interface CaptionedInput : Captioned {
/**
* Not full list of entities. This list WILL NOT contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
* @see [CaptionedInput.fullEntitiesList]
*/
val captionEntities: List<TextPart>
}
/**
* Convert its [CaptionedInput.captionEntities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
fun CaptionedInput.fullEntitiesList(): FullTextSourcesList = caption ?.fullListOfSubSource(captionEntities) ?.map { it.source } ?: emptyList()

View File

@@ -0,0 +1,36 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.payments.abstracts.Currencied
import dev.inmo.tgbotapi.types.payments.abstracts.Priced
interface CommonSendInvoiceData : Titled, Currencied, Priced {
val description: String
val payload: String
val providerToken: String
val maxTipAmount: Int?
val suggestedTipAmounts: List<Int>?
val providerData: String?
val requireName: Boolean
val requirePhoneNumber: Boolean
val requireEmail: Boolean
val requireShippingAddress: Boolean
val shouldSendPhoneNumberToProvider: Boolean
val shouldSendEmailToProvider: Boolean
val priceDependOnShipAddress: Boolean
val photoUrl: String?
val photoSize: Long?
val photoWidth: Int?
val photoHeight: Int?
fun setPhoto(
photoUrl: String,
photoSize: Long? = null,
photoWidth: Int? = null,
photoHeight: Int? = null
)
fun unsetPhoto()
}

View File

@@ -1,8 +1,12 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.*
interface CommonVenueData : Titled {
override val title: String
val address: String
val foursquareId: String?
val foursquareType: String? // TODO:: Rewrite with enum or interface
val foursquareId: FoursquareId?
val foursquareType: FoursquareType? // TODO:: Rewrite with enum or interface
val googlePlaceId: GooglePlaceId?
val googlePlaceType: GooglePlaceType?
}

View File

@@ -1,26 +0,0 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.utils.fullListOfSubSource
interface Explained {
val explanation: String?
}
interface ExplainedOutput : Explained {
val parseMode: ParseMode?
}
interface ExplainedInput : Explained {
/**
* Not full list of entities. This list WILL NOT contain [TextPart]s with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
* @see [ExplainedInput.fullEntitiesList]
*/
val explanationEntities: List<TextPart>
}
/**
* Convert its [ExplainedInput.explanationEntities] to list of [dev.inmo.tgbotapi.CommonAbstracts.TextSource]
* with [dev.inmo.tgbotapi.types.MessageEntity.textsources.RegularTextSource]
*/
fun ExplainedInput.fullEntitiesList(): FullTextSourcesList = explanation ?.fullListOfSubSource(explanationEntities) ?.map { it.source } ?: emptyList()

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.User
interface FromUser {
val user: User
}

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.Degrees
interface Headed {
val heading: Degrees?
}

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.Meters
interface HorizontallyAccured {
val horizontalAccuracy: Meters?
}

View File

@@ -1,8 +1,10 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.Seconds
interface Livable {
/**
* Period in SECONDS
* Period in [Seconds]
*/
val livePeriod: Int?
val livePeriod: Seconds?
}

View File

@@ -0,0 +1,7 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.Meters
interface ProximityAlertable {
val proximityAlertRadius: Meters?
}

View File

@@ -1,23 +1,79 @@
package dev.inmo.tgbotapi.CommonAbstracts
typealias FullTextSourcesList = List<TextSource>
typealias FullTextPartsList = List<TextPart>
import dev.inmo.tgbotapi.types.MessageEntity.textsources.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.MultilevelTextSource
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.MessageEntity.textsources.separateForCaption
import dev.inmo.tgbotapi.types.MessageEntity.textsources.separateForMessage
import dev.inmo.tgbotapi.types.MessageEntity.textsources.separateForText
import dev.inmo.tgbotapi.types.captionLength
import dev.inmo.tgbotapi.types.textLength
import dev.inmo.tgbotapi.utils.extensions.makeString
interface TextSource {
val asMarkdownSource: String
val asMarkdownV2Source: String
val asHtmlSource: String
val source: String
}
const val DirectInvocationOfTextSourceConstructor =
"It is strongly not recommended to use constructors directly instead of factory methods"
interface MultilevelTextSource : TextSource {
val textParts: List<TextPart>
}
data class TextPart(
val range: IntRange,
val source: TextSource
@Deprecated(
"Replaced",
ReplaceWith("TextSourcesList", "dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList")
)
typealias TextSourcesList = TextSourcesList
fun List<TextPart>.justTextSources() = map { it.source }
@Deprecated("Replaced", ReplaceWith("TextSource", "dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource"))
typealias TextSource = TextSource
@Suppress("NOTHING_TO_INLINE")
@Deprecated("Replaced", ReplaceWith("plus", "dev.inmo.tgbotapi.types.MessageEntity.textsources.plus"))
inline operator fun TextSource.plus(other: TextSource) =
listOf(this, other)
@Suppress("NOTHING_TO_INLINE")
@Deprecated("Replaced", ReplaceWith("plus", "dev.inmo.tgbotapi.types.MessageEntity.textsources.plus"))
inline operator fun TextSource.plus(other: List<TextSource>) =
listOf(this) + other
@Suppress("NOTHING_TO_INLINE")
@Deprecated("Replaced", ReplaceWith("plus", "dev.inmo.tgbotapi.types.MessageEntity.textsources.plus"))
inline operator fun TextSource.plus(text: String) =
listOf(this, regular(text))
@Suppress("NOTHING_TO_INLINE")
@Deprecated("Replaced", ReplaceWith("plus", "dev.inmo.tgbotapi.types.MessageEntity.textsources.plus"))
inline operator fun List<TextSource>.plus(text: String) = this + regular(text)
@Deprecated(
"Replaced",
ReplaceWith("MultilevelTextSource", "dev.inmo.tgbotapi.types.MessageEntity.textsources.MultilevelTextSource")
)
typealias MultilevelTextSource = MultilevelTextSource
@Deprecated("Replaced", ReplaceWith("makeString()", "dev.inmo.tgbotapi.utils.extensions.makeString"))
fun List<TextSource>.makeString() = makeString()
@Deprecated(
"Replaced",
ReplaceWith("separateForMessage", "dev.inmo.tgbotapi.types.MessageEntity.textsources.separateForMessage")
)
fun List<TextSource>.separateForMessage(limit: IntRange, numberOfParts: Int? = null) =
separateForMessage(limit, numberOfParts)
/**
* This method will prepare [TextSource]s list for messages. Remember, that first part will be separated with
* [captionLength] and all others with
*/
@Deprecated(
"Replaced",
ReplaceWith("separateForCaption", "dev.inmo.tgbotapi.types.MessageEntity.textsources.separateForCaption")
)
fun List<TextSource>.separateForCaption() = separateForCaption()
/**
* This method will prepare [TextSource]s list for messages with [textLength]
*/
@Suppress("NOTHING_TO_INLINE")
@Deprecated(
"Replaced",
ReplaceWith("separateForText", "dev.inmo.tgbotapi.types.MessageEntity.textsources.separateForText")
)
inline fun List<TextSource>.separateForText() = separateForText()

View File

@@ -0,0 +1,29 @@
package dev.inmo.tgbotapi.CommonAbstracts
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
interface Texted {
val text: String?
}
interface TextedWithTextSources : Texted {
/**
* Full list of [TextSource]s
*/
val textSources: List<TextSource>?
}
interface ParsableOutput : Texted {
val parseMode: ParseMode?
}
interface EntitiesOutput : TextedWithTextSources {
val entities: List<TextSource>?
get() = textSources
}
interface TextedOutput : ParsableOutput, EntitiesOutput
interface TextedInput : TextedWithTextSources {
override val textSources: List<TextSource>
}

View File

@@ -4,4 +4,5 @@ import dev.inmo.tgbotapi.types.MessageIdentifier
interface ReplyMessageId {
val replyToMessageId: MessageIdentifier?
val allowSendingWithoutReply: Boolean?
}

View File

@@ -1,30 +1,66 @@
package dev.inmo.tgbotapi.bot.Ktor
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.tgbotapi.bot.BaseRequestsExecutor
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.settings.limiters.EmptyLimiter
import dev.inmo.tgbotapi.bot.settings.limiters.ExceptionsOnlyLimiter
import dev.inmo.tgbotapi.bot.settings.limiters.RequestLimiter
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.types.Response
import dev.inmo.tgbotapi.utils.*
import io.ktor.client.HttpClient
import io.ktor.client.features.*
import io.ktor.client.statement.HttpStatement
import io.ktor.client.statement.readText
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)
@RiskFeature
fun createTelegramBotDefaultKtorCallRequestsFactories() = listOf(
SimpleRequestCallFactory(),
MultipartRequestCallFactory(),
DownloadFileRequestCallFactory,
DownloadFileChannelRequestCallFactory
)
class KtorRequestsExecutor(
telegramAPIUrlsKeeper: TelegramAPIUrlsKeeper,
client: HttpClient = HttpClient(),
callsFactories: List<KtorCallFactory> = emptyList(),
excludeDefaultFactories: Boolean = false,
private val requestsLimiter: RequestLimiter = EmptyLimiter,
private val requestsLimiter: RequestLimiter = ExceptionsOnlyLimiter(),
private val jsonFormatter: Json = nonstrictJsonFormat
) : BaseRequestsExecutor(telegramAPIUrlsKeeper) {
private val callsFactories: List<KtorCallFactory> = callsFactories.run {
if (!excludeDefaultFactories) {
this + listOf(SimpleRequestCallFactory, MultipartRequestCallFactory, DownloadFileRequestCallFactory)
this + createTelegramBotDefaultKtorCallRequestsFactories()
} else {
this
}
@@ -37,10 +73,10 @@ class KtorRequestsExecutor(
}
override suspend fun <T : Any> execute(request: Request<T>): T {
return handleSafely(
return safely(
{ e ->
throw if (e is ClientRequestException) {
val content = e.response ?.readText() ?: throw e
val content = e.response.readText()
val responseObject = jsonFormatter.decodeFromString(Response.serializer(), content)
newRequestException(
responseObject,

View File

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

View File

@@ -0,0 +1,39 @@
package dev.inmo.tgbotapi.bot.Ktor.base
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
import dev.inmo.tgbotapi.requests.DownloadFileStream
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient
import io.ktor.client.call.receive
import io.ktor.client.request.get
import io.ktor.client.statement.HttpStatement
import io.ktor.utils.io.*
import kotlinx.coroutines.*
import kotlinx.serialization.json.Json
import kotlin.coroutines.coroutineContext
object DownloadFileChannelRequestCallFactory : KtorCallFactory {
override suspend fun <T : Any> makeCall(
client: HttpClient,
urlsKeeper: TelegramAPIUrlsKeeper,
request: Request<T>,
jsonFormatter: Json
): T? = (request as? DownloadFileStream) ?.let {
val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath)
ByteReadChannelAllocator {
val scope = CoroutineScope(coroutineContext)
val outChannel = ByteChannel()
scope.launchSafelyWithoutExceptions {
client.get<HttpStatement>(fullUrl).execute { httpResponse ->
val channel: ByteReadChannel = httpResponse.receive()
channel.copyAndClose(outChannel)
}
}
outChannel
} as T
}
}

View File

@@ -1,15 +1,12 @@
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.RequestsExecutor
import dev.inmo.tgbotapi.requests.DownloadFile
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.utils.handleSafely
import io.ktor.client.HttpClient
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.HttpMethod
import io.ktor.client.request.get
import kotlinx.serialization.json.Json
object DownloadFileRequestCallFactory : KtorCallFactory {
@@ -19,9 +16,9 @@ object DownloadFileRequestCallFactory : KtorCallFactory {
request: Request<T>,
jsonFormatter: Json
): T? = (request as? DownloadFile) ?.let {
val fullUrl = "${urlsKeeper.fileBaseUrl}/${it.filePath}"
val fullUrl = urlsKeeper.createFileLinkUrl(it.filePath)
return handleSafely {
safely {
@Suppress("UNCHECKED_CAST")
client.get<ByteArray>(fullUrl) as T // always ByteArray
}

View File

@@ -1,5 +1,6 @@
package dev.inmo.tgbotapi.bot.Ktor.base
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import dev.inmo.tgbotapi.utils.mapWithCommonValues
@@ -9,7 +10,7 @@ import io.ktor.client.request.forms.formData
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
object MultipartRequestCallFactory : AbstractRequestCallFactory() {
class MultipartRequestCallFactory : AbstractRequestCallFactory() {
override fun <T : Any> prepareCallBody(
client: HttpClient,
urlsKeeper: TelegramAPIUrlsKeeper,
@@ -23,12 +24,10 @@ object MultipartRequestCallFactory : AbstractRequestCallFactory() {
is MultipartFile -> appendInput(
key,
Headers.build {
append(HttpHeaders.ContentType, value.mimeType)
append(HttpHeaders.ContentDisposition, "filename=${value.fileId}")
}
) {
value.file.asInput()
}
},
block = value.file::input
)
is FileId -> append(key, value.fileId)
else -> append(key, value.toString())
}
@@ -36,4 +35,7 @@ object MultipartRequestCallFactory : AbstractRequestCallFactory() {
}
)
}
}
@Deprecated("Use class MultipartRequestCallFactory() constructor call instead of just MultipartRequestCallFactory")
companion object : KtorCallFactory by MultipartRequestCallFactory()
}

View File

@@ -1,12 +1,13 @@
package dev.inmo.tgbotapi.bot.Ktor.base
import dev.inmo.tgbotapi.bot.Ktor.KtorCallFactory
import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.client.HttpClient
import io.ktor.http.ContentType
import io.ktor.http.content.TextContent
object SimpleRequestCallFactory : AbstractRequestCallFactory() {
class SimpleRequestCallFactory : AbstractRequestCallFactory() {
override fun <T : Any> prepareCallBody(
client: HttpClient,
urlsKeeper: TelegramAPIUrlsKeeper,
@@ -19,4 +20,7 @@ object SimpleRequestCallFactory : AbstractRequestCallFactory() {
ContentType.Application.Json
)
}
}
@Deprecated("Use class SimpleRequestCallFactory() constructor call instead of just SimpleRequestCallFactory")
companion object : KtorCallFactory by SimpleRequestCallFactory()
}

View File

@@ -1,6 +1,8 @@
package dev.inmo.tgbotapi.bot.exceptions
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.types.Response
import dev.inmo.tgbotapi.types.RetryAfterError
import io.ktor.utils.io.errors.IOException
fun newRequestException(
@@ -10,12 +12,25 @@ fun newRequestException(
cause: Throwable? = null
) = response.description ?.let { description ->
when {
description == "Bad Request: reply message not found" -> ReplyMessageNotFoundException(response, plainAnswer, message, cause)
description == "Bad Request: reply message not found" || description == "Bad Request: replied message not found" -> ReplyMessageNotFoundException(response, plainAnswer, message, cause)
description == "Bad Request: message to edit not found" -> MessageToEditNotFoundException(response, plainAnswer, message, cause)
description.contains("Bad Request: message is not modified") -> MessageIsNotModifiedException(response, plainAnswer, message, cause)
description == "Unauthorized" -> UnauthorizedException(response, plainAnswer, message, cause)
description.contains("PHOTO_INVALID_DIMENSIONS") -> InvalidPhotoDimensionsException(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
)
description.contains("Conflict: terminated by other getUpdates request") -> GetUpdatesConflict(
response,
plainAnswer,
message,
cause
)
else -> null
}
} ?: CommonRequestException(response, plainAnswer, message, cause)
@@ -49,3 +64,9 @@ class InvalidPhotoDimensionsException(response: Response, plainAnswer: String, m
class WrongFileIdentifierException(response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
RequestException(response, plainAnswer, message, cause)
class TooMuchRequestsException(val retryAfter: RetryAfterError, response: Response, plainAnswer: String, message: String?, cause: Throwable?) :
RequestException(response, plainAnswer, message, cause)
class GetUpdatesConflict(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
import com.soywiz.klock.DateTime
import dev.inmo.tgbotapi.types.MilliSeconds
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()
@Serializable
class CommonLimiter(
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 {
private var doLimit: Boolean = false
private val counterChannel = Channel<Unit>(Channel.UNLIMITED)
private val scope = CoroutineScope(Dispatchers.Default)
private val counterJob = scope.launch {
var wasLastSecond = 0
var lastCountTime = now()
var limitManagementJob: Job? = null
var removeLimitTime: Long = lastCountTime
for (counter in counterChannel) {
val now = now()
if (now - lastCountTime > 1000) {
lastCountTime = now
wasLastSecond = 1
} else {
wasLastSecond++
}
if (wasLastSecond >= lockCount) {
removeLimitTime = now + regenTime
if (limitManagementJob == null) {
limitManagementJob = launch {
doLimit = true
var internalNow = now()
while (internalNow < removeLimitTime) {
delay(removeLimitTime - internalNow)
internalNow = now()
}
doLimit = false
}
@Transient
private val quotaSemaphore = Semaphore(lockCount)
@Transient
private val counterRegeneratorJob = scope.launch {
val regenDelay: MilliSeconds = (regenTime.toDouble() / lockCount).roundToLong()
while (isActive) {
delay(regenDelay)
if (quotaSemaphore.availablePermits < lockCount) {
try {
quotaSemaphore.release()
} catch (_: IllegalStateException) {
// Skip IllegalStateException due to the fact that this exception may happens in release method
}
}
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 {
counterChannel.send(Unit)
return if (!doLimit) {
block()
} else {
quoterChannel.receive()
block()
}
quotaSemaphore.acquire()
return 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
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.channels.Channel
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import kotlin.coroutines.*
@@ -9,62 +11,60 @@ import kotlin.math.pow
private sealed class RequestEvent
private class AddRequest(
val continuation: Continuation<Long>
val continuation: Continuation<MilliSeconds>
) : RequestEvent()
private object CompleteRequest : RequestEvent()
@Serializable
data class PowLimiter(
private val minAwaitTime: Long = 0L,
private val maxAwaitTime: Long = 10000L,
private val minAwaitTime: MilliSeconds = 0L,
private val maxAwaitTime: MilliSeconds = 10000L,
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 {
@Transient
private val scope = CoroutineScope(Dispatchers.Default)
@Transient
private val eventsChannel = Channel<RequestEvent>(Channel.UNLIMITED)
@Transient
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 {
scope.launch {
var requestsInWork: Double = 0.0
for (event in eventsChannel) {
when (event) {
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--
it.continuation.resume(
when {
awaitTime in awaitTimeRange -> awaitTime
awaitTime < awaitTimeRange.first -> awaitTimeRange.first
else -> awaitTimeRange.last
}
)
}
is CompleteRequest -> requestsInWork--
}
}
}
override suspend fun <T> limit(
block: suspend () -> T
private suspend inline fun <T> withDelay(
crossinline block: suspend () -> T
): T {
val delayMillis = suspendCoroutine<Long> {
scope.launch { eventsChannel.send(AddRequest(it)) }
}
delay(delayMillis)
return try {
block()
safely { block() }
} finally {
eventsChannel.send(CompleteRequest)
}
}
override suspend fun <T> limit(
block: suspend () -> T
): T {
return withDelay(block)
}
}

View File

@@ -0,0 +1,15 @@
package dev.inmo.tgbotapi.requests
import dev.inmo.tgbotapi.requests.abstracts.Request
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocator
import dev.inmo.tgbotapi.utils.ByteReadChannelAllocatorDeserializationStrategy
import kotlinx.serialization.DeserializationStrategy
class DownloadFileStream(
val filePath: String
) : Request<ByteReadChannelAllocator> {
override fun method(): String = filePath
override val resultDeserializer: DeserializationStrategy<ByteReadChannelAllocator>
get() = ByteReadChannelAllocatorDeserializationStrategy
}

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

@@ -6,6 +6,7 @@ import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.polls.Poll
import dev.inmo.tgbotapi.types.polls.PollSerializer
import kotlinx.serialization.*
@Serializable
@@ -19,7 +20,7 @@ data class StopPoll(
) : MessageAction, SimpleRequest<Poll>, ReplyMarkup {
override fun method(): String = "stopPoll"
override val resultDeserializer: DeserializationStrategy<Poll>
get() = Poll.serializer()
get() = PollSerializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -1,7 +1,9 @@
package dev.inmo.tgbotapi.requests.abstracts
import dev.inmo.tgbotapi.utils.StorageFile
import kotlinx.serialization.*
import dev.inmo.tgbotapi.utils.*
import io.ktor.utils.io.ByteReadChannel
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@@ -30,8 +32,8 @@ data class FileId(
fun String.toInputFile() = FileId(this)
@Serializer(InputFile::class)
internal object InputFileSerializer : KSerializer<InputFile> {
@RiskFeature
object InputFileSerializer : KSerializer<InputFile> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor(FileId::class.toString(), PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: InputFile) = encoder.encodeString(value.fileId)
override fun deserialize(decoder: Decoder): FileId = FileId(decoder.decodeString())
@@ -40,12 +42,36 @@ internal object InputFileSerializer : KSerializer<InputFile> {
// TODO:: add checks for files size
/**
* Contains info about file for sending
*
* @see asMultipartFile
*/
@Serializable(InputFileSerializer::class)
data class MultipartFile (
val file: StorageFile,
val mimeType: String = file.storageFileInfo.contentType,
val filename: String = file.storageFileInfo.fileName
) : InputFile() {
override val fileId: String = file.storageFileInfo.generateCustomName()
@Deprecated("This constructor is redundant. Use constructor without mime type")
constructor(file: StorageFile, mimeType: String, filename: String): this(file, filename)
}
@Suppress("NOTHING_TO_INLINE", "unused")
inline fun StorageFile.asMultipartFile() = MultipartFile(this)
@Deprecated("This method is redundant. Use asMultipartFile without mime type")
@Suppress("NOTHING_TO_INLINE", "unused")
inline fun ByteArray.asMultipartFile(
fileName: String,
mimeType: MimeType
) = MultipartFile(asStorageFile(fileName))
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannel.asMultipartFile(
fileName: String
) = MultipartFile(asStorageFile(fileName))
@Suppress("NOTHING_TO_INLINE", "unused")
suspend inline fun ByteReadChannelAllocator.asMultipartFile(
fileName: String
) = this.invoke().asMultipartFile(fileName)

View File

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

View File

@@ -4,7 +4,8 @@ import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.abstracts.InlineQueryResult
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.serializers.InlineQueryResultSerializer
import dev.inmo.tgbotapi.types.InlineQueries.abstracts.InlineQuery
import dev.inmo.tgbotapi.types.InlineQueries.query.InlineQuery
import dev.inmo.tgbotapi.utils.RiskFeature
import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.serializer
@@ -16,7 +17,7 @@ data class AnswerInlineQuery(
@Serializable(InlineQueryAnswersResultsSerializer::class)
@SerialName(resultsField)
val results: List<InlineQueryResult> = emptyList(),
@SerialName(cachedTimeField)
@SerialName(cacheTimeField)
val cachedTime: Int? = null,
@SerialName(isPersonalField)
val isPersonal: Boolean? = null,
@@ -26,7 +27,7 @@ data class AnswerInlineQuery(
val switchPmText: String? = null,
@SerialName(switchPmParameterField)
val switchPmParameter: String? = null
): SimpleRequest<Boolean> {
) : SimpleRequest<Boolean> {
override fun method(): String = "answerInlineQuery"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
@@ -51,6 +52,7 @@ fun InlineQuery.createAnswer(
switchPmParameter
)
internal object InlineQueryAnswersResultsSerializer: KSerializer<List<InlineQueryResult>> by ListSerializer(
@RiskFeature
object InlineQueryAnswersResultsSerializer : KSerializer<List<InlineQueryResult>> by ListSerializer(
InlineQueryResultSerializer
)

View File

@@ -4,6 +4,7 @@ import dev.inmo.tgbotapi.requests.answers.payments.abstracts.AnswerShippingQuery
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.payments.ShippingOption
import dev.inmo.tgbotapi.types.payments.ShippingQuery
import dev.inmo.tgbotapi.utils.RiskFeature
import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer
@@ -21,7 +22,8 @@ data class AnswerShippingQueryOk(
get() = serializer()
}
internal object ShippingOptionsSerializer : KSerializer<List<ShippingOption>> by ListSerializer(
@RiskFeature
object ShippingOptionsSerializer : KSerializer<List<ShippingOption>> by ListSerializer(
ShippingOption.serializer()
)

View File

@@ -0,0 +1,9 @@
package dev.inmo.tgbotapi.requests.bot
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.abstracts.WithOptionalLanguageCode
import dev.inmo.tgbotapi.types.commands.BotCommandScope
sealed interface MyCommandsRequest<T : Any> : SimpleRequest<T>, WithOptionalLanguageCode {
val scope: BotCommandScope
}

View File

@@ -0,0 +1,33 @@
package dev.inmo.tgbotapi.requests.bot
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
import dev.inmo.tgbotapi.types.commands.*
import dev.inmo.tgbotapi.types.languageCodeField
import dev.inmo.tgbotapi.types.scopeField
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class DeleteMyCommands(
@SerialName(scopeField)
@Serializable(BotCommandScopeSerializer::class)
override val scope: BotCommandScope = BotCommandScopeDefault,
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : MyCommandsRequest<Boolean> {
override fun method(): String = "deleteMyCommands"
override val requestSerializer: SerializationStrategy<DeleteMyCommands> = serializer()
override val resultDeserializer: DeserializationStrategy<Boolean> = Boolean.serializer()
constructor(
scope: BotCommandScope = BotCommandScopeDefault,
languageCode: String?
) : this(
scope,
languageCode ?.let(::IetfLanguageCode)
)
companion object : MyCommandsRequest<Boolean> by DeleteMyCommands()
}

View File

@@ -1,17 +1,36 @@
package dev.inmo.tgbotapi.requests.bot
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.commands.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer
private val getMyCommandsSerializer = ListSerializer(BotCommand.serializer())
@Serializable
object GetMyCommands : SimpleRequest<List<BotCommand>> {
data class GetMyCommands(
@SerialName(scopeField)
@Serializable(BotCommandScopeSerializer::class)
override val scope: BotCommandScope = BotCommandScopeDefault,
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : MyCommandsRequest<List<BotCommand>> {
override fun method(): String = "getMyCommands"
override val resultDeserializer: DeserializationStrategy<List<BotCommand>>
get() = getMyCommandsSerializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
constructor(
scope: BotCommandScope = BotCommandScopeDefault,
languageCode: String?
) : this(
scope,
languageCode ?.let(::IetfLanguageCode)
)
companion object : MyCommandsRequest<List<BotCommand>> by GetMyCommands()
}

View File

@@ -1,21 +1,39 @@
package dev.inmo.tgbotapi.requests.bot
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.micro_utils.language_codes.IetfLanguageCode
import dev.inmo.micro_utils.language_codes.IetfLanguageCodeSerializer
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.commands.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
class SetMyCommands(
@SerialName(botCommandsField)
val commands: List<BotCommand>
) : SimpleRequest<Boolean> {
val commands: List<BotCommand>,
@SerialName(scopeField)
@Serializable(BotCommandScopeSerializer::class)
override val scope: BotCommandScope = BotCommandScopeDefault,
@SerialName(languageCodeField)
@Serializable(IetfLanguageCodeSerializer::class)
override val ietfLanguageCode: IetfLanguageCode? = null
) : MyCommandsRequest<Boolean> {
override fun method(): String = "setMyCommands"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
constructor(
commands: List<BotCommand>,
scope: BotCommandScope = BotCommandScopeDefault,
languageCode: String?
) : this(
commands,
scope,
languageCode ?.let(::IetfLanguageCode)
)
init {
if (commands.size !in botCommandsLimit) {
error("Bot commands list size able to be in range $botCommandsLimit, but incoming size is ${commands.size}")

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.types.ChatIdentifier
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 kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer
private val chatMembersListSerializer = ListSerializer(
AdministratorChatMemberSerializerWithoutDeserialization
AdministratorChatMemberSerializer
)
@Serializable

View File

@@ -8,13 +8,16 @@ import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class GetChatMembersCount(
data class GetChatMemberCount(
@SerialName(chatIdField)
override val chatId: ChatIdentifier
): ChatRequest, SimpleRequest<Int> {
override fun method(): String = "getChatMembersCount"
override fun method(): String = "getChatMemberCount"
override val resultDeserializer: DeserializationStrategy<Int>
get() = Int.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}
@Deprecated("Renamed", ReplaceWith("GetChatMemberCount", "dev.inmo.tgbotapi.requests.chat.get.GetChatMemberCount"))
typealias GetChatMembersCount = GetChatMemberCount

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

@@ -7,17 +7,22 @@ import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class KickChatMember(
data class BanChatMember(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(userIdField)
override val userId: UserId,
@SerialName(untilDateField)
override val untilDate: TelegramDate? = null
override val untilDate: TelegramDate? = null,
@SerialName(revokeMessagesField)
val revokeMessages: Boolean? = null
) : ChatMemberRequest<Boolean>, UntilDate {
override fun method(): String = "kickChatMember"
override fun method(): String = "banChatMember"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}
@Deprecated("Renamed", ReplaceWith("BanChatMember", "dev.inmo.tgbotapi.requests.chat.members.BanChatMember"))
typealias KickChatMember = BanChatMember

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.types.*
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.*
@Serializable
@@ -15,7 +15,7 @@ data class GetChatMember(
) : ChatMemberRequest<ChatMember> {
override fun method(): String = "getChatMember"
override val resultDeserializer: DeserializationStrategy<ChatMember>
get() = ChatMemberDeserializationStrategy
get() = ChatMemberSerializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -14,6 +14,8 @@ data class PromoteChatMember(
override val userId: UserId,
@SerialName(untilDateField)
override val untilDate: TelegramDate? = null,
@SerialName(isAnonymousField)
private val isAnonymous: Boolean? = null,
@SerialName(canChangeInfoField)
private val canChangeInfo: Boolean? = null,
@SerialName(canPostMessagesField)
@@ -29,7 +31,11 @@ data class PromoteChatMember(
@SerialName(canPinMessagesField)
private val canPinMessages: Boolean? = null,
@SerialName(canPromoteMembersField)
private val canPromoteMembers: Boolean? = null
private val canPromoteMembers: Boolean? = null,
@SerialName(canManageVoiceChatsField)
private val canManageVoiceChats: Boolean? = null,
@SerialName(canManageChatField)
private val canManageChat: Boolean? = null
) : ChatMemberRequest<Boolean>, UntilDate {
override fun method(): String = "promoteChatMember"
override val resultDeserializer: DeserializationStrategy<Boolean>

View File

@@ -10,7 +10,9 @@ data class UnbanChatMember(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(userIdField)
override val userId: UserId
override val userId: UserId,
@SerialName(onlyIfBannedField)
val onlyIfBanned: Boolean? = null
) : ChatMemberRequest<Boolean> {
override fun method(): String = "unbanChatMember"
override val resultDeserializer: DeserializationStrategy<Boolean>

View File

@@ -6,6 +6,11 @@ import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
/**
* Use this method to add a message to the list of pinned messages in a chat. If the chat is not a private chat, the bot
* must be an administrator in the chat for this to work and must have the 'can_pin_messages' admin right in a
* supergroup or 'can_edit_messages' admin right in a channel.
*/
@Serializable
data class PinChatMessage (
@SerialName(chatIdField)

View File

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

View File

@@ -0,0 +1,28 @@
package dev.inmo.tgbotapi.requests.chat.modify
import dev.inmo.tgbotapi.CommonAbstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.chatIdField
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
/**
* Use this method to clear the list of pinned messages in a chat. If the chat is not a private chat, the bot must be an
* administrator in the chat for this to work and must have the 'can_pin_messages' admin right in a supergroup or
* 'can_edit_messages' admin right in a channel.
*
* @see PinChatMessage
* @see UnpinChatMessage
*/
@Serializable
data class UnpinAllChatMessages(
@SerialName(chatIdField)
override val chatId: ChatIdentifier
): ChatRequest, SimpleRequest<Boolean> {
override fun method(): String = "unpinAllChatMessages"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -2,15 +2,16 @@ package dev.inmo.tgbotapi.requests.chat.modify
import dev.inmo.tgbotapi.CommonAbstracts.types.ChatRequest
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.ChatIdentifier
import dev.inmo.tgbotapi.types.chatIdField
import dev.inmo.tgbotapi.types.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
@Serializable
data class UnpinChatMessage(
@SerialName(chatIdField)
override val chatId: ChatIdentifier
override val chatId: ChatIdentifier,
@SerialName(messageIdField)
val messageId: MessageIdentifier? = null
): ChatRequest, SimpleRequest<Boolean> {
override fun method(): String = "unpinChatMessage"
override val resultDeserializer: DeserializationStrategy<Boolean>

View File

@@ -6,9 +6,11 @@ import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.LocationContent
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
private val commonResultDeserializer = TelegramBotAPIMessageDeserializationStrategyClass<ContentMessage<LocationContent>>()
const val editMessageLiveLocationMethod = "editMessageLiveLocation"
@Serializable
data class EditChatMessageLiveLocation(
@@ -20,12 +22,24 @@ data class EditChatMessageLiveLocation(
override val latitude: Double,
@SerialName(longitudeField)
override val longitude: Double,
@SerialName(horizontalAccuracyField)
override val horizontalAccuracy: Meters? = null,
@SerialName(headingField)
override val heading: Degrees? = null,
@SerialName(proximityAlertRadiusField)
override val proximityAlertRadius: Meters? = null,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditChatMessage<LocationContent>, EditReplyMessage, EditLocationMessage {
override fun method(): String = "editMessageLiveLocation"
override fun method(): String = editMessageLiveLocationMethod
override val resultDeserializer: DeserializationStrategy<ContentMessage<LocationContent>>
get() = commonResultDeserializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
init {
if (horizontalAccuracy != null && horizontalAccuracy !in horizontalAccuracyLimit) {
throwRangeError("horizontalAccuracy", horizontalAccuracyLimit, horizontalAccuracy)
}
}
}

View File

@@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.requests.edit.LiveLocation
import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
@Serializable
@@ -13,10 +14,22 @@ data class EditInlineMessageLiveLocation(
override val latitude: Double,
@SerialName(longitudeField)
override val longitude: Double,
@SerialName(horizontalAccuracyField)
override val horizontalAccuracy: Meters? = null,
@SerialName(headingField)
override val heading: Degrees? = null,
@SerialName(proximityAlertRadiusField)
override val proximityAlertRadius: Meters? = null,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditInlineMessage, EditReplyMessage, EditLocationMessage {
override fun method(): String = "editMessageLiveLocation"
override fun method(): String = editMessageLiveLocationMethod
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
init {
if (horizontalAccuracy != null && horizontalAccuracy !in horizontalAccuracyLimit) {
throwRangeError("horizontalAccuracy", horizontalAccuracyLimit, horizontalAccuracy)
}
}
}

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.requests.edit.abstracts
interface EditLocationMessage {
val latitude: Double
val longitude: Double
}
import dev.inmo.tgbotapi.CommonAbstracts.*
interface EditLocationMessage : Locationed, HorizontallyAccured, ProximityAlertable, Headed

View File

@@ -1,8 +1,7 @@
package dev.inmo.tgbotapi.requests.edit.abstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
interface EditTextChatMessage {
val text: String
val parseMode: ParseMode?
interface EditTextChatMessage : TextedOutput {
override val text: String
}

View File

@@ -3,17 +3,49 @@ package dev.inmo.tgbotapi.requests.edit.caption
import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.requests.edit.media.MediaContentMessageResultDeserializer
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.abstracts.MediaContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import kotlinx.serialization.*
const val editMessageCaptionMethod = "editMessageCaption"
fun EditChatMessageCaption(
chatId: ChatIdentifier,
messageId: MessageIdentifier,
text: String,
parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditChatMessageCaption(
chatId,
messageId,
text,
parseMode,
null,
replyMarkup
)
fun EditChatMessageCaption(
chatId: ChatIdentifier,
messageId: MessageIdentifier,
entities: TextSourcesList,
replyMarkup: InlineKeyboardMarkup? = null
) = EditChatMessageCaption(
chatId,
messageId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
replyMarkup
)
@Serializable
data class EditChatMessageCaption(
data class EditChatMessageCaption internal constructor(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(messageIdField)
@@ -22,9 +54,14 @@ data class EditChatMessageCaption(
override val text: String,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditChatMessage<MediaContent>, EditTextChatMessage, EditReplyMessage {
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text)
}
override fun method(): String = editMessageCaptionMethod
override val resultDeserializer: DeserializationStrategy<ContentMessage<MediaContent>>

View File

@@ -2,22 +2,56 @@ package dev.inmo.tgbotapi.requests.edit.caption
import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.utils.extensions.makeString
import kotlinx.serialization.*
fun EditInlineMessageCaption(
inlineMessageId: InlineMessageIdentifier,
text: String,
parseMode: ParseMode? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditInlineMessageCaption(
inlineMessageId,
text,
parseMode,
null,
replyMarkup
)
fun EditInlineMessageCaption(
inlineMessageId: InlineMessageIdentifier,
entities: TextSourcesList,
replyMarkup: InlineKeyboardMarkup? = null
) = EditInlineMessageCaption(
inlineMessageId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
replyMarkup
)
@Serializable
data class EditInlineMessageCaption(
data class EditInlineMessageCaption internal constructor(
@SerialName(inlineMessageIdField)
override val inlineMessageId: InlineMessageIdentifier,
@SerialName(captionField)
override val text: String,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditInlineMessage, EditTextChatMessage, EditReplyMessage {
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text)
}
override fun method(): String = editMessageCaptionMethod
override val requestSerializer: SerializationStrategy<*>
get() = serializer()

View File

@@ -3,17 +3,53 @@ package dev.inmo.tgbotapi.requests.edit.text
import dev.inmo.tgbotapi.requests.edit.abstracts.*
import dev.inmo.tgbotapi.requests.send.TextContentMessageResultDeserializer
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import kotlinx.serialization.*
const val editMessageTextMethod = "editMessageText"
fun EditChatMessageText(
chatId: ChatIdentifier,
messageId: MessageIdentifier,
text: String,
parseMode: ParseMode? = null,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditChatMessageText(
chatId,
messageId,
text,
parseMode,
null,
disableWebPagePreview,
replyMarkup
)
fun EditChatMessageText(
chatId: ChatIdentifier,
messageId: MessageIdentifier,
entities: TextSourcesList,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditChatMessageText(
chatId,
messageId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
disableWebPagePreview,
replyMarkup
)
@Serializable
data class EditChatMessageText(
data class EditChatMessageText internal constructor(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(messageIdField)
@@ -22,11 +58,16 @@ data class EditChatMessageText(
override val text: String,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(entitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(disableWebPagePreviewField)
override val disableWebPagePreview: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditChatMessage<TextContent>, EditTextChatMessage, EditReplyMessage, EditDisableWebPagePreviewMessage {
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text)
}
override fun method(): String = editMessageTextMethod
override val resultDeserializer: DeserializationStrategy<ContentMessage<TextContent>>

View File

@@ -1,27 +1,64 @@
package dev.inmo.tgbotapi.requests.edit.text
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.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.utils.extensions.makeString
import kotlinx.serialization.*
fun EditInlineMessageText(
inlineMessageId: InlineMessageIdentifier,
text: String,
parseMode: ParseMode? = null,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditInlineMessageText(
inlineMessageId,
text,
parseMode,
null,
disableWebPagePreview,
replyMarkup
)
fun EditInlineMessageText(
inlineMessageId: InlineMessageIdentifier,
entities: TextSourcesList,
disableWebPagePreview: Boolean? = null,
replyMarkup: InlineKeyboardMarkup? = null
) = EditInlineMessageText(
inlineMessageId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
disableWebPagePreview,
replyMarkup
)
@Serializable
data class EditInlineMessageText(
data class EditInlineMessageText internal constructor(
@SerialName(inlineMessageIdField)
override val inlineMessageId: InlineMessageIdentifier,
@SerialName(textField)
override val text: String,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(entitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(disableWebPagePreviewField)
override val disableWebPagePreview: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: InlineKeyboardMarkup? = null
) : EditInlineMessage, EditTextChatMessage, EditReplyMessage, EditDisableWebPagePreviewMessage {
override fun method(): String = editMessageMediaMethod
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text)
}
override fun method(): String = editMessageTextMethod
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -3,6 +3,7 @@ package dev.inmo.tgbotapi.requests.games.abstracts
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.types.UserId
import dev.inmo.tgbotapi.types.games.GameHighScore
import dev.inmo.tgbotapi.utils.RiskFeature
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer
@@ -15,4 +16,5 @@ interface GetGameHighScores : SimpleRequest<List<GameHighScore>> {
get() = GameHighScoresSerializer
}
internal object GameHighScoresSerializer : KSerializer<List<GameHighScore>> by ListSerializer(GameHighScore.serializer())
@RiskFeature
object GameHighScoresSerializer : KSerializer<List<GameHighScore>> by ListSerializer(GameHighScore.serializer())

View File

@@ -0,0 +1,23 @@
package dev.inmo.tgbotapi.requests.local
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
/**
* Use this method to close the bot instance before moving it from one local server to another. You need to delete the
* webhook before calling this method to ensure that the bot isn't launched again after server restart. The method will
* return error 429 in the first 10 minutes after the bot is launched.
*
* @see io.ktor.client.features.ClientRequestException
*/
@Serializable
object Close : SimpleRequest<Boolean> {
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "close"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
}

View File

@@ -0,0 +1,21 @@
package dev.inmo.tgbotapi.requests.local
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
/**
* Use this method to log out from the cloud Bot API server before launching the bot locally. You **must** log out the bot
* before running it locally, otherwise there is no guarantee that the bot will receive updates. After a successful
* call, you will not be able to log in again using the same token for 10 minutes
*/
@Serializable
object LogOut : SimpleRequest<Boolean> {
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override fun method(): String = "logOut"
override val resultDeserializer: DeserializationStrategy<Boolean>
get() = Boolean.serializer()
}

View File

@@ -0,0 +1,88 @@
package dev.inmo.tgbotapi.requests.send
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
import dev.inmo.tgbotapi.CommonAbstracts.types.MessageAction
import dev.inmo.tgbotapi.requests.abstracts.SimpleRequest
import dev.inmo.tgbotapi.requests.send.abstracts.ReplyingMarkupSendMessageRequest
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.utils.extensions.makeString
import kotlinx.serialization.*
fun CopyMessage(
fromChatId: ChatIdentifier,
toChatId: ChatIdentifier,
messageId: MessageIdentifier,
text: String? = null,
parseMode: ParseMode? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = CopyMessage(fromChatId, toChatId, messageId, text, parseMode, null, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
fun CopyMessage(
fromChatId: ChatIdentifier,
toChatId: ChatIdentifier,
messageId: MessageIdentifier,
entities: List<TextSource>,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = CopyMessage(
fromChatId,
toChatId,
messageId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@Serializable
data class CopyMessage internal constructor(
@SerialName(fromChatIdField)
val fromChatId: ChatIdentifier,
@SerialName(chatIdField)
val toChatId: ChatIdentifier,
@SerialName(messageIdField)
override val messageId: MessageIdentifier,
@SerialName(captionField)
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
): SimpleRequest<MessageIdentifier>,
ReplyingMarkupSendMessageRequest<MessageIdentifier>,
MessageAction,
TextedOutput {
override val chatId: ChatIdentifier
get() = fromChatId
override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
override fun method(): String = "copyMessage"
override val resultDeserializer: DeserializationStrategy<MessageIdentifier>
get() = MessageIdSerializer
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
}

View File

@@ -26,6 +26,8 @@ data class SendContact(
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendMessageRequest<ContentMessage<ContactContent>>,
@@ -36,6 +38,7 @@ data class SendContact(
contact: Contact,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): this(
chatId,
@@ -44,6 +47,7 @@ data class SendContact(
contact.lastName,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@@ -58,11 +62,13 @@ fun Contact.toRequest(
chatId: ChatIdentifier,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): SendContact = SendContact(
chatId,
this,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)

View File

@@ -24,6 +24,8 @@ data class SendDice(
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : ReplyingMarkupSendMessageRequest<ContentMessage<DiceContent>>, ReplyMessageId, DisableNotification {

View File

@@ -1,19 +1,79 @@
package dev.inmo.tgbotapi.requests.send
import dev.inmo.tgbotapi.CommonAbstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.LocationContent
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<LocationContent>>
= TelegramBotAPIMessageDeserializationStrategyClass()
fun SendLocation(
chatId: ChatIdentifier,
latitude: Double,
longitude: Double,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendLocation(
chatId,
latitude,
longitude,
null,
null,
null,
null,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
fun SendStaticLocation(
chatId: ChatIdentifier,
latitude: Double,
longitude: Double,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendLocation(chatId, latitude, longitude, disableNotification, replyToMessageId, allowSendingWithoutReply, replyMarkup)
fun SendLiveLocation(
chatId: ChatIdentifier,
latitude: Double,
longitude: Double,
livePeriod: Seconds,
horizontalAccuracy: Meters? = null,
heading: Degrees? = null,
proximityAlertRadius: Meters? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendLocation(
chatId,
latitude,
longitude,
livePeriod,
horizontalAccuracy,
heading,
proximityAlertRadius,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@Serializable
data class SendLocation(
data class SendLocation internal constructor(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(latitudeField)
@@ -21,16 +81,28 @@ data class SendLocation(
@SerialName(longitudeField)
override val longitude: Double,
@SerialName(livePeriodField)
val livePeriod: Long? = null,
override val livePeriod: Seconds? = null,
@SerialName(horizontalAccuracyField)
override val horizontalAccuracy: Meters? = null,
@SerialName(headingField)
override val heading: Degrees? = null,
@SerialName(proximityAlertRadiusField)
override val proximityAlertRadius: Meters? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendMessageRequest<ContentMessage<LocationContent>>,
ReplyingMarkupSendMessageRequest<ContentMessage<LocationContent>>,
PositionedSendMessageRequest<ContentMessage<LocationContent>>
PositionedSendMessageRequest<ContentMessage<LocationContent>>,
HorizontallyAccured,
Livable,
ProximityAlertable,
Headed
{
override fun method(): String = "sendLocation"
override val resultDeserializer: DeserializationStrategy<ContentMessage<LocationContent>>
@@ -42,5 +114,8 @@ data class SendLocation(
if (livePeriod != null && livePeriod !in livePeriodLimit) {
error("Live period for sending location must be in $livePeriodLimit, but was $livePeriod")
}
if (horizontalAccuracy != null && horizontalAccuracy !in horizontalAccuracyLimit) {
throwRangeError("horizontalAccuracy", horizontalAccuracyLimit, horizontalAccuracy)
}
}
}

View File

@@ -3,32 +3,80 @@ package dev.inmo.tgbotapi.requests.send
import dev.inmo.tgbotapi.CommonAbstracts.types.DisableWebPagePreview
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
internal val TextContentMessageResultDeserializer: DeserializationStrategy<ContentMessage<TextContent>>
= TelegramBotAPIMessageDeserializationStrategyClass()
fun SendTextMessage(
chatId: ChatIdentifier,
text: String,
parseMode: ParseMode? = null,
disableWebPagePreview: Boolean? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendTextMessage(
chatId,
text,
parseMode,
null,
disableWebPagePreview,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
fun SendTextMessage(
chatId: ChatIdentifier,
entities: TextSourcesList,
disableWebPagePreview: Boolean? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
) = SendTextMessage(
chatId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
disableWebPagePreview,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@Serializable
data class SendTextMessage(
data class SendTextMessage internal constructor(
@SerialName(chatIdField)
override val chatId: ChatIdentifier,
@SerialName(textField)
override val text: String,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(entitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(disableWebPagePreviewField)
override val disableWebPagePreview: Boolean? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendMessageRequest<ContentMessage<TextContent>>,
@@ -36,6 +84,10 @@ data class SendTextMessage(
TextableSendMessageRequest<ContentMessage<TextContent>>,
DisableWebPagePreview
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text)
}
init {
if (text.length !in textLength) {
throwRangeError("Text length", textLength, text.length)

View File

@@ -25,11 +25,19 @@ data class SendVenue(
@SerialName(addressField)
val address: String,
@SerialName(foursquareIdField)
val foursquareId: String? = null,
val foursquareId: FoursquareId? = null,
@SerialName(foursquareTypeField)
val foursquareType: FoursquareType? = null,
@SerialName(googlePlaceIdField)
val googlePlaceId: GooglePlaceId? = null,
@SerialName(googlePlaceTypeField)
val googlePlaceType: GooglePlaceType? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendMessageRequest<ContentMessage<VenueContent>>,
@@ -42,17 +50,22 @@ data class SendVenue(
venue: Venue,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): this(
chatId,
venue.location.latitude,
venue.location.longitude,
venue.title,
venue.address,
venue.foursquareId,
disableNotification,
replyToMessageId,
replyMarkup
chatId = chatId,
latitude = venue.location.latitude,
longitude = venue.location.longitude,
title = venue.title,
address = venue.address,
foursquareId = venue.foursquareId,
foursquareType = venue.foursquareType,
googlePlaceId = venue.googlePlaceId,
googlePlaceType = venue.googlePlaceType,
disableNotification = disableNotification,
replyToMessageId = replyToMessageId,
allowSendingWithoutReply = allowSendingWithoutReply,
replyMarkup = replyMarkup
)
override fun method(): String = "sendVenue"
@@ -66,11 +79,13 @@ fun Venue.toRequest(
chatId: ChatIdentifier,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): SendVenue = SendVenue(
chatId,
this,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)

View File

@@ -1,6 +1,5 @@
package dev.inmo.tgbotapi.requests.send.abstracts
interface PositionedSendMessageRequest<T: Any>: SendMessageRequest<T> {
val latitude: Double
val longitude: Double
}
import dev.inmo.tgbotapi.CommonAbstracts.Locationed
interface PositionedSendMessageRequest<T: Any>: SendMessageRequest<T>, Locationed

View File

@@ -1,8 +1,5 @@
package dev.inmo.tgbotapi.requests.send.abstracts
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.CommonAbstracts.TextedOutput
interface TextableSendMessageRequest<T: Any>: SendMessageRequest<T> {
val text: String?
val parseMode: ParseMode?
}
interface TextableSendMessageRequest<T: Any>: SendMessageRequest<T>, TextedOutput

View File

@@ -22,6 +22,8 @@ data class SendGame (
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendMessageRequest<ContentMessage<GameContent>>,

View File

@@ -4,12 +4,15 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.media.AnimationContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.mapOfNotNull
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
@@ -18,13 +21,14 @@ fun SendAnimation(
chatId: ChatIdentifier,
animation: InputFile,
thumb: InputFile? = null,
caption: String? = null,
text: String? = null,
parseMode: ParseMode? = null,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<AnimationContent>> {
val animationAsFileId = (animation as? FileId) ?.fileId
@@ -36,13 +40,59 @@ fun SendAnimation(
chatId,
animationAsFileId,
thumbAsFileId,
caption,
text,
parseMode,
null,
duration,
width,
height,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
return if (animationAsFile == null && thumbAsFile == null) {
data
} else {
MultipartRequestImpl(
data,
SendAnimationFiles(animationAsFile, thumbAsFile)
)
}
}
fun SendAnimation(
chatId: ChatIdentifier,
animation: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<AnimationContent>> {
val animationAsFileId = (animation as? FileId) ?.fileId
val animationAsFile = animation as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId
val thumbAsFile = thumb as? MultipartFile
val data = SendAnimationData(
chatId,
animationAsFileId,
thumbAsFileId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
duration,
width,
height,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@@ -71,6 +121,8 @@ data class SendAnimationData internal constructor(
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(durationField)
override val duration: Long? = null,
@SerialName(widthField)
@@ -81,6 +133,8 @@ data class SendAnimationData internal constructor(
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : DataRequest<ContentMessage<AnimationContent>>,
@@ -91,6 +145,10 @@ data class SendAnimationData internal constructor(
DuratedSendMessageRequest<ContentMessage<AnimationContent>>,
SizedSendMessageRequest<ContentMessage<AnimationContent>>
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
init {
text ?.let {
if (it.length !in captionLength) {

View File

@@ -5,12 +5,15 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSource
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.media.AudioContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.mapOfNotNull
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
@@ -19,13 +22,14 @@ fun SendAudio(
chatId: ChatIdentifier,
audio: InputFile,
thumb: InputFile? = null,
caption: String? = null,
text: String? = null,
parseMode: ParseMode? = null,
duration: Long? = null,
performer: String? = null,
title: String? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<AudioContent>> {
val audioAsFileId = (audio as? FileId) ?.fileId
@@ -37,13 +41,59 @@ fun SendAudio(
chatId,
audioAsFileId,
thumbAsFileId,
caption,
text,
parseMode,
null,
duration,
performer,
title,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
return if (audioAsFile == null && thumbAsFile == null) {
data
} else {
MultipartRequestImpl(
data,
SendAudioFiles(audioAsFile, thumbAsFile)
)
}
}
fun SendAudio(
chatId: ChatIdentifier,
audio: InputFile,
thumb: InputFile? = null,
entities: List<TextSource>,
duration: Long? = null,
performer: String? = null,
title: String? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<AudioContent>> {
val audioAsFileId = (audio as? FileId) ?.fileId
val audioAsFile = audio as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId
val thumbAsFile = thumb as? MultipartFile
val data = SendAudioData(
chatId,
audioAsFileId,
thumbAsFileId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
duration,
performer,
title,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@@ -72,6 +122,8 @@ data class SendAudioData internal constructor(
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(durationField)
override val duration: Long? = null,
@SerialName(performerField)
@@ -82,6 +134,8 @@ data class SendAudioData internal constructor(
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : DataRequest<ContentMessage<AudioContent>>,
@@ -93,6 +147,10 @@ data class SendAudioData internal constructor(
DuratedSendMessageRequest<ContentMessage<AudioContent>>,
Performerable
{
override val textSources: List<TextSource>? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
init {
text ?.let {
if (it.length !in captionLength) {

View File

@@ -4,25 +4,39 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.media.DocumentContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.mapOfNotNull
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
/**
* Use this method to send general files. On success, the sent [ContentMessage] with [DocumentContent] is returned.
* Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
*
* @param disableContentTypeDetection Disables automatic server-side content type detection for [document] [MultipartFile]
*
* @see ContentMessage
* @see DocumentContent
*/
fun SendDocument(
chatId: ChatIdentifier,
document: InputFile,
thumb: InputFile? = null,
caption: String? = null,
text: String? = null,
parseMode: ParseMode? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
replyMarkup: KeyboardMarkup? = null
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null,
disableContentTypeDetection: Boolean? = null
): Request<ContentMessage<DocumentContent>> {
val documentAsFileId = (document as? FileId) ?.fileId
val documentAsFile = document as? MultipartFile
@@ -33,11 +47,63 @@ fun SendDocument(
chatId,
documentAsFileId,
thumbAsFileId,
caption,
text,
parseMode,
null,
disableNotification,
replyToMessageId,
replyMarkup
allowSendingWithoutReply,
replyMarkup,
disableContentTypeDetection
)
return if (documentAsFile == null && thumbAsFile == null) {
data
} else {
MultipartRequestImpl(
data,
SendDocumentFiles(documentAsFile, thumbAsFile)
)
}
}
/**
* Use this method to send general files. On success, the sent [ContentMessage] with [DocumentContent] is returned.
* Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
*
* @param disableContentTypeDetection Disables automatic server-side content type detection for [document] [MultipartFile]
*
* @see ContentMessage
* @see DocumentContent
*/
fun SendDocument(
chatId: ChatIdentifier,
document: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null,
disableContentTypeDetection: Boolean? = null
): Request<ContentMessage<DocumentContent>> {
val documentAsFileId = (document as? FileId) ?.fileId
val documentAsFile = document as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId
val thumbAsFile = thumb as? MultipartFile
val data = SendDocumentData(
chatId,
documentAsFileId,
thumbAsFileId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup,
disableContentTypeDetection
)
return if (documentAsFile == null && thumbAsFile == null) {
@@ -53,6 +119,15 @@ fun SendDocument(
private val commonResultDeserializer: DeserializationStrategy<ContentMessage<DocumentContent>>
= TelegramBotAPIMessageDeserializationStrategyClass()
/**
* Use this method to send general files. On success, the sent [ContentMessage] with [DocumentContent] is returned.
* Bots can currently send files of any type of up to 50 MB in size, this limit may be changed in the future.
*
* @param disableContentTypeDetection Disables automatic server-side content type detection for [document] [MultipartFile]
*
* @see ContentMessage
* @see DocumentContent
*/
@Serializable
data class SendDocumentData internal constructor(
@SerialName(chatIdField)
@@ -65,18 +140,28 @@ data class SendDocumentData internal constructor(
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
override val replyMarkup: KeyboardMarkup? = null,
@SerialName(disableContentTypeDetectionField)
val disableContentTypeDetection: Boolean? = null
) : DataRequest<ContentMessage<DocumentContent>>,
SendMessageRequest<ContentMessage<DocumentContent>>,
ReplyingMarkupSendMessageRequest<ContentMessage<DocumentContent>>,
TextableSendMessageRequest<ContentMessage<DocumentContent>>,
ThumbedSendMessageRequest<ContentMessage<DocumentContent>>
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
init {
text ?.let {
if (it.length !in captionLength) {

View File

@@ -8,8 +8,11 @@ import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.InputMedia.*
import dev.inmo.tgbotapi.types.message.abstracts.MediaGroupMessage
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.throwRangeError
import kotlinx.serialization.*
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.buildJsonArray
@@ -18,12 +21,13 @@ const val rawSendingMediaGroupsWarning = "Media groups contains restrictions rel
" types. Currently it is possible to combine photo + video OR audio OR documents"
@RiskFeature(rawSendingMediaGroupsWarning)
fun SendMediaGroup(
fun <T : MediaGroupContent> SendMediaGroup(
chatId: ChatIdentifier,
media: List<MediaGroupMemberInputMedia>,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null
): Request<List<MediaGroupMessage>> {
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null
): Request<List<MediaGroupMessage<T>>> {
if (media.size !in mediaCountInMediaGroup) {
throwRangeError("Count of members in media group", mediaCountInMediaGroup, media.size)
}
@@ -43,17 +47,18 @@ fun SendMediaGroup(
chatId,
media,
disableNotification,
replyToMessageId
replyToMessageId,
allowSendingWithoutReply
)
return if (files.isEmpty()) {
return (if (files.isEmpty()) {
data
} else {
MultipartRequestImpl(
data,
SendMediaGroupFiles(files)
)
}
}) as Request<List<MediaGroupMessage<T>>>
}
/**
@@ -66,8 +71,9 @@ inline fun SendPlaylist(
chatId: ChatIdentifier,
media: List<AudioMediaGroupMemberInputMedia>,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null
) = SendMediaGroup(chatId, media, disableNotification, replyToMessageId)
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null
) = SendMediaGroup<AudioContent>(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply)
/**
* Use this method to be sure that you are correctly sending documents media group
@@ -79,8 +85,9 @@ inline fun SendDocumentsGroup(
chatId: ChatIdentifier,
media: List<DocumentMediaGroupMemberInputMedia>,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null
) = SendMediaGroup(chatId, media, disableNotification, replyToMessageId)
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null
) = SendMediaGroup<DocumentContent>(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply)
/**
* Use this method to be sure that you are correctly sending visual media group
@@ -93,10 +100,11 @@ inline fun SendVisualMediaGroup(
chatId: ChatIdentifier,
media: List<VisualMediaGroupMemberInputMedia>,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null
) = SendMediaGroup(chatId, media, disableNotification, replyToMessageId)
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null
) = SendMediaGroup<VisualMediaGroupContent>(chatId, media, disableNotification, replyToMessageId, allowSendingWithoutReply)
private val messagesListSerializer: KSerializer<List<MediaGroupMessage>>
private val messagesListSerializer: KSerializer<List<MediaGroupMessage<MediaGroupContent>>>
= ListSerializer(TelegramBotAPIMessageDeserializeOnlySerializerClass())
@Serializable
@@ -107,8 +115,10 @@ data class SendMediaGroupData internal constructor(
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null
) : DataRequest<List<MediaGroupMessage>>, SendMessageRequest<List<MediaGroupMessage>> {
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null
) : DataRequest<List<MediaGroupMessage<MediaGroupContent>>>, SendMessageRequest<List<MediaGroupMessage<MediaGroupContent>>> {
@SerialName(mediaField)
private val convertedMedia: String
get() = buildJsonArray {
@@ -121,7 +131,7 @@ data class SendMediaGroupData internal constructor(
override fun method(): String = "sendMediaGroup"
override val requestSerializer: SerializationStrategy<*>
get() = serializer()
override val resultDeserializer: DeserializationStrategy<List<MediaGroupMessage>>
override val resultDeserializer: DeserializationStrategy<List<MediaGroupMessage<MediaGroupContent>>>
get() = messagesListSerializer
}

View File

@@ -4,31 +4,65 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.media.PhotoContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
fun SendPhoto(
chatId: ChatIdentifier,
photo: InputFile,
caption: String? = null,
text: String? = null,
parseMode: ParseMode? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<PhotoContent>> {
val data = SendPhotoData(
chatId,
(photo as? FileId) ?.fileId,
caption,
text,
parseMode,
null,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
return data.photo ?.let {
data
} ?: MultipartRequestImpl(
data,
SendPhotoFiles(photo as MultipartFile)
)
}
fun SendPhoto(
chatId: ChatIdentifier,
photo: InputFile,
entities: TextSourcesList,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<PhotoContent>> {
val data = SendPhotoData(
chatId,
(photo as? FileId)?.fileId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
return data.photo ?.let {
@@ -52,10 +86,14 @@ data class SendPhotoData internal constructor(
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : DataRequest<ContentMessage<PhotoContent>>,
@@ -63,6 +101,10 @@ data class SendPhotoData internal constructor(
ReplyingMarkupSendMessageRequest<ContentMessage<PhotoContent>>,
TextableSendMessageRequest<ContentMessage<PhotoContent>>
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
init {
text ?.let {
if (it.length !in captionLength) {

View File

@@ -17,12 +17,14 @@ fun SendSticker(
sticker: InputFile,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<StickerContent>> = SendStickerByFileId(
chatId,
sticker as? FileId,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
).let {
when (sticker) {
@@ -44,6 +46,8 @@ data class SendStickerByFileId internal constructor(
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : SendMessageRequest<ContentMessage<StickerContent>>, ReplyingMarkupSendMessageRequest<ContentMessage<StickerContent>> {

View File

@@ -4,12 +4,15 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.media.VideoContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.mapOfNotNull
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
@@ -18,7 +21,7 @@ fun SendVideo(
chatId: ChatIdentifier,
video: InputFile,
thumb: InputFile? = null,
caption: String? = null,
text: String? = null,
parseMode: ParseMode? = null,
duration: Long? = null,
width: Int? = null,
@@ -26,6 +29,7 @@ fun SendVideo(
supportStreaming: Boolean? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VideoContent>> {
val videoAsFileId = (video as? FileId) ?.fileId
@@ -37,14 +41,62 @@ fun SendVideo(
chatId,
videoAsFileId,
thumbAsFileId,
caption,
text,
parseMode,
null,
duration,
width,
height,
supportStreaming,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
return if (videoAsFile == null && thumbAsFile == null) {
data
} else {
MultipartRequestImpl(
data,
SendVideoFiles(videoAsFile, thumbAsFile)
)
}
}
fun SendVideo(
chatId: ChatIdentifier,
video: InputFile,
thumb: InputFile? = null,
entities: TextSourcesList,
duration: Long? = null,
width: Int? = null,
height: Int? = null,
supportStreaming: Boolean? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VideoContent>> {
val videoAsFileId = (video as? FileId) ?.fileId
val videoAsFile = video as? MultipartFile
val thumbAsFileId = (thumb as? FileId) ?.fileId
val thumbAsFile = thumb as? MultipartFile
val data = SendVideoData(
chatId,
videoAsFileId,
thumbAsFileId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
duration,
width,
height,
supportStreaming,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@@ -73,6 +125,8 @@ data class SendVideoData internal constructor(
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(durationField)
override val duration: Long? = null,
@SerialName(widthField)
@@ -85,6 +139,8 @@ data class SendVideoData internal constructor(
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : DataRequest<ContentMessage<VideoContent>>,
@@ -95,6 +151,10 @@ data class SendVideoData internal constructor(
DuratedSendMessageRequest<ContentMessage<VideoContent>>,
SizedSendMessageRequest<ContentMessage<VideoContent>>
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
init {
text ?.let {
if (it.length !in captionLength) {

View File

@@ -4,26 +4,22 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.media.VideoNoteContent
import dev.inmo.tgbotapi.utils.mapOfNotNull
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
fun SendVideoNote(
chatId: ChatIdentifier,
videoNote: InputFile,
thumb: InputFile? = null,
caption: String? = null,
parseMode: ParseMode? = null,
duration: Long? = null,
size: Int? = null, // in documentation - length (size of video side)
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VideoNoteContent>> {
val videoNoteAsFileId = (videoNote as? FileId) ?.fileId
@@ -35,12 +31,11 @@ fun SendVideoNote(
chatId,
videoNoteAsFileId,
thumbAsFileId,
caption,
parseMode,
duration,
size,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@@ -65,10 +60,6 @@ data class SendVideoNoteData internal constructor(
val videoNote: String? = null,
@SerialName(thumbField)
override val thumb: String? = null,
@SerialName(captionField)
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(durationField)
override val duration: Long? = null,
@SerialName(lengthField)
@@ -77,12 +68,13 @@ data class SendVideoNoteData internal constructor(
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : DataRequest<ContentMessage<VideoNoteContent>>,
SendMessageRequest<ContentMessage<VideoNoteContent>>,
ReplyingMarkupSendMessageRequest<ContentMessage<VideoNoteContent>>,
TextableSendMessageRequest<ContentMessage<VideoNoteContent>>,
ThumbedSendMessageRequest<ContentMessage<VideoNoteContent>>,
DuratedSendMessageRequest<ContentMessage<VideoNoteContent>>,
SizedSendMessageRequest<ContentMessage<VideoNoteContent>>
@@ -90,14 +82,6 @@ data class SendVideoNoteData internal constructor(
override val height: Int?
get() = width
init {
text ?.let {
if (it.length !in captionLength) {
throwRangeError("Caption length", captionLength, it.length)
}
}
}
override fun method(): String = "sendVideoNote"
override val resultDeserializer: DeserializationStrategy<ContentMessage<VideoNoteContent>>
get() = commonResultDeserializer

View File

@@ -4,12 +4,15 @@ import dev.inmo.tgbotapi.requests.abstracts.*
import dev.inmo.tgbotapi.requests.send.abstracts.*
import dev.inmo.tgbotapi.requests.send.media.base.*
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.MessageEntity.*
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextSourcesList
import dev.inmo.tgbotapi.types.ParseMode.ParseMode
import dev.inmo.tgbotapi.types.ParseMode.parseModeField
import dev.inmo.tgbotapi.types.buttons.KeyboardMarkup
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.abstracts.TelegramBotAPIMessageDeserializationStrategyClass
import dev.inmo.tgbotapi.types.message.content.media.VoiceContent
import dev.inmo.tgbotapi.utils.extensions.makeString
import dev.inmo.tgbotapi.utils.mapOfNotNull
import dev.inmo.tgbotapi.utils.throwRangeError
import kotlinx.serialization.*
@@ -17,11 +20,12 @@ import kotlinx.serialization.*
fun SendVoice(
chatId: ChatIdentifier,
voice: InputFile,
caption: String? = null,
text: String? = null,
parseMode: ParseMode? = null,
duration: Long? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VoiceContent>> {
val voiceAsFileId = (voice as? FileId) ?.fileId
@@ -30,11 +34,49 @@ fun SendVoice(
val data = SendVoiceData(
chatId,
voiceAsFileId,
caption,
text,
parseMode,
null,
duration,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
return if (voiceAsFile == null) {
data
} else {
MultipartRequestImpl(
data,
SendVoiceFiles(voiceAsFile)
)
}
}
fun SendVoice(
chatId: ChatIdentifier,
voice: InputFile,
entities: TextSourcesList,
duration: Long? = null,
disableNotification: Boolean = false,
replyToMessageId: MessageIdentifier? = null,
allowSendingWithoutReply: Boolean? = null,
replyMarkup: KeyboardMarkup? = null
): Request<ContentMessage<VoiceContent>> {
val voiceAsFileId = (voice as? FileId) ?.fileId
val voiceAsFile = voice as? MultipartFile
val data = SendVoiceData(
chatId,
voiceAsFileId,
entities.makeString(),
null,
entities.toRawMessageEntities(),
duration,
disableNotification,
replyToMessageId,
allowSendingWithoutReply,
replyMarkup
)
@@ -61,12 +103,16 @@ data class SendVoiceData internal constructor(
override val text: String? = null,
@SerialName(parseModeField)
override val parseMode: ParseMode? = null,
@SerialName(captionEntitiesField)
private val rawEntities: List<RawMessageEntity>? = null,
@SerialName(durationField)
override val duration: Long? = null,
@SerialName(disableNotificationField)
override val disableNotification: Boolean = false,
@SerialName(replyToMessageIdField)
override val replyToMessageId: MessageIdentifier? = null,
@SerialName(allowSendingWithoutReplyField)
override val allowSendingWithoutReply: Boolean? = null,
@SerialName(replyMarkupField)
override val replyMarkup: KeyboardMarkup? = null
) : DataRequest<ContentMessage<VoiceContent>>,
@@ -75,6 +121,10 @@ data class SendVoiceData internal constructor(
TextableSendMessageRequest<ContentMessage<VoiceContent>>,
DuratedSendMessageRequest<ContentMessage<VoiceContent>>
{
override val textSources: TextSourcesList? by lazy {
rawEntities ?.asTextSources(text ?: return@lazy null)
}
init {
text ?.let {
if (it.length !in captionLength) {

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