用于与 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助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公 文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。
openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。
高分辨率纹理 3D 资产生成
Hunyuan3D-2 是腾讯开发的用于 3D 资产生成的强大工具,支持从文本描述、单张图片或多视角图片生成 3D 模型,具备快速形状生成能力,可生成带纹理的高质量 3D 模型,适用于多个领域,为 3D 创作提供了高效解决方案。
一个具备存储、管理和客户端操作等多种功能的分布式文件系统相关项目。
3FS 是一个功能强大的分布式文件系统项目,涵盖了存储引擎、元数据管理、客户端工具等多个模块。它支持多种文件操作,如创建文件和目录、设置布局等,同时具备高效的事件循环、节点选择和协程池管理等特性。适用于需要大规模数据存储和管理的场景,能够提高系统的性能和可靠性,是分布式存储领域的优质解决方案。
用于可扩展和多功能 3D 生成的结构化 3D 潜在表示
TRELLIS 是一 个专注于 3D 生成的项目,它利用结构化 3D 潜在表示技术,实现了可扩展且多功能的 3D 生成。项目提供了多种 3D 生成的方法和工具,包括文本到 3D、图像到 3D 等,并且支持多种输出格式,如 3D 高斯、辐射场和网格等。通过 TRELLIS,用户可以根据文本描述或图像输入快速生成高质量的 3D 资产,适用于游戏开发、动画制作、虚拟现实等多个领域。
10 节课教你开启构建 AI 代理所需的一切知识
AI Agents for Beginners 是一个专为初学者打造的课程项目,提供 10 节课程,涵盖构建 AI 代理的必备知识,支持多种语言,包含规划设计、工具使用、多代理等丰富内容,助您快速入门 AI 代理领域。
AI Excel全自动制表工具
AEE 在线 AI 全自动 Excel 编辑器,提供智能录入、自动公式、数据整理、图表生成等功能,高效处理 Excel 任务,提升办公效率。支持自动高亮数据、批量计算、不规则数据录入,适用于企业、教育、金融等多场景。
基于 UI-TARS 视觉语言模型的桌面应用,可通过自然语言控制计算机进行多模态操作。
UI-TARS-desktop 是一款功能强大的桌面应用,基于 UI-TARS(视觉语言模型)构建。它具备自然语言控制、截图与视觉识别、精确的鼠标键盘控制等功能,支持跨平台使用(Windows/MacOS),能提供实时反馈和状态显示,且数据完全本地处理,保障隐私安全。该应用集成了多种大语言模型和搜索方式,还可进行文件系统操作。适用于需要智能交互和自动化任务的场景,如信息检索、文件管理等。其提供了详细的文档,包括快速启动、部署、贡献指南和 SDK 使用说明等,方便开发者使用和扩展。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号