@@ -8,8 +8,21 @@ import {
88 type IAdminForth ,
99} from "adminforth" ;
1010import { AdapterOptions } from "./types.js" ;
11+ import { getFinalMessageStreamPreview , renderFinalMessageImages } from "./renderers.js" ;
1112import { randomInt } from "node:crypto" ;
1213export type { AdapterOptions , TelegramStreamingMode } from "./types.js" ;
14+ export {
15+ getFinalMessageStreamPreview ,
16+ renderFinalMessageImages ,
17+ renderHtmlBlockToPng ,
18+ renderTablePng ,
19+ renderVegaLitePng ,
20+ type RenderedMessage ,
21+ type RenderedMessageImage ,
22+ type RenderTableColumn ,
23+ type RenderTablePngInput ,
24+ type VegaLiteSpec ,
25+ } from "./renderers.js" ;
1326
1427type TelegramUpdate = {
1528 message ?: {
@@ -165,16 +178,18 @@ export class TelegramChatSurfaceAdapter implements ChatSurfaceAdapter {
165178 } ;
166179
167180 const flushDraft = async ( ) => {
181+ const draftPreviewText = getFinalMessageStreamPreview ( text ) ;
182+
168183 if (
169184 closed ||
170185 done ||
171186 streamingMode !== "draft" ||
172- ! text
187+ ! draftPreviewText
173188 ) {
174189 return ;
175190 }
176191
177- const draftText = truncateTelegramDraft ( text ) ;
192+ const draftText = truncateTelegramDraft ( draftPreviewText ) ;
178193
179194 if ( draftText === lastDraftText ) {
180195 return ;
@@ -225,7 +240,7 @@ export class TelegramChatSurfaceAdapter implements ChatSurfaceAdapter {
225240 stopTyping ( ) ;
226241 clearDraftTimer ( ) ;
227242
228- await this . sendMessage (
243+ await this . sendFinalMessage (
229244 chatId ,
230245 text || event . text ,
231246 ) ;
@@ -301,6 +316,34 @@ export class TelegramChatSurfaceAdapter implements ChatSurfaceAdapter {
301316 }
302317 }
303318
319+ private async sendFinalMessage ( chatId : string , text : string ) {
320+ const renderedMessage = await renderFinalMessageImages ( text ) ;
321+
322+ await this . sendMessage ( chatId , renderedMessage . text ) ;
323+
324+ for ( const image of renderedMessage . images ) {
325+ await this . sendPhoto ( chatId , image . buffer , image . filename ) ;
326+ }
327+ }
328+
329+ private async sendPhoto ( chatId : string , png : Buffer , filename : string ) {
330+ const photoBytes = new Uint8Array ( png ) ;
331+ const formData = new FormData ( ) ;
332+ formData . append ( "chat_id" , chatId ) ;
333+ formData . append ( "photo" , new Blob ( [ photoBytes ] , {
334+ type : "image/png" ,
335+ } ) , filename ) ;
336+
337+ const response = await fetch ( `${ TELEGRAM_API_BASE_URL } /bot${ this . options . botToken } /sendPhoto` , {
338+ method : "POST" ,
339+ body : formData ,
340+ } ) ;
341+
342+ if ( ! response . ok ) {
343+ throw new Error ( `Telegram sendPhoto failed: ${ response . status } ${ await response . text ( ) } ` ) ;
344+ }
345+ }
346+
304347 private async sendChatAction ( chatId : string , action : "typing" ) {
305348 const response = await fetch ( `${ TELEGRAM_API_BASE_URL } /bot${ this . options . botToken } /sendChatAction` , {
306349 method : "POST" ,
@@ -343,4 +386,4 @@ export class TelegramChatSurfaceAdapter implements ChatSurfaceAdapter {
343386 }
344387}
345388
346- export default TelegramChatSurfaceAdapter ;
389+ export default TelegramChatSurfaceAdapter ;
0 commit comments