1 module telega.botapi; 2 3 import vibe.http.client : HTTPMethod; 4 import vibe.core.core; 5 import vibe.core.log; 6 import asdf; 7 import std.conv; 8 import std.typecons; 9 import std.exception; 10 import std.traits; 11 import telega.http; 12 import telega.serialization; 13 14 class TelegramBotApiException : Exception 15 { 16 ushort code; 17 18 this(ushort code, string description, string file = __FILE__, size_t line = __LINE__, 19 Throwable next = null) @nogc @safe pure nothrow 20 { 21 this.code = code; 22 super(description, file, line, next); 23 } 24 } 25 26 enum isTelegramId(T) = isSomeString!T || isIntegral!T; 27 28 /******************************************************************/ 29 /* Telegram types and enums */ 30 /******************************************************************/ 31 32 struct User 33 { 34 int id; 35 bool is_bot; 36 string first_name; 37 38 Nullable!string last_name; 39 Nullable!string username; 40 Nullable!string language_code; 41 } 42 43 unittest 44 { 45 string json = `{ 46 "id": 42, 47 "is_bot": false, 48 "first_name": "FirstName" 49 }`; 50 51 User u = deserialize!User(json); 52 53 assert(u.last_name.isNull); 54 } 55 56 unittest 57 { 58 string json = `{ 59 "id": 42, 60 "is_bot": false, 61 "first_name": "FirstName", 62 "last_name": "LastName" 63 }`; 64 65 User u = deserialize!User(json); 66 67 assert(false == u.last_name.isNull); 68 } 69 70 71 72 @serializedAs!ChatTypeProxy 73 enum ChatType : string 74 { 75 Private = "private", 76 Group = "group", 77 Supergroup = "supergroup", 78 Channel = "channel" 79 } 80 81 struct ChatTypeProxy 82 { 83 ChatType t; 84 85 this(ChatType type) 86 { 87 t = type; 88 } 89 90 ChatType opCast(T : ChatType)() 91 { 92 return t; 93 } 94 95 static ChatTypeProxy deserialize(Asdf v) 96 { 97 return ChatTypeProxy(cast(ChatType)cast(string)v); 98 } 99 } 100 101 struct Chat 102 { 103 long id; 104 ChatType type; 105 Nullable!string title; 106 Nullable!string first_name; 107 Nullable!string last_name; 108 Nullable!string username; 109 Nullable!bool all_members_are_administrators; 110 Nullable!ChatPhoto photo; 111 Nullable!string description; 112 Nullable!string invite_link; 113 // TODO Nullable!Message pinned_message; 114 Nullable!string sticker_set_name; 115 Nullable!bool can_set_sticker_set; 116 } 117 118 unittest 119 { 120 string json = `{ 121 "id": 42, 122 "type": "group", 123 "title": "chat title" 124 }`; 125 126 Chat c = deserialize!Chat(json); 127 128 assert(c.id == 42); 129 assert(c.type == ChatType.Group); 130 } 131 132 struct Message 133 { 134 uint message_id; 135 uint date; 136 Chat chat; 137 Nullable!User from; 138 Nullable!User forward_from; 139 Nullable!Chat forward_from_chat; 140 Nullable!uint forward_from_message_id; 141 Nullable!string forward_signature; 142 Nullable!uint forward_date; 143 Nullable!uint edit_date; 144 Nullable!string media_group_id; 145 Nullable!string author_signature; 146 Nullable!string text; 147 Nullable!MessageEntity[] entities; 148 Nullable!MessageEntity[] caption_entities; 149 Nullable!Audio audio; 150 Nullable!Document document; 151 Nullable!Animation animation; 152 Nullable!Game game; 153 Nullable!PhotoSize[] photo; 154 Nullable!Sticker sticker; 155 Nullable!Video video; 156 Nullable!Voice voice; 157 Nullable!VideoNote video_note; 158 // TODO Nullable!Message reply_to_message; 159 // TODO Nullable!Message pinned_message; 160 Nullable!string caption; 161 Nullable!Contact contact; 162 Nullable!Location location; 163 Nullable!Venue venue; 164 Nullable!User[] new_chat_members; 165 Nullable!User left_chat_member; 166 Nullable!string new_chat_title; 167 Nullable!PhotoSize[] new_chat_photo; 168 Nullable!bool delete_chat_photo; 169 Nullable!bool group_chat_created; 170 Nullable!bool supergroup_chat_created; 171 Nullable!bool channel_chat_created; 172 Nullable!long migrate_to_chat_id; 173 Nullable!long migrate_from_chat_id; 174 Nullable!Invoice invoice; 175 Nullable!SuccessfulPayment successful_payment; 176 Nullable!string connected_website; 177 178 @property 179 uint id() 180 { 181 return message_id; 182 } 183 } 184 185 struct Update 186 { 187 uint update_id; 188 Nullable!Message message; 189 190 Nullable!Message edited_message; 191 Nullable!Message channel_post; 192 Nullable!Message edited_channel_post; 193 Nullable!InlineQuery inline_query; 194 Nullable!ChosenInlineResult chosen_inline_result; 195 Nullable!CallbackQuery callback_query; 196 Nullable!ShippingQuery shipping_query; 197 Nullable!PreCheckoutQuery pre_checkout_query; 198 199 @property 200 uint id() 201 { 202 return update_id; 203 } 204 } 205 206 unittest 207 { 208 string json = `{ 209 "update_id": 143, 210 "message": { 211 "message_id": 243, 212 "text": "message text" 213 } 214 }`; 215 216 Update u = deserialize!Update(json); 217 218 assert(u.id == 143); 219 assert(u.message.message_id == 243); 220 assert(u.message.text == "message text"); 221 } 222 223 struct WebhookInfo 224 { 225 string url; 226 bool has_custom_certificate; 227 uint pending_update_count; 228 Nullable!uint last_error_date; 229 Nullable!string last_error_message; 230 Nullable!uint max_connections; 231 Nullable!string[] allowed_updates; 232 } 233 234 enum ParseMode 235 { 236 Markdown = "Markdown", 237 HTML = "HTML", 238 None = "", 239 } 240 241 struct MessageEntity 242 { 243 string type; 244 uint offset; 245 uint length; 246 Nullable!string url; 247 Nullable!User user; 248 } 249 250 struct PhotoSize 251 { 252 string file_id; 253 int width; 254 int height; 255 256 Nullable!uint file_size; 257 } 258 259 struct Audio 260 { 261 string file_id; 262 uint duration; 263 Nullable!string performer; 264 Nullable!string title; 265 Nullable!string mime_type; 266 Nullable!uint file_size; 267 Nullable!PhotoSize thumb; 268 } 269 270 // TODO Add Nullable fields 271 struct Document 272 { 273 string file_id; 274 PhotoSize thumb; 275 string file_name; 276 string mime_type; 277 uint file_size; 278 } 279 280 // TODO Add Nullable fields 281 struct Video 282 { 283 string file_id; 284 uint width; 285 uint height; 286 uint duration; 287 PhotoSize thumb; 288 string mime_type; 289 uint file_size; 290 } 291 292 // TODO Add Nullable fields 293 struct Voice 294 { 295 string file_id; 296 uint duration; 297 string mime_type; 298 uint file_size; 299 } 300 301 // TODO Add Nullable fields 302 struct VideoNote 303 { 304 string file_id; 305 uint length; 306 uint duration; 307 PhotoSize thumb; 308 uint file_size; 309 } 310 311 // TODO Add Nullable fields 312 struct Contact 313 { 314 string phone_number; 315 string first_name; 316 string last_name; 317 string user_id; 318 } 319 320 // TODO Add Nullable fields 321 struct Location 322 { 323 float longitude; 324 float latitude; 325 } 326 327 // TODO Add Nullable fields 328 struct Venue 329 { 330 Location location; 331 string title; 332 string address; 333 string foursquare_id; 334 } 335 336 // TODO Add Nullable fields 337 struct UserProfilePhotos 338 { 339 uint total_count; 340 PhotoSize[][] photos; 341 } 342 343 // TODO Add Nullable fields 344 struct File 345 { 346 string file_id; 347 uint file_size; 348 string file_path; 349 } 350 351 import std.meta : AliasSeq, staticIndexOf; 352 import std.variant : Algebraic; 353 354 alias ReplyMarkupStructs = AliasSeq!(ReplyKeyboardMarkup, ReplyKeyboardRemove, InlineKeyboardMarkup, ForceReply); 355 356 /** 357 Abstract structure for unioining ReplyKeyboardMarkup, ReplyKeyboardRemove, 358 InlineKeyboardMarkup and ForceReply 359 */ 360 361 alias ReplyMarkup = JsonableAlgebraicProxy!ReplyMarkupStructs; 362 enum isReplyMarkup(T) = 363 is(T == ReplyMarkup) || staticIndexOf!(T, ReplyMarkupStructs) >= 0; 364 365 import std.algorithm.iteration; 366 import std.array; 367 368 static bool falseIfNull(Nullable!bool value) 369 { 370 if (value.isNull) { 371 return false; 372 } 373 374 return cast(bool)value; 375 } 376 377 static bool trueIfNull(Nullable!bool value) 378 { 379 if (value.isNull) { 380 return true; 381 } 382 383 return cast(bool)value; 384 } 385 386 struct ReplyKeyboardMarkup 387 { 388 KeyboardButton[][] keyboard; 389 390 // TODO @serializationTransformOut!falseIfNull 391 Nullable!bool resize_keyboard = false; 392 393 // TODO @serializationTransformOut!falseIfNull 394 Nullable!bool one_time_keyboard = false; 395 396 // TODO @serializationTransformOut!falseIfNull 397 Nullable!bool selective = false; 398 399 this (string[][] keyboard) 400 { 401 this.keyboard = keyboard.map!toKeyboardButtonRow.array; 402 } 403 404 void opOpAssign(string op : "~")(KeyboardButton[] buttons) 405 { 406 keyboard ~= buttons; 407 } 408 } 409 410 struct KeyboardButton 411 { 412 string text; 413 414 Nullable!bool request_contact; 415 Nullable!bool request_location; 416 417 this(string text, bool requestContact = false, bool requestLocation = false) 418 { 419 this.text = text; 420 this.request_contact = requestContact; 421 this.request_location = requestLocation; 422 } 423 } 424 425 KeyboardButton[] toKeyboardButtonRow(string[] row) 426 { 427 return row.map!(b => KeyboardButton(b)).array; 428 } 429 430 struct ReplyKeyboardRemove 431 { 432 bool remove_keyboard = true; 433 Nullable!bool selective = false; 434 } 435 436 struct InlineKeyboardMarkup 437 { 438 InlineKeyboardButton[][] inline_keyboard; 439 } 440 441 struct InlineKeyboardButton 442 { 443 string text; 444 Nullable!string url; 445 Nullable!string callback_data; 446 Nullable!string switch_inline_query; 447 Nullable!string switch_inline_query_current_chat; 448 Nullable!CallbackGame callback_game; 449 Nullable!bool pay; 450 } 451 452 // TODO Add Nullable fields 453 struct CallbackQuery 454 { 455 string id; 456 User from; 457 Nullable!Message message; 458 string inline_message_id; 459 string chat_instance; 460 string data; 461 string game_short_name; 462 } 463 464 struct ForceReply 465 { 466 bool force_reply = true; 467 Nullable!bool selective; 468 } 469 470 struct ChatPhoto 471 { 472 string small_file_id; 473 string big_file_id; 474 } 475 476 // TODO Add Nullable fields 477 struct ChatMember 478 { 479 User user; 480 string status; 481 uint until_date; 482 bool can_be_edited; 483 bool can_change_info; 484 bool can_post_messages; 485 bool can_edit_messages; 486 bool can_delete_messages; 487 bool can_invite_users; 488 bool can_restrict_members; 489 bool can_pin_messages; 490 bool can_promote_members; 491 bool can_send_messages; 492 bool can_send_media_messages; 493 bool can_send_other_messages; 494 bool can_add_web_page_previews; 495 } 496 497 // TODO Add Nullable fields 498 struct ResponseParameters 499 { 500 long migrate_to_chat_id; 501 uint retry_after; 502 } 503 504 alias InputMediaStructs = AliasSeq!(InputMediaPhoto, InputMediaVideo); 505 506 alias InputMedia = JsonableAlgebraicProxy!InputMediaStructs; 507 508 struct InputMediaPhoto 509 { 510 string type; 511 string media; 512 Nullable!string caption; 513 Nullable!ParseMode parse_mode; 514 } 515 516 struct InputMediaVideo 517 { 518 string type; 519 string media; 520 Nullable!string caption; 521 Nullable!ParseMode parse_mode; 522 Nullable!uint width; 523 Nullable!uint height; 524 Nullable!uint duration; 525 Nullable!bool supports_streaming; 526 } 527 528 // TODO InputMediaAnimation 529 // TODO InputMediaAudio 530 // TODO InputMediaDocument 531 532 struct InputFile 533 { 534 // no fields 535 } 536 537 struct Sticker 538 { 539 string file_id; 540 uint width; 541 uint height; 542 PhotoSize thumb; 543 string emoji; 544 string set_name; 545 MaskPosition mask_position; 546 uint file_size; 547 } 548 549 struct StickerSet 550 { 551 string name; 552 string title; 553 bool contains_masks; 554 Sticker[] stickers; 555 } 556 557 struct MaskPosition 558 { 559 string point; 560 float x_shift; 561 float y_shift; 562 float scale; 563 } 564 565 566 /*** Inline mode types ***/ 567 568 struct InlineQuery 569 { 570 string id; 571 User from; 572 Nullable!Location location; 573 string query; 574 string offset; 575 } 576 577 alias InlineQueryResultStructs = AliasSeq!( 578 InlineQueryResultArticle, InlineQueryResultPhoto, InlineQueryResultGif, InlineQueryResultMpeg4Gif, 579 InlineQueryResultVideo, InlineQueryResultAudio, InlineQueryResultVoice, InlineQueryResultDocument, 580 InlineQueryResultLocation, InlineQueryResultVenue, InlineQueryResultContact, InlineQueryResultGame, 581 InlineQueryResultCachedPhoto, InlineQueryResultCachedGif, InlineQueryResultCachedMpeg4Gif, 582 InlineQueryResultCachedSticker, InlineQueryResultCachedDocument, InlineQueryResultCachedVideo, 583 InlineQueryResultCachedVoice, InlineQueryResultCachedAudio 584 ); 585 586 alias InlineQueryResult = JsonableAlgebraicProxy!InlineQueryResultStructs; 587 588 mixin template InlineQueryFields() 589 { 590 Nullable!InlineKeyboardMarkup reply_markup; 591 Nullable!InputMessageContent input_message_content; 592 } 593 594 struct InlineQueryResultArticle 595 { 596 string type = "article"; 597 string id; 598 string title; 599 Nullable!string url; 600 Nullable!bool hide_url; 601 Nullable!string description; 602 Nullable!string thumb_url; 603 Nullable!uint thumb_width; 604 Nullable!uint thumb_height; 605 606 Nullable!InlineKeyboardMarkup reply_markup; 607 InputMessageContent input_message_content; // can't be nullable 608 } 609 610 struct InlineQueryResultPhoto 611 { 612 string type = "photo"; 613 string id; 614 string photo_url; 615 string thumb_url; 616 Nullable!uint photo_width; 617 Nullable!uint photo_height; 618 Nullable!string title; 619 Nullable!string description; 620 Nullable!string caption; 621 Nullable!ParseMode parse_mode; 622 623 mixin InlineQueryFields; 624 } 625 626 struct InlineQueryResultGif 627 { 628 string type = "gif"; 629 string id; 630 string gif_url; 631 Nullable!uint gif_width; 632 Nullable!uint gif_height; 633 Nullable!uint gif_duration; 634 Nullable!string thumb_url; 635 Nullable!string title; 636 Nullable!string caption; 637 Nullable!ParseMode parse_mode; 638 639 mixin InlineQueryFields; 640 } 641 642 struct InlineQueryResultMpeg4Gif 643 { 644 string type ="mpeg4_gif"; 645 string id; 646 string mpeg4_url; 647 Nullable!uint mpeg4_width; 648 Nullable!uint mpeg4_height; 649 Nullable!uint mpeg4_duration; 650 Nullable!string thumb_url; 651 Nullable!string title; 652 Nullable!string caption; 653 Nullable!ParseMode parse_mode; 654 655 mixin InlineQueryFields; 656 } 657 658 struct InlineQueryResultVideo 659 { 660 string type ="video"; 661 string id; 662 string video_url; 663 string mime_type; 664 string thumb_url; 665 string title; 666 Nullable!string caption; 667 Nullable!ParseMode parse_mode; 668 Nullable!uint video_width; 669 Nullable!uint video_height; 670 Nullable!uint video_duration; 671 Nullable!string description; 672 673 mixin InlineQueryFields; 674 } 675 676 struct InlineQueryResultAudio 677 { 678 string type = "audio"; 679 string id; 680 string audio_url; 681 string title; 682 Nullable!string caption; 683 Nullable!ParseMode parse_mode; 684 Nullable!string performer; 685 Nullable!uint audio_duration; 686 687 mixin InlineQueryFields; 688 } 689 690 struct InlineQueryResultVoice 691 { 692 string type = "voice"; 693 string id; 694 string voice_url; 695 string title; 696 Nullable!string caption; 697 Nullable!ParseMode parse_mode; 698 Nullable!uint voice_duration; 699 700 mixin InlineQueryFields; 701 } 702 703 struct InlineQueryResultDocument 704 { 705 string type = "document"; 706 string id; 707 string title; 708 Nullable!string caption; 709 Nullable!ParseMode parse_mode; 710 Nullable!string document_url; 711 Nullable!string mime_type; 712 Nullable!string description; 713 Nullable!string thumb_url; 714 Nullable!uint thumb_width; 715 Nullable!uint thumb_height; 716 717 mixin InlineQueryFields; 718 } 719 720 struct InlineQueryResultLocation 721 { 722 string type = "location"; 723 string id; 724 float latitude; 725 float longitude; 726 string title; 727 Nullable!uint live_period; 728 Nullable!string thumb_url; 729 Nullable!uint thumb_width; 730 Nullable!uint thumb_height; 731 732 mixin InlineQueryFields; 733 } 734 735 struct InlineQueryResultVenue 736 { 737 string type = "venue"; 738 string id; 739 float latitude; 740 float longitude; 741 string title; 742 string address; 743 Nullable!string foursquare_id; 744 Nullable!string thumb_url; 745 Nullable!uint thumb_width; 746 Nullable!uint thumb_height; 747 748 mixin InlineQueryFields; 749 } 750 751 struct InlineQueryResultContact 752 { 753 string type = "contact"; 754 string id; 755 string phone_number; 756 string first_name; 757 Nullable!string last_name; 758 Nullable!string thumb_url; 759 Nullable!uint thumb_width; 760 Nullable!uint thumb_height; 761 762 mixin InlineQueryFields; 763 } 764 765 struct InlineQueryResultGame 766 { 767 string type = "game"; 768 string id; 769 string game_short_name; 770 Nullable!InlineKeyboardMarkup reply_markup; 771 } 772 773 774 struct InlineQueryResultCachedPhoto 775 { 776 string type = "photo"; 777 string id; 778 string photo_file_id; 779 Nullable!string title; 780 Nullable!string description; 781 Nullable!string caption; 782 Nullable!ParseMode parse_mode; 783 784 mixin InlineQueryFields; 785 } 786 787 struct InlineQueryResultCachedGif 788 { 789 string type = "gif"; 790 string id; 791 string gif_file_id; 792 Nullable!string title; 793 Nullable!string caption; 794 Nullable!ParseMode parse_mode; 795 796 mixin InlineQueryFields; 797 } 798 799 struct InlineQueryResultCachedMpeg4Gif 800 { 801 string type = "mpeg4_gif"; 802 string id; 803 string mpeg4_file_id; 804 Nullable!string title; 805 Nullable!string caption; 806 Nullable!ParseMode parse_mode; 807 808 mixin InlineQueryFields; 809 } 810 811 struct InlineQueryResultCachedSticker 812 { 813 string type = "sticker"; 814 string id; 815 string sticker_file_id; 816 817 mixin InlineQueryFields; 818 } 819 820 struct InlineQueryResultCachedDocument 821 { 822 string type = "document"; 823 string id; 824 string title; 825 string document_file_id; 826 Nullable!string description; 827 Nullable!string caption; 828 Nullable!ParseMode parse_mode; 829 830 mixin InlineQueryFields; 831 } 832 833 struct InlineQueryResultCachedVideo 834 { 835 string type = "video"; 836 string id; 837 string video_file_id; 838 string title; 839 Nullable!string description; 840 Nullable!string caption; 841 Nullable!ParseMode parse_mode; 842 843 mixin InlineQueryFields; 844 } 845 846 struct InlineQueryResultCachedVoice 847 { 848 string type = "voice"; 849 string id; 850 string voice_file_id; 851 string title; 852 Nullable!string caption; 853 Nullable!ParseMode parse_mode; 854 855 mixin InlineQueryFields; 856 } 857 858 859 struct InlineQueryResultCachedAudio 860 { 861 string type = "audio"; 862 string id; 863 string audio_file_id; 864 Nullable!string caption; 865 Nullable!ParseMode parse_mode; 866 867 mixin InlineQueryFields; 868 } 869 870 alias InputMessageContentStructs = AliasSeq!( 871 InputTextMessageContent, InputLocationMessageContent, InputVenueMessageContent, InputContactMessageContent 872 ); 873 874 alias InputMessageContent = JsonableAlgebraicProxy!InputMessageContentStructs; 875 876 struct InputTextMessageContent 877 { 878 string message_text; 879 Nullable!ParseMode parse_mode; 880 Nullable!bool disable_web_page_preview; 881 } 882 883 struct InputLocationMessageContent 884 { 885 float latitude; 886 float longitude; 887 Nullable!uint live_period; 888 } 889 890 struct InputVenueMessageContent 891 { 892 float latitude; 893 float longitude; 894 string title; 895 string address; 896 Nullable!string foursquare_id; 897 // TODO new field Nullable!string foursquare_type; 898 } 899 900 struct InputContactMessageContent 901 { 902 string phone_number; 903 string first_name; 904 Nullable!string last_name; 905 // TODO new field Nullable!string vcard; 906 } 907 908 struct ChosenInlineResult 909 { 910 string result_id; 911 User from; 912 Nullable!Location location; 913 Nullable!string inline_message_id; 914 string query; 915 } 916 917 /*** Payments types ***/ 918 struct LabeledPrice 919 { 920 string label; 921 uint amount; 922 } 923 924 struct Invoice 925 { 926 string title; 927 string description; 928 string start_parameter; 929 string currency; 930 uint total_amount; 931 } 932 933 struct ShippingAddress 934 { 935 string country_code; 936 string state; 937 string city; 938 string street_line1; 939 string street_line2; 940 string post_code; 941 } 942 943 // TODO add nullable fields 944 struct OrderInfo 945 { 946 string name; 947 string phone_number; 948 string email; 949 Nullable!ShippingAddress shipping_address; 950 } 951 952 struct ShippingOption 953 { 954 string id; 955 string title; 956 LabeledPrice[] prices; 957 } 958 959 // TODO add nullable fields 960 struct SuccessfulPayment 961 { 962 string currency; 963 uint total_amount; 964 string invoice_payload; 965 string shipping_option_id; 966 Nullable!OrderInfo order_info; 967 string telegram_payment_charge_id; 968 string provider_payment_charge_id; 969 } 970 971 struct ShippingQuery 972 { 973 string id; 974 User from; 975 string invoice_payload; 976 ShippingAddress shipping_address; 977 } 978 979 // TODO add nullable fields 980 struct PreCheckoutQuery 981 { 982 string id; 983 User from; 984 string currency; 985 uint total_amount; 986 string invoice_payload; 987 string shipping_option_id; 988 Nullable!OrderInfo order_info; 989 } 990 991 /*** Telegram Passport ***/ 992 // TODO 993 994 /*** Games types ***/ 995 996 // TODO add nullable fields 997 struct Game 998 { 999 string title; 1000 string description; 1001 PhotoSize[] photo; 1002 string text; 1003 MessageEntity text_entities; 1004 Animation animation; 1005 } 1006 1007 // TODO add nullable fields and a new fields 1008 struct Animation 1009 { 1010 string file_id; 1011 PhotoSize thumb; 1012 string file_name; 1013 string mime_type; 1014 uint file_size; 1015 } 1016 1017 struct CallbackGame 1018 { 1019 // no fields 1020 } 1021 1022 struct GameHighScore 1023 { 1024 uint position; 1025 User user; 1026 uint score; 1027 } 1028 1029 /******************************************************************/ 1030 /* Telegram methods */ 1031 /******************************************************************/ 1032 1033 mixin template TelegramMethod(string path, HTTPMethod method = HTTPMethod.POST) 1034 { 1035 package: 1036 immutable string _path = path; 1037 HTTPMethod _httpMethod = method; 1038 } 1039 1040 /// UDA for telegram methods 1041 struct Method 1042 { 1043 string path; 1044 } 1045 1046 struct GetUpdatesMethod 1047 { 1048 mixin TelegramMethod!"/getUpdates"; 1049 1050 int offset; 1051 ubyte limit; 1052 uint timeout; 1053 } 1054 1055 struct SetWebhookMethod 1056 { 1057 mixin TelegramMethod!"/setWebhook"; 1058 1059 string url; 1060 Nullable!InputFile certificate; 1061 uint max_connections; 1062 string[] allowed_updates; 1063 } 1064 1065 struct DeleteWebhookMethod 1066 { 1067 mixin TelegramMethod!"/deleteWebhook"; 1068 } 1069 1070 struct GetWebhookInfoMethod 1071 { 1072 mixin TelegramMethod!("/getWebhookInfo", HTTPMethod.GET); 1073 } 1074 1075 struct GetMeMethod 1076 { 1077 mixin TelegramMethod!("/getMe", HTTPMethod.GET); 1078 } 1079 1080 struct SendMessageMethod 1081 { 1082 mixin TelegramMethod!"/sendMessage"; 1083 1084 string chat_id; 1085 string text; 1086 ParseMode parse_mode; 1087 bool disable_web_page_preview; 1088 bool disable_notification; 1089 uint reply_to_message_id; 1090 1091 ReplyMarkup reply_markup; 1092 } 1093 1094 struct ForwardMessageMethod 1095 { 1096 mixin TelegramMethod!"/forwardMessage"; 1097 1098 string chat_id; 1099 string from_chat_id; 1100 bool disable_notification; 1101 uint message_id; 1102 } 1103 1104 struct SendPhotoMethod 1105 { 1106 mixin TelegramMethod!"/sendPhoto"; 1107 1108 string chat_id; 1109 string photo; 1110 string caption; 1111 ParseMode parse_mode; 1112 bool disable_notification; 1113 uint reply_to_message_id; 1114 ReplyMarkup reply_markup; 1115 } 1116 1117 struct SendAudioMethod 1118 { 1119 mixin TelegramMethod!"/sendAudio"; 1120 1121 string chat_id; 1122 string audio; 1123 string caption; 1124 ParseMode parse_mode; 1125 uint duration; 1126 string performer; 1127 string title; 1128 bool disable_notification; 1129 uint reply_to_message_id; 1130 ReplyMarkup reply_markup; 1131 1132 } 1133 1134 struct SendDocumentMethod 1135 { 1136 mixin TelegramMethod!"/sendDocument"; 1137 1138 string chat_id; 1139 string document; 1140 string caption; 1141 ParseMode parse_mode; 1142 bool disable_notification; 1143 uint reply_to_message_id; 1144 ReplyMarkup reply_markup; 1145 } 1146 1147 struct SendVideoMethod 1148 { 1149 mixin TelegramMethod!"/sendVideo"; 1150 1151 string chat_id; 1152 string video; 1153 uint duration; 1154 uint width; 1155 uint height; 1156 string caption; 1157 ParseMode parse_mode; 1158 bool supports_streaming; 1159 bool disable_notification; 1160 uint reply_to_message_id; 1161 ReplyMarkup reply_markup; 1162 } 1163 1164 struct SendVoiceMethod 1165 { 1166 mixin TelegramMethod!"/sendVoice"; 1167 1168 string chat_id; 1169 string voice; 1170 string caption; 1171 ParseMode parse_mode; 1172 uint duration; 1173 bool disable_notification; 1174 uint reply_to_message_id; 1175 ReplyMarkup reply_markup; 1176 } 1177 1178 struct SendVideoNoteMethod 1179 { 1180 mixin TelegramMethod!"/sendVideoNote"; 1181 1182 string chat_id; 1183 string video_note; 1184 uint duration; 1185 uint length; 1186 bool disable_notification; 1187 uint reply_to_message_id; 1188 ReplyMarkup reply_markup; 1189 1190 } 1191 1192 struct SendMediaGroupMethod 1193 { 1194 mixin TelegramMethod!"/sendMediaGroup"; 1195 1196 string chat_id; 1197 InputMedia[] media; 1198 bool disable_notification; 1199 uint reply_to_message_id; 1200 } 1201 1202 struct SendLocationMethod 1203 { 1204 mixin TelegramMethod!"/sendLocation"; 1205 1206 string chat_id; 1207 float latitude; 1208 float longitude; 1209 uint live_period; 1210 bool disable_notification; 1211 uint reply_to_message_id; 1212 ReplyMarkup reply_markup; 1213 } 1214 1215 struct EditMessageLiveLocationMethod 1216 { 1217 mixin TelegramMethod!"/editMessageLiveLocation"; 1218 1219 string chat_id; 1220 uint message_id; 1221 string inline_message_id; 1222 float latitude; 1223 float longitude; 1224 ReplyMarkup reply_markup; 1225 } 1226 1227 struct StopMessageLiveLocationMethod 1228 { 1229 mixin TelegramMethod!"/stopMessageLiveLocation"; 1230 1231 string chat_id; 1232 uint message_id; 1233 string inline_message_id; 1234 ReplyMarkup reply_markup; 1235 } 1236 1237 struct SendVenueMethod 1238 { 1239 mixin TelegramMethod!"/sendVenue"; 1240 1241 string chat_id; 1242 float latitude; 1243 float longitude; 1244 string title; 1245 string address; 1246 string foursquare_id; 1247 bool disable_notification; 1248 uint reply_to_message_id; 1249 ReplyMarkup reply_markup; 1250 } 1251 1252 struct SendContactMethod 1253 { 1254 mixin TelegramMethod!"/sendContact"; 1255 1256 string chat_id; 1257 string phone_number; 1258 string first_name; 1259 string last_name; 1260 bool disable_notification; 1261 uint reply_to_message_id; 1262 ReplyMarkup reply_markup; 1263 } 1264 1265 struct SendChatActionMethod 1266 { 1267 mixin TelegramMethod!"/sendChatAction"; 1268 1269 string chat_id; 1270 string action; // TODO enum 1271 } 1272 1273 struct GetUserProfilePhotosMethod 1274 { 1275 mixin TelegramMethod!("/getUserProfilePhotos", HTTPMethod.GET); 1276 1277 int user_id; 1278 uint offset; 1279 uint limit; 1280 } 1281 1282 struct GetFileMethod 1283 { 1284 mixin TelegramMethod!("/getFile", HTTPMethod.GET); 1285 1286 string file_id; 1287 } 1288 1289 struct KickChatMemberMethod 1290 { 1291 mixin TelegramMethod!"/kickChatMember"; 1292 1293 string chat_id; 1294 uint user_id; 1295 uint until_date; 1296 } 1297 1298 struct UnbanChatMemberMethod 1299 { 1300 mixin TelegramMethod!"/unbanChatMember"; 1301 1302 string chat_id; 1303 uint user_id; 1304 } 1305 1306 struct RestrictChatMemberMethod 1307 { 1308 mixin TelegramMethod!"/restrictChatMember"; 1309 1310 string chat_id; 1311 uint user_id; 1312 uint until_date; 1313 bool can_send_messages; 1314 bool can_send_media_messages; 1315 bool can_send_other_messages; 1316 bool can_add_web_page_previews; 1317 } 1318 1319 struct PromoteChatMemberMethod 1320 { 1321 mixin TelegramMethod!"/promoteChatMember"; 1322 1323 string chat_id; 1324 uint user_id; 1325 bool can_change_info; 1326 bool can_post_messages; 1327 bool can_edit_messages; 1328 bool can_delete_messages; 1329 bool can_invite_users; 1330 bool can_restrict_members; 1331 bool can_pin_messages; 1332 bool can_promote_members; 1333 } 1334 1335 struct ExportChatInviteLinkMethod 1336 { 1337 mixin TelegramMethod!"/exportChatInviteLink"; 1338 1339 string chat_id; 1340 } 1341 1342 struct SetChatPhotoMethod 1343 { 1344 mixin TelegramMethod!"/setChatPhoto"; 1345 1346 string chat_id; 1347 InputFile photo; 1348 1349 } 1350 1351 struct DeleteChatPhotoMethod 1352 { 1353 mixin TelegramMethod!"/deleteChatPhoto"; 1354 1355 string chat_id; 1356 } 1357 1358 struct SetChatTitleMethod 1359 { 1360 mixin TelegramMethod!"/setChatTitle"; 1361 1362 string chat_id; 1363 string title; 1364 } 1365 1366 struct SetChatDescriptionMethod 1367 { 1368 mixin TelegramMethod!"/setChatDescription"; 1369 1370 string chat_id; 1371 string description; 1372 } 1373 1374 struct PinChatMessageMethod 1375 { 1376 mixin TelegramMethod!"/pinChatMessage"; 1377 1378 string chat_id; 1379 uint message_id; 1380 bool disable_notification; 1381 } 1382 1383 struct UnpinChatMessageMethod 1384 { 1385 mixin TelegramMethod!"/unpinChatMessage"; 1386 1387 string chat_id; 1388 } 1389 1390 struct LeaveChatMethod 1391 { 1392 mixin TelegramMethod!"/leaveChat"; 1393 1394 string chat_id; 1395 } 1396 1397 struct GetChatMethod 1398 { 1399 mixin TelegramMethod!("/getChat", HTTPMethod.GET); 1400 1401 string chat_id; 1402 } 1403 1404 struct GetChatAdministratorsMethod 1405 { 1406 mixin TelegramMethod!("/getChatAdministrators", HTTPMethod.GET); 1407 1408 string chat_id; 1409 } 1410 1411 struct GetChatMembersCountMethod 1412 { 1413 mixin TelegramMethod!("/getChatMembersCount", HTTPMethod.GET); 1414 1415 string chat_id; 1416 } 1417 1418 struct GetChatMemberMethod 1419 { 1420 mixin TelegramMethod!("/getChatMember", HTTPMethod.GET); 1421 1422 string chat_id; 1423 uint user_id; 1424 } 1425 1426 struct SetChatStickerSetMethod 1427 { 1428 mixin TelegramMethod!"/setChatStickerSet"; 1429 1430 string chat_id; 1431 string sticker_set_name; 1432 } 1433 1434 struct DeleteChatStickerSetMethod 1435 { 1436 mixin TelegramMethod!"/deleteChatStickerSet"; 1437 1438 string chat_id; 1439 } 1440 1441 struct AnswerCallbackQueryMethod 1442 { 1443 mixin TelegramMethod!"/answerCallbackQuery"; 1444 1445 string callback_query_id; 1446 string text; 1447 bool show_alert; 1448 string url; 1449 uint cache_time; 1450 } 1451 1452 struct EditMessageTextMethod 1453 { 1454 mixin TelegramMethod!"/editMessageTextMethod"; 1455 1456 string chat_id; 1457 uint message_id; 1458 string inline_message_id; 1459 string text; 1460 ParseMode parse_mode; 1461 bool disable_web_page_preview; 1462 ReplyMarkup reply_markup; 1463 } 1464 1465 struct EditMessageCaptionMethod 1466 { 1467 mixin TelegramMethod!"/editMessageCaptionMethod"; 1468 1469 string chat_id; 1470 uint message_id; 1471 string inline_message_id; 1472 string caption; 1473 ParseMode parse_mode; 1474 ReplyMarkup reply_markup; 1475 } 1476 1477 struct EditMessageReplyMarkupMethod 1478 { 1479 mixin TelegramMethod!"/editMessageReplyMarkupMethod"; 1480 1481 string chat_id; 1482 uint message_id; 1483 string inline_message_id; 1484 ReplyMarkup reply_markup; 1485 } 1486 1487 struct DeleteMessageMethod 1488 { 1489 mixin TelegramMethod!"/deleteMessageMethod"; 1490 1491 string chat_id; 1492 uint message_id; 1493 } 1494 1495 struct SendStickerMethod 1496 { 1497 mixin TelegramMethod!"/sendStickerMethod"; 1498 1499 string chat_id; 1500 string sticker; // TODO InputFile|string 1501 bool disable_notification; 1502 uint reply_to_message_id; 1503 ReplyMarkup reply_markup; 1504 } 1505 1506 struct GetStickerSetMethod 1507 { 1508 mixin TelegramMethod!("/getStickerSetMethod", HTTPMethod.GET); 1509 1510 string name; 1511 } 1512 1513 struct UploadStickerFileMethod 1514 { 1515 mixin TelegramMethod!"/uploadStickerFileMethod"; 1516 1517 int user_id; 1518 InputFile png_sticker; 1519 } 1520 1521 struct CreateNewStickerSetMethod 1522 { 1523 mixin TelegramMethod!"/createNewStickerSetMethod"; 1524 1525 int user_id; 1526 string name; 1527 string title; 1528 string png_sticker; // TODO InputFile|string 1529 string emojis; 1530 bool contains_masks; 1531 MaskPosition mask_position; 1532 } 1533 1534 struct AddStickerToSetMethod 1535 { 1536 mixin TelegramMethod!"/addStickerToSetMethod"; 1537 1538 int user_id; 1539 string name; 1540 string png_sticker; // TODO InputFile|string 1541 string emojis; 1542 MaskPosition mask_position; 1543 } 1544 1545 struct SetStickerPositionInSetMethod 1546 { 1547 mixin TelegramMethod!"/setStickerPositionInSetMethod"; 1548 1549 string sticker; 1550 int position; 1551 } 1552 1553 struct DeleteStickerFromSetMethod 1554 { 1555 mixin TelegramMethod!"/deleteStickerFromSetMethod"; 1556 1557 string sticker; 1558 } 1559 1560 struct AnswerInlineQueryMethod 1561 { 1562 mixin TelegramMethod!"/answerInlineQuery"; 1563 1564 string inline_query_id; 1565 InlineQueryResult[] results; 1566 uint cache_time; 1567 bool is_personal; 1568 string next_offset; 1569 string switch_pm_text; 1570 string switch_pm_parameter; 1571 } 1572 1573 /******************************************************************/ 1574 /* Telegram API */ 1575 /******************************************************************/ 1576 1577 enum BaseApiUrl = "https://api.telegram.org/bot"; 1578 1579 class BotApi 1580 { 1581 private: 1582 string baseUrl; 1583 string apiUrl; 1584 1585 ulong requestCounter = 1; 1586 uint maxUpdateId = 1; 1587 1588 struct MethodResult(T) 1589 { 1590 bool ok; 1591 T result; 1592 ushort error_code; 1593 string description; 1594 } 1595 1596 protected: 1597 HttpClient httpClient; 1598 1599 public: 1600 this(string token, string baseUrl = BaseApiUrl, HttpClient httpClient = null) 1601 { 1602 this.baseUrl = baseUrl; 1603 this.apiUrl = baseUrl ~ token; 1604 1605 if (httpClient is null) { 1606 version(TelegaVibedDriver) { 1607 import telega.drivers.vibe; 1608 1609 httpClient = new VibedHttpClient(); 1610 } else version(TelegaRequestsDriver) { 1611 import telega.drivers.requests; 1612 1613 httpClient = new RequestsHttpClient(); 1614 } else { 1615 assert(false, `No HTTP client is set, maybe you should enable "default" configuration?`); 1616 } 1617 } 1618 this.httpClient = httpClient; 1619 } 1620 1621 void updateProcessed(int updateId) 1622 { 1623 if (updateId >= maxUpdateId) { 1624 maxUpdateId = updateId + 1; 1625 } 1626 } 1627 1628 void updateProcessed(ref Update update) 1629 { 1630 updateProcessed(update.id); 1631 } 1632 1633 T callMethod(T, M)(M method) 1634 { 1635 T result; 1636 1637 logDiagnostic("[%d] Requesting %s", requestCounter, method._path); 1638 1639 version(unittest) 1640 { 1641 import std.stdio; 1642 serializeToJsonString(method).writeln(); 1643 } else { 1644 string answer; 1645 1646 if (method._httpMethod == HTTPMethod.POST) { 1647 string bodyJson = serializeToJsonString(method); 1648 logDebugV("[%d] Sending body:\n %s", requestCounter, bodyJson); 1649 1650 answer = httpClient.sendPostRequestJson(apiUrl ~ method._path, bodyJson); 1651 } else { 1652 answer = httpClient.sendGetRequest(apiUrl ~ method._path); 1653 } 1654 1655 logDebugV("[%d] Data received:\n %s", requestCounter, answer); 1656 1657 auto json = answer.deserialize!(MethodResult!T); 1658 1659 enforce(json.ok == true, new TelegramBotApiException(json.error_code, json.description)); 1660 1661 result = json.result; 1662 requestCounter++; 1663 } 1664 1665 return result; 1666 } 1667 1668 Update[] getUpdates(ubyte limit = 5, uint timeout = 30) 1669 { 1670 GetUpdatesMethod m = { 1671 offset: maxUpdateId, 1672 limit: limit, 1673 timeout: timeout, 1674 }; 1675 1676 return callMethod!(Update[], GetUpdatesMethod)(m); 1677 } 1678 1679 bool setWebhook(string url) 1680 { 1681 SetWebhookMethod m = { 1682 url : url 1683 }; 1684 1685 return setWebhook(m); 1686 } 1687 1688 bool setWebhook(ref SetWebhookMethod m) 1689 { 1690 return callMethod!(bool, SetWebhookMethod)(m); 1691 } 1692 1693 bool deleteWebhook() 1694 { 1695 DeleteWebhookMethod m = DeleteWebhookMethod(); 1696 1697 return callMethod!(bool, DeleteWebhookMethod)(m); 1698 } 1699 1700 WebhookInfo getWebhookInfo() 1701 { 1702 GetWebhookInfoMethod m = GetWebhookInfoMethod(); 1703 1704 return callMethod!(WebhookInfo, GetWebhookInfoMethod)(m); 1705 } 1706 1707 User getMe() 1708 { 1709 GetMeMethod m; 1710 1711 return callMethod!(User, GetMeMethod)(m); 1712 } 1713 1714 Message sendMessage(T)(T chatId, string text) 1715 if (isTelegramId!T) 1716 { 1717 SendMessageMethod m = { 1718 text : text, 1719 }; 1720 1721 static if (isIntegral!T) { 1722 m.chat_id = chatId.to!string; 1723 } else { 1724 m.chat_id = chatId; 1725 } 1726 1727 return sendMessage(m); 1728 } 1729 1730 Message sendMessage(ref SendMessageMethod m) 1731 { 1732 return callMethod!(Message, SendMessageMethod)(m); 1733 } 1734 1735 Message forwardMessage(T1, T2)(T1 chatId, T2 fromChatId, uint messageId) 1736 if (isTelegramId!T1 && isTelegramId!T2) 1737 { 1738 ForwardMessageMethod m = { 1739 message_id : messageId 1740 }; 1741 1742 static if (isIntegral!T1) { 1743 m.chat_id = chatId.to!string; 1744 } else { 1745 m.chat_id = chatId; 1746 } 1747 1748 static if (isIntegral!T2) { 1749 m.from_chat_id = fromChatId.to!string; 1750 } else { 1751 m.from_chat_id = fromChatId; 1752 } 1753 1754 return callMethod!(Message, ForwardMessageMethod)(m); 1755 } 1756 1757 Message forwardMessage(ref ForwardMessageMethod m) 1758 { 1759 return callMethod!(Message, ForwardMessageMethod)(m); 1760 } 1761 1762 Message sendPhoto(ref SendPhotoMethod m) 1763 { 1764 return callMethod!(Message, SendPhotoMethod)(m); 1765 } 1766 1767 Message sendPhoto(T1)(T1 chatId, string photo) 1768 if (isTelegramId!T1) 1769 { 1770 SendPhotoMethod m = { 1771 photo : photo 1772 }; 1773 1774 static if (isIntegral!T1) { 1775 m.chat_id = chatId.to!string; 1776 } else { 1777 m.chat_id = chatId; 1778 } 1779 1780 return sendPhoto(m); 1781 } 1782 1783 Message sendAudio(ref SendAudioMethod m) 1784 { 1785 return callMethod!(Message, SendAudioMethod)(m); 1786 } 1787 1788 Message sendAudio(T1)(T1 chatId, string audio) 1789 if (isTelegramId!T1) 1790 { 1791 SendAudioMethod m = { 1792 audio : audio 1793 }; 1794 1795 static if (isIntegral!T1) { 1796 m.chat_id = chatId.to!string; 1797 } else { 1798 m.chat_id = chatId; 1799 } 1800 1801 return sendAudio(m); 1802 } 1803 1804 Message sendDocument(ref SendDocumentMethod m) 1805 { 1806 return callMethod!(Message, SendDocumentMethod)(m); 1807 } 1808 1809 Message sendDocument(T1)(T1 chatId, string document) 1810 if (isTelegramId!T1) 1811 { 1812 SendDocumentMethod m = { 1813 document : document 1814 }; 1815 1816 static if (isIntegral!T1) { 1817 m.chat_id = chatId.to!string; 1818 } else { 1819 m.chat_id = chatId; 1820 } 1821 1822 return sendDocument(m); 1823 } 1824 1825 Message sendVideo(ref SendVideoMethod m) 1826 { 1827 return callMethod!(Message, SendVideoMethod)(m); 1828 } 1829 1830 Message sendVideo(T1)(T1 chatId, string video) 1831 if (isTelegramId!T1) 1832 { 1833 SendVideoMethod m = { 1834 video : video 1835 }; 1836 1837 static if (isIntegral!T1) { 1838 m.chat_id = chatId.to!string; 1839 } else { 1840 m.chat_id = chatId; 1841 } 1842 1843 return sendVideo(m); 1844 } 1845 1846 Message sendVoice(ref SendVoiceMethod m) 1847 { 1848 return callMethod!(Message, SendVoiceMethod)(m); 1849 } 1850 1851 Message sendVoice(T1)(T1 chatId, string voice) 1852 if (isTelegramId!T1) 1853 { 1854 SendVoiceMethod m = { 1855 voice : voice 1856 }; 1857 1858 static if (isIntegral!T1) { 1859 m.chat_id = chatId.to!string; 1860 } else { 1861 m.chat_id = chatId; 1862 } 1863 1864 return sendVoice(m); 1865 } 1866 1867 Message sendVideoNote(ref SendVideoNoteMethod m) 1868 { 1869 return callMethod!(Message, SendVideoNoteMethod)(m); 1870 } 1871 1872 Message sendVideoNote(T1)(T1 chatId, string videoNote) 1873 if (isTelegramId!T1) 1874 { 1875 SendVideoNoteMethod m = { 1876 video_note : videoNote 1877 }; 1878 1879 static if (isIntegral!T1) { 1880 m.chat_id = chatId.to!string; 1881 } else { 1882 m.chat_id = chatId; 1883 } 1884 1885 return sendVideoNote(m); 1886 } 1887 1888 Message sendMediaGroup(ref SendMediaGroupMethod m) 1889 { 1890 return callMethod!(Message, SendMediaGroupMethod)(m); 1891 } 1892 1893 Message sendMediaGroup(T1)(T1 chatId, InputMedia[] media) 1894 if (isTelegramId!T1) 1895 { 1896 SendMediaGroupMethod m = { 1897 media : media 1898 }; 1899 1900 static if (isIntegral!T1) { 1901 m.chat_id = chatId.to!string; 1902 } else { 1903 m.chat_id = chatId; 1904 } 1905 1906 return sendMediaGroup(m); 1907 } 1908 1909 Message sendLocation(ref SendLocationMethod m) 1910 { 1911 return callMethod!(Message, SendLocationMethod)(m); 1912 } 1913 1914 Message sendLocation(T1)(T1 chatId, float latitude, float longitude) 1915 if (isTelegramId!T1) 1916 { 1917 SendLocationMethod m = { 1918 latitude : latitude, 1919 longitude : longitude, 1920 }; 1921 1922 static if (isIntegral!T1) { 1923 m.chat_id = chatId.to!string; 1924 } else { 1925 m.chat_id = chatId; 1926 } 1927 1928 return sendLocation(m); 1929 } 1930 1931 Nullable!Message editMessageLiveLocation(ref EditMessageLiveLocationMethod m) 1932 { 1933 return callMethod!(Nullable!Message, EditMessageLiveLocationMethod)(m); 1934 } 1935 1936 Nullable!Message editMessageLiveLocation(string inlineMessageId, float latitude, float longitude) 1937 { 1938 EditMessageLiveLocationMethod m = { 1939 inline_message_id : inlineMessageId, 1940 latitude : latitude, 1941 longitude : longitude 1942 }; 1943 1944 return editMessageLiveLocation(m); 1945 } 1946 1947 Nullable!Message editMessageLiveLocation(T1)(T1 chatId, uint messageId, float latitude, float longitude) 1948 if (isTelegramId!T1) 1949 { 1950 EditMessageLiveLocationMethod m = { 1951 message_id : messageId, 1952 latitude : latitude, 1953 longitude : longitude 1954 }; 1955 1956 static if (isIntegral!T1) { 1957 m.chat_id = chatId.to!string; 1958 } else { 1959 m.chat_id = chatId; 1960 } 1961 1962 return editMessageLiveLocation(m); 1963 } 1964 1965 Nullable!Message stopMessageLiveLocation(ref StopMessageLiveLocationMethod m) 1966 { 1967 return callMethod!(Nullable!Message, StopMessageLiveLocationMethod)(m); 1968 } 1969 1970 Nullable!Message stopMessageLiveLocation(string inlineMessageId) 1971 { 1972 StopMessageLiveLocationMethod m = { 1973 inline_message_id : inlineMessageId 1974 }; 1975 1976 return stopMessageLiveLocation(m); 1977 } 1978 1979 Nullable!Message stopMessageLiveLocation(T1)(T1 chatId, uint messageId) 1980 if (isTelegramId!T1) 1981 { 1982 StopMessageLiveLocationMethod m = { 1983 message_id : messageId 1984 }; 1985 1986 static if (isIntegral!T1) { 1987 m.chat_id = chatId.to!string; 1988 } else { 1989 m.chat_id = chatId; 1990 } 1991 1992 return stopMessageLiveLocation(m); 1993 } 1994 1995 Message sendVenue(ref SendVenueMethod m) 1996 { 1997 return callMethod!(Message, SendVenueMethod)(m); 1998 } 1999 2000 Message sendVenue(T1)(T1 chatId, float latitude, float longitude, 2001 string title, string address) 2002 if (isTelegramId!T1) 2003 { 2004 SendVenueMethod m = { 2005 latitude : latitude, 2006 longitude : longitude, 2007 title : title, 2008 address : address 2009 }; 2010 2011 static if (isIntegral!T1) { 2012 m.chat_id = chatId.to!string; 2013 } else { 2014 m.chat_id = chatId; 2015 } 2016 2017 return sendVenue(m); 2018 } 2019 2020 Message sendContact(ref SendContactMethod m) 2021 { 2022 return callMethod!(Message, SendContactMethod)(m); 2023 } 2024 2025 Message sendContact(T1)(T1 chatId, string phone_number, string first_name) 2026 if (isTelegramId!T1) 2027 { 2028 SendContactMethod m = { 2029 phone_number : phone_number, 2030 first_name : first_name 2031 }; 2032 2033 static if (isIntegral!T1) { 2034 m.chat_id = chatId.to!string; 2035 } else { 2036 m.chat_id = chatId; 2037 } 2038 2039 return sendContact(m); 2040 } 2041 2042 bool sendChatAction(ref SendChatActionMethod m) 2043 { 2044 return callMethod!(bool, SendChatActionMethod)(m); 2045 } 2046 2047 bool sendChatAction(T1)(T1 chatId, string action) 2048 if (isTelegramId!T1) 2049 { 2050 SendChatActionMethod m = { 2051 action : action 2052 }; 2053 2054 static if (isIntegral!T1) { 2055 m.chat_id = chatId.to!string; 2056 } else { 2057 m.chat_id = chatId; 2058 } 2059 2060 return sendChatAction(m); 2061 } 2062 2063 UserProfilePhotos getUserProfilePhotos(ref GetUserProfilePhotosMethod m) 2064 { 2065 return callMethod!(UserProfilePhotos, GetUserProfilePhotosMethod)(m); 2066 } 2067 2068 UserProfilePhotos getUserProfilePhotos(int userId) 2069 { 2070 GetUserProfilePhotosMethod m = { 2071 user_id : userId 2072 }; 2073 2074 return getUserProfilePhotos(m); 2075 } 2076 2077 File getFile(ref GetFileMethod m) 2078 { 2079 return callMethod!(File, GetFileMethod)(m); 2080 } 2081 2082 File getFile(string fileId) 2083 { 2084 GetFileMethod m = { 2085 file_id : fileId 2086 }; 2087 2088 return getFile(m); 2089 } 2090 2091 bool kickChatMember(ref KickChatMemberMethod m) 2092 { 2093 return callMethod!(bool, KickChatMemberMethod)(m); 2094 } 2095 2096 bool kickChatMember(T1)(T1 chatId, int userId) 2097 if(isTelegramId!T1) 2098 { 2099 KickChatMemberMethod m = { 2100 user_id : userId 2101 }; 2102 2103 static if (isIntegral!T1) { 2104 m.chat_id = chatId.to!string; 2105 } else { 2106 m.chat_id = chatId; 2107 } 2108 2109 return kickChatMember(m); 2110 } 2111 2112 bool unbanChatMember(ref UnbanChatMemberMethod m) 2113 { 2114 return callMethod!(bool, UnbanChatMemberMethod)(m); 2115 } 2116 2117 bool unbanChatMember(T1)(T1 chatId, int userId) 2118 if(isTelegramId!T1) 2119 { 2120 UnbanChatMemberMethod m = { 2121 user_id : userId 2122 }; 2123 2124 static if (isIntegral!T1) { 2125 m.chat_id = chatId.to!string; 2126 } else { 2127 m.chat_id = chatId; 2128 } 2129 2130 return unbanChatMember(m); 2131 } 2132 2133 bool restrictChatMember(ref RestrictChatMemberMethod m) 2134 { 2135 return callMethod!bool(m); 2136 } 2137 2138 bool restrictChatMember(T1)(T1 chatId, int userId) 2139 if(isTelegramId!T1) 2140 { 2141 RestrictChatMemberMethod m = { 2142 user_id : userId 2143 }; 2144 2145 static if (isIntegral!T1) { 2146 m.chat_id = chatId.to!string; 2147 } else { 2148 m.chat_id = chatId; 2149 } 2150 2151 return restrictChatMember(m); 2152 } 2153 2154 bool promoteChatMember(ref PromoteChatMemberMethod m) 2155 { 2156 return callMethod!bool(m); 2157 } 2158 2159 bool promoteChatMember(T1)(T1 chatId, int userId) 2160 if(isTelegramId!T1) 2161 { 2162 PromoteChatMemberMethod m = { 2163 user_id : userId 2164 }; 2165 2166 static if (isIntegral!T1) { 2167 m.chat_id = chatId.to!string; 2168 } else { 2169 m.chat_id = chatId; 2170 } 2171 2172 return promoteChatMember(m); 2173 } 2174 2175 string exportChatInviteLink(ref ExportChatInviteLinkMethod m) 2176 { 2177 return callMethod!string(m); 2178 } 2179 2180 string exportChatInviteLink(T1)(T1 chatId) 2181 if(isTelegramId!T1) 2182 { 2183 ExportChatInviteLinkMethod m; 2184 2185 static if (isIntegral!T1) { 2186 m.chat_id = chatId.to!string; 2187 } else { 2188 m.chat_id = chatId; 2189 } 2190 2191 return exportChatInviteLink(m); 2192 } 2193 2194 bool setChatPhoto(ref SetChatPhotoMethod m) 2195 { 2196 return callMethod!bool(m); 2197 } 2198 2199 bool setChatPhoto(T1)(T1 chatId, InputFile photo) 2200 if (isTelegramId!T1) 2201 { 2202 SetChatPhotoMethod m = { 2203 photo : photo 2204 }; 2205 2206 static if (isIntegral!T1) { 2207 m.chat_id = chatId.to!string; 2208 } else { 2209 m.chat_id = chatId; 2210 } 2211 2212 return setChatPhoto(m); 2213 } 2214 2215 bool deleteChatPhoto(ref DeleteChatPhotoMethod m) 2216 { 2217 return callMethod!bool(m); 2218 } 2219 2220 bool deleteChatPhoto(T1)(T1 chatId) 2221 if (isTelegramId!T1) 2222 { 2223 DeleteChatPhotoMethod m; 2224 2225 static if (isIntegral!T1) { 2226 m.chat_id = chatId.to!string; 2227 } else { 2228 m.chat_id = chatId; 2229 } 2230 2231 return deleteChatPhoto(m); 2232 } 2233 2234 bool setChatTitle(ref SetChatTitleMethod m) 2235 { 2236 return callMethod!bool(m); 2237 } 2238 2239 bool setChatTitle(T1)(T1 chatId, string title) 2240 if (isTelegramId!T1) 2241 { 2242 SetChatTitleMethod m = { 2243 title : title 2244 }; 2245 2246 static if (isIntegral!T1) { 2247 m.chat_id = chatId.to!string; 2248 } else { 2249 m.chat_id = chatId; 2250 } 2251 2252 return setChatTitle(m); 2253 } 2254 2255 bool setChatDescription(ref SetChatDescriptionMethod m) 2256 { 2257 return callMethod!bool(m); 2258 } 2259 2260 bool setChatDescription(T1)(T1 chatId, string description) 2261 if (isTelegramId!T1) 2262 { 2263 SetChatDescriptionMethod m = { 2264 description : description 2265 }; 2266 2267 static if (isIntegral!T1) { 2268 m.chat_id = chatId.to!string; 2269 } else { 2270 m.chat_id = chatId; 2271 } 2272 2273 return setChatDescription(m); 2274 } 2275 2276 bool pinChatMessage(ref PinChatMessageMethod m) 2277 { 2278 return callMethod!bool(m); 2279 } 2280 2281 bool pinChatMessage(T1)(T1 chatId, uint messageId) 2282 if (isTelegramId!T1) 2283 { 2284 PinChatMessageMethod m = { 2285 message_id : messageId 2286 }; 2287 2288 static if (isIntegral!T1) { 2289 m.chat_id = chatId.to!string; 2290 } else { 2291 m.chat_id = chatId; 2292 } 2293 2294 return pinChatMessage(m); 2295 } 2296 2297 bool unpinChatMessage(ref UnpinChatMessageMethod m) 2298 { 2299 return callMethod!bool(m); 2300 } 2301 2302 bool unpinChatMessage(T1)(T1 chatId) 2303 if (isTelegramId!T1) 2304 { 2305 UnpinChatMessageMethod m; 2306 2307 static if (isIntegral!T1) { 2308 m.chat_id = chatId.to!string; 2309 } else { 2310 m.chat_id = chatId; 2311 } 2312 2313 return unpinChatMessage(m); 2314 } 2315 2316 bool leaveChat(ref LeaveChatMethod m) 2317 { 2318 return callMethod!bool(m); 2319 } 2320 2321 bool leaveChat(T1)(T1 chatId) 2322 if (isTelegramId!T1) 2323 { 2324 LeaveChatMethod m; 2325 2326 static if (isIntegral!T1) { 2327 m.chat_id = chatId.to!string; 2328 } else { 2329 m.chat_id = chatId; 2330 } 2331 2332 return leaveChat(m); 2333 } 2334 2335 Chat getChat(ref GetChatMethod m) 2336 { 2337 return callMethod!Chat(m); 2338 } 2339 2340 Chat getChat(T1)(T1 chatId) 2341 if (isTelegramId!T1) 2342 { 2343 GetChatMethod m; 2344 2345 static if (isIntegral!T1) { 2346 m.chat_id = chatId.to!string; 2347 } else { 2348 m.chat_id = chatId; 2349 } 2350 2351 return getChat(m); 2352 } 2353 2354 ChatMember getChatAdministrators(ref GetChatAdministratorsMethod m) 2355 { 2356 return callMethod!ChatMember(m); 2357 } 2358 2359 ChatMember getChatAdministrators(T1)(T1 chatId) 2360 if (isTelegramId!T1) 2361 { 2362 GetChatAdministratorsMethod m; 2363 2364 static if (isIntegral!T1) { 2365 m.chat_id = chatId.to!string; 2366 } else { 2367 m.chat_id = chatId; 2368 } 2369 2370 return getChatAdministrators(m); 2371 } 2372 2373 uint getChatMembersCount(ref GetChatMembersCountMethod m) 2374 { 2375 return callMethod!uint(m); 2376 } 2377 2378 uint getChatMembersCount(T1)(T1 chatId) 2379 if (isTelegramId!T1) 2380 { 2381 GetChatMembersCountMethod m; 2382 2383 static if (isIntegral!T1) { 2384 m.chat_id = chatId.to!string; 2385 } else { 2386 m.chat_id = chatId; 2387 } 2388 2389 return getChatMembersCount(m); 2390 } 2391 2392 ChatMember getChatMember(ref GetChatMemberMethod m) 2393 { 2394 return callMethod!ChatMember(m); 2395 } 2396 2397 ChatMember getChatMember(T1)(T1 chatId, int userId) 2398 if (isTelegramId!T1) 2399 { 2400 GetChatMemberMethod m = { 2401 user_id : userId 2402 }; 2403 2404 static if (isIntegral!T1) { 2405 m.chat_id = chatId.to!string; 2406 } else { 2407 m.chat_id = chatId; 2408 } 2409 2410 return getChatMember(m); 2411 } 2412 2413 bool setChatStickerSet(ref SetChatStickerSetMethod m) 2414 { 2415 return callMethod!bool(m); 2416 } 2417 2418 bool setChatStickerSet(T1)(T1 chatId, string stickerSetName) 2419 if (isTelegramId!T1) 2420 { 2421 SetChatStickerSetMethod m = { 2422 sticker_set_name : stickerSetName 2423 }; 2424 2425 static if (isIntegral!T1) { 2426 m.chat_id = chatId.to!string; 2427 } else { 2428 m.chat_id = chatId; 2429 } 2430 2431 return setChatStickerSet(m); 2432 } 2433 2434 bool deleteChatStickerSet(ref DeleteChatStickerSetMethod m) 2435 { 2436 return callMethod!bool(m); 2437 } 2438 2439 bool deleteChatStickerSet(T1)(T1 chatId) 2440 if (isTelegramId!T1) 2441 { 2442 DeleteChatStickerSetMethod m; 2443 2444 static if (isIntegral!T1) { 2445 m.chat_id = chatId.to!string; 2446 } else { 2447 m.chat_id = chatId; 2448 } 2449 2450 return deleteChatStickerSet(m); 2451 } 2452 2453 bool answerCallbackQuery(ref AnswerCallbackQueryMethod m) 2454 { 2455 return callMethod!bool(m); 2456 } 2457 2458 bool answerCallbackQuery(string callbackQueryId) 2459 { 2460 AnswerCallbackQueryMethod m = { 2461 callback_query_id : callbackQueryId 2462 }; 2463 2464 return answerCallbackQuery(m); 2465 } 2466 2467 bool editMessageText(ref EditMessageTextMethod m) 2468 { 2469 return callMethod!bool(m); 2470 } 2471 2472 bool editMessageText(T1)(T1 chatId, uint messageId, string text) 2473 if (isTelegramId!T1) 2474 { 2475 EditMessageTextMethod m = { 2476 message_id : messageId, 2477 text : text 2478 }; 2479 2480 static if (isIntegral!T1) { 2481 m.chat_id = chatId.to!string; 2482 } else { 2483 m.chat_id = chatId; 2484 } 2485 2486 return editMessageText(m); 2487 } 2488 2489 bool editMessageText(string inlineMessageId, string text) 2490 { 2491 EditMessageTextMethod m = { 2492 inline_message_id : inlineMessageId, 2493 text : text 2494 }; 2495 2496 return editMessageText(m); 2497 } 2498 2499 bool editMessageCaption(ref EditMessageCaptionMethod m) 2500 { 2501 return callMethod!bool(m); 2502 } 2503 2504 bool editMessageCaption(T1)(T1 chatId, uint messageId, string caption = null) 2505 if (isTelegramId!T1) 2506 { 2507 EditMessageCaptionMethod m = { 2508 message_id : messageId, 2509 caption : caption 2510 }; 2511 2512 static if (isIntegral!T1) { 2513 m.chat_id = chatId.to!string; 2514 } else { 2515 m.chat_id = chatId; 2516 } 2517 2518 return editMessageCaption(m); 2519 } 2520 2521 bool editMessageCaption(string inlineMessageId, string caption = null) 2522 { 2523 EditMessageCaptionMethod m = { 2524 inline_message_id : inlineMessageId, 2525 caption : caption 2526 }; 2527 2528 return editMessageCaption(m); 2529 } 2530 2531 bool editMessageReplyMarkup(ref EditMessageReplyMarkupMethod m) 2532 { 2533 return callMethod!bool(m); 2534 } 2535 2536 bool editMessageReplyMarkup(T1, T2)(T1 chatId, uint messageId, T2 replyMarkup) 2537 if (isTelegramId!T1 && isReplyMarkup!T2) 2538 { 2539 EditMessageReplyMarkupMethod m = { 2540 message_id : messageId 2541 }; 2542 2543 m.reply_markup = replyMarkup; 2544 2545 static if (isIntegral!T1) { 2546 m.chat_id = chatId.to!string; 2547 } else { 2548 m.chat_id = chatId; 2549 } 2550 2551 return editMessageReplyMarkup(m); 2552 } 2553 2554 bool editMessageReplyMarkup(string inlineMessageId, Nullable!ReplyMarkup replyMarkup) 2555 { 2556 EditMessageReplyMarkupMethod m = { 2557 inline_message_id : inlineMessageId, 2558 reply_markup : replyMarkup 2559 }; 2560 2561 return editMessageReplyMarkup(m); 2562 } 2563 2564 bool deleteMessage(ref DeleteMessageMethod m) 2565 { 2566 return callMethod!bool(m); 2567 } 2568 2569 bool deleteMessage(T1)(T1 chatId, uint messageId) 2570 if (isTelegramId!T1) 2571 { 2572 DeleteMessageMethod m = { 2573 message_id : messageId 2574 }; 2575 2576 static if (isIntegral!T1) { 2577 m.chat_id = chatId.to!string; 2578 } else { 2579 m.chat_id = chatId; 2580 } 2581 2582 return deleteMessage(m); 2583 } 2584 2585 Message sendSticker(ref SendStickerMethod m) 2586 { 2587 return callMethod!Message(m); 2588 } 2589 2590 // TODO sticker is InputFile|string 2591 Message sendSticker(T1)(T1 chatId, string sticker) 2592 if (isTelegramId!T1) 2593 { 2594 SendStickerMethod m = { 2595 sticker : sticker 2596 }; 2597 2598 static if (isIntegral!T1) { 2599 m.chat_id = chatId.to!string; 2600 } else { 2601 m.chat_id = chatId; 2602 } 2603 2604 return sendSticker(m); 2605 } 2606 2607 StickerSet getStickerSet(ref GetStickerSetMethod m) 2608 { 2609 return callMethod!StickerSet(m); 2610 } 2611 2612 StickerSet getStickerSet(string name) 2613 { 2614 GetStickerSetMethod m = { 2615 name : name 2616 }; 2617 2618 return getStickerSet(m); 2619 } 2620 2621 File uploadStickerFile(ref UploadStickerFileMethod m) 2622 { 2623 return callMethod!File(m); 2624 } 2625 2626 File uploadStickerFile(int userId, InputFile pngSticker) 2627 { 2628 UploadStickerFileMethod m = { 2629 user_id : userId, 2630 png_sticker : pngSticker 2631 }; 2632 2633 return uploadStickerFile(m); 2634 } 2635 2636 bool createNewStickerSet(ref CreateNewStickerSetMethod m) 2637 { 2638 return callMethod!bool(m); 2639 } 2640 2641 // TODO pngSticker is InputFile|string 2642 bool createNewStickerSet(int userId, string name, string title, string pngSticker, string emojis) 2643 { 2644 CreateNewStickerSetMethod m = { 2645 user_id : userId, 2646 name : name, 2647 title : title, 2648 png_sticker : pngSticker, 2649 emojis : emojis 2650 }; 2651 2652 return createNewStickerSet(m); 2653 } 2654 2655 bool addStickerToSet(ref AddStickerToSetMethod m) 2656 { 2657 return callMethod!bool(m); 2658 } 2659 2660 bool addStickerToSet(int userId, string name, string pngSticker, string emojis) 2661 { 2662 AddStickerToSetMethod m = { 2663 user_id : userId, 2664 name : name, 2665 png_sticker : pngSticker, 2666 emojis : emojis 2667 }; 2668 2669 return addStickerToSet(m); 2670 } 2671 2672 bool setStickerPositionInSet(ref SetStickerPositionInSetMethod m) 2673 { 2674 return callMethod!bool(m); 2675 } 2676 2677 bool setStickerPositionInSet(string sticker, uint position) 2678 { 2679 SetStickerPositionInSetMethod m = { 2680 sticker : sticker, 2681 position : position 2682 }; 2683 2684 return setStickerPositionInSet(m); 2685 } 2686 2687 bool deleteStickerFromSet(ref DeleteStickerFromSetMethod m) 2688 { 2689 return callMethod!bool(m); 2690 } 2691 2692 bool deleteStickerFromSet(string sticker) 2693 { 2694 SetStickerPositionInSetMethod m = { 2695 sticker : sticker 2696 }; 2697 2698 return setStickerPositionInSet(m); 2699 } 2700 2701 bool answerInlineQuery(ref AnswerInlineQueryMethod m) 2702 { 2703 return callMethod!bool(m); 2704 } 2705 2706 bool answerInlineQuery(string inlineQueryId, InlineQueryResult[] results) 2707 { 2708 AnswerInlineQueryMethod m = { 2709 inline_query_id : inlineQueryId, 2710 results : results 2711 }; 2712 2713 return answerInlineQuery(m); 2714 } 2715 2716 unittest 2717 { 2718 class BotApiMock : BotApi 2719 { 2720 this(string token) 2721 { 2722 super(token); 2723 } 2724 2725 T callMethod(T, M)(M method) 2726 { 2727 T result; 2728 2729 logDiagnostic("[%d] Requesting %s", requestCounter, method.name); 2730 2731 return result; 2732 } 2733 } 2734 2735 auto api = new BotApiMock(null); 2736 2737 api.getUpdates(5,30); 2738 api.setWebhook("https://webhook.url"); 2739 api.deleteWebhook(); 2740 api.getWebhookInfo(); 2741 api.getMe(); 2742 api.sendMessage("chat-id", "hello"); 2743 api.forwardMessage("chat-id", "from-chat-id", 123); 2744 api.sendPhoto("chat-id", "photo-url"); 2745 api.sendAudio("chat-id", "audio-url"); 2746 api.sendDocument("chat-id", "document-url"); 2747 api.sendVideo("chat-id", "video-url"); 2748 api.sendVoice("chat-id", "voice-url"); 2749 api.sendVideoNote("chat-id", "video-note-url"); 2750 api.sendMediaGroup("chat-id", []); 2751 api.sendLocation("chat-id", 123, 123); 2752 api.editMessageLiveLocation("chat-id", 1, 1.23, 4.56); 2753 api.editMessageLiveLocation("inline-message-id", 1.23, 4.56); 2754 api.stopMessageLiveLocation("chat-id", 1); 2755 api.stopMessageLiveLocation("inline-message-id"); 2756 api.sendVenue("chat-id", 123, 123, "title", "address"); 2757 api.sendContact("chat-id", "+123", "First Name"); 2758 api.sendChatAction("chat-id", "typing"); 2759 api.getUserProfilePhotos(1); 2760 api.getFile("file-id"); 2761 api.kickChatMember("chat-id", 1); 2762 api.unbanChatMember("chat-id", 1); 2763 api.restrictChatMember("chat-id", 1); 2764 api.promoteChatMember("chat-id", 1); 2765 api.exportChatInviteLink("chat-id"); 2766 api.setChatPhoto("chat-id", InputFile()); 2767 api.deleteChatPhoto("chat-id"); 2768 api.setChatTitle("chat-id", "chat-title"); 2769 api.setChatDescription("chat-id", "chat-description"); 2770 api.pinChatMessage("chat-id", 1); 2771 api.unpinChatMessage("chat-id"); 2772 api.leaveChat("chat-id"); 2773 api.getChat("chat-id"); 2774 api.getChatAdministrators("chat-id"); 2775 api.getChatMembersCount("chat-id"); 2776 api.getChatMember("chat-id", 1); 2777 api.setChatStickerSet("chat-id", "sticker-set"); 2778 api.deleteChatStickerSet("chat-id"); 2779 api.answerCallbackQuery("callback-query-id"); 2780 api.editMessageText("chat-id", 123, "new text"); 2781 api.editMessageText("inline-message-id", "new text"); 2782 api.editMessageCaption("chat-id", 123, "new caption"); 2783 api.editMessageCaption("chat-id", 123, null); 2784 api.editMessageCaption("inline-message-id", "new caption"); 2785 api.editMessageCaption("inline-message-id", null); 2786 2787 api.editMessageReplyMarkup("chat-id", 123, ForceReply()); 2788 api.editMessageReplyMarkup("chat-id", 123, ReplyKeyboardMarkup()); 2789 api.editMessageReplyMarkup("chat-id", 123, ReplyKeyboardRemove()); 2790 api.editMessageReplyMarkup("chat-id", 123, InlineKeyboardMarkup()); 2791 api.editMessageReplyMarkup("chat-id", 123, ReplyMarkup()); 2792 2793 api.deleteMessage("chat-id", 123); 2794 api.sendSticker("chat-id", "sticker"); 2795 api.getStickerSet("sticker-set"); 2796 api.uploadStickerFile(1, InputFile()); 2797 api.createNewStickerSet(1, "name", "title", "png-sticker", "emojis"); 2798 api.addStickerToSet(1, "name", "png-sticker", "emojis"); 2799 api.setStickerPositionInSet("sticker", 42); 2800 api.deleteStickerFromSet("sticker"); 2801 2802 InlineQueryResult[] iqr = new InlineQueryResult[20]; 2803 2804 iqr[0] = InlineQueryResultArticle(); 2805 iqr[1] = InlineQueryResultPhoto(); 2806 iqr[2] = InlineQueryResultGif(); 2807 iqr[3] = InlineQueryResultMpeg4Gif(); 2808 iqr[4] = InlineQueryResultVideo(); 2809 iqr[5] = InlineQueryResultAudio(); 2810 iqr[6] = InlineQueryResultVoice(); 2811 iqr[7] = InlineQueryResultDocument(); 2812 iqr[8] = InlineQueryResultLocation(); 2813 iqr[9] = InlineQueryResultVenue(); 2814 iqr[10] = InlineQueryResultContact(); 2815 iqr[11] = InlineQueryResultGame(); 2816 iqr[12] = InlineQueryResultCachedPhoto(); 2817 iqr[13] = InlineQueryResultCachedGif(); 2818 iqr[14] = InlineQueryResultCachedMpeg4Gif(); 2819 iqr[15] = InlineQueryResultCachedSticker(); 2820 iqr[16] = InlineQueryResultCachedDocument(); 2821 iqr[17] = InlineQueryResultCachedVideo(); 2822 iqr[18] = InlineQueryResultCachedVoice(); 2823 iqr[19] = InlineQueryResultCachedAudio(); 2824 2825 api.answerInlineQuery("answer-inline-query", iqr); 2826 } 2827 }