Skip to content

Commit c79f9fd

Browse files
committed
Telegram Bot API March 30,2020 updates (v4.7).
1 parent b71b5e2 commit c79f9fd

18 files changed

+776
-43
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package telegramium.bots
2+
3+
/** This object represents a bot command.*/
4+
final case class BotCommand(
5+
/** Text of the command, 1-32 characters. Can contain only
6+
* lowercase English letters, digits and underscores.*/
7+
command: String,
8+
/** Description of the command, 3-256 characters.*/
9+
description: String)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package telegramium.bots
2+
3+
/** This object represents a dice with random value from 1 to 6. (Yes, we're aware
4+
* of the “proper” singular of die. But it's awkward, and we decided to help it
5+
* change. One dice at a time!)*/
6+
final case class Dice(
7+
/** Value of the dice, 1-6*/
8+
value: Int)

telegramium-core/src/main/scala/telegramium/bots/Message.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ final case class Message(
9191
/** Optional. Message is a native poll, information about the
9292
* poll*/
9393
poll: Option[Poll] = Option.empty,
94+
/** Optional. Message is a dice with random value from 1 to 6*/
95+
dice: Option[Dice] = Option.empty,
9496
/** Optional. New members that were added to the group or
9597
* supergroup and information about them (the bot itself may be
9698
* one of these members)*/

telegramium-core/src/main/scala/telegramium/bots/StickerSet.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,6 @@ final case class StickerSet(
1111
/** True, if the sticker set contains masks*/
1212
containsMasks: Boolean,
1313
/** List of all set stickers*/
14-
stickers: List[Sticker] = List.empty)
14+
stickers: List[Sticker] = List.empty,
15+
/** Optional. Sticker set thumbnail in the .WEBP or .TGS format*/
16+
thumb: Option[PhotoSize] = Option.empty)

telegramium-core/src/main/scala/telegramium/bots/client/AddStickerToSetReq.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@ final case class AddStickerToSetReq(
88
userId: Int,
99
/** Sticker set name*/
1010
name: String,
11-
/** Png image with the sticker, must be up to 512 kilobytes in
11+
/** PNG image with the sticker, must be up to 512 kilobytes in
1212
* size, dimensions must not exceed 512px, and either width or
1313
* height must be exactly 512px. Pass a file_id as a String to
1414
* send a file that already exists on the Telegram servers,
1515
* pass an HTTP URL as a String for Telegram to get a file from
1616
* the Internet, or upload a new one using multipart/form-data.
1717
* More info on Sending Files »*/
1818
pngSticker: IFile,
19+
/** TGS animation with the sticker, uploaded using
20+
* multipart/form-data. See
21+
* https://core.telegram.org/animated_stickers#technical-requirements
22+
* for technical requirements*/
23+
tgsSticker: Option[IFile] = Option.empty,
1924
/** One or more emoji corresponding to the sticker*/
2025
emojis: String,
2126
/** A JSON-serialized object for position where the mask should

telegramium-core/src/main/scala/telegramium/bots/client/Api.scala

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ trait Api[F[_]] {
77
* return an object with the url field empty.*/
88
def getWebhookInfo(): F[GetWebhookInfoRes]
99

10+
/** Use this method to change the list of the bot's commands. Returns True on
11+
* success.*/
12+
def setMyCommands(x: SetMyCommandsReq): F[SetMyCommandsRes]
13+
1014
/** Use this method to set a new profile photo for the chat. Photos can't be
1115
* changed for private chats. The bot must be an administrator in the chat for this
1216
* to work and must have the appropriate admin rights. Returns True on success.*/
@@ -38,8 +42,9 @@ trait Api[F[_]] {
3842
* returned.*/
3943
def sendContact(x: SendContactReq): F[SendContactRes]
4044

41-
/** Use this method to create new sticker set owned by a user. The bot will be able
42-
* to edit the created sticker set. Returns True on success.*/
45+
/** Use this method to create a new sticker set owned by a user. The bot will be
46+
* able to edit the sticker set thus created. You must use exactly one of the
47+
* fields png_sticker or tgs_sticker. Returns True on success.*/
4348
def createNewStickerSet(x: CreateNewStickerSetReq): F[CreateNewStickerSetRes]
4449

4550
/** Use this method to upload a .PNG file with a sticker for later use in
@@ -73,13 +78,22 @@ trait Api[F[_]] {
7378
* as String on success.*/
7479
def exportChatInviteLink(x: ExportChatInviteLinkReq): F[ExportChatInviteLinkRes]
7580

81+
/** Use this method to send a dice, which will have a random value from 1 to 6. On
82+
* success, the sent Message is returned. (Yes, we're aware of the “proper”
83+
* singular of die. But it's awkward, and we decided to help it change. One dice at
84+
* a time!)*/
85+
def sendDice(x: SendDiceReq): F[SendDiceRes]
86+
7687
/** Use this method when you need to tell the user that something is happening on
7788
* the bot's side. The status is set for 5 seconds or less (when a message arrives
7889
* from your bot, Telegram clients clear its typing status). Returns True on
7990
* success.*/
8091
def sendChatAction(): F[SendChatActionRes]
8192

82-
/** Use this method to add a new sticker to a set created by the bot. Returns True
93+
/** Use this method to add a new sticker to a set created by the bot. You must use
94+
* exactly one of the fields png_sticker or tgs_sticker. Animated stickers can be
95+
* added to animated sticker sets and only to them. Animated sticker sets can have
96+
* up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns True
8397
* on success.*/
8498
def addStickerToSet(x: AddStickerToSetReq): F[AddStickerToSetRes]
8599

@@ -183,12 +197,13 @@ trait Api[F[_]] {
183197

184198
/** Use this method to delete a message, including service messages, with the
185199
* following limitations: - A message can only be deleted if it was sent less than
186-
* 48 hours ago. - Bots can delete outgoing messages in private chats, groups, and
187-
* supergroups. - Bots can delete incoming messages in private chats. - Bots
188-
* granted can_post_messages permissions can delete outgoing messages in channels.
189-
* - If the bot is an administrator of a group, it can delete any message there. -
190-
* If the bot has can_delete_messages permission in a supergroup or a channel, it
191-
* can delete any message there. Returns True on success.*/
200+
* 48 hours ago. - A dice message in a private chat can only be deleted if it was
201+
* sent more than 24 hours ago. - Bots can delete outgoing messages in private
202+
* chats, groups, and supergroups. - Bots can delete incoming messages in private
203+
* chats. - Bots granted can_post_messages permissions can delete outgoing messages
204+
* in channels. - If the bot is an administrator of a group, it can delete any
205+
* message there. - If the bot has can_delete_messages permission in a supergroup
206+
* or a channel, it can delete any message there. Returns True on success.*/
192207
def deleteMessage(x: DeleteMessageReq): F[DeleteMessageRes]
193208

194209
/** Use this method to send answers to an inline query. On success, True is
@@ -227,6 +242,10 @@ trait Api[F[_]] {
227242
* ChatMember object on success.*/
228243
def getChatMember(x: GetChatMemberReq): F[GetChatMemberRes]
229244

245+
/** Use this method to get the current list of the bot's commands. Requires no
246+
* parameters. Returns Array of BotCommand on success.*/
247+
def getMyCommands(): F[GetMyCommandsRes]
248+
230249
/** Use this method to get a list of administrators in a chat. On success, returns
231250
* an Array of ChatMember objects that contains information about all chat
232251
* administrators except other bots. If the chat is a group or a supergroup and no
@@ -264,6 +283,10 @@ trait Api[F[_]] {
264283
* right in the channel. Returns True on success.*/
265284
def pinChatMessage(x: PinChatMessageReq): F[PinChatMessageRes]
266285

286+
/** Use this method to set the thumbnail of a sticker set. Animated thumbnails can
287+
* be set for animated sticker sets only. Returns True on success.*/
288+
def setStickerSetThumb(x: SetStickerSetThumbReq): F[SetStickerSetThumbRes]
289+
267290
/** Use this method to edit only the reply markup of messages. On success, if
268291
* edited message is sent by the bot, the edited Message is returned, otherwise
269292
* True is returned.*/

telegramium-core/src/main/scala/telegramium/bots/client/ApiHttp4sImp.scala

Lines changed: 135 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
5555

5656
}
5757

58+
/** Use this method to change the list of the bot's commands. Returns True on
59+
success. */
60+
def setMyCommands(x: SetMyCommandsReq): F[SetMyCommandsRes] = {
61+
for {
62+
uri <- F.fromEither[Uri](Uri.fromString(s"$baseUrl/setMyCommands"))
63+
req = Request[F]()
64+
.withMethod(GET)
65+
.withUri(uri)
66+
.withEntity(x.asJson)
67+
res <- http.expect(req)(jsonOf[F, SetMyCommandsRes])
68+
} yield {
69+
res
70+
}
71+
72+
}
73+
5874
/** Use this method to set a new profile photo for the chat. Photos can't be
5975
changed for private chats. The bot must be an administrator in the chat for this
6076
to work and must have the appropriate admin rights. Returns True on success. */
@@ -200,20 +216,27 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
200216

201217
}
202218

203-
/** Use this method to create new sticker set owned by a user. The bot will be able
204-
to edit the created sticker set. Returns True on success. */
219+
/** Use this method to create a new sticker set owned by a user. The bot will be
220+
able to edit the sticker set thus created. You must use exactly one of the
221+
fields png_sticker or tgs_sticker. Returns True on success. */
205222
def createNewStickerSet(x: CreateNewStickerSetReq): F[CreateNewStickerSetRes] = {
206223

207224
val pngStickerPartF = x.pngSticker match {
208-
case InputPartFile(f) => makePart("png_sticker", f)
209-
case _ => F.pure(List.empty[Part[F]])
225+
case Some(InputPartFile(f)) => makePart("png_sticker", f)
226+
case _ => F.pure(List.empty[Part[F]])
210227
}
211228

212-
List(pngStickerPartF).sequence.map(_.flatten).flatMap { l =>
229+
val tgsStickerPartF = x.tgsSticker match {
230+
case Some(InputPartFile(f)) => makePart("tgs_sticker", f)
231+
case _ => F.pure(List.empty[Part[F]])
232+
}
233+
234+
List(pngStickerPartF, tgsStickerPartF).sequence.map(_.flatten).flatMap { l =>
213235
if (l.nonEmpty) {
214236
for {
215237
uri <- F.fromEither[Uri](Uri.fromString(s"$baseUrl/createNewStickerSet"))
216238
pngStickerPart <- pngStickerPartF
239+
tgsStickerPart <- tgsStickerPartF
217240
body = Multipart[F](
218241
Vector(
219242
("user_id", x.userId.asJson),
@@ -222,9 +245,11 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
222245
("emojis", x.emojis.asJson),
223246
("contains_masks", x.containsMasks.asJson),
224247
("mask_position", x.maskPosition.asJson),
225-
("pngSticker", if (pngStickerPart.isEmpty) { x.pngSticker.asJson } else { Json.Null })
248+
("pngSticker",
249+
if (pngStickerPart.isEmpty) { x.pngSticker.asJson } else { Json.Null }),
250+
("tgsSticker", if (tgsStickerPart.isEmpty) { x.tgsSticker.asJson } else { Json.Null })
226251
).filter(!_._2.isNull).map { case (n, v) => Part.formData(n, v.noSpaces) } ++
227-
pngStickerPart
252+
pngStickerPart ++ tgsStickerPart
228253
)
229254
req = Request[F]()
230255
.withMethod(POST)
@@ -384,6 +409,24 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
384409

385410
}
386411

412+
/** Use this method to send a dice, which will have a random value from 1 to 6. On
413+
success, the sent Message is returned. (Yes, we're aware of the “proper”
414+
singular of die. But it's awkward, and we decided to help it change. One dice at
415+
a time!) */
416+
def sendDice(x: SendDiceReq): F[SendDiceRes] = {
417+
for {
418+
uri <- F.fromEither[Uri](Uri.fromString(s"$baseUrl/sendDice"))
419+
req = Request[F]()
420+
.withMethod(GET)
421+
.withUri(uri)
422+
.withEntity(x.asJson)
423+
res <- http.expect(req)(jsonOf[F, SendDiceRes])
424+
} yield {
425+
res
426+
}
427+
428+
}
429+
387430
/** Use this method when you need to tell the user that something is happening on
388431
the bot's side. The status is set for 5 seconds or less (when a message arrives
389432
from your bot, Telegram clients clear its typing status). Returns True on
@@ -402,7 +445,10 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
402445

403446
}
404447

405-
/** Use this method to add a new sticker to a set created by the bot. Returns True
448+
/** Use this method to add a new sticker to a set created by the bot. You must use
449+
exactly one of the fields png_sticker or tgs_sticker. Animated stickers can be
450+
added to animated sticker sets and only to them. Animated sticker sets can have
451+
up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns True
406452
on success. */
407453
def addStickerToSet(x: AddStickerToSetReq): F[AddStickerToSetRes] = {
408454

@@ -411,20 +457,28 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
411457
case _ => F.pure(List.empty[Part[F]])
412458
}
413459

414-
List(pngStickerPartF).sequence.map(_.flatten).flatMap { l =>
460+
val tgsStickerPartF = x.tgsSticker match {
461+
case Some(InputPartFile(f)) => makePart("tgs_sticker", f)
462+
case _ => F.pure(List.empty[Part[F]])
463+
}
464+
465+
List(pngStickerPartF, tgsStickerPartF).sequence.map(_.flatten).flatMap { l =>
415466
if (l.nonEmpty) {
416467
for {
417468
uri <- F.fromEither[Uri](Uri.fromString(s"$baseUrl/addStickerToSet"))
418469
pngStickerPart <- pngStickerPartF
470+
tgsStickerPart <- tgsStickerPartF
419471
body = Multipart[F](
420472
Vector(
421473
("user_id", x.userId.asJson),
422474
("name", x.name.asJson),
423475
("emojis", x.emojis.asJson),
424476
("mask_position", x.maskPosition.asJson),
425-
("pngSticker", if (pngStickerPart.isEmpty) { x.pngSticker.asJson } else { Json.Null })
477+
("pngSticker",
478+
if (pngStickerPart.isEmpty) { x.pngSticker.asJson } else { Json.Null }),
479+
("tgsSticker", if (tgsStickerPart.isEmpty) { x.tgsSticker.asJson } else { Json.Null })
426480
).filter(!_._2.isNull).map { case (n, v) => Part.formData(n, v.noSpaces) } ++
427-
pngStickerPart
481+
pngStickerPart ++ tgsStickerPart
428482
)
429483
req = Request[F]()
430484
.withMethod(POST)
@@ -863,12 +917,13 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
863917

864918
/** Use this method to delete a message, including service messages, with the
865919
following limitations: - A message can only be deleted if it was sent less than
866-
48 hours ago. - Bots can delete outgoing messages in private chats, groups, and
867-
supergroups. - Bots can delete incoming messages in private chats. - Bots
868-
granted can_post_messages permissions can delete outgoing messages in channels.
869-
- If the bot is an administrator of a group, it can delete any message there. -
870-
If the bot has can_delete_messages permission in a supergroup or a channel, it
871-
can delete any message there. Returns True on success. */
920+
48 hours ago. - A dice message in a private chat can only be deleted if it was
921+
sent more than 24 hours ago. - Bots can delete outgoing messages in private
922+
chats, groups, and supergroups. - Bots can delete incoming messages in private
923+
chats. - Bots granted can_post_messages permissions can delete outgoing messages
924+
in channels. - If the bot is an administrator of a group, it can delete any
925+
message there. - If the bot has can_delete_messages permission in a supergroup
926+
or a channel, it can delete any message there. Returns True on success. */
872927
def deleteMessage(x: DeleteMessageReq): F[DeleteMessageRes] = {
873928
for {
874929
uri <- F.fromEither[Uri](Uri.fromString(s"$baseUrl/deleteMessage"))
@@ -1048,6 +1103,22 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
10481103

10491104
}
10501105

1106+
/** Use this method to get the current list of the bot's commands. Requires no
1107+
parameters. Returns Array of BotCommand on success. */
1108+
def getMyCommands(): F[GetMyCommandsRes] = {
1109+
for {
1110+
uri <- F.fromEither[Uri](Uri.fromString(s"$baseUrl/getMyCommands"))
1111+
req = Request[F]()
1112+
.withMethod(GET)
1113+
.withUri(uri)
1114+
1115+
res <- http.expect(req)(jsonOf[F, GetMyCommandsRes])
1116+
} yield {
1117+
res
1118+
}
1119+
1120+
}
1121+
10511122
/** Use this method to get a list of administrators in a chat. On success, returns
10521123
an Array of ChatMember objects that contains information about all chat
10531124
administrators except other bots. If the chat is a group or a supergroup and no
@@ -1193,6 +1264,53 @@ class ApiHttp4sImp[F[_]: ConcurrentEffect: ContextShift](http: Client[F], baseUr
11931264

11941265
}
11951266

1267+
/** Use this method to set the thumbnail of a sticker set. Animated thumbnails can
1268+
be set for animated sticker sets only. Returns True on success. */
1269+
def setStickerSetThumb(x: SetStickerSetThumbReq): F[SetStickerSetThumbRes] = {
1270+
1271+
val thumbPartF = x.thumb match {
1272+
case Some(InputPartFile(f)) => makePart("thumb", f)
1273+
case _ => F.pure(List.empty[Part[F]])
1274+
}
1275+
1276+
List(thumbPartF).sequence.map(_.flatten).flatMap { l =>
1277+
if (l.nonEmpty) {
1278+
for {
1279+
uri <- F.fromEither[Uri](Uri.fromString(s"$baseUrl/setStickerSetThumb"))
1280+
thumbPart <- thumbPartF
1281+
body = Multipart[F](
1282+
Vector(("name", x.name.asJson),
1283+
("user_id", x.userId.asJson),
1284+
("thumb", if (thumbPart.isEmpty) { x.thumb.asJson } else { Json.Null }))
1285+
.filter(!_._2.isNull)
1286+
.map { case (n, v) => Part.formData(n, v.noSpaces) } ++
1287+
thumbPart
1288+
)
1289+
req = Request[F]()
1290+
.withMethod(POST)
1291+
.withUri(uri)
1292+
.withEntity(body)
1293+
.withHeaders(body.headers)
1294+
res <- http.expect(req)(jsonOf[F, SetStickerSetThumbRes])
1295+
} yield {
1296+
res
1297+
}
1298+
} else {
1299+
for {
1300+
uri <- F.fromEither[Uri](Uri.fromString(s"$baseUrl/setStickerSetThumb"))
1301+
req = Request[F]()
1302+
.withMethod(GET)
1303+
.withUri(uri)
1304+
.withEntity(x.asJson)
1305+
res <- http.expect(req)(jsonOf[F, SetStickerSetThumbRes])
1306+
} yield {
1307+
res
1308+
}
1309+
1310+
}
1311+
}
1312+
}
1313+
11961314
/** Use this method to edit only the reply markup of messages. On success, if
11971315
edited message is sent by the bot, the edited Message is returned, otherwise
11981316
True is returned. */

0 commit comments

Comments
 (0)