@effect-ak/tg-bot-client 0.5.3 → 0.6.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/bot.d.ts +110 -0
- package/dist/bot.js +1 -0
- package/dist/bot.mjs +1 -0
- package/dist/config-CmVKgghE.d.ts +3067 -0
- package/dist/index.d.ts +38 -3243
- package/dist/index.js +1 -22
- package/dist/index.mjs +1 -22
- package/dist/webapp.d.ts +391 -0
- package/dist/webapp.js +1 -0
- package/dist/webapp.mjs +0 -0
- package/package.json +26 -8
- package/readme.md +36 -28
package/dist/bot.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { U as Update, A as Api, a as TgBotApiToken, T as TgBotClientError } from './config-CmVKgghE.js';
|
|
2
|
+
import * as effect_Cause from 'effect/Cause';
|
|
3
|
+
import * as effect_Types from 'effect/Types';
|
|
4
|
+
import * as Micro from 'effect/Micro';
|
|
5
|
+
import * as Data from 'effect/Data';
|
|
6
|
+
import * as Context from 'effect/Context';
|
|
7
|
+
|
|
8
|
+
type PollSettings = {
|
|
9
|
+
log_level: "info" | "debug";
|
|
10
|
+
on_error: "stop" | "continue";
|
|
11
|
+
batch_size: number;
|
|
12
|
+
poll_timeout: number;
|
|
13
|
+
max_empty_responses: number | undefined;
|
|
14
|
+
};
|
|
15
|
+
declare class BotPollSettings extends Data.Class<PollSettings> {
|
|
16
|
+
static make(input: Partial<PollSettings>): BotPollSettings;
|
|
17
|
+
}
|
|
18
|
+
declare const BotPollSettingsTag_base: Context.ReferenceClass<BotPollSettings, "BotSettings", BotPollSettings>;
|
|
19
|
+
declare class BotPollSettingsTag extends BotPollSettingsTag_base {
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface RunBotInput {
|
|
23
|
+
bot_token: string;
|
|
24
|
+
mode: BotMode;
|
|
25
|
+
poll?: Partial<PollSettings>;
|
|
26
|
+
}
|
|
27
|
+
type ExtractedUpdate<K extends AvailableUpdateTypes> = {
|
|
28
|
+
type: K;
|
|
29
|
+
} & Update[K];
|
|
30
|
+
type AvailableUpdateTypes = Exclude<keyof Update, 'update_id'>;
|
|
31
|
+
type BotResult = {
|
|
32
|
+
[K in keyof Api]: K extends `send_${infer R}` ? {
|
|
33
|
+
type: R;
|
|
34
|
+
} & Omit<Parameters<Api[K]>[0], 'chat_id'> : never;
|
|
35
|
+
}[keyof Api];
|
|
36
|
+
declare const BotResponse_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => Readonly<A> & {
|
|
37
|
+
readonly _tag: "BotResponse";
|
|
38
|
+
};
|
|
39
|
+
declare class BotResponse extends BotResponse_base<{
|
|
40
|
+
response?: BotResult;
|
|
41
|
+
}> {
|
|
42
|
+
static make(result: BotResult): BotResponse;
|
|
43
|
+
static readonly ignore: BotResponse;
|
|
44
|
+
}
|
|
45
|
+
type HandleUpdateFunction<U> = (update: U) => BotResponse | PromiseLike<BotResponse>;
|
|
46
|
+
type BotUpdatesHandlers = {
|
|
47
|
+
readonly [K in AvailableUpdateTypes as `on_${K}`]?: HandleUpdateFunction<NonNullable<Update[K]>>;
|
|
48
|
+
};
|
|
49
|
+
type HandleBatchUpdateFunction = {
|
|
50
|
+
readonly on_batch: (update: Update[]) => boolean | PromiseLike<boolean>;
|
|
51
|
+
};
|
|
52
|
+
interface BotSingleMode extends BotUpdatesHandlers {
|
|
53
|
+
type: "single";
|
|
54
|
+
}
|
|
55
|
+
interface BotBatchMode extends HandleBatchUpdateFunction {
|
|
56
|
+
type: "batch";
|
|
57
|
+
}
|
|
58
|
+
type BotMode = BotSingleMode | BotBatchMode;
|
|
59
|
+
declare const BotUpdateHandlersTag_base: Context.TagClass<BotUpdateHandlersTag, "BotUpdateHandlers", BotMode>;
|
|
60
|
+
declare class BotUpdateHandlersTag extends BotUpdateHandlersTag_base {
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
declare const extractUpdate: <U extends AvailableUpdateTypes>(input: Update) => ExtractedUpdate<U> | undefined;
|
|
64
|
+
declare class BatchUpdateResult extends Data.Class<{
|
|
65
|
+
hasErrors: boolean;
|
|
66
|
+
updates: Update[];
|
|
67
|
+
}> {
|
|
68
|
+
}
|
|
69
|
+
declare const handleUpdates: (updates: Update[]) => Micro.Micro<BatchUpdateResult, never, TgBotApiToken | BotUpdateHandlersTag>;
|
|
70
|
+
declare const handleEntireBatch: (updates: Update[], handlers: HandleBatchUpdateFunction) => Micro.Micro<BatchUpdateResult, never, never>;
|
|
71
|
+
declare const HandleUpdateError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
|
|
72
|
+
readonly _tag: "HandleUpdateError";
|
|
73
|
+
} & Readonly<A>;
|
|
74
|
+
declare class HandleUpdateError extends HandleUpdateError_base<{
|
|
75
|
+
name: "UnknownUpdate" | "HandlerNotDefined" | "BotHandlerError";
|
|
76
|
+
update: Update;
|
|
77
|
+
cause?: unknown;
|
|
78
|
+
}> {
|
|
79
|
+
}
|
|
80
|
+
declare const handleOneByOne: (updates: Update[], handlers: BotUpdatesHandlers, pollSettings: PollSettings) => Micro.Micro<BatchUpdateResult, never, TgBotApiToken>;
|
|
81
|
+
declare const handleOneUpdate: (updateObject: Update, handlers: BotUpdatesHandlers) => Micro.Micro<HandleUpdateError | undefined, TgBotClientError | HandleUpdateError, TgBotApiToken>;
|
|
82
|
+
|
|
83
|
+
declare const FetchUpdatesError_base: new <A extends Record<string, any> = {}>(args: effect_Types.Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => effect_Cause.YieldableError & {
|
|
84
|
+
readonly _tag: "FetchUpdatesError";
|
|
85
|
+
} & Readonly<A>;
|
|
86
|
+
declare class FetchUpdatesError extends FetchUpdatesError_base<{
|
|
87
|
+
name: "TooManyEmptyResponses" | "NoUpdatesToCommit";
|
|
88
|
+
}> {
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
type BotInstance = Micro.Micro.Success<ReturnType<typeof launchBot>>;
|
|
92
|
+
declare const launchBot: (input: RunBotInput) => Micro.Micro<{
|
|
93
|
+
readonly reload: (mode: BotMode) => Promise<void>;
|
|
94
|
+
readonly fiber: () => Micro.MicroFiber<BatchUpdateResult, TgBotClientError | FetchUpdatesError> | undefined;
|
|
95
|
+
}, never, never>;
|
|
96
|
+
|
|
97
|
+
declare const BotRunService_base: Context.ReferenceClass<BotRunService, "BotRunService", {
|
|
98
|
+
readonly runBotInBackground: Micro.Micro<void, never, TgBotApiToken | BotUpdateHandlersTag>;
|
|
99
|
+
readonly getFiber: () => Micro.MicroFiber<BatchUpdateResult, TgBotClientError | FetchUpdatesError> | undefined;
|
|
100
|
+
}>;
|
|
101
|
+
declare class BotRunService extends BotRunService_base {
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
declare const runTgChatBot: (input: RunBotInput) => Promise<{
|
|
105
|
+
readonly reload: (mode: BotMode) => Promise<void>;
|
|
106
|
+
readonly fiber: () => Micro.MicroFiber<BatchUpdateResult, TgBotClientError | FetchUpdatesError> | undefined;
|
|
107
|
+
}>;
|
|
108
|
+
declare const defineBot: (input: BotUpdatesHandlers) => BotUpdatesHandlers;
|
|
109
|
+
|
|
110
|
+
export { type AvailableUpdateTypes, BatchUpdateResult, type BotBatchMode, type BotInstance, type BotMode, BotPollSettings, BotPollSettingsTag, BotResponse, BotRunService, type BotSingleMode, BotUpdateHandlersTag, type BotUpdatesHandlers, type ExtractedUpdate, type HandleBatchUpdateFunction, HandleUpdateError, type HandleUpdateFunction, type PollSettings, type RunBotInput, defineBot, extractUpdate, handleEntireBatch, handleOneByOne, handleOneUpdate, handleUpdates, launchBot, runTgChatBot };
|
package/dist/bot.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var te=Object.create;var T=Object.defineProperty;var oe=Object.getOwnPropertyDescriptor;var ne=Object.getOwnPropertyNames;var re=Object.getPrototypeOf,se=Object.prototype.hasOwnProperty;var ie=(e,o)=>{for(var t in o)T(e,t,{get:o[t],enumerable:!0})},P=(e,o,t,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of ne(o))!se.call(e,n)&&n!==t&&T(e,n,{get:()=>o[n],enumerable:!(r=oe(o,n))||r.enumerable});return e};var p=(e,o,t)=>(t=e!=null?te(re(e)):{},P(o||!e||!e.__esModule?T(t,"default",{value:e,enumerable:!0}):t,e)),ae=e=>P(T({},"__esModule",{value:!0}),e);var fe={};ie(fe,{BatchUpdateResult:()=>B,BotPollSettings:()=>h,BotPollSettingsTag:()=>m,BotResponse:()=>_,BotRunService:()=>b,BotUpdateHandlersTag:()=>g,HandleUpdateError:()=>x,defineBot:()=>me,extractUpdate:()=>z,handleEntireBatch:()=>V,handleOneByOne:()=>W,handleOneUpdate:()=>J,handleUpdates:()=>A,launchBot:()=>F,runTgChatBot:()=>le});module.exports=ae(fe);var s=p(require("effect/Micro")),R=p(require("effect/Data")),C=p(require("effect/Function"));var N=p(require("effect/String")),u=p(require("effect/Micro"));var I=p(require("effect/Data")),y=class e extends I.TaggedError("TgBotClientError"){static missingSuccess=new e({cause:{type:"ClientInternalError",cause:"Expected 'success' to be defined"}})};var H=e=>typeof e=="object"&&e!=null&&"file_content"in e&&e.file_content instanceof Uint8Array&&"file_name"in e&&typeof e.file_name=="string",D=e=>typeof e=="object"&&e!=null&&"ok"in e&&typeof e.ok=="boolean";var $=e=>{let o=Object.entries(e);if(o.length==0)return;let t=new FormData;for(let[r,n]of o)n&&(typeof n!="object"?t.append(r,`${n}`):H(n)?t.append(r,new Blob([n.file_content]),n.file_name):t.append(r,JSON.stringify(n)));return t};var k=p(require("effect/Context"));var K="https://api.telegram.org",w={"\u{1F525}":"5104841245755180586","\u{1F44D}":"5107584321108051014","\u{1F44E}":"5104858069142078462","\u2764\uFE0F":"5159385139981059251","\u{1F389}":"5046509860389126442","\u{1F4A9}":"5046589136895476101"},he=Object.keys(w);var E=class extends k.Reference()("TgBotApiBaseUrl",{defaultValue:()=>K}){},M=class extends k.Tag("TgBotApiToken")(){};var U=(e,o)=>u.gen(function*(){let t=yield*u.service(M),r=yield*u.service(E),n=yield*u.tryPromise({try:()=>fetch(`${r}/bot${t}/${N.snakeToCamel(e)}`,{body:$(o)??null,method:"POST"}),catch:l=>new y({cause:{type:"ClientInternalError",cause:l}})}),i=yield*u.tryPromise({try:()=>n.json(),catch:()=>new y({cause:{type:"UnexpectedResponse",response:n}})});return D(i)?n.ok?i.result:yield*u.fail(new y({cause:{type:"NotOkResponse",...i.error_code?{errorCode:i.error_code}:void 0,...i.description?{details:i.description}:void 0}})):yield*u.fail(new y({cause:{type:"UnexpectedResponse",response:i}}))});var O=p(require("effect/Context")),j=p(require("effect/Data")),_=class e extends j.TaggedClass("BotResponse"){static make(o){return new e({response:o})}static ignore=new e({})},g=class extends O.Tag("BotUpdateHandlers")(){};var G=p(require("effect/Context")),L=p(require("effect/Data")),h=class e extends L.Class{static make(o){let t=o.batch_size??10,r=o.poll_timeout??10,n=o.max_empty_responses,i=o.log_level??"info",l=o.on_error;(t<10||t>100)&&(console.warn("Wrong batch_size, must be in [10..100], using 10 instead"),t=10),(r<2||r>120)&&(console.warn("Wrong poll_timeout, must be in [2..120], using 20 instead"),r=20),n&&n<2&&(console.warn("Wrong max_empty_responses, must be in [2..infinity], using infinity"),n=void 0),i||(i="info"),l||(l="stop");let c=new e({batch_size:t,poll_timeout:r,max_empty_responses:n,log_level:i,on_error:l});return console.log("bot poll settings",c),c}},m=class extends G.Reference()("BotSettings",{defaultValue(){return h.make({})}}){};var z=e=>{for(let[o,t]of Object.entries(e))if(o!="update_id")return{type:o,...t}},B=class extends R.Class{},A=e=>s.gen(function*(){let o=yield*s.service(m),t=yield*s.service(g);return t.type=="single"?yield*W(e,t,o):yield*V(e,t)}),V=(e,o)=>s.try({try:()=>o.on_batch(e),catch:C.identity}).pipe(s.andThen(t=>t instanceof Promise?s.tryPromise({try:()=>t,catch:C.identity}):s.succeed(t)),s.andThen(t=>new B({hasErrors:!t,updates:e})),s.catchAll(t=>(console.warn("handle batch error",{errorMessage:t instanceof Error?t.message:void 0,updates:e.map(r=>Object.keys(r).at(1)),error:t}),s.succeed(new B({hasErrors:!0,updates:e}))))),x=class extends R.TaggedError("HandleUpdateError"){},W=(e,o,t)=>s.forEach(e,r=>J(r,o).pipe(s.catchAll(n=>(console.log("update handle error",{updateId:r.update_id,updateKey:Object.keys(r).at(1),name:n._tag,...n.cause instanceof Error?{error:n.cause.message}:void 0}),s.succeed(n)))),{concurrency:10}).pipe(s.andThen(r=>(t.log_level=="debug"&&console.debug("handle batch result",r),new B({hasErrors:!r.every(n=>n==null),updates:e})))),J=(e,o)=>s.gen(function*(){let t=z(e);if(!t)return yield*s.fail(new x({name:"UnknownUpdate",update:e}));let r=o[`on_${t.type}`];if(!r)return yield*s.fail(new x({name:"HandlerNotDefined",update:e}));t.type=="message"&&"text"in t&&console.info("Got a new text message",{chatId:t.chat.id,chatType:t.chat.type,message:`${t.text.slice(0,5)}...`});let n,i=yield*s.try({try:()=>r(t),catch:c=>new x({name:"BotHandlerError",update:e,cause:c})}).pipe(s.andThen(c=>c instanceof Promise?s.tryPromise({try:()=>c,catch:ee=>new x({name:"BotHandlerError",update:e,cause:ee})}):s.succeed(c)),s.catchAll(c=>(n=c,console.log("error",{updateId:e.update_id,updateKey:Object.keys(e).at(1),name:c._tag,...c.cause instanceof Error?{error:c.cause.message}:void 0}),s.succeed(_.make({type:"message",text:`Some internal error has happend(${c.name}) while handling this message`,message_effect_id:w["\u{1F4A9}"],...e.message?.message_id?{reply_parameters:{message_id:e.message?.message_id}}:void 0}))))),l=yield*s.service(m);if(!i&&l.log_level=="debug"){console.log(`Bot response is undefined for update with ID #${e.update_id}.`);return}if("chat"in t&&i.response){let c=yield*U(`send_${i.response.type}`,{...i.response,chat_id:t.chat.id});l.log_level=="debug"&&console.debug("bot response",c)}return n});var f=p(require("effect/Micro"));var X=p(require("effect/Context")),a=p(require("effect/Micro"));var q=p(require("effect/Context")),Q=p(require("effect/Data")),d=p(require("effect/Micro"));var v=class extends q.Reference()("BotFetchUpdatesService",{defaultValue:()=>{let o={lastUpdateId:void 0,emptyResponses:0},t=pe(o).pipe(d.tap(n=>{let i=n.map(l=>l.update_id).sort().at(-1);console.log("updating last update id",i),o.lastUpdateId=i?i+1:void 0,console.log(o)})),r=ce(o);return{state:o,fetchUpdates:t,commit:r}}}){},S=class extends Q.TaggedError("FetchUpdatesError"){},pe=e=>d.gen(function*(){let o=yield*d.service(m);if(o.max_empty_responses&&e.emptyResponses==o.max_empty_responses)return yield*d.fail(new S({name:"TooManyEmptyResponses"}));let t=e.lastUpdateId;o.log_level=="debug"&&console.debug("getting updates",e);let r=yield*U("get_updates",{timeout:o.poll_timeout,...t?{offset:t}:void 0}).pipe(d.andThen(n=>n.sort(i=>i.update_id)));return r.length?(console.debug(`got a batch of updates (${r.length})`),e.emptyResponses=0,r):(e.emptyResponses+=1,[])}),ce=e=>d.gen(function*(){return console.log("commit",{pollState:e}),e.lastUpdateId?yield*U("get_updates",{offset:e.lastUpdateId,limit:0}).pipe(d.andThen(d.andThen(d.service(m),o=>{o.log_level=="debug"&&console.debug("committed offset",e)}))):yield*d.fail(new S({name:"NoUpdatesToCommit"}))});var b=class extends X.Reference()("BotRunService",{defaultValue:()=>{console.log("Initiating BotRunService");let o={fiber:void 0};return{runBotInBackground:de(o),getFiber:()=>o.fiber}}}){},de=e=>a.gen(function*(){console.log("running telegram chat bot");let o=yield*a.service(v),t=yield*a.service(m),r=i=>t.on_error=="continue"?!0:!i,n=a.delay(1e3)(o.fetchUpdates.pipe(a.andThen(A),a.tap(i=>i.updates.length>0&&r(i.hasErrors)?o.commit:a.void))).pipe(a.repeat({while:i=>r(i.hasErrors)}),a.forkDaemon,a.tap(i=>i.addObserver(l=>{console.log("bot's fiber has been closed",l)})));e.fiber&&(console.log("killing previous bot's fiber"),yield*a.fiberInterrupt(e.fiber)),e.fiber=yield*n,console.log("Fetching bot updates via long polling...")});var Y=require("effect"),F=e=>f.gen(function*(){let o=yield*f.service(b),t=Y.Context.make(M,e.bot_token);return yield*o.runBotInBackground.pipe(f.provideService(g,e.mode),f.provideService(m,h.make(e.poll??{})),f.provideContext(t)),{reload:n=>o.runBotInBackground.pipe(f.provideService(g,n),f.provideContext(t),f.runPromise),fiber:o.getFiber}});var Z=p(require("effect/Micro"));var le=e=>F(e).pipe(Z.runPromise),me=e=>(Object.keys(e).length==0&&console.warn("No handlers are defined for bot"),e);0&&(module.exports={BatchUpdateResult,BotPollSettings,BotPollSettingsTag,BotResponse,BotRunService,BotUpdateHandlersTag,HandleUpdateError,defineBot,extractUpdate,handleEntireBatch,handleOneByOne,handleOneUpdate,handleUpdates,launchBot,runTgChatBot});
|
package/dist/bot.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as s from"effect/Micro";import*as T from"effect/Data";import*as S from"effect/Function";import*as I from"effect/String";import*as f from"effect/Micro";import*as w from"effect/Data";var u=class e extends w.TaggedError("TgBotClientError"){static missingSuccess=new e({cause:{type:"ClientInternalError",cause:"Expected 'success' to be defined"}})};var C=e=>typeof e=="object"&&e!=null&&"file_content"in e&&e.file_content instanceof Uint8Array&&"file_name"in e&&typeof e.file_name=="string",A=e=>typeof e=="object"&&e!=null&&"ok"in e&&typeof e.ok=="boolean";var F=e=>{let o=Object.entries(e);if(o.length==0)return;let t=new FormData;for(let[r,n]of o)n&&(typeof n!="object"?t.append(r,`${n}`):C(n)?t.append(r,new Blob([n.file_content]),n.file_name):t.append(r,JSON.stringify(n)));return t};import*as _ from"effect/Context";var P="https://api.telegram.org",v={"\u{1F525}":"5104841245755180586","\u{1F44D}":"5107584321108051014","\u{1F44E}":"5104858069142078462","\u2764\uFE0F":"5159385139981059251","\u{1F389}":"5046509860389126442","\u{1F4A9}":"5046589136895476101"},se=Object.keys(v);var U=class extends _.Reference()("TgBotApiBaseUrl",{defaultValue:()=>P}){},y=class extends _.Tag("TgBotApiToken")(){};var M=(e,o)=>f.gen(function*(){let t=yield*f.service(y),r=yield*f.service(U),n=yield*f.tryPromise({try:()=>fetch(`${r}/bot${t}/${I.snakeToCamel(e)}`,{body:F(o)??null,method:"POST"}),catch:d=>new u({cause:{type:"ClientInternalError",cause:d}})}),i=yield*f.tryPromise({try:()=>n.json(),catch:()=>new u({cause:{type:"UnexpectedResponse",response:n}})});return A(i)?n.ok?i.result:yield*f.fail(new u({cause:{type:"NotOkResponse",...i.error_code?{errorCode:i.error_code}:void 0,...i.description?{details:i.description}:void 0}})):yield*f.fail(new u({cause:{type:"UnexpectedResponse",response:i}}))});import*as H from"effect/Context";import*as D from"effect/Data";var b=class e extends D.TaggedClass("BotResponse"){static make(o){return new e({response:o})}static ignore=new e({})},g=class extends H.Tag("BotUpdateHandlers")(){};import*as $ from"effect/Context";import*as K from"effect/Data";var h=class e extends K.Class{static make(o){let t=o.batch_size??10,r=o.poll_timeout??10,n=o.max_empty_responses,i=o.log_level??"info",d=o.on_error;(t<10||t>100)&&(console.warn("Wrong batch_size, must be in [10..100], using 10 instead"),t=10),(r<2||r>120)&&(console.warn("Wrong poll_timeout, must be in [2..120], using 20 instead"),r=20),n&&n<2&&(console.warn("Wrong max_empty_responses, must be in [2..infinity], using infinity"),n=void 0),i||(i="info"),d||(d="stop");let p=new e({batch_size:t,poll_timeout:r,max_empty_responses:n,log_level:i,on_error:d});return console.log("bot poll settings",p),p}},m=class extends $.Reference()("BotSettings",{defaultValue(){return h.make({})}}){};var W=e=>{for(let[o,t]of Object.entries(e))if(o!="update_id")return{type:o,...t}},B=class extends T.Class{},N=e=>s.gen(function*(){let o=yield*s.service(m),t=yield*s.service(g);return t.type=="single"?yield*q(e,t,o):yield*J(e,t)}),J=(e,o)=>s.try({try:()=>o.on_batch(e),catch:S.identity}).pipe(s.andThen(t=>t instanceof Promise?s.tryPromise({try:()=>t,catch:S.identity}):s.succeed(t)),s.andThen(t=>new B({hasErrors:!t,updates:e})),s.catchAll(t=>(console.warn("handle batch error",{errorMessage:t instanceof Error?t.message:void 0,updates:e.map(r=>Object.keys(r).at(1)),error:t}),s.succeed(new B({hasErrors:!0,updates:e}))))),x=class extends T.TaggedError("HandleUpdateError"){},q=(e,o,t)=>s.forEach(e,r=>Q(r,o).pipe(s.catchAll(n=>(console.log("update handle error",{updateId:r.update_id,updateKey:Object.keys(r).at(1),name:n._tag,...n.cause instanceof Error?{error:n.cause.message}:void 0}),s.succeed(n)))),{concurrency:10}).pipe(s.andThen(r=>(t.log_level=="debug"&&console.debug("handle batch result",r),new B({hasErrors:!r.every(n=>n==null),updates:e})))),Q=(e,o)=>s.gen(function*(){let t=W(e);if(!t)return yield*s.fail(new x({name:"UnknownUpdate",update:e}));let r=o[`on_${t.type}`];if(!r)return yield*s.fail(new x({name:"HandlerNotDefined",update:e}));t.type=="message"&&"text"in t&&console.info("Got a new text message",{chatId:t.chat.id,chatType:t.chat.type,message:`${t.text.slice(0,5)}...`});let n,i=yield*s.try({try:()=>r(t),catch:p=>new x({name:"BotHandlerError",update:e,cause:p})}).pipe(s.andThen(p=>p instanceof Promise?s.tryPromise({try:()=>p,catch:V=>new x({name:"BotHandlerError",update:e,cause:V})}):s.succeed(p)),s.catchAll(p=>(n=p,console.log("error",{updateId:e.update_id,updateKey:Object.keys(e).at(1),name:p._tag,...p.cause instanceof Error?{error:p.cause.message}:void 0}),s.succeed(b.make({type:"message",text:`Some internal error has happend(${p.name}) while handling this message`,message_effect_id:v["\u{1F4A9}"],...e.message?.message_id?{reply_parameters:{message_id:e.message?.message_id}}:void 0}))))),d=yield*s.service(m);if(!i&&d.log_level=="debug"){console.log(`Bot response is undefined for update with ID #${e.update_id}.`);return}if("chat"in t&&i.response){let p=yield*M(`send_${i.response.type}`,{...i.response,chat_id:t.chat.id});d.log_level=="debug"&&console.debug("bot response",p)}return n});import*as l from"effect/Micro";import*as G from"effect/Context";import*as a from"effect/Micro";import*as O from"effect/Context";import*as j from"effect/Data";import*as c from"effect/Micro";var E=class extends O.Reference()("BotFetchUpdatesService",{defaultValue:()=>{let o={lastUpdateId:void 0,emptyResponses:0},t=X(o).pipe(c.tap(n=>{let i=n.map(d=>d.update_id).sort().at(-1);console.log("updating last update id",i),o.lastUpdateId=i?i+1:void 0,console.log(o)})),r=Y(o);return{state:o,fetchUpdates:t,commit:r}}}){},k=class extends j.TaggedError("FetchUpdatesError"){},X=e=>c.gen(function*(){let o=yield*c.service(m);if(o.max_empty_responses&&e.emptyResponses==o.max_empty_responses)return yield*c.fail(new k({name:"TooManyEmptyResponses"}));let t=e.lastUpdateId;o.log_level=="debug"&&console.debug("getting updates",e);let r=yield*M("get_updates",{timeout:o.poll_timeout,...t?{offset:t}:void 0}).pipe(c.andThen(n=>n.sort(i=>i.update_id)));return r.length?(console.debug(`got a batch of updates (${r.length})`),e.emptyResponses=0,r):(e.emptyResponses+=1,[])}),Y=e=>c.gen(function*(){return console.log("commit",{pollState:e}),e.lastUpdateId?yield*M("get_updates",{offset:e.lastUpdateId,limit:0}).pipe(c.andThen(c.andThen(c.service(m),o=>{o.log_level=="debug"&&console.debug("committed offset",e)}))):yield*c.fail(new k({name:"NoUpdatesToCommit"}))});var R=class extends G.Reference()("BotRunService",{defaultValue:()=>{console.log("Initiating BotRunService");let o={fiber:void 0};return{runBotInBackground:Z(o),getFiber:()=>o.fiber}}}){},Z=e=>a.gen(function*(){console.log("running telegram chat bot");let o=yield*a.service(E),t=yield*a.service(m),r=i=>t.on_error=="continue"?!0:!i,n=a.delay(1e3)(o.fetchUpdates.pipe(a.andThen(N),a.tap(i=>i.updates.length>0&&r(i.hasErrors)?o.commit:a.void))).pipe(a.repeat({while:i=>r(i.hasErrors)}),a.forkDaemon,a.tap(i=>i.addObserver(d=>{console.log("bot's fiber has been closed",d)})));e.fiber&&(console.log("killing previous bot's fiber"),yield*a.fiberInterrupt(e.fiber)),e.fiber=yield*n,console.log("Fetching bot updates via long polling...")});import{Context as ee}from"effect";var L=e=>l.gen(function*(){let o=yield*l.service(R),t=ee.make(y,e.bot_token);return yield*o.runBotInBackground.pipe(l.provideService(g,e.mode),l.provideService(m,h.make(e.poll??{})),l.provideContext(t)),{reload:n=>o.runBotInBackground.pipe(l.provideService(g,n),l.provideContext(t),l.runPromise),fiber:o.getFiber}});import*as z from"effect/Micro";var Ge=e=>L(e).pipe(z.runPromise),Le=e=>(Object.keys(e).length==0&&console.warn("No handlers are defined for bot"),e);export{B as BatchUpdateResult,h as BotPollSettings,m as BotPollSettingsTag,b as BotResponse,R as BotRunService,g as BotUpdateHandlersTag,x as HandleUpdateError,Le as defineBot,W as extractUpdate,J as handleEntireBatch,q as handleOneByOne,Q as handleOneUpdate,N as handleUpdates,L as launchBot,Ge as runTgChatBot};
|