{"id":13694775,"url":"https://github.com/pengrad/java-telegram-bot-api","last_synced_at":"2026-03-02T22:15:06.252Z","repository":{"id":35895527,"uuid":"40182023","full_name":"pengrad/java-telegram-bot-api","owner":"pengrad","description":"Telegram Bot API for Java","archived":false,"fork":false,"pushed_at":"2025-03-02T23:27:32.000Z","size":2725,"stargazers_count":1857,"open_issues_count":8,"forks_count":381,"subscribers_count":64,"default_branch":"master","last_synced_at":"2025-03-03T00:48:59.583Z","etag":null,"topics":["bot","telegram","telegram-api","telegram-bot","telegram-bot-api"],"latest_commit_sha":null,"homepage":"https://core.telegram.org/bots","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pengrad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"pengrad"}},"created_at":"2015-08-04T11:58:56.000Z","updated_at":"2025-02-28T03:13:26.000Z","dependencies_parsed_at":"2024-01-03T06:54:46.192Z","dependency_job_id":"4fe1d438-dc52-43fb-8f63-c9a1bce3ba2f","html_url":"https://github.com/pengrad/java-telegram-bot-api","commit_stats":null,"previous_names":[],"tags_count":78,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengrad%2Fjava-telegram-bot-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengrad%2Fjava-telegram-bot-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengrad%2Fjava-telegram-bot-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pengrad%2Fjava-telegram-bot-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pengrad","download_url":"https://codeload.github.com/pengrad/java-telegram-bot-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252144478,"owners_count":21701420,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","telegram","telegram-api","telegram-bot","telegram-bot-api"],"created_at":"2024-08-02T17:01:41.797Z","updated_at":"2026-03-02T22:15:01.200Z","avatar_url":"https://github.com/pengrad.png","language":"Java","readme":"# Java Telegram Bot API\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.pengrad/java-telegram-bot-api.svg)](https://search.maven.org/artifact/com.github.pengrad/java-telegram-bot-api)\n[![codecov](https://codecov.io/gh/pengrad/java-telegram-bot-api/branch/master/graph/badge.svg)](https://codecov.io/gh/pengrad/java-telegram-bot-api)\n\nJava library for interacting with [Telegram Bot API](https://core.telegram.org/bots/api)\n- Full support of all Bot API 8.3 methods\n- Telegram [Passport](https://core.telegram.org/passport) and Decryption API\n- Bot [Payments](https://core.telegram.org/bots/payments)\n- [Gaming Platform](https://telegram.org/blog/games)\n\n## Download\n\nGradle:\n```groovy\nimplementation 'com.github.pengrad:java-telegram-bot-api:8.3.0'\n```\nMaven:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.pengrad\u003c/groupId\u003e\n  \u003cartifactId\u003ejava-telegram-bot-api\u003c/artifactId\u003e\n  \u003cversion\u003e8.3.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n[JAR with all dependencies on release page](https://github.com/pengrad/java-telegram-bot-api/releases)\n\n## Usage\n\n```java\n// Create your bot passing the token received from @BotFather\nTelegramBot bot = new TelegramBot(\"BOT_TOKEN\");\n\n// Register for updates\nbot.setUpdatesListener(updates -\u003e {\n    // ... process updates\n    // return id of last processed update or confirm them all\n    return UpdatesListener.CONFIRMED_UPDATES_ALL;\n// Create Exception Handler\n}, e -\u003e {\n    if (e.response() != null) {\n        // got bad response from telegram\n        e.response().errorCode();\n        e.response().description();\n    } else {\n        // probably network error\n        e.printStackTrace();\n    }\n});\n\n// Send messages\nlong chatId = update.message().chat().id();\nSendResponse response = bot.execute(new SendMessage(chatId, \"Hello!\"));\n```\n\n## Documentation\n\n- [Creating your bot](#creating-your-bot)\n- [Making requests](#making-requests)\n- [Getting updates](#getting-updates)\n- [Available types](#available-types)\n- [Available methods](#available-methods)\n- [Updating messages](#updating-messages)\n- [Stickers](#stickers)\n- [Inline mode](#inline-mode)\n- [Payments](#payments)\n- [Telegram Passport](#telegram-passport)\n- [Games](#games)\n\n### Creating your bot\n\n```java\nTelegramBot bot = new TelegramBot(\"BOT_TOKEN\");\n```\n\nNetwork operations based on [OkHttp](https://github.com/square/okhttp) library.  \nYou can build bot with custom OkHttpClient, for specific timeouts or interceptors.\n\n```java\nTelegramBot bot = new TelegramBot.Builder(\"BOT_TOKEN\").okHttpClient(client).build();\n```\n\n### Making requests\n\nSynchronous\n```java\nBaseResponse response = bot.execute(request);\n```\n\nAsynchronous\n```java\nbot.execute(request, new Callback() {\n    @Override\n    public void onResponse(BaseRequest request, BaseResponse response) {\n    \n    }\n    @Override\n    public void onFailure(BaseRequest request, IOException e) {\n    \n    }\n});\n```\n\nRequest [in response to update](https://core.telegram.org/bots/faq#how-can-i-make-requests-in-response-to-updates)\n```java\nString response = request.toWebhookResponse();\n```\n\n### Getting updates\n\nYou can use **getUpdates** request, parse incoming **Webhook** request, or set listener to receive updates.  \nUpdate object just copies Telegram's response.\n\n```java\nclass Update {\n    Integer updateId();\n    Message message();\n    Message editedMessage();\n    InlineQuery inlineQuery();\n    ChosenInlineResult chosenInlineResult();\n    CallbackQuery callbackQuery();\n}\n```\n\n#### Get updates\n\nBuilding request\n```java\nGetUpdates getUpdates = new GetUpdates().limit(100).offset(0).timeout(0);\n```\n\nThe getUpdates method returns the earliest 100 unconfirmed updates. To confirm an update, use the offset parameter when calling getUpdates like this:\n`offset = updateId of last processed update + 1`  \nAll updates with updateId less than offset will be marked as confirmed on the server and will no longer be returned.\n\nExecuting\n```java\n// sync\nGetUpdatesResponse updatesResponse = bot.execute(getUpdates);\nList\u003cUpdate\u003e updates = updatesResponse.updates();\n...\nMessage message = update.message()\n\n\n// async\nbot.execute(getUpdates, new Callback\u003cGetUpdates, GetUpdatesResponse\u003e() {\n    @Override\n    public void onResponse(GetUpdates request, GetUpdatesResponse response) {\n        List\u003cUpdate\u003e updates = response.updates();\n    }\n    \n    @Override\n    public void onFailure(GetUpdates request, IOException e) {\n    \n    }\n});\n```\n\n#### Webhook\n\nBuilding request\n```java\nSetWebhook request = new SetWebhook()\n       .url(\"url\")\n       .certificate(new byte[]{}) // byte[]\n       .certificate(new File(\"path\")); // or file \n```\n\nExecuting\n```java\n// sync\nBaseResponse response = bot.execute(request);\nboolean ok = response.isOk();\n\n// async\nbot.execute(request, new Callback\u003cSetWebhook, BaseResponse\u003e() {\n    @Override\n    public void onResponse(SetWebhook request, BaseResponse response) {\n    \n    }\n    @Override\n    public void onFailure(SetWebhook request, IOException e) {\n        \n    }\n});\n```\n\nUsing Webhook you can parse request to Update\n```java\nUpdate update = BotUtils.parseUpdate(stringRequest); // from String\nUpdate update = BotUtils.parseUpdate(reader); // or from java.io.Reader\n\nMessage message = update.message();\n``` \n\n#### Updates Listener\n\nYou can set a listener to receive incoming updates as if using Webhook.  \nThis will trigger executing getUpdates requests in a loop.\n\n```java\nbot.setUpdatesListener(new UpdatesListener() {\n    @Override\n    public int process(List\u003cUpdate\u003e updates) {\n\n        // process updates\n\n        return UpdatesListener.CONFIRMED_UPDATES_ALL;\n    }\n// Create Exception Handler\n}, new ExceptionHandler() {\n    @override\n    public void onException(TelegramException e)\n    {\n        if (e.response() != null) {\n            // got bad response from telegram\n            e.response().errorCode();\n            e.response().description();\n        } else {\n            // probably network error\n            e            .printStackTrace();\n        }\n    }\n});\n```\n\nListener should return id of the last processed (confirmed) update.  \nTo confirm all updates return `UpdatesListener.CONFIRMED_UPDATES_ALL`, this should be enough in most cases.  \nTo not confirm any updates return `UpdatesListener.CONFIRMED_UPDATES_NONE`, these updates will be redelivered.  \nTo set a specific update as last confirmed, just return the required updateId.\n\nTo stop receiving updates\n```java\nbot.removeGetUpdatesListener();\n```\n\n### Available types\n\nAll types have the same name as original ones.  \nType's fields are methods in lowerCamelCase.\n\nTypes used in responses **(Update, Message, User, Document...)** are in `com.pengrad.telegrambot.model` package. \n\nTypes used in requests **(Keyboard, InlineQueryResult, ParseMode, InputMessageContent...)** are in `com.pengrad.telegrambot.model.request` package.  \nWhen creating a request's type, required params should be passed in the constructor, optional params can be added in chains.\n\n#### Keyboards\n\nForceReply, ReplyKeyboardRemove\n```java\nKeyboard forceReply = new ForceReply(isSelective); // or just new ForceReply();\nKeyboard replyKeyboardRemove = new ReplyKeyboardRemove(); // new ReplyKeyboardRemove(isSelective)\n```\n\nReplyKeyboardMarkup\n```java\nKeyboard replyKeyboardMarkup = new ReplyKeyboardMarkup(\n                new String[]{\"first row button1\", \"first row button2\"},\n                new String[]{\"second row button1\", \"second row button2\"})\n                .oneTimeKeyboard(true)   // optional\n                .resizeKeyboard(true)    // optional\n                .selective(true);        // optional\n```\n\nKeyboardButton\n```java\nKeyboard keyboard = new ReplyKeyboardMarkup(\n        new KeyboardButton[]{\n                new KeyboardButton(\"text\"),\n                new KeyboardButton(\"contact\").requestContact(true),\n                new KeyboardButton(\"location\").requestLocation(true)\n        }\n);                \n```\n\nInlineKeyboardMarkup\n```java\nInlineKeyboardMarkup inlineKeyboard = new InlineKeyboardMarkup(\n        new InlineKeyboardButton[]{\n                new InlineKeyboardButton(\"url\").url(\"www.google.com\"),\n                new InlineKeyboardButton(\"callback_data\").callbackData(\"callback_data\"),\n                new InlineKeyboardButton(\"Switch!\").switchInlineQuery(\"switch_inline_query\")\n        });\n```\n\n#### Chat Action\n\n```java\nChatAction action = ChatAction.typing;\nChatAction action = ChatAction.upload_photo;\nChatAction action = ChatAction.find_location;\n```\n\n### Available methods\n\nAll request methods have the same names as original ones.  \nRequired params should be passed in the constructor.  \nOptional params can be added in chains.\n\n#### Send message \n\nAll send requests **(SendMessage, SendPhoto, SendLocation...)** return **SendResponse** object that contains **Message**.\n\n```java\nSendMessage request = new SendMessage(chatId, \"text\")\n        .parseMode(ParseMode.HTML)\n        .disableWebPagePreview(true)\n        .disableNotification(true)\n        .replyToMessageId(1)\n        .replyMarkup(new ForceReply());\n\n// sync\nSendResponse sendResponse = bot.execute(request);\nboolean ok = sendResponse.isOk();\nMessage message = sendResponse.message();\n\n// async\nbot.execute(request, new Callback\u003cSendMessage, SendResponse\u003e() {\n    @Override\n    public void onResponse(SendMessage request, SendResponse response) {\n       \n    }\n    \n    @Override\n    public void onFailure(SendMessage request, IOException e) {\n    \n    }\n});\n```\n\n#### Formatting options\n\n```java\nParseMode parseMode = ParseMode.Markdown;\nParseMode parseMode = ParseMode.HTML;\n```\n\n#### Get file\n\n```java\nGetFile request = new GetFile(\"fileId\")\nGetFileResponse getFileResponse = bot.execute(request);\n\nFile file = getFileResponse.file(); // com.pengrad.telegrambot.model.File\nfile.fileId();\nfile.filePath();  // relative path\nfile.fileSize();\n```\nTo get downloading link as `https://api.telegram.org/file/\u003cBOT_TOKEN\u003e/\u003cFILE_PATH\u003e`\n```java\nString fullPath = bot.getFullFilePath(file);  // com.pengrad.telegrambot.model.File\n```\n\n#### Other requests\n\nAll requests return BaseResponse if not mention here\n```java\nclass BaseResponse {\n  boolean isOk();\n  int errorCode();\n  String description();\n}\n```\n\nGetMe request returns GetMeResponse  \n```java\nclass GetMeResponse {\n  User user();\n}\n```\n\nGetChatAdministrators\n```java\nclass GetChatAdministratorsResponse {\n  List\u003cChatMember\u003e administrators()\n}\n```\n\nGetChatMembersCount\n```java\nclass GetChatMembersCountResponse {\n  int count() \n}\n```\n\nGetChatMember\n```java\nclass GetChatMemberResponse {\n  ChatMember chatMember()\n}\n```\n\nGetChat\n```java\nclass GetChatResponse {\n  Chat chat()\n}\n```\n\nGetUserProfilePhotos\n```java\nclass GetUserProfilePhotosResponse {\n  UserProfilePhotos photos()\n}\n```\n\nStopPoll\n```java\nclass PollResponse {\n  Poll poll()\n}\n```\n\n### Updating messages\n\nNormal message\n```java\nEditMessageText editMessageText = new EditMessageText(chatId, messageId, \"new test\")\n        .parseMode(ParseMode.HTML)\n        .disableWebPagePreview(true)\n        .replyMarkup(new ReplyKeyboardRemove());\n        \nBaseResponse response = bot.execute(editMessageText);\n```\n\nInline message\n```java\nEditMessageText editInlineMessageText = new EditMessageText(inlineMessageId, \"new text\");\nBaseResponse response = bot.execute(editInlineMessageText);\n```\n\nDelete message\n```java\nDeleteMessage deleteMessage = new DeleteMessage(chatId, messageId);\nBaseResponse response = bot.execute(deleteMessage);\n```\n\n### Stickers\n\nSend sticker\n```java\n// File or byte[] or string fileId of existing sticker or string URL\nSendSticker sendSticker = new SendSticker(chatId, imageFile);\nSendResponse response = bot.execute(sendSticker);\n```\n\nGet sticker set\n```java\nGetStickerSet getStickerSet = new GetStickerSet(stickerSet);\nGetStickerSetResponse response = bot.execute(getStickerSet);\nStickerSet stickerSet = response.stickerSet();\n```\n\nUpload sticker file\n```java\n// File or byte[] or string URL\nUploadStickerFile uploadStickerFile = new UploadStickerFile(chatId, stickerFile);\nGetFileResponse response = bot.execute(uploadStickerFile);\n```\n\n### Inline mode\n\nGetting updates\n```java\nGetUpdatesResponse updatesResponse = bot.execute(new GetUpdates());\nList\u003cUpdate\u003e updates = updatesResponse.updates();\n...\nInlineQuery inlineQuery = update.inlineQuery();\nChosenInlineResult chosenInlineResult = update.chosenInlineResult();\nCallbackQuery callbackQuery = update.callbackQuery();\n```\n\nIf using webhook, you can parse request to InlineQuery\n```java\nUpdate update = BotUtils.parseUpdate(stringRequest); // from String\nUpdate update = BotUtils.parseUpdate(reader); // from java.io.Reader\n\nInlineQuery inlineQuery = update.inlineQuery();\n```\n\n#### Inline query result\n\n```java\nInlineQueryResult r1 = new InlineQueryResultPhoto(\"id\", \"photoUrl\", \"thumbUrl\");\nInlineQueryResult r2 = new InlineQueryResultArticle(\"id\", \"title\", \"message text\").thumbUrl(\"url\");\nInlineQueryResult r3 = new InlineQueryResultGif(\"id\", \"gifUrl\", \"thumbUrl\");\nInlineQueryResult r4 = new InlineQueryResultMpeg4Gif(\"id\", \"mpeg4Url\", \"thumbUrl\");\n\nInlineQueryResult r5 = new InlineQueryResultVideo(\n  \"id\", \"videoUrl\", InlineQueryResultVideo.MIME_VIDEO_MP4, \"message\", \"thumbUrl\", \"video title\")\n    .inputMessageContent(new InputLocationMessageContent(21.03f, 105.83f));\n```\n\n#### Answer inline query\n\n```java\nBaseResponse response = bot.execute(new AnswerInlineQuery(inlineQuery.id(), r1, r2, r3, r4, r5));\n\n// or full\nbot.execute(\n        new AnswerInlineQuery(inlineQuery.id(), new InlineQueryResult[]{r1, r2, r3, r4, r5})\n                .cacheTime(cacheTime)\n                .isPersonal(isPersonal)\n                .nextOffset(\"offset\")\n                .switchPmParameter(\"pmParam\")\n                .switchPmText(\"pmText\")\n);\n```\n\n### Payments\n\nSend invoice\n```java\nSendInvoice sendInvoice = new SendInvoice(chatId, \"title\", \"desc\", \"my_payload\",\n        \"providerToken\", \"my_start_param\", \"USD\", new LabeledPrice(\"label\", 200))\n        .needPhoneNumber(true)\n        .needShippingAddress(true)\n        .isFlexible(true)\n        .replyMarkup(new InlineKeyboardMarkup(new InlineKeyboardButton[]{\n                new InlineKeyboardButton(\"just pay\").pay(),\n                new InlineKeyboardButton(\"google it\").url(\"www.google.com\")\n        }));\nSendResponse response = bot.execute(sendInvoice);\n```\n\nAnswer shipping query\n```java\nLabeledPrice[] prices = new LabeledPrice[]{\n        new LabeledPrice(\"delivery\", 100),\n        new LabeledPrice(\"tips\", 50)\n};\nAnswerShippingQuery answerShippingQuery = new AnswerShippingQuery(shippingQueryId,\n        new ShippingOption(\"1\", \"VNPT\", prices),\n        new ShippingOption(\"2\", \"FREE\", new LabeledPrice(\"free delivery\", 0))\n);\nBaseResponse response = bot.execute(answerShippingQuery);\n\n// answer with error\nAnswerShippingQuery answerShippingError = new AnswerShippingQuery(id, \"Can't deliver here!\");\nBaseResponse response = bot.execute(answerShippingError);\n```\n\nAnswer pre-checkout query\n```java\nAnswerPreCheckoutQuery answerCheckout = new AnswerPreCheckoutQuery(preCheckoutQueryId);\nBaseResponse response = bot.execute(answerPreCheckoutQuery);\n\n// answer with error\nAnswerPreCheckoutQuery answerCheckout = new AnswerPreCheckoutQuery(id, \"Sorry, item not available\");\nBaseResponse response = bot.execute(answerPreCheckoutQuery);\n```\n\n### Telegram Passport\n\nWhen the user confirms your request by pressing the ‘Authorize’ button, the Bot API sends an Update with the field `passport_data` to the bot that contains encrypted Telegram Passport data. [Telegram Passport Manual](https://core.telegram.org/passport#receiving-information)\n\n#### Receiving information\n\nYou can get encrypted Passport data from Update (via UpdatesListener or Webhook)\n\n```java\nPassportData passportData = update.message().passportData();\n```\n\nPassportData contains anarray of `EncryptedPassportElement` and `EncryptedCredentials`.  \nYou need to decrypt `Credentials` using private key (public key you uploaded to `@BotFather`)\n\n```java\nString privateKey = \"...\";\nEncryptedCredentials encryptedCredentials = passportData.credentials();\nCredentials credentials = encryptedCredentials.decrypt(privateKey);\n```\n\nThese `Credentials` can be used to decrypt encrypted data in `EncryptedPassportElement`.\n\n```java\nEncryptedPassportElement[] encryptedPassportElements = passportData.data();\nfor (EncryptedPassportElement element : encryptedPassportElements) {\n    DecryptedData decryptedData = element.decryptData(credentials);\n    // DecryptedData can be cast to specific type by checking instanceOf \n    if (decryptedData instanceof PersonalDetails) {\n        PersonalDetails personalDetails = (PersonalDetails) decryptedData;\n    }\n    // Or by checking type of passport element\n    if (element.type() == EncryptedPassportElement.Type.address) {\n        ResidentialAddress address = (ResidentialAddress) decryptedData;\n    }\n}\n```\n\n`EncryptedPassportElement` also contains an array of `PassportFile` (file uploaded to Telegram Passport).  \nYou need to download them 1 by 1 and decrypt content.  \nThis library supports downloading and decryption, returns decrypted byte[]\n\n```java\nEncryptedPassportElement element = ...\n\n// Combine all files \nList\u003cPassportFile\u003e files = new ArrayList\u003cPassportFile\u003e();\nfiles.add(element.frontSide());\nfiles.add(element.reverseSide());\nfiles.add(element.selfie());\nif (element.files() != null) {\n    files.addAll(Arrays.asList(element.files()));\n}\nif (element.translation() != null) {\n    files.addAll(Arrays.asList(element.translation()));\n}\n\n// Decrypt\nfor (PassportFile file : files) {\n    if (file == null) continue;\n    byte[] data = element.decryptFile(file, credentials, bot); // GetFile request and decrypt content\n    // save to file if needed\n    new FileOutputStream(\"files/\" + element.type()).write(data);\n}\n```\n\n#### Set Passport data errors\n\n``` java\nSetPassportDataErrors setPassportDataErrors = new SetPassportDataErrors(chatId,\n        new PassportElementErrorDataField(\"personal_details\", \"first_name\", \"dataHash\",\n                \"Please enter a valid First name\"),\n        new PassportElementErrorSelfie(\"driver_license\", \"fileHash\",\n                \"Can't see your face on photo\")\n);\nbot.execute(setPassportDataErrors);\n```\n\n### Games\n\nSend game\n```java\nSendResponse response = bot.execute(new SendGame(chatId, \"my_super_game\"));\n```\n\nSet game score\n```java\nBaseResponse response = bot.execute(new SetGameScore(userId, score, chatId, messageId));\n```\n\nGet game high scores\n```java\nGetGameHighScoresResponse response = bot.execute(new GetGameHighScores(userId, chatId, messageId));\nGameHighScore[] scores = response.result();\n```\n","funding_links":["https://github.com/sponsors/pengrad"],"categories":["Libraries","Java","Telegram Libraries","Bots"],"sub_categories":["Telegram","Java","Bot Libs"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpengrad%2Fjava-telegram-bot-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpengrad%2Fjava-telegram-bot-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpengrad%2Fjava-telegram-bot-api/lists"}