@effect-ak/tg-bot-client 0.6.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,51 +1,84 @@
1
- import * as Micro from 'effect/Micro';
2
- import { A as Api, T as TgBotClientError, a as TgBotApiToken, U as Update } from './config-3uU0YevV.js';
3
- export { bK as AcceptedGiftTypes, c as AddStickerToSetInput, bL as AffiliateInfo, bJ as AllowedUpdateName, bM as Animation, d as AnswerCallbackQueryInput, e as AnswerInlineQueryInput, f as AnswerPreCheckoutQueryInput, g as AnswerShippingQueryInput, h as AnswerWebAppQueryInput, i as ApproveChatJoinRequestInput, j as ApproveSuggestedPostInput, bN as Audio, bO as BackgroundFill, bP as BackgroundFillFreeformGradient, bQ as BackgroundFillGradient, bR as BackgroundFillSolid, bS as BackgroundType, bT as BackgroundTypeChatTheme, bU as BackgroundTypeFill, bV as BackgroundTypePattern, bW as BackgroundTypeWallpaper, B as BanChatMemberInput, k as BanChatSenderChatInput, bX as Birthdate, bY as BotCommand, bZ as BotCommandScope, b_ as BotCommandScopeAllChatAdministrators, b$ as BotCommandScopeAllGroupChats, c0 as BotCommandScopeAllPrivateChats, c1 as BotCommandScopeChat, c2 as BotCommandScopeChatAdministrators, c3 as BotCommandScopeChatMember, c4 as BotCommandScopeDefault, c5 as BotDescription, c6 as BotName, c7 as BotShortDescription, c8 as BusinessBotRights, c9 as BusinessConnection, ca as BusinessIntro, cb as BusinessLocation, cc as BusinessMessagesDeleted, cd as BusinessOpeningHours, ce as BusinessOpeningHoursInterval, cf as CallbackGame, cg as CallbackQuery, ch as Chat, ci as ChatAdministratorRights, cj as ChatBackground, ck as ChatBoost, cl as ChatBoostAdded, cm as ChatBoostRemoved, cn as ChatBoostSource, co as ChatBoostSourceGiftCode, cp as ChatBoostSourceGiveaway, cq as ChatBoostSourcePremium, cr as ChatBoostUpdated, cs as ChatFullInfo, ct as ChatInviteLink, cu as ChatJoinRequest, cv as ChatLocation, cw as ChatMember, cx as ChatMemberAdministrator, cy as ChatMemberBanned, cz as ChatMemberLeft, cA as ChatMemberMember, cB as ChatMemberOwner, cC as ChatMemberRestricted, cD as ChatMemberUpdated, cE as ChatPermissions, cF as ChatPhoto, cG as ChatShared, cH as Checklist, cI as ChecklistTask, cJ as ChecklistTasksAdded, cK as ChecklistTasksDone, cL as ChosenInlineResult, l as CloseForumTopicInput, m as CloseGeneralForumTopicInput, C as CloseInput, cM as Contact, n as ConvertGiftToStarsInput, o as CopyMessageInput, p as CopyMessagesInput, cN as CopyTextButton, q as CreateChatInviteLinkInput, r as CreateChatSubscriptionInviteLinkInput, s as CreateForumTopicInput, t as CreateInvoiceLinkInput, u as CreateNewStickerSetInput, D as DeclineChatJoinRequestInput, v as DeclineSuggestedPostInput, w as DeleteBusinessMessagesInput, x as DeleteChatPhotoInput, y as DeleteChatStickerSetInput, z as DeleteForumTopicInput, E as DeleteMessageInput, F as DeleteMessagesInput, G as DeleteMyCommandsInput, H as DeleteStickerFromSetInput, I as DeleteStickerSetInput, J as DeleteStoryInput, K as DeleteWebhookInput, cO as Dice, cP as DirectMessagePriceChanged, cQ as DirectMessagesTopic, cR as Document, L as EditChatInviteLinkInput, M as EditChatSubscriptionInviteLinkInput, N as EditForumTopicInput, O as EditGeneralForumTopicInput, P as EditMessageCaptionInput, Q as EditMessageChecklistInput, R as EditMessageLiveLocationInput, S as EditMessageMediaInput, V as EditMessageReplyMarkupInput, W as EditMessageTextInput, X as EditStoryInput, Y as EditUserStarSubscriptionInput, cS as EncryptedCredentials, cT as EncryptedPassportElement, Z as ExportChatInviteLinkInput, cU as ExternalReplyInfo, cV as File, cW as ForceReply, cX as ForumTopic, cY as ForumTopicClosed, cZ as ForumTopicCreated, c_ as ForumTopicEdited, c$ as ForumTopicReopened, _ as ForwardMessageInput, $ as ForwardMessagesInput, d0 as Game, d1 as GameHighScore, d2 as GeneralForumTopicHidden, d3 as GeneralForumTopicUnhidden, a0 as GetAvailableGiftsInput, a1 as GetBusinessAccountGiftsInput, a2 as GetBusinessAccountStarBalanceInput, a3 as GetBusinessConnectionInput, a5 as GetChatAdministratorsInput, a4 as GetChatInput, a7 as GetChatMemberCountInput, a6 as GetChatMemberInput, a8 as GetChatMenuButtonInput, a9 as GetCustomEmojiStickersInput, aa as GetFileInput, ab as GetForumTopicIconStickersInput, ac as GetGameHighScoresInput, ad as GetMeInput, ae as GetMyCommandsInput, af as GetMyDefaultAdministratorRightsInput, ag as GetMyDescriptionInput, ah as GetMyNameInput, ai as GetMyShortDescriptionInput, aj as GetMyStarBalanceInput, ak as GetStarTransactionsInput, al as GetStickerSetInput, am as GetUpdatesInput, an as GetUserChatBoostsInput, ao as GetUserProfilePhotosInput, ap as GetWebhookInfoInput, d4 as Gift, d5 as GiftInfo, aq as GiftPremiumSubscriptionInput, d6 as Gifts, d7 as Giveaway, d8 as GiveawayCompleted, d9 as GiveawayCreated, da as GiveawayWinners, ar as HideGeneralForumTopicInput, db as InaccessibleMessage, dc as InlineKeyboardButton, dd as InlineKeyboardMarkup, de as InlineQuery, df as InlineQueryResult, dg as InlineQueryResultArticle, dh as InlineQueryResultAudio, di as InlineQueryResultCachedAudio, dj as InlineQueryResultCachedDocument, dk as InlineQueryResultCachedGif, dl as InlineQueryResultCachedMpeg4Gif, dm as InlineQueryResultCachedPhoto, dn as InlineQueryResultCachedSticker, dp as InlineQueryResultCachedVideo, dq as InlineQueryResultCachedVoice, dr as InlineQueryResultContact, ds as InlineQueryResultDocument, dt as InlineQueryResultGame, du as InlineQueryResultGif, dv as InlineQueryResultLocation, dw as InlineQueryResultMpeg4Gif, dx as InlineQueryResultPhoto, dz as InlineQueryResultVenue, dA as InlineQueryResultVideo, dB as InlineQueryResultVoice, dy as InlineQueryResultsButton, dC as InputChecklist, dD as InputChecklistTask, dE as InputContactMessageContent, dF as InputFile, dG as InputInvoiceMessageContent, dH as InputLocationMessageContent, dI as InputMedia, dJ as InputMediaAnimation, dK as InputMediaAudio, dL as InputMediaDocument, dM as InputMediaPhoto, dN as InputMediaVideo, dO as InputMessageContent, dP as InputPaidMedia, dQ as InputPaidMediaPhoto, dR as InputPaidMediaVideo, dS as InputPollOption, dT as InputProfilePhoto, dU as InputProfilePhotoAnimated, dV as InputProfilePhotoStatic, dW as InputSticker, dX as InputStoryContent, dY as InputStoryContentPhoto, dZ as InputStoryContentVideo, d_ as InputTextMessageContent, d$ as InputVenueMessageContent, e0 as Invoice, e1 as KeyboardButton, e2 as KeyboardButtonPollType, e3 as KeyboardButtonRequestChat, e4 as KeyboardButtonRequestUsers, e5 as LabeledPrice, as as LeaveChatInput, e6 as LinkPreviewOptions, e7 as Location, e8 as LocationAddress, at as LogOutInput, e9 as LoginUrl, ea as MaskPosition, eb as MaybeInaccessibleMessage, ec as MenuButton, ed as MenuButtonCommands, ee as MenuButtonDefault, ef as MenuButtonWebApp, eg as Message, eh as MessageAutoDeleteTimerChanged, ei as MessageEntity, ej as MessageId, ek as MessageOrigin, el as MessageOriginChannel, em as MessageOriginChat, en as MessageOriginHiddenUser, eo as MessageOriginUser, ep as MessageReactionCountUpdated, eq as MessageReactionUpdated, er as OrderInfo, es as OwnedGift, et as OwnedGiftRegular, ev as OwnedGiftUnique, eu as OwnedGifts, ew as PaidMedia, ex as PaidMediaInfo, ey as PaidMediaPhoto, ez as PaidMediaPreview, eA as PaidMediaPurchased, eB as PaidMediaVideo, eC as PaidMessagePriceChanged, eD as PassportData, eE as PassportElementError, eF as PassportElementErrorDataField, eG as PassportElementErrorFile, eH as PassportElementErrorFiles, eI as PassportElementErrorFrontSide, eJ as PassportElementErrorReverseSide, eK as PassportElementErrorSelfie, eL as PassportElementErrorTranslationFile, eM as PassportElementErrorTranslationFiles, eN as PassportElementErrorUnspecified, eO as PassportFile, eP as PhotoSize, au as PinChatMessageInput, eQ as Poll, eR as PollAnswer, eS as PollOption, av as PostStoryInput, eT as PreCheckoutQuery, eU as PreparedInlineMessage, aw as PromoteChatMemberInput, eV as ProximityAlertTriggered, eW as ReactionCount, eX as ReactionType, eY as ReactionTypeCustomEmoji, eZ as ReactionTypeEmoji, e_ as ReactionTypePaid, ax as ReadBusinessMessageInput, ay as RefundStarPaymentInput, e$ as RefundedPayment, az as RemoveBusinessAccountProfilePhotoInput, aA as RemoveChatVerificationInput, aB as RemoveUserVerificationInput, aC as ReopenForumTopicInput, aD as ReopenGeneralForumTopicInput, aE as ReplaceStickerInSetInput, f0 as ReplyKeyboardMarkup, f1 as ReplyKeyboardRemove, f2 as ReplyParameters, f3 as ResponseParameters, aF as RestrictChatMemberInput, f4 as RevenueWithdrawalState, f5 as RevenueWithdrawalStateFailed, f6 as RevenueWithdrawalStatePending, f7 as RevenueWithdrawalStateSucceeded, aG as RevokeChatInviteLinkInput, aH as SavePreparedInlineMessageInput, aI as SendAnimationInput, aJ as SendAudioInput, aK as SendChatActionInput, aL as SendChecklistInput, aM as SendContactInput, aN as SendDiceInput, aO as SendDocumentInput, aP as SendGameInput, aQ as SendGiftInput, aR as SendInvoiceInput, aS as SendLocationInput, aT as SendMediaGroupInput, aU as SendMessageInput, aV as SendPaidMediaInput, aW as SendPhotoInput, aX as SendPollInput, aY as SendStickerInput, aZ as SendVenueInput, a_ as SendVideoInput, a$ as SendVideoNoteInput, b0 as SendVoiceInput, f8 as SentWebAppMessage, b1 as SetBusinessAccountBioInput, b2 as SetBusinessAccountGiftSettingsInput, b3 as SetBusinessAccountNameInput, b4 as SetBusinessAccountProfilePhotoInput, b5 as SetBusinessAccountUsernameInput, b6 as SetChatAdministratorCustomTitleInput, b7 as SetChatDescriptionInput, b8 as SetChatMenuButtonInput, b9 as SetChatPermissionsInput, ba as SetChatPhotoInput, bb as SetChatStickerSetInput, bc as SetChatTitleInput, bd as SetCustomEmojiStickerSetThumbnailInput, be as SetGameScoreInput, bf as SetMessageReactionInput, bg as SetMyCommandsInput, bh as SetMyDefaultAdministratorRightsInput, bi as SetMyDescriptionInput, bj as SetMyNameInput, bk as SetMyShortDescriptionInput, bl as SetPassportDataErrorsInput, bm as SetStickerEmojiListInput, bn as SetStickerKeywordsInput, bo as SetStickerMaskPositionInput, bp as SetStickerPositionInSetInput, bq as SetStickerSetThumbnailInput, br as SetStickerSetTitleInput, bs as SetUserEmojiStatusInput, bt as SetWebhookInput, f9 as SharedUser, fa as ShippingAddress, fb as ShippingOption, fc as ShippingQuery, fd as StarAmount, fe as StarTransaction, ff as StarTransactions, fg as Sticker, fh as StickerSet, bu as StopMessageLiveLocationInput, bv as StopPollInput, fi as Story, fj as StoryArea, fk as StoryAreaPosition, fl as StoryAreaType, fm as StoryAreaTypeLink, fn as StoryAreaTypeLocation, fo as StoryAreaTypeSuggestedReaction, fp as StoryAreaTypeUniqueGift, fq as StoryAreaTypeWeather, fr as SuccessfulPayment, fs as SuggestedPostApprovalFailed, ft as SuggestedPostApproved, fu as SuggestedPostDeclined, fv as SuggestedPostInfo, fw as SuggestedPostPaid, fx as SuggestedPostParameters, fy as SuggestedPostPrice, fz as SuggestedPostRefunded, fA as SwitchInlineQueryChosenChat, fB as TextQuote, b as TgBotApiBaseUrl, fC as TransactionPartner, fD as TransactionPartnerAffiliateProgram, fE as TransactionPartnerChat, fF as TransactionPartnerFragment, fG as TransactionPartnerOther, fH as TransactionPartnerTelegramAds, fI as TransactionPartnerTelegramApi, fJ as TransactionPartnerUser, bw as TransferBusinessAccountStarsInput, bx as TransferGiftInput, by as UnbanChatMemberInput, bz as UnbanChatSenderChatInput, bA as UnhideGeneralForumTopicInput, fK as UniqueGift, fL as UniqueGiftBackdrop, fM as UniqueGiftBackdropColors, fN as UniqueGiftInfo, fO as UniqueGiftModel, fP as UniqueGiftSymbol, bB as UnpinAllChatMessagesInput, bC as UnpinAllForumTopicMessagesInput, bD as UnpinAllGeneralForumTopicMessagesInput, bE as UnpinChatMessageInput, bF as UpgradeGiftInput, bG as UploadStickerFileInput, fQ as User, fR as UserChatBoosts, fS as UserProfilePhotos, fT as UsersShared, fU as Venue, bH as VerifyChatInput, bI as VerifyUserInput, fV as Video, fW as VideoChatEnded, fX as VideoChatParticipantsInvited, fY as VideoChatScheduled, fZ as VideoChatStarted, f_ as VideoNote, f$ as Voice, g0 as WebAppData, g1 as WebAppInfo, g2 as WebhookInfo, g3 as WriteAccessAllowed } from './config-3uU0YevV.js';
4
- import 'effect/Cause';
5
- import 'effect/Types';
6
- import 'effect/Data';
7
- import 'effect/Context';
1
+ import { Api } from '@effect-ak/tg-bot-api';
8
2
 
9
- declare const executeTgBotMethod: <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Micro.Micro<ReturnType<Api[M]>, TgBotClientError, TgBotApiToken>;
3
+ interface TgBotConfig {
4
+ botToken: string;
5
+ baseUrl?: string;
6
+ }
7
+ declare const getBaseUrl: (config?: Pick<TgBotConfig, "baseUrl">) => string;
8
+
9
+ declare function executeTgBotMethod<M extends keyof Api>(params: {
10
+ config: TgBotConfig;
11
+ method: M;
12
+ input: Parameters<Api[M]>[0];
13
+ }): Promise<ReturnType<Api[M]>>;
14
+ declare const makePayload: (body: object) => FormData | undefined;
10
15
 
11
- type GetFile = {
16
+ interface GetFile {
12
17
  fileId: string;
13
18
  type?: string;
14
- };
15
- declare const getFile: ({ fileId, type }: GetFile) => Micro.Micro<File, TgBotClientError, TgBotApiToken>;
16
- declare const getFileAsBase64String: ({ fileId, type, }: GetFile & {
17
- type: string;
18
- }) => Micro.Micro<{
19
- encoded: string;
20
- file_name: string;
21
- }, TgBotClientError, TgBotApiToken>;
22
- declare const getFileBytes: (fileId: string) => Micro.Micro<{
19
+ }
20
+ interface FileBytes {
23
21
  content: ArrayBuffer;
24
22
  file_name: string;
25
- }, TgBotClientError, TgBotApiToken>;
23
+ base64String: () => string;
24
+ }
25
+ interface FileContext {
26
+ config: TgBotConfig;
27
+ execute: <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Promise<ReturnType<Api[M]>>;
28
+ }
29
+ declare const getFileBytes: (fileId: string, context: FileContext) => Promise<FileBytes>;
30
+ declare const getFile: (input: GetFile, context: FileContext) => Promise<File>;
26
31
 
27
32
  interface TgBotClient {
28
33
  readonly execute: <M extends keyof Api>(method: M, input: Parameters<Api[M]>[0]) => Promise<ReturnType<Api[M]>>;
29
34
  readonly getFile: (input: GetFile) => Promise<File>;
30
35
  }
31
- type MakeTgClient = {
36
+ interface MakeTgClient {
32
37
  bot_token: string;
33
- };
38
+ base_url?: string;
39
+ }
34
40
  declare function makeTgBotClient(config: MakeTgClient): TgBotClient;
35
41
 
36
- type FileContent = {
37
- file_content: Uint8Array;
38
- file_name: string;
42
+ type ErrorReason = {
43
+ _tag: "NotOkResponse";
44
+ errorCode?: number;
45
+ details?: string;
46
+ } | {
47
+ _tag: "UnexpectedResponse";
48
+ response: unknown;
49
+ } | {
50
+ _tag: "ClientInternalError";
51
+ cause: unknown;
52
+ } | {
53
+ _tag: "UnableToGetFile";
54
+ cause: unknown;
55
+ } | {
56
+ _tag: "BotHandlerError";
57
+ cause: unknown;
58
+ } | {
59
+ _tag: "NotJsonResponse";
60
+ response: unknown;
39
61
  };
62
+ declare class TgBotClientError extends Error {
63
+ readonly _tag = "TgBotClientError";
64
+ readonly cause: ErrorReason;
65
+ constructor(options: {
66
+ cause: ErrorReason;
67
+ });
68
+ }
69
+
70
+ interface FileContent {
71
+ file_content: Uint8Array<ArrayBuffer>;
72
+ file_name: string;
73
+ }
40
74
  declare const isFileContent: (input: unknown) => input is FileContent;
41
- type TgBotApiResponseSchema = {
75
+ interface TgBotApiResponseSchema {
42
76
  ok: boolean;
43
77
  error_code?: number;
44
78
  description?: string;
45
79
  result?: unknown;
46
- };
80
+ }
47
81
  declare const isTgBotApiResponse: (input: unknown) => input is TgBotApiResponseSchema;
48
- declare const isTgBotApiUpdate: (input: unknown) => input is Update;
49
82
 
50
83
  declare const TG_BOT_API_URL = "https://api.telegram.org";
51
84
  declare const MESSAGE_EFFECTS: {
@@ -60,4 +93,6 @@ type MessageEffect = keyof typeof MESSAGE_EFFECTS;
60
93
  declare const messageEffectIdCodes: MessageEffect[];
61
94
  declare const isMessageEffect: (input: unknown) => input is MessageEffect;
62
95
 
63
- export { Api, type FileContent, type GetFile, MESSAGE_EFFECTS, type MessageEffect, TG_BOT_API_URL, type TgBotApiResponseSchema, TgBotApiToken, type TgBotClient, TgBotClientError, Update, executeTgBotMethod, getFile, getFileAsBase64String, getFileBytes, isFileContent, isMessageEffect, isTgBotApiResponse, isTgBotApiUpdate, makeTgBotClient, messageEffectIdCodes };
96
+ declare const snakeToCamel: (str: string) => string;
97
+
98
+ export { type FileBytes, type FileContent, type GetFile, MESSAGE_EFFECTS, type MakeTgClient, type MessageEffect, TG_BOT_API_URL, type TgBotApiResponseSchema, type TgBotClient, TgBotClientError, type TgBotConfig, executeTgBotMethod, getBaseUrl, getFile, getFileBytes, isFileContent, isMessageEffect, isTgBotApiResponse, makePayload, makeTgBotClient, messageEffectIdCodes, snakeToCamel };
package/dist/index.js CHANGED
@@ -1 +1,169 @@
1
- "use strict";var P=Object.create;var y=Object.defineProperty;var v=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var D=(e,o)=>{for(var t in o)y(e,t,{get:o[t],enumerable:!0})},b=(e,o,t,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of $(o))!O.call(e,r)&&r!==t&&y(e,r,{get:()=>o[r],enumerable:!(n=v(o,r))||n.enumerable});return e};var l=(e,o,t)=>(t=e!=null?P(j(e)):{},b(o||!e||!e.__esModule?y(t,"default",{value:e,enumerable:!0}):t,e)),I=e=>b(y({},"__esModule",{value:!0}),e);var q={};D(q,{MESSAGE_EFFECTS:()=>_,TG_BOT_API_URL:()=>F,TgBotApiBaseUrl:()=>d,TgBotApiToken:()=>f,TgBotClientError:()=>p,executeTgBotMethod:()=>g,getFile:()=>B,getFileAsBase64String:()=>H,getFileBytes:()=>C,isFileContent:()=>T,isMessageEffect:()=>L,isTgBotApiResponse:()=>k,isTgBotApiUpdate:()=>N,makeTgBotClient:()=>V,messageEffectIdCodes:()=>J});module.exports=I(q);var R=l(require("effect/String")),c=l(require("effect/Micro"));var E=l(require("effect/Data")),p=class extends E.TaggedError("TgBotClientError"){};var T=e=>typeof e=="object"&&e!=null&&"file_content"in e&&e.file_content instanceof Uint8Array&&"file_name"in e&&typeof e.file_name=="string",k=e=>typeof e=="object"&&e!=null&&"ok"in e&&typeof e.ok=="boolean",N=e=>typeof e=="object"&&e!=null&&"update_id"in e&&typeof e.update_id=="number";var x=l(require("effect/Context"));var F="https://api.telegram.org",_={"\u{1F525}":"5104841245755180586","\u{1F44D}":"5107584321108051014","\u{1F44E}":"5104858069142078462","\u2764\uFE0F":"5159385139981059251","\u{1F389}":"5046509860389126442","\u{1F4A9}":"5046589136895476101"},J=Object.keys(_),L=e=>typeof e=="string"&&e in _;var d=class extends x.Reference()("TgBotApiBaseUrl",{defaultValue:()=>F}){},f=class extends x.Tag("TgBotApiToken")(){};var h=e=>{let o=Object.entries(e);if(o.length==0)return;let t=new FormData;for(let[n,r]of o)r&&(typeof r!="object"?t.append(n,`${r}`):T(r)?t.append(n,new Blob([r.file_content]),r.file_name):t.append(n,JSON.stringify(r)));return t};var g=(e,o)=>c.gen(function*(){let t=yield*c.service(f),n=yield*c.service(d),r=yield*c.tryPromise({try:()=>fetch(`${n}/bot${t}/${R.snakeToCamel(e)}`,{body:h(o)??null,method:"POST"}),catch:m=>new p({cause:{_tag:"ClientInternalError",cause:m}})}),a=yield*c.tryPromise({try:()=>r.json(),catch:()=>new p({cause:{_tag:"NotJsonResponse",response:r}})});return k(a)?r.ok?a.result:yield*c.fail(new p({cause:{_tag:"NotOkResponse",...a.error_code?{errorCode:a.error_code}:void 0,...a.description?{details:a.description}:void 0}})):yield*c.fail(new p({cause:{_tag:"UnexpectedResponse",response:a}}))});var s=l(require("effect/Micro"));var B=({fileId:e,type:o})=>C(e).pipe(s.andThen(({content:t,file_name:n})=>new File([t],n,{...o?{type:o}:void 0}))),H=({fileId:e,type:o})=>C(e).pipe(s.andThen(({content:t,file_name:n})=>{let r=Buffer.from(t).toString("base64");return{encoded:`data:${o};base64,${r}`,file_name:n}})),C=e=>s.gen(function*(){let t=(yield*g("get_file",{file_id:e})).file_path;if(!t||t.length==0)return yield*s.fail(new p({cause:{_tag:"UnableToGetFile",cause:"File path not defined"}}));let n=t.replaceAll("/","-"),r=yield*s.service(d),a=yield*s.service(f),m=`${r}/file/bot${a}/${t}`;return{content:yield*s.tryPromise({try:()=>fetch(m).then(M=>M.arrayBuffer()),catch:M=>new p({cause:{_tag:"UnableToGetFile",cause:M}})}),file_name:n}});var i=l(require("effect/Micro")),G=l(require("effect/Context"));var S=l(require("effect/Micro")),w=l(require("effect/Context"));var u=class extends w.Tag("ClientFileService")(){},U=S.gen(function*(){return{getFile:B}});function V(e){return i.gen(function*(){let t=yield*i.service(u),n=G.make(f,e.bot_token);return{execute:(m,A)=>g(m,A).pipe(i.provideContext(n),i.runPromise),getFile:m=>t.getFile(m).pipe(i.provideContext(n),i.runPromise)}}).pipe(i.provideServiceEffect(u,U),i.runSync)}0&&(module.exports={MESSAGE_EFFECTS,TG_BOT_API_URL,TgBotApiBaseUrl,TgBotApiToken,TgBotClientError,executeTgBotMethod,getFile,getFileAsBase64String,getFileBytes,isFileContent,isMessageEffect,isTgBotApiResponse,isTgBotApiUpdate,makeTgBotClient,messageEffectIdCodes});
1
+ // src/errors.ts
2
+ var TgBotClientError = class extends Error {
3
+ _tag = "TgBotClientError";
4
+ cause;
5
+ constructor(options) {
6
+ super(`TgBotClientError: ${options.cause._tag}`);
7
+ this.cause = options.cause;
8
+ this.name = "TgBotClientError";
9
+ }
10
+ };
11
+
12
+ // src/guards.ts
13
+ var isFileContent = (input) => typeof input == "object" && input != null && "file_content" in input && input.file_content instanceof Uint8Array && "file_name" in input && typeof input.file_name == "string";
14
+ var isTgBotApiResponse = (input) => typeof input == "object" && input != null && "ok" in input && typeof input.ok == "boolean";
15
+
16
+ // src/const.ts
17
+ var TG_BOT_API_URL = "https://api.telegram.org";
18
+ var MESSAGE_EFFECTS = {
19
+ "\u{1F525}": "5104841245755180586",
20
+ "\u{1F44D}": "5107584321108051014",
21
+ "\u{1F44E}": "5104858069142078462",
22
+ "\u2764\uFE0F": "5159385139981059251",
23
+ "\u{1F389}": "5046509860389126442",
24
+ "\u{1F4A9}": "5046589136895476101"
25
+ };
26
+ var messageEffectIdCodes = Object.keys(
27
+ MESSAGE_EFFECTS
28
+ );
29
+ var isMessageEffect = (input) => {
30
+ return typeof input === "string" && input in MESSAGE_EFFECTS;
31
+ };
32
+
33
+ // src/config.ts
34
+ var getBaseUrl = (config) => {
35
+ return config?.baseUrl ?? TG_BOT_API_URL;
36
+ };
37
+
38
+ // src/utils.ts
39
+ var snakeToCamel = (str) => {
40
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
41
+ };
42
+
43
+ // src/execute.ts
44
+ async function executeTgBotMethod(params) {
45
+ const { config, method, input } = params;
46
+ const baseUrl = getBaseUrl(config);
47
+ const botToken = config.botToken;
48
+ let httpResponse;
49
+ try {
50
+ httpResponse = await fetch(
51
+ `${baseUrl}/bot${botToken}/${snakeToCamel(method)}`,
52
+ {
53
+ body: makePayload(input) ?? null,
54
+ method: "POST"
55
+ }
56
+ );
57
+ } catch (cause) {
58
+ throw new TgBotClientError({
59
+ cause: { _tag: "ClientInternalError", cause }
60
+ });
61
+ }
62
+ let response;
63
+ try {
64
+ response = await httpResponse.json();
65
+ } catch {
66
+ throw new TgBotClientError({
67
+ cause: { _tag: "NotJsonResponse", response: httpResponse }
68
+ });
69
+ }
70
+ if (!isTgBotApiResponse(response)) {
71
+ throw new TgBotClientError({
72
+ cause: { _tag: "UnexpectedResponse", response }
73
+ });
74
+ }
75
+ if (!httpResponse.ok) {
76
+ throw new TgBotClientError({
77
+ cause: {
78
+ _tag: "NotOkResponse",
79
+ ...response.error_code ? { errorCode: response.error_code } : {},
80
+ ...response.description ? { details: response.description } : {}
81
+ }
82
+ });
83
+ }
84
+ return response.result;
85
+ }
86
+ var makePayload = (body) => {
87
+ const entries = Object.entries(body);
88
+ if (entries.length == 0) return void 0;
89
+ const result = new FormData();
90
+ for (const [key, value] of entries) {
91
+ if (!value) continue;
92
+ if (typeof value != "object") {
93
+ result.append(key, `${value}`);
94
+ } else if (isFileContent(value)) {
95
+ result.append(key, new Blob([value.file_content]), value.file_name);
96
+ } else {
97
+ result.append(key, JSON.stringify(value));
98
+ }
99
+ }
100
+ return result;
101
+ };
102
+
103
+ // src/client-file.ts
104
+ var getFileBytes = async (fileId, context) => {
105
+ const { config, execute } = context;
106
+ const response = await execute("get_file", { file_id: fileId });
107
+ const file_path = response.file_path;
108
+ if (!file_path || file_path.length === 0) {
109
+ throw new TgBotClientError({
110
+ cause: {
111
+ _tag: "UnableToGetFile",
112
+ cause: "File path not defined"
113
+ }
114
+ });
115
+ }
116
+ const file_name = file_path.replaceAll("/", "-");
117
+ const baseUrl = getBaseUrl(config);
118
+ const botToken = config.botToken;
119
+ const url = `${baseUrl}/file/bot${botToken}/${file_path}`;
120
+ let content;
121
+ try {
122
+ content = await fetch(url).then((_) => _.arrayBuffer());
123
+ } catch (cause) {
124
+ throw new TgBotClientError({
125
+ cause: { _tag: "UnableToGetFile", cause }
126
+ });
127
+ }
128
+ const base64String = () => Buffer.from(content).toString("base64");
129
+ return {
130
+ content,
131
+ file_name,
132
+ base64String
133
+ };
134
+ };
135
+ var getFile = async (input, context) => {
136
+ const { content, file_name } = await getFileBytes(input.fileId, context);
137
+ return new File([content], file_name, {
138
+ ...input.type ? { type: input.type } : {}
139
+ });
140
+ };
141
+
142
+ // src/client.ts
143
+ function makeTgBotClient(config) {
144
+ const tgConfig = {
145
+ botToken: config.bot_token,
146
+ ...config.base_url ? { baseUrl: config.base_url } : {}
147
+ };
148
+ const execute = (method, input) => executeTgBotMethod({ config: tgConfig, method, input });
149
+ return {
150
+ execute,
151
+ getFile: (input) => getFile(input, { config: tgConfig, execute })
152
+ };
153
+ }
154
+ export {
155
+ MESSAGE_EFFECTS,
156
+ TG_BOT_API_URL,
157
+ TgBotClientError,
158
+ executeTgBotMethod,
159
+ getBaseUrl,
160
+ getFile,
161
+ getFileBytes,
162
+ isFileContent,
163
+ isMessageEffect,
164
+ isTgBotApiResponse,
165
+ makePayload,
166
+ makeTgBotClient,
167
+ messageEffectIdCodes,
168
+ snakeToCamel
169
+ };
package/package.json CHANGED
@@ -1,75 +1,38 @@
1
1
  {
2
2
  "name": "@effect-ak/tg-bot-client",
3
- "version": "0.6.4",
4
- "homepage": "https://effect-ak.github.io/telegram-bot-playground/",
3
+ "type": "module",
4
+ "description": "Type-safe HTTP client for Telegram Bot API",
5
+ "version": "1.1.0",
6
+ "license": "MIT",
7
+ "scripts": {
8
+ "build": "tsup"
9
+ },
5
10
  "author": {
6
11
  "name": "Aleksandr Kondaurov",
7
12
  "email": "kondaurov.dev@gmail.com"
8
13
  },
9
- "publishConfig": {
10
- "access": "public"
11
- },
12
- "description": "TypeScript types for Telegram Bot Api and Telegram.Webapp",
13
- "files": [
14
- "dist/*.js",
15
- "dist/*.mjs",
16
- "dist/*.d.ts",
17
- "!dist/bot-bundle.d.ts",
18
- "!dist/bot-bundle.d.mts"
19
- ],
20
- "keywords": [
21
- "telegram typescript types",
22
- "telegram bot api client",
23
- "telegram webapp"
24
- ],
25
14
  "repository": {
26
15
  "type": "git",
27
- "url": "https://github.com/effect-ak/tg-bot-client"
16
+ "url": "https://github.com/effect-ak/tg-bot-client",
17
+ "directory": "packages/client"
28
18
  },
29
19
  "bugs": {
30
20
  "url": "https://github.com/effect-ak/tg-bot-client/issues"
31
21
  },
32
- "license": "MIT",
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
33
25
  "types": "./dist/index.d.ts",
34
- "main": "./dist/index.js",
35
- "module": "./dist/index.mjs",
26
+ "main": "./dist/index.cjs",
27
+ "module": "./dist/index.js",
36
28
  "exports": {
37
29
  ".": {
38
30
  "types": "./dist/index.d.ts",
39
- "require": "./dist/index.js",
40
- "import": "./dist/index.mjs"
41
- },
42
- "./bot": {
43
- "types": "./dist/bot.d.ts",
44
- "require": "./dist/bot.js",
45
- "import": "./dist/bot.mjs"
46
- },
47
- "./bot-bundle": {
48
- "types": "./dist/bot.d.ts",
49
- "require": "./dist/bot-bundle.js",
50
- "import": "./dist/bot-bundle.mjs"
51
- },
52
- "./webapp": {
53
- "types": "./dist/webapp.d.ts",
54
- "require": "./dist/webapp.js",
55
- "import": "./dist/webapp.mjs"
31
+ "import": "./dist/index.js",
32
+ "require": "./dist/index.cjs"
56
33
  }
57
34
  },
58
- "devDependencies": {
59
- "@types/node": "^22.10.1",
60
- "@types/js-yaml": "^4.0.9",
61
- "js-yaml": "^4.1.0",
62
- "node-html-parser": "^6.1.13",
63
- "openapi-types": "^12.1.3",
64
- "ts-morph": "^24.0.0",
65
- "tsx": "^4.19.3",
66
- "typescript": "^5.8.3",
67
- "vite-tsconfig-paths": "^5.1.4",
68
- "vitest": "^3.1.1",
69
- "effect": "3.12.0",
70
- "tsup": "^8.5.0"
71
- },
72
- "peerDependencies": {
73
- "effect": "^3.12.0"
35
+ "dependencies": {
36
+ "@effect-ak/tg-bot-api": "workspace:*"
74
37
  }
75
- }
38
+ }
@@ -0,0 +1,73 @@
1
+ import type { Api } from "@effect-ak/tg-bot-api"
2
+ import { TgBotClientError } from "./errors"
3
+ import type { TgBotConfig } from "./config"
4
+ import { getBaseUrl } from "./config"
5
+
6
+ export interface GetFile {
7
+ fileId: string
8
+ type?: string
9
+ }
10
+
11
+ export interface FileBytes {
12
+ content: ArrayBuffer
13
+ file_name: string
14
+ base64String: () => string
15
+ }
16
+
17
+ interface FileContext {
18
+ config: TgBotConfig
19
+ execute: <M extends keyof Api>(
20
+ method: M,
21
+ input: Parameters<Api[M]>[0]
22
+ ) => Promise<ReturnType<Api[M]>>
23
+ }
24
+
25
+ export const getFileBytes = async (
26
+ fileId: string,
27
+ context: FileContext
28
+ ): Promise<FileBytes> => {
29
+ const { config, execute } = context
30
+ const response = await execute("get_file", { file_id: fileId })
31
+ const file_path = response.file_path
32
+
33
+ if (!file_path || file_path.length === 0) {
34
+ throw new TgBotClientError({
35
+ cause: {
36
+ _tag: "UnableToGetFile",
37
+ cause: "File path not defined"
38
+ }
39
+ })
40
+ }
41
+
42
+ const file_name = file_path.replaceAll("/", "-")
43
+ const baseUrl = getBaseUrl(config)
44
+ const botToken = config.botToken
45
+ const url = `${baseUrl}/file/bot${botToken}/${file_path}`
46
+
47
+ let content: ArrayBuffer
48
+ try {
49
+ content = await fetch(url).then((_) => _.arrayBuffer())
50
+ } catch (cause) {
51
+ throw new TgBotClientError({
52
+ cause: { _tag: "UnableToGetFile", cause }
53
+ })
54
+ }
55
+
56
+ const base64String = () => Buffer.from(content).toString("base64")
57
+
58
+ return {
59
+ content,
60
+ file_name,
61
+ base64String
62
+ }
63
+ }
64
+
65
+ export const getFile = async (
66
+ input: GetFile,
67
+ context: FileContext
68
+ ): Promise<File> => {
69
+ const { content, file_name } = await getFileBytes(input.fileId, context)
70
+ return new File([content], file_name, {
71
+ ...(input.type ? { type: input.type } : {})
72
+ })
73
+ }
package/src/client.ts ADDED
@@ -0,0 +1,34 @@
1
+ import type { Api } from "@effect-ak/tg-bot-api"
2
+ import { executeTgBotMethod } from "./execute"
3
+ import type { TgBotConfig } from "./config"
4
+ import { getFile as getFileImpl, type GetFile } from "./client-file"
5
+
6
+ export interface TgBotClient {
7
+ readonly execute: <M extends keyof Api>(
8
+ method: M,
9
+ input: Parameters<Api[M]>[0]
10
+ ) => Promise<ReturnType<Api[M]>>
11
+ readonly getFile: (input: GetFile) => Promise<File>
12
+ }
13
+
14
+ export interface MakeTgClient {
15
+ bot_token: string
16
+ base_url?: string
17
+ }
18
+
19
+ export function makeTgBotClient(config: MakeTgClient): TgBotClient {
20
+ const tgConfig: TgBotConfig = {
21
+ botToken: config.bot_token,
22
+ ...(config.base_url ? { baseUrl: config.base_url } : {})
23
+ }
24
+
25
+ const execute = <M extends keyof Api>(
26
+ method: M,
27
+ input: Parameters<Api[M]>[0]
28
+ ) => executeTgBotMethod({ config: tgConfig, method, input })
29
+
30
+ return {
31
+ execute,
32
+ getFile: (input: GetFile) => getFileImpl(input, { config: tgConfig, execute })
33
+ }
34
+ }
package/src/config.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { TG_BOT_API_URL } from "./const"
2
+
3
+ export interface TgBotConfig {
4
+ botToken: string
5
+ baseUrl?: string
6
+ }
7
+
8
+ export const getBaseUrl = (config?: Pick<TgBotConfig, "baseUrl">): string => {
9
+ return config?.baseUrl ?? TG_BOT_API_URL
10
+ }
package/src/const.ts ADDED
@@ -0,0 +1,20 @@
1
+ export const TG_BOT_API_URL = "https://api.telegram.org"
2
+
3
+ export const MESSAGE_EFFECTS = {
4
+ "🔥": "5104841245755180586",
5
+ "👍": "5107584321108051014",
6
+ "👎": "5104858069142078462",
7
+ "❤️": "5159385139981059251",
8
+ "🎉": "5046509860389126442",
9
+ "💩": "5046589136895476101"
10
+ } as const
11
+
12
+ export type MessageEffect = keyof typeof MESSAGE_EFFECTS
13
+
14
+ export const messageEffectIdCodes = Object.keys(
15
+ MESSAGE_EFFECTS
16
+ ) as MessageEffect[]
17
+
18
+ export const isMessageEffect = (input: unknown): input is MessageEffect => {
19
+ return typeof input === "string" && input in MESSAGE_EFFECTS
20
+ }
package/src/errors.ts ADDED
@@ -0,0 +1,18 @@
1
+ type ErrorReason =
2
+ | { _tag: "NotOkResponse"; errorCode?: number; details?: string }
3
+ | { _tag: "UnexpectedResponse"; response: unknown }
4
+ | { _tag: "ClientInternalError"; cause: unknown }
5
+ | { _tag: "UnableToGetFile"; cause: unknown }
6
+ | { _tag: "BotHandlerError"; cause: unknown }
7
+ | { _tag: "NotJsonResponse"; response: unknown }
8
+
9
+ export class TgBotClientError extends Error {
10
+ readonly _tag = "TgBotClientError"
11
+ readonly cause: ErrorReason
12
+
13
+ constructor(options: { cause: ErrorReason }) {
14
+ super(`TgBotClientError: ${options.cause._tag}`)
15
+ this.cause = options.cause
16
+ this.name = "TgBotClientError"
17
+ }
18
+ }
package/src/execute.ts ADDED
@@ -0,0 +1,81 @@
1
+ import type { Api } from "@effect-ak/tg-bot-api"
2
+
3
+ import { TgBotClientError } from "./errors"
4
+ import { isFileContent, isTgBotApiResponse } from "./guards"
5
+ import type { TgBotConfig } from "./config"
6
+ import { getBaseUrl } from "./config"
7
+ import { snakeToCamel } from "./utils"
8
+
9
+ export async function executeTgBotMethod<M extends keyof Api>(params: {
10
+ config: TgBotConfig
11
+ method: M
12
+ input: Parameters<Api[M]>[0]
13
+ }): Promise<ReturnType<Api[M]>> {
14
+ const { config, method, input } = params
15
+ const baseUrl = getBaseUrl(config)
16
+ const botToken = config.botToken
17
+
18
+ let httpResponse: Response
19
+ try {
20
+ httpResponse = await fetch(
21
+ `${baseUrl}/bot${botToken}/${snakeToCamel(method)}`,
22
+ {
23
+ body: makePayload(input) ?? null,
24
+ method: "POST"
25
+ }
26
+ )
27
+ } catch (cause) {
28
+ throw new TgBotClientError({
29
+ cause: { _tag: "ClientInternalError", cause }
30
+ })
31
+ }
32
+
33
+ let response: unknown
34
+ try {
35
+ response = await httpResponse.json()
36
+ } catch {
37
+ throw new TgBotClientError({
38
+ cause: { _tag: "NotJsonResponse", response: httpResponse }
39
+ })
40
+ }
41
+
42
+ if (!isTgBotApiResponse(response)) {
43
+ throw new TgBotClientError({
44
+ cause: { _tag: "UnexpectedResponse", response }
45
+ })
46
+ }
47
+
48
+ if (!httpResponse.ok) {
49
+ throw new TgBotClientError({
50
+ cause: {
51
+ _tag: "NotOkResponse",
52
+ ...(response.error_code ? { errorCode: response.error_code } : {}),
53
+ ...(response.description ? { details: response.description } : {})
54
+ }
55
+ })
56
+ }
57
+
58
+ return response.result as ReturnType<Api[M]>
59
+ }
60
+
61
+ export const makePayload = (body: object): FormData | undefined => {
62
+ const entries = Object.entries(body)
63
+
64
+ if (entries.length == 0) return undefined
65
+
66
+ const result = new FormData()
67
+
68
+ for (const [key, value] of entries) {
69
+ if (!value) continue
70
+
71
+ if (typeof value != "object") {
72
+ result.append(key, `${value}`)
73
+ } else if (isFileContent(value)) {
74
+ result.append(key, new Blob([value.file_content]), value.file_name)
75
+ } else {
76
+ result.append(key, JSON.stringify(value))
77
+ }
78
+ }
79
+
80
+ return result
81
+ }