用于与 Telegram Bot API 交互的 Java 库
Gradle:
implementation 'com.github.pengrad:java-telegram-bot-api:7.8.0'
Maven:
<dependency> <groupId>com.github.pengrad</groupId> <artifactId>java-telegram-bot-api</artifactId> <version>7.8.0</version> </dependency>
// 使用从 @BotFather 获得的令牌创建您的机器人 TelegramBot bot = new TelegramBot("BOT_TOKEN"); // 注册更新监听器 bot.setUpdatesListener(updates -> { // ... 处理更新 // 返回最后处理的更新 ID 或确认所有更新 return UpdatesListener.CONFIRMED_UPDATES_ALL; // 创建异常处理器 }, e -> { if (e.response() != null) { // 从 Telegram 收到错误响应 e.response().errorCode(); e.response().description(); } else { // 可能是网络错误 e.printStackTrace(); } }); // 发送消息 long chatId = update.message().chat().id(); SendResponse response = bot.execute(new SendMessage(chatId, "你好!"));
TelegramBot bot = new TelegramBot("BOT_TOKEN");
网络操作基于 OkHttp 库。
您可以使用自定义 OkHttpClient 构建机器人,以设置特定的超时时间或拦截器。
TelegramBot bot = new TelegramBot.Builder("BOT_TOKEN").okHttpClient(client).build();
同步
BaseResponse response = bot.execute(request);
异步
bot.execute(request, new Callback() { @Override public void onResponse(BaseRequest request, BaseResponse response) { } @Override public void onFailure(BaseRequest request, IOException e) { } });
String response = request.toWebhookResponse();
您可以使用 getUpdates 请求,解析传入的 Webhook 请求,或设置监听器来接收更新。
Update 对象只是复制 Telegram 的响应。
class Update { Integer updateId(); Message message(); Message editedMessage(); InlineQuery inlineQuery(); ChosenInlineResult chosenInlineResult(); CallbackQuery callbackQuery(); }
构建请求
GetUpdates getUpdates = new GetUpdates().limit(100).offset(0).timeout(0);
getUpdates 方法返回最早的 100 个未确认更新。要确认更新,在调用 getUpdates 时使用 offset 参数,如下所示:
offset = 最后处理的更新的 updateId + 1
所有 updateId 小于 offset 的更新将在服务器上被标记为已确认,不再返回。
执行
// 同步 GetUpdatesResponse updatesResponse = bot.execute(getUpdates); List<Update> updates = updatesResponse.updates(); ... Message message = update.message() // 异步 bot.execute(getUpdates, new Callback<GetUpdates, GetUpdatesResponse>() { @Override public void onResponse(GetUpdates request, GetUpdatesResponse response) { List<Update> updates = response.updates(); } @Override public void onFailure(GetUpdates request, IOException e) { } });
构建请求
SetWebhook request = new SetWebhook() .url("url") .certificate(new byte[]{}) // byte[] .certificate(new File("path")); // 或文件
执行
// 同步 BaseResponse response = bot.execute(request); boolean ok = response.isOk(); // 异步 bot.execute(request, new Callback<SetWebhook, BaseResponse>() { @Override public void onResponse(SetWebhook request, BaseResponse response) { } @Override public void onFailure(SetWebhook request, IOException e) { } });
使用 Webhook 时,您可以将请求解析为 Update
Update update = BotUtils.parseUpdate(stringRequest); // 从字符串 Update update = BotUtils.parseUpdate(reader); // 或从 java.io.Reader Message message = update.message();
您可以设置监听器来接收传入的更新,就像使用 Webhook 一样。
这将触发循环执行 getUpdates 请求。
bot.setUpdatesListener(new UpdatesListener() { @Override public int process(List<Update> updates) { // 处理更新 return UpdatesListener.CONFIRMED_UPDATES_ALL; } // 创建异常处理器 }, new ExceptionHandler() { @override public void onException(TelegramException e) { if (e.response() != null) { // 从 Telegram 收到错误响应 e.response().errorCode(); e.response().description(); } else { // 可能是网络错误 e.printStackTrace(); } } });
监听器应返回最后一个已处理(已确认)更新的 id。
要确认所有更新,请返回 UpdatesListener.CONFIRMED_UPDATES_ALL,这在大多数情况下应该足够。
要不确认任何更新,请返回 UpdatesListener.CONFIRMED_UPDATES_NONE,这些更新将被重新传递。
要将特定更新设置为最后确认的更新,只需返回所需的 updateId。
要停止接收更新
bot.removeGetUpdatesListener();
所有类型的名称与原始名称相同。 类型的字段是采用小驼峰命名法的方法。
响应中使用的类型(Update、Message、User、Document...)位于 com.pengrad.telegrambot.model 包中。
请求中使用的类型(Keyboard、InlineQueryResult、ParseMode、InputMessageContent...)位于 com.pengrad.telegrambot.model.request 包中。
创建请求类型时,必需的参数应在构造函数中传递,可选参数可以通过链式调用添加。
ForceReply, ReplyKeyboardRemove
Keyboard forceReply = new ForceReply(isSelective); // 或直接使用 new ForceReply(); Keyboard replyKeyboardRemove = new ReplyKeyboardRemove(); // new ReplyKeyboardRemove(isSelective)
ReplyKeyboardMarkup
Keyboard replyKeyboardMarkup = new ReplyKeyboardMarkup( new String[]{"第一行按钮1", "第一行按钮2"}, new String[]{"第二行按钮1", "第二行按钮2"}) .oneTimeKeyboard(true) // 可选 .resizeKeyboard(true) // 可选 .selective(true); // 可选
KeyboardButton
Keyboard keyboard = new ReplyKeyboardMarkup( new KeyboardButton[]{ new KeyboardButton("文本"), new KeyboardButton("联系人").requestContact(true), new KeyboardButton("位置").requestLocation(true) } );
InlineKeyboardMarkup
InlineKeyboardMarkup inlineKeyboard = new InlineKeyboardMarkup( new InlineKeyboardButton[]{ new InlineKeyboardButton("url").url("www.google.com"), new InlineKeyboardButton("callback_data").callbackData("callback_data"), new InlineKeyboardButton("切换!").switchInlineQuery("switch_inline_query") });
ChatAction action = ChatAction.typing; ChatAction action = ChatAction.upload_photo; ChatAction action = ChatAction.find_location;
所有请求方法的名称与原始名称相同。 必需的参数应在构造函数中传递。 可选参数可以通过链式调用添加。
所有发送请求(SendMessage、SendPhoto、SendLocation...)都返回包含 Message 的 SendResponse 对象。
SendMessage request = new SendMessage(chatId, "文本") .parseMode(ParseMode.HTML) .disableWebPagePreview(true) .disableNotification(true) .replyToMessageId(1) .replyMarkup(new ForceReply()); // 同步 SendResponse sendResponse = bot.execute(request); boolean ok = sendResponse.isOk(); Message message = sendResponse.message(); // 异步 bot.execute(request, new Callback<SendMessage, SendResponse>() { @Override public void onResponse(SendMessage request, SendResponse response) { } @Override public void onFailure(SendMessage request, IOException e) { } });
ParseMode parseMode = ParseMode.Markdown; ParseMode parseMode = ParseMode.HTML;
GetFile request = new GetFile("fileId") GetFileResponse getFileResponse = bot.execute(request); File file = getFileResponse.file(); // com.pengrad.telegrambot.model.File file.fileId(); file.filePath(); // 相对路径 file.fileSize();
要获取下载链接,格式为 https://api.telegram.org/file/<BOT_TOKEN>/<FILE_PATH>
String fullPath = bot.getFullFilePath(file); // com.pengrad.telegrambot.model.File
如果这里没有提到,所有请求都返回 BaseResponse
class BaseResponse { boolean isOk(); int errorCode(); String description(); }
GetMe 请求返回 GetMeResponse
class GetMeResponse { User user(); }
GetChatAdministrators
class GetChatAdministratorsResponse { List<ChatMember> administrators() }
GetChatMembersCount
class GetChatMembersCountResponse { int count() }
GetChatMember
class GetChatMemberResponse { ChatMember chatMember() }
GetChat
class GetChatResponse { Chat chat() }
GetUserProfilePhotos
class GetUserProfilePhotosResponse { UserProfilePhotos photos() }
StopPoll
class PollResponse { Poll poll() }
普通消息
EditMessageText editMessageText = new EditMessageText(chatId, messageId, "新测试") .parseMode(ParseMode.HTML) .disableWebPagePreview(true) .replyMarkup(new ReplyKeyboardRemove()); BaseResponse response = bot.execute(editMessageText);
内联消息
EditMessageText editInlineMessageText = new EditMessageText(inlineMessageId, "新文本"); BaseResponse response = bot.execute(editInlineMessageText);
删除消息
DeleteMessage deleteMessage = new DeleteMessage(chatId, messageId); BaseResponse response = bot.execute(deleteMessage);
发送贴纸
// File 或 byte[] 或现有贴纸的 fileId 字符串或 URL 字符串 SendSticker sendSticker = new SendSticker(chatId, imageFile); SendResponse response = bot.execute(sendSticker);
获取贴纸集
GetStickerSet getStickerSet = new GetStickerSet(stickerSet); GetStickerSetResponse response = bot.execute(getStickerSet); StickerSet stickerSet = response.stickerSet();
上传贴纸文件
// File 或 byte[] 或 URL 字符串 UploadStickerFile uploadStickerFile = new UploadStickerFile(chatId, stickerFile); GetFileResponse response = bot.execute(uploadStickerFile);
获取更新
GetUpdatesResponse updatesResponse = bot.execute(new GetUpdates()); List<Update> updates = updatesResponse.updates(); ... InlineQuery inlineQuery = update.inlineQuery(); ChosenInlineResult chosenInlineResult = update.chosenInlineResult(); CallbackQuery callbackQuery = update.callbackQuery();
如果使用 webhook,您可以将请求解析为 InlineQuery
Update update = BotUtils.parseUpdate(stringRequest); // 从 String Update update = BotUtils.parseUpdate(reader); // 从 java.io.Reader InlineQuery inlineQuery = update.inlineQuery();
InlineQueryResult r1 = new InlineQueryResultPhoto("id", "photoUrl", "thumbUrl"); InlineQueryResult r2 = new InlineQueryResultArticle("id", "title", "message text").thumbUrl("url"); InlineQueryResult r3 = new InlineQueryResultGif("id", "gifUrl", "thumbUrl"); InlineQueryResult r4 = new InlineQueryResultMpeg4Gif("id", "mpeg4Url", "thumbUrl"); InlineQueryResult r5 = new InlineQueryResultVideo( "id", "videoUrl", InlineQueryResultVideo.MIME_VIDEO_MP4, "message", "thumbUrl", "video title") .inputMessageContent(new InputLocationMessageContent(21.03f, 105.83f));
BaseResponse response = bot.execute(new AnswerInlineQuery(inlineQuery.id(), r1, r2, r3, r4, r5)); // 或完整版 bot.execute( new AnswerInlineQuery(inlineQuery.id(), new InlineQueryResult[]{r1, r2, r3, r4, r5}) .cacheTime(cacheTime) .isPersonal(isPersonal) .nextOffset("offset") .switchPmParameter("pmParam") .switchPmText("pmText") );
发送账单
SendInvoice sendInvoice = new SendInvoice(chatId, "标题", "描述", "my_payload", "providerToken", "my_start_param", "USD", new LabeledPrice("标签", 200)) .needPhoneNumber(true) .needShippingAddress(true) .isFlexible(true) .replyMarkup(new InlineKeyboardMarkup(new InlineKeyboardButton[]{ new InlineKeyboardButton("直接支付").pay(), new InlineKeyboardButton("谷歌一下").url("www.google.com") })); SendResponse response = bot.execute(sendInvoice);
回答配送查询
LabeledPrice[] prices = new LabeledPrice[]{ new LabeledPrice("配送", 100), new LabeledPrice("小费", 50) }; AnswerShippingQuery answerShippingQuery = new AnswerShippingQuery(shippingQueryId, new ShippingOption("1", "VNPT", prices), new ShippingOption("2", "免费", new LabeledPrice("免费配送", 0)) ); BaseResponse response = bot.execute(answerShippingQuery); // 回答错误 AnswerShippingQuery answerShippingError = new AnswerShippingQuery(id, "无法配送到这里!"); BaseResponse response = bot.execute(answerShippingError);
回答预结账查询
AnswerPreCheckoutQuery answerCheckout = new AnswerPreCheckoutQuery(preCheckoutQueryId); BaseResponse response = bot.execute(answerPreCheckoutQuery); // 回答错误 AnswerPreCheckoutQuery answerCheckout = new AnswerPreCheckoutQuery(id, "抱歉,商品不可用"); BaseResponse response = bot.execute(answerPreCheckoutQuery);
当用户点击"授权"按钮确认您的请求时,Bot API会向机器人发送一个包含加密的Telegram Passport数据的更新,该更新包含passport_data字段。Telegram Passport 手册
您可以从更新中获取加密的Passport数据(通过UpdatesListener或Webhook)
PassportData passportData = update.message().passportData();
PassportData包含一组EncryptedPassportElement和EncryptedCredentials。
您需要使用私钥解密Credentials(公钥已上传到@BotFather)
String privateKey = "..."; EncryptedCredentials encryptedCredentials = passportData.credentials(); Credentials credentials = encryptedCredentials.decrypt(privateKey);
这些Credentials可用于解密EncryptedPassportElement中的加密数据。
EncryptedPassportElement[] encryptedPassportElements = passportData.data(); for (EncryptedPassportElement element : encryptedPassportElements) { DecryptedData decryptedData = element.decryptData(credentials); // DecryptedData可以通过检查instanceOf转换为特定类型 if (decryptedData instanceof PersonalDetails) { PersonalDetails personalDetails = (PersonalDetails) decryptedData; } // 或者通过检查护照元 素的类型 if (element.type() == EncryptedPassportElement.Type.address) { ResidentialAddress address = (ResidentialAddress) decryptedData; } }
EncryptedPassportElement还包含一组PassportFile(上传到Telegram Passport的文件)。
您需要逐个下载并解密内容。
该库支持下载和解密,返回解密后的byte[]
EncryptedPassportElement element = ... // 合并所有文件 List<PassportFile> files = new ArrayList<PassportFile>(); files.add(element.frontSide()); files.add(element.reverseSide()); files.add(element.selfie()); if (element.files() != null) { files.addAll(Arrays.asList(element.files())); } if (element.translation() != null) { files.addAll(Arrays.asList(element.translation())); } // 解密 for (PassportFile file : files) { if (file == null) continue; byte[] data = element.decryptFile(file, credentials, bot); // GetFile请求并解密内容 // 如果需要,保存到文件 new FileOutputStream("files/" + element.type()).write(data); }
SetPassportDataErrors setPassportDataErrors = new SetPassportDataErrors(chatId, new PassportElementErrorDataField("personal_details", "first_name", "dataHash", "请输入有效的名字"), new PassportElementErrorSelfie("driver_license", "fileHash", "照片上看不清您的脸") ); bot.execute(setPassportDataErrors);
发送游戏
SendResponse response = bot.execute(new SendGame(chatId, "my_super_game"));
设置游戏分数
BaseResponse response = bot.execute(new SetGameScore(userId, score, chatId, messageId));
获取游戏高分
GetGameHighScoresResponse response = bot.execute(new GetGameHighScores(userId, chatId, messageId)); GameHighScore[] scores = response.result();


全球首个AI音乐社区
音述AI是全球首个AI音乐社区,致力让每个人都能用音乐表达自我。音述AI提供零门槛AI创作工具,独创GETI法则帮助用户精准定义音乐风格,AI润色功能支持自动优化作品质感。音述AI支持交流讨论、二次创作与价值变现。针对中文用户的语言习惯与文化背景进行专门优化,支持国风融合、C-pop等本土音乐标签,让技术更好地承载人文表达。


一站式搞定所有学习需求
不再被海量信息淹没,开始真正理解知识。Lynote 可摘要 YouTube 视频、PDF、文章等内容。即时创建笔记,检测 AI 内容并下载资料,将您的 学习效率提升 10 倍。


为AI短剧协作而生
专为AI短剧协作而生的AniShort正式发布,深度重构AI短剧全流程生产模式,整合创意策划、制作执行、实时协作、在线审片、资产复用等全链路功能,独创无限画布、双轨并行工业化工作流与Ani智能体助手,集成多款主流AI大模型,破解素材零散、版本混乱、沟通低效等行业痛点,助力3人团队效率提升800%,打造标准化、可追溯的AI短剧量产体系,是AI短剧团队协同创作、提升制作效率的核心工具。


能听懂你表达的视频模型
Seedance two是基于seedance2.0的中国大模型,支持图像、视频、音频、文本四种模态输入,表达方式更丰富,生成也更可控。


国内直接访问,限时3折
输入简单文字,生成想要的图片,纳米香蕉中文站基于 Google 模型的 AI 图片生成网站,支持文字生图、图生图。官网价格限时3折活动


职场AI,就用扣子
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!


多风格AI绘画神器
堆友平台由阿里巴巴设计团队创建,作为一款AI驱动的设计工具,专为设计师提供一站式增长服务。功能覆盖海量3D素材、AI绘画、实时渲染以及专业抠图,显著提升设计品质和效率。平台不仅提供工具,还是一个促进创意交流和个人发展的空间,界面友好,适合所有级别的设计师和创意工作者。


零代码AI应用开发平台
零代码AI应用开发平台,用户只需一句话简单描述需求,AI能自动生成小程序、APP或H5网页应用,无需编写代码。


免费创建高清无水印Sora视频
Vora是一个免费创建高清无水印Sora视频的AI工具


最适合小白的AI自动化工作流平台
无需编码,轻松生成可复用、可变现的AI自动化工作流