@adstelo/sdk 0.1.0 → 0.1.1
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/README.md +1 -30
- package/dist/index.cjs +4 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -24
- package/dist/index.d.ts +1 -24
- package/dist/index.js +3 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @adstelo/sdk
|
|
2
2
|
|
|
3
|
-
Adstelo JS SDK for Telegram bots. Supports Telegraf
|
|
3
|
+
Adstelo JS SDK for Telegram bots monetization. Supports Telegraf and grammY. To use it, you must obtain keys from adstelo platform. Each bot gets a unique secret key. Dont mix them up!
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -25,16 +25,6 @@ bot.use(
|
|
|
25
25
|
);
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
## Optional Explicit Init
|
|
29
|
-
|
|
30
|
-
```js
|
|
31
|
-
import { adstelo, init } from "@adstelo/sdk";
|
|
32
|
-
|
|
33
|
-
init({ botSecret: "bs-...", apiKey: "sk-..." });
|
|
34
|
-
|
|
35
|
-
bot.use(adstelo.grammy());
|
|
36
|
-
```
|
|
37
|
-
|
|
38
28
|
## Telegraf
|
|
39
29
|
|
|
40
30
|
```js
|
|
@@ -51,26 +41,7 @@ bot.use(
|
|
|
51
41
|
);
|
|
52
42
|
```
|
|
53
43
|
|
|
54
|
-
## Manual Hook (no middleware)
|
|
55
|
-
|
|
56
|
-
```js
|
|
57
|
-
import { init, reportEvent } from "@adstelo/sdk";
|
|
58
|
-
|
|
59
|
-
init({ botSecret: "bs-...", apiKey: "sk-..." });
|
|
60
|
-
|
|
61
|
-
// In your update handler:
|
|
62
|
-
reportEvent({
|
|
63
|
-
chatId: msg.chat.id,
|
|
64
|
-
userId: msg.from.id,
|
|
65
|
-
event: "message",
|
|
66
|
-
isStart: msg.text === "/start"
|
|
67
|
-
});
|
|
68
|
-
```
|
|
69
|
-
|
|
70
44
|
## API
|
|
71
45
|
|
|
72
|
-
- `init({ botSecret, apiKey, cooldownSeconds })`
|
|
73
|
-
- `validateInitCredentials()`
|
|
74
|
-
- `reportEvent({ chatId, userId, event, isStart })`
|
|
75
46
|
- `adstelo.telegraf(options?)`
|
|
76
47
|
- `adstelo.grammy(options?)`
|
package/dist/index.cjs
CHANGED
|
@@ -31,10 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
_internal: () => _internal,
|
|
34
|
-
adstelo: () => adstelo
|
|
35
|
-
init: () => init,
|
|
36
|
-
reportEvent: () => reportEvent,
|
|
37
|
-
validateInitCredentials: () => validateInitCredentials
|
|
34
|
+
adstelo: () => adstelo
|
|
38
35
|
});
|
|
39
36
|
module.exports = __toCommonJS(index_exports);
|
|
40
37
|
var import_node_crypto = __toESM(require("crypto"), 1);
|
|
@@ -92,7 +89,7 @@ function init(options) {
|
|
|
92
89
|
function ensureInit(options) {
|
|
93
90
|
if (initialized) return;
|
|
94
91
|
if (!options?.botSecret || !options?.apiKey) {
|
|
95
|
-
throw new Error("Missing botSecret or apiKey. Pass them to adstelo.grammy/adstelo.telegraf
|
|
92
|
+
throw new Error("Missing botSecret or apiKey. Pass them to adstelo.grammy/adstelo.telegraf.");
|
|
96
93
|
}
|
|
97
94
|
init(options);
|
|
98
95
|
if (!validationPromise) {
|
|
@@ -137,7 +134,7 @@ async function validateInitCredentials() {
|
|
|
137
134
|
}
|
|
138
135
|
async function reportEvent(input) {
|
|
139
136
|
if (!config.botSecret || !config.apiKey) {
|
|
140
|
-
throw new Error("SDK not initialized.
|
|
137
|
+
throw new Error("SDK not initialized. Pass credentials via adstelo.grammy/adstelo.telegraf.");
|
|
141
138
|
}
|
|
142
139
|
if (!input?.userId || !input?.event) {
|
|
143
140
|
return { ok: false, detail: "Missing userId or event" };
|
|
@@ -206,9 +203,6 @@ function adsteloGrammyMiddleware(options) {
|
|
|
206
203
|
};
|
|
207
204
|
}
|
|
208
205
|
var adstelo = {
|
|
209
|
-
init,
|
|
210
|
-
reportEvent,
|
|
211
|
-
validateInitCredentials,
|
|
212
206
|
telegraf: adsteloTelegrafMiddleware,
|
|
213
207
|
grammy: adsteloGrammyMiddleware
|
|
214
208
|
};
|
|
@@ -220,9 +214,6 @@ var _internal = {
|
|
|
220
214
|
// Annotate the CommonJS export names for ESM import in node:
|
|
221
215
|
0 && (module.exports = {
|
|
222
216
|
_internal,
|
|
223
|
-
adstelo
|
|
224
|
-
init,
|
|
225
|
-
reportEvent,
|
|
226
|
-
validateInitCredentials
|
|
217
|
+
adstelo
|
|
227
218
|
});
|
|
228
219
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import crypto from \"node:crypto\";\n\nexport type InitOptions = {\n botSecret: string;\n apiKey: string;\n cooldownSeconds?: number;\n baseUrl?: string;\n};\n\nexport type ReportEventInput = {\n chatId: number | string;\n userId: number | string;\n event: string;\n isStart?: boolean;\n};\n\ntype Config = {\n apiKey: string | null;\n botSecret: string | null;\n endpoint: string;\n validateEndpoint: string;\n cooldownSeconds: number;\n};\n\nconst DEFAULT_BASE_URL = \"https://sdk.adstelo.com\";\n\nconst config: Config = {\n apiKey: null,\n botSecret: null,\n endpoint: `${DEFAULT_BASE_URL}/event`,\n validateEndpoint: `${DEFAULT_BASE_URL}/event/validate`,\n cooldownSeconds: 2\n};\n\nlet initialized = false;\nlet validationPromise: Promise<void> | null = null;\nconst cooldownMap = new Map<string, number>();\n\nfunction buildHeaders(payloadBytes: string) {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"ngrok-skip-browser-warning\": \"true\"\n };\n\n if (config.apiKey) {\n headers[\"X-Api-Key\"] = config.apiKey;\n const signature = crypto\n .createHmac(\"sha256\", config.apiKey)\n .update(payloadBytes)\n .digest(\"hex\");\n headers[\"X-Signature\"] = signature;\n }\n\n return headers;\n}\n\nfunction nowSeconds() {\n return Math.floor(Date.now() / 1000);\n}\n\nfunction cooldownKey(userId: string | number, event: string) {\n return `${userId}:${event}`;\n}\n\nfunction allowEvent(userId: string | number, event: string) {\n const key = cooldownKey(userId, event);\n const current = nowSeconds();\n const last = cooldownMap.get(key) ?? 0;\n if (current - last < config.cooldownSeconds) {\n return false;\n }\n cooldownMap.set(key, current);\n return true;\n}\n\nexport function init(options: InitOptions) {\n if (!options || !options.botSecret || !options.apiKey) {\n throw new Error(\"botSecret and apiKey are required\");\n }\n\n config.botSecret = options.botSecret;\n config.apiKey = options.apiKey;\n config.cooldownSeconds = options.cooldownSeconds ?? 2;\n\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n config.endpoint = `${baseUrl.replace(/\\/$/, \"\")}/event`;\n config.validateEndpoint = `${baseUrl.replace(/\\/$/, \"\")}/event/validate`;\n initialized = true;\n}\n\nfunction ensureInit(options?: InitOptions) {\n if (initialized) return;\n if (!options?.botSecret || !options?.apiKey) {\n throw new Error(\"Missing botSecret or apiKey. Pass them to adstelo.grammy/adstelo.telegraf or call init().\");\n }\n init(options);\n if (!validationPromise) {\n validationPromise = validateInitCredentials()\n .then(({ ok, detail }) => {\n if (!ok) {\n console.error(\"[adstelo] init validation failed:\", detail);\n process.exit(1);\n }\n console.log(\"[adstelo] init validation ok\");\n })\n .catch((err) => {\n console.error(\"[adstelo] init validation failed:\", err?.message || err);\n process.exit(1);\n });\n }\n}\n\nexport async function validateInitCredentials() {\n if (!config.botSecret) {\n return { ok: false, detail: \"Missing botSecret\" };\n }\n if (!config.apiKey) {\n return { ok: false, detail: \"Missing apiKey\" };\n }\n\n const payload = { secret: config.botSecret };\n const payloadBytes = JSON.stringify(payload);\n const res = await fetch(config.validateEndpoint, {\n method: \"POST\",\n headers: buildHeaders(payloadBytes),\n body: payloadBytes\n });\n\n if (res.ok) {\n return { ok: true, detail: \"ok\" };\n }\n\n let detail = `HTTP ${res.status}`;\n try {\n const data = await res.json();\n if (data && typeof data.detail === \"string\") {\n detail = data.detail;\n }\n } catch {\n // ignore\n }\n return { ok: false, detail };\n}\n\nexport async function reportEvent(input: ReportEventInput) {\n if (!config.botSecret || !config.apiKey) {\n throw new Error(\"SDK not initialized. Call init() first.\");\n }\n if (!input?.userId || !input?.event) {\n return { ok: false, detail: \"Missing userId or event\" };\n }\n\n if (!allowEvent(input.userId, input.event)) {\n return { ok: true, detail: \"cooldown\" };\n }\n\n const payload = {\n chat_id: input.chatId,\n user_id: input.userId,\n event: input.event,\n ts: Date.now() / 1000,\n is_start: Boolean(input.isStart),\n secret: config.botSecret\n };\n\n const payloadBytes = JSON.stringify(payload);\n const res = await fetch(config.endpoint, {\n method: \"POST\",\n headers: buildHeaders(payloadBytes),\n body: payloadBytes\n });\n\n return { ok: res.ok, status: res.status };\n}\n\nfunction inferEventFromMessage(message: any) {\n if (!message) return \"message\";\n if (message.photo?.length) return \"photo\";\n if (message.video) return \"video\";\n if (message.sticker) return \"sticker\";\n if (message.animation) return \"media\";\n return \"message\";\n}\n\nfunction adsteloTelegrafMiddleware(options?: InitOptions) {\n ensureInit(options);\n return async (ctx: any, next: () => Promise<void>) => {\n try {\n const event = ctx?.callbackQuery\n ? \"button\"\n : ctx?.inlineQuery\n ? \"inline_query\"\n : inferEventFromMessage(ctx?.message);\n const chatId = ctx?.chat?.id ?? ctx?.message?.chat?.id;\n const userId = ctx?.from?.id;\n const isStart = typeof ctx?.message?.text === \"string\" && ctx.message.text.startsWith(\"/start\");\n\n if (chatId && userId) {\n await reportEvent({ chatId, userId, event, isStart });\n }\n } catch {\n // swallow\n }\n\n if (next) {\n await next();\n }\n };\n}\n\nfunction adsteloGrammyMiddleware(options?: InitOptions) {\n ensureInit(options);\n return async (ctx: any, next: () => Promise<void>) => {\n try {\n const event = ctx?.callbackQuery\n ? \"button\"\n : ctx?.inlineQuery\n ? \"inline_query\"\n : inferEventFromMessage(ctx?.message);\n const chatId = ctx?.chat?.id ?? ctx?.message?.chat?.id;\n const userId = ctx?.from?.id;\n const isStart = typeof ctx?.message?.text === \"string\" && ctx.message.text.startsWith(\"/start\");\n\n if (chatId && userId) {\n await reportEvent({ chatId, userId, event, isStart });\n }\n } catch {\n // swallow\n }\n\n if (next) {\n await next();\n }\n };\n}\n\nexport const adstelo = {\n init,\n reportEvent,\n validateInitCredentials,\n telegraf: adsteloTelegrafMiddleware,\n grammy: adsteloGrammyMiddleware\n};\n\nexport const _internal = {\n buildHeaders,\n allowEvent,\n inferEventFromMessage\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAmB;AAwBnB,IAAM,mBAAmB;AAEzB,IAAM,SAAiB;AAAA,EACrB,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU,GAAG,gBAAgB;AAAA,EAC7B,kBAAkB,GAAG,gBAAgB;AAAA,EACrC,iBAAiB;AACnB;AAEA,IAAI,cAAc;AAClB,IAAI,oBAA0C;AAC9C,IAAM,cAAc,oBAAI,IAAoB;AAE5C,SAAS,aAAa,cAAsB;AAC1C,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,8BAA8B;AAAA,EAChC;AAEA,MAAI,OAAO,QAAQ;AACjB,YAAQ,WAAW,IAAI,OAAO;AAC9B,UAAM,YAAY,mBAAAA,QACf,WAAW,UAAU,OAAO,MAAM,EAClC,OAAO,YAAY,EACnB,OAAO,KAAK;AACf,YAAQ,aAAa,IAAI;AAAA,EAC3B;AAEA,SAAO;AACT;AAEA,SAAS,aAAa;AACpB,SAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACrC;AAEA,SAAS,YAAY,QAAyB,OAAe;AAC3D,SAAO,GAAG,MAAM,IAAI,KAAK;AAC3B;AAEA,SAAS,WAAW,QAAyB,OAAe;AAC1D,QAAM,MAAM,YAAY,QAAQ,KAAK;AACrC,QAAM,UAAU,WAAW;AAC3B,QAAM,OAAO,YAAY,IAAI,GAAG,KAAK;AACrC,MAAI,UAAU,OAAO,OAAO,iBAAiB;AAC3C,WAAO;AAAA,EACT;AACA,cAAY,IAAI,KAAK,OAAO;AAC5B,SAAO;AACT;AAEO,SAAS,KAAK,SAAsB;AACzC,MAAI,CAAC,WAAW,CAAC,QAAQ,aAAa,CAAC,QAAQ,QAAQ;AACrD,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,SAAO,YAAY,QAAQ;AAC3B,SAAO,SAAS,QAAQ;AACxB,SAAO,kBAAkB,QAAQ,mBAAmB;AAEpD,QAAM,UAAU,QAAQ,WAAW;AACnC,SAAO,WAAW,GAAG,QAAQ,QAAQ,OAAO,EAAE,CAAC;AAC/C,SAAO,mBAAmB,GAAG,QAAQ,QAAQ,OAAO,EAAE,CAAC;AACvD,gBAAc;AAChB;AAEA,SAAS,WAAW,SAAuB;AACzC,MAAI,YAAa;AACjB,MAAI,CAAC,SAAS,aAAa,CAAC,SAAS,QAAQ;AAC3C,UAAM,IAAI,MAAM,2FAA2F;AAAA,EAC7G;AACA,OAAK,OAAO;AACZ,MAAI,CAAC,mBAAmB;AACtB,wBAAoB,wBAAwB,EACzC,KAAK,CAAC,EAAE,IAAI,OAAO,MAAM;AACxB,UAAI,CAAC,IAAI;AACP,gBAAQ,MAAM,qCAAqC,MAAM;AACzD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,cAAQ,IAAI,8BAA8B;AAAA,IAC5C,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,cAAQ,MAAM,qCAAqC,KAAK,WAAW,GAAG;AACtE,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AAAA,EACL;AACF;AAEA,eAAsB,0BAA0B;AAC9C,MAAI,CAAC,OAAO,WAAW;AACrB,WAAO,EAAE,IAAI,OAAO,QAAQ,oBAAoB;AAAA,EAClD;AACA,MAAI,CAAC,OAAO,QAAQ;AAClB,WAAO,EAAE,IAAI,OAAO,QAAQ,iBAAiB;AAAA,EAC/C;AAEA,QAAM,UAAU,EAAE,QAAQ,OAAO,UAAU;AAC3C,QAAM,eAAe,KAAK,UAAU,OAAO;AAC3C,QAAM,MAAM,MAAM,MAAM,OAAO,kBAAkB;AAAA,IAC/C,QAAQ;AAAA,IACR,SAAS,aAAa,YAAY;AAAA,IAClC,MAAM;AAAA,EACR,CAAC;AAED,MAAI,IAAI,IAAI;AACV,WAAO,EAAE,IAAI,MAAM,QAAQ,KAAK;AAAA,EAClC;AAEA,MAAI,SAAS,QAAQ,IAAI,MAAM;AAC/B,MAAI;AACF,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,QAAQ,OAAO,KAAK,WAAW,UAAU;AAC3C,eAAS,KAAK;AAAA,IAChB;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO,EAAE,IAAI,OAAO,OAAO;AAC7B;AAEA,eAAsB,YAAY,OAAyB;AACzD,MAAI,CAAC,OAAO,aAAa,CAAC,OAAO,QAAQ;AACvC,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACA,MAAI,CAAC,OAAO,UAAU,CAAC,OAAO,OAAO;AACnC,WAAO,EAAE,IAAI,OAAO,QAAQ,0BAA0B;AAAA,EACxD;AAEA,MAAI,CAAC,WAAW,MAAM,QAAQ,MAAM,KAAK,GAAG;AAC1C,WAAO,EAAE,IAAI,MAAM,QAAQ,WAAW;AAAA,EACxC;AAEA,QAAM,UAAU;AAAA,IACd,SAAS,MAAM;AAAA,IACf,SAAS,MAAM;AAAA,IACf,OAAO,MAAM;AAAA,IACb,IAAI,KAAK,IAAI,IAAI;AAAA,IACjB,UAAU,QAAQ,MAAM,OAAO;AAAA,IAC/B,QAAQ,OAAO;AAAA,EACjB;AAEA,QAAM,eAAe,KAAK,UAAU,OAAO;AAC3C,QAAM,MAAM,MAAM,MAAM,OAAO,UAAU;AAAA,IACvC,QAAQ;AAAA,IACR,SAAS,aAAa,YAAY;AAAA,IAClC,MAAM;AAAA,EACR,CAAC;AAED,SAAO,EAAE,IAAI,IAAI,IAAI,QAAQ,IAAI,OAAO;AAC1C;AAEA,SAAS,sBAAsB,SAAc;AAC3C,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,QAAQ,OAAO,OAAQ,QAAO;AAClC,MAAI,QAAQ,MAAO,QAAO;AAC1B,MAAI,QAAQ,QAAS,QAAO;AAC5B,MAAI,QAAQ,UAAW,QAAO;AAC9B,SAAO;AACT;AAEA,SAAS,0BAA0B,SAAuB;AACxD,aAAW,OAAO;AAClB,SAAO,OAAO,KAAU,SAA8B;AACpD,QAAI;AACF,YAAM,QAAQ,KAAK,gBACf,WACA,KAAK,cACL,iBACA,sBAAsB,KAAK,OAAO;AACtC,YAAM,SAAS,KAAK,MAAM,MAAM,KAAK,SAAS,MAAM;AACpD,YAAM,SAAS,KAAK,MAAM;AAC1B,YAAM,UAAU,OAAO,KAAK,SAAS,SAAS,YAAY,IAAI,QAAQ,KAAK,WAAW,QAAQ;AAE9F,UAAI,UAAU,QAAQ;AACpB,cAAM,YAAY,EAAE,QAAQ,QAAQ,OAAO,QAAQ,CAAC;AAAA,MACtD;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,QAAI,MAAM;AACR,YAAM,KAAK;AAAA,IACb;AAAA,EACF;AACF;AAEA,SAAS,wBAAwB,SAAuB;AACtD,aAAW,OAAO;AAClB,SAAO,OAAO,KAAU,SAA8B;AACpD,QAAI;AACF,YAAM,QAAQ,KAAK,gBACf,WACA,KAAK,cACL,iBACA,sBAAsB,KAAK,OAAO;AACtC,YAAM,SAAS,KAAK,MAAM,MAAM,KAAK,SAAS,MAAM;AACpD,YAAM,SAAS,KAAK,MAAM;AAC1B,YAAM,UAAU,OAAO,KAAK,SAAS,SAAS,YAAY,IAAI,QAAQ,KAAK,WAAW,QAAQ;AAE9F,UAAI,UAAU,QAAQ;AACpB,cAAM,YAAY,EAAE,QAAQ,QAAQ,OAAO,QAAQ,CAAC;AAAA,MACtD;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,QAAI,MAAM;AACR,YAAM,KAAK;AAAA,IACb;AAAA,EACF;AACF;AAEO,IAAM,UAAU;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,QAAQ;AACV;AAEO,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF;","names":["crypto"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import crypto from \"node:crypto\";\n\nexport type InitOptions = {\n botSecret: string;\n apiKey: string;\n cooldownSeconds?: number;\n baseUrl?: string;\n};\n\ntype ReportEventInput = {\n chatId: number | string;\n userId: number | string;\n event: string;\n isStart?: boolean;\n};\n\ntype Config = {\n apiKey: string | null;\n botSecret: string | null;\n endpoint: string;\n validateEndpoint: string;\n cooldownSeconds: number;\n};\n\nconst DEFAULT_BASE_URL = \"https://sdk.adstelo.com\";\n\nconst config: Config = {\n apiKey: null,\n botSecret: null,\n endpoint: `${DEFAULT_BASE_URL}/event`,\n validateEndpoint: `${DEFAULT_BASE_URL}/event/validate`,\n cooldownSeconds: 2\n};\n\nlet initialized = false;\nlet validationPromise: Promise<void> | null = null;\nconst cooldownMap = new Map<string, number>();\n\nfunction buildHeaders(payloadBytes: string) {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"ngrok-skip-browser-warning\": \"true\"\n };\n\n if (config.apiKey) {\n headers[\"X-Api-Key\"] = config.apiKey;\n const signature = crypto\n .createHmac(\"sha256\", config.apiKey)\n .update(payloadBytes)\n .digest(\"hex\");\n headers[\"X-Signature\"] = signature;\n }\n\n return headers;\n}\n\nfunction nowSeconds() {\n return Math.floor(Date.now() / 1000);\n}\n\nfunction cooldownKey(userId: string | number, event: string) {\n return `${userId}:${event}`;\n}\n\nfunction allowEvent(userId: string | number, event: string) {\n const key = cooldownKey(userId, event);\n const current = nowSeconds();\n const last = cooldownMap.get(key) ?? 0;\n if (current - last < config.cooldownSeconds) {\n return false;\n }\n cooldownMap.set(key, current);\n return true;\n}\n\nfunction init(options: InitOptions) {\n if (!options || !options.botSecret || !options.apiKey) {\n throw new Error(\"botSecret and apiKey are required\");\n }\n\n config.botSecret = options.botSecret;\n config.apiKey = options.apiKey;\n config.cooldownSeconds = options.cooldownSeconds ?? 2;\n\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n config.endpoint = `${baseUrl.replace(/\\/$/, \"\")}/event`;\n config.validateEndpoint = `${baseUrl.replace(/\\/$/, \"\")}/event/validate`;\n initialized = true;\n}\n\nfunction ensureInit(options?: InitOptions) {\n if (initialized) return;\n if (!options?.botSecret || !options?.apiKey) {\n throw new Error(\"Missing botSecret or apiKey. Pass them to adstelo.grammy/adstelo.telegraf.\");\n }\n init(options);\n if (!validationPromise) {\n validationPromise = validateInitCredentials()\n .then(({ ok, detail }) => {\n if (!ok) {\n console.error(\"[adstelo] init validation failed:\", detail);\n process.exit(1);\n }\n console.log(\"[adstelo] init validation ok\");\n })\n .catch((err) => {\n console.error(\"[adstelo] init validation failed:\", err?.message || err);\n process.exit(1);\n });\n }\n}\n\nasync function validateInitCredentials() {\n if (!config.botSecret) {\n return { ok: false, detail: \"Missing botSecret\" };\n }\n if (!config.apiKey) {\n return { ok: false, detail: \"Missing apiKey\" };\n }\n\n const payload = { secret: config.botSecret };\n const payloadBytes = JSON.stringify(payload);\n const res = await fetch(config.validateEndpoint, {\n method: \"POST\",\n headers: buildHeaders(payloadBytes),\n body: payloadBytes\n });\n\n if (res.ok) {\n return { ok: true, detail: \"ok\" };\n }\n\n let detail = `HTTP ${res.status}`;\n try {\n const data = await res.json();\n if (data && typeof data.detail === \"string\") {\n detail = data.detail;\n }\n } catch {\n // ignore\n }\n return { ok: false, detail };\n}\n\nasync function reportEvent(input: ReportEventInput) {\n if (!config.botSecret || !config.apiKey) {\n throw new Error(\"SDK not initialized. Pass credentials via adstelo.grammy/adstelo.telegraf.\");\n }\n if (!input?.userId || !input?.event) {\n return { ok: false, detail: \"Missing userId or event\" };\n }\n\n if (!allowEvent(input.userId, input.event)) {\n return { ok: true, detail: \"cooldown\" };\n }\n\n const payload = {\n chat_id: input.chatId,\n user_id: input.userId,\n event: input.event,\n ts: Date.now() / 1000,\n is_start: Boolean(input.isStart),\n secret: config.botSecret\n };\n\n const payloadBytes = JSON.stringify(payload);\n const res = await fetch(config.endpoint, {\n method: \"POST\",\n headers: buildHeaders(payloadBytes),\n body: payloadBytes\n });\n\n return { ok: res.ok, status: res.status };\n}\n\nfunction inferEventFromMessage(message: any) {\n if (!message) return \"message\";\n if (message.photo?.length) return \"photo\";\n if (message.video) return \"video\";\n if (message.sticker) return \"sticker\";\n if (message.animation) return \"media\";\n return \"message\";\n}\n\nfunction adsteloTelegrafMiddleware(options?: InitOptions) {\n ensureInit(options);\n return async (ctx: any, next: () => Promise<void>) => {\n try {\n const event = ctx?.callbackQuery\n ? \"button\"\n : ctx?.inlineQuery\n ? \"inline_query\"\n : inferEventFromMessage(ctx?.message);\n const chatId = ctx?.chat?.id ?? ctx?.message?.chat?.id;\n const userId = ctx?.from?.id;\n const isStart = typeof ctx?.message?.text === \"string\" && ctx.message.text.startsWith(\"/start\");\n\n if (chatId && userId) {\n await reportEvent({ chatId, userId, event, isStart });\n }\n } catch {\n // swallow\n }\n\n if (next) {\n await next();\n }\n };\n}\n\nfunction adsteloGrammyMiddleware(options?: InitOptions) {\n ensureInit(options);\n return async (ctx: any, next: () => Promise<void>) => {\n try {\n const event = ctx?.callbackQuery\n ? \"button\"\n : ctx?.inlineQuery\n ? \"inline_query\"\n : inferEventFromMessage(ctx?.message);\n const chatId = ctx?.chat?.id ?? ctx?.message?.chat?.id;\n const userId = ctx?.from?.id;\n const isStart = typeof ctx?.message?.text === \"string\" && ctx.message.text.startsWith(\"/start\");\n\n if (chatId && userId) {\n await reportEvent({ chatId, userId, event, isStart });\n }\n } catch {\n // swallow\n }\n\n if (next) {\n await next();\n }\n };\n}\n\nexport const adstelo = {\n telegraf: adsteloTelegrafMiddleware,\n grammy: adsteloGrammyMiddleware\n};\n\nexport const _internal = {\n buildHeaders,\n allowEvent,\n inferEventFromMessage\n};\n"],"mappings":"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","names":["crypto"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -4,35 +4,12 @@ type InitOptions = {
|
|
|
4
4
|
cooldownSeconds?: number;
|
|
5
5
|
baseUrl?: string;
|
|
6
6
|
};
|
|
7
|
-
type ReportEventInput = {
|
|
8
|
-
chatId: number | string;
|
|
9
|
-
userId: number | string;
|
|
10
|
-
event: string;
|
|
11
|
-
isStart?: boolean;
|
|
12
|
-
};
|
|
13
7
|
declare function buildHeaders(payloadBytes: string): Record<string, string>;
|
|
14
8
|
declare function allowEvent(userId: string | number, event: string): boolean;
|
|
15
|
-
declare function init(options: InitOptions): void;
|
|
16
|
-
declare function validateInitCredentials(): Promise<{
|
|
17
|
-
ok: boolean;
|
|
18
|
-
detail: string;
|
|
19
|
-
}>;
|
|
20
|
-
declare function reportEvent(input: ReportEventInput): Promise<{
|
|
21
|
-
ok: boolean;
|
|
22
|
-
detail: string;
|
|
23
|
-
status?: undefined;
|
|
24
|
-
} | {
|
|
25
|
-
ok: boolean;
|
|
26
|
-
status: number;
|
|
27
|
-
detail?: undefined;
|
|
28
|
-
}>;
|
|
29
9
|
declare function inferEventFromMessage(message: any): "message" | "photo" | "video" | "sticker" | "media";
|
|
30
10
|
declare function adsteloTelegrafMiddleware(options?: InitOptions): (ctx: any, next: () => Promise<void>) => Promise<void>;
|
|
31
11
|
declare function adsteloGrammyMiddleware(options?: InitOptions): (ctx: any, next: () => Promise<void>) => Promise<void>;
|
|
32
12
|
declare const adstelo: {
|
|
33
|
-
init: typeof init;
|
|
34
|
-
reportEvent: typeof reportEvent;
|
|
35
|
-
validateInitCredentials: typeof validateInitCredentials;
|
|
36
13
|
telegraf: typeof adsteloTelegrafMiddleware;
|
|
37
14
|
grammy: typeof adsteloGrammyMiddleware;
|
|
38
15
|
};
|
|
@@ -42,4 +19,4 @@ declare const _internal: {
|
|
|
42
19
|
inferEventFromMessage: typeof inferEventFromMessage;
|
|
43
20
|
};
|
|
44
21
|
|
|
45
|
-
export { type InitOptions,
|
|
22
|
+
export { type InitOptions, _internal, adstelo };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,35 +4,12 @@ type InitOptions = {
|
|
|
4
4
|
cooldownSeconds?: number;
|
|
5
5
|
baseUrl?: string;
|
|
6
6
|
};
|
|
7
|
-
type ReportEventInput = {
|
|
8
|
-
chatId: number | string;
|
|
9
|
-
userId: number | string;
|
|
10
|
-
event: string;
|
|
11
|
-
isStart?: boolean;
|
|
12
|
-
};
|
|
13
7
|
declare function buildHeaders(payloadBytes: string): Record<string, string>;
|
|
14
8
|
declare function allowEvent(userId: string | number, event: string): boolean;
|
|
15
|
-
declare function init(options: InitOptions): void;
|
|
16
|
-
declare function validateInitCredentials(): Promise<{
|
|
17
|
-
ok: boolean;
|
|
18
|
-
detail: string;
|
|
19
|
-
}>;
|
|
20
|
-
declare function reportEvent(input: ReportEventInput): Promise<{
|
|
21
|
-
ok: boolean;
|
|
22
|
-
detail: string;
|
|
23
|
-
status?: undefined;
|
|
24
|
-
} | {
|
|
25
|
-
ok: boolean;
|
|
26
|
-
status: number;
|
|
27
|
-
detail?: undefined;
|
|
28
|
-
}>;
|
|
29
9
|
declare function inferEventFromMessage(message: any): "message" | "photo" | "video" | "sticker" | "media";
|
|
30
10
|
declare function adsteloTelegrafMiddleware(options?: InitOptions): (ctx: any, next: () => Promise<void>) => Promise<void>;
|
|
31
11
|
declare function adsteloGrammyMiddleware(options?: InitOptions): (ctx: any, next: () => Promise<void>) => Promise<void>;
|
|
32
12
|
declare const adstelo: {
|
|
33
|
-
init: typeof init;
|
|
34
|
-
reportEvent: typeof reportEvent;
|
|
35
|
-
validateInitCredentials: typeof validateInitCredentials;
|
|
36
13
|
telegraf: typeof adsteloTelegrafMiddleware;
|
|
37
14
|
grammy: typeof adsteloGrammyMiddleware;
|
|
38
15
|
};
|
|
@@ -42,4 +19,4 @@ declare const _internal: {
|
|
|
42
19
|
inferEventFromMessage: typeof inferEventFromMessage;
|
|
43
20
|
};
|
|
44
21
|
|
|
45
|
-
export { type InitOptions,
|
|
22
|
+
export { type InitOptions, _internal, adstelo };
|
package/dist/index.js
CHANGED
|
@@ -54,7 +54,7 @@ function init(options) {
|
|
|
54
54
|
function ensureInit(options) {
|
|
55
55
|
if (initialized) return;
|
|
56
56
|
if (!options?.botSecret || !options?.apiKey) {
|
|
57
|
-
throw new Error("Missing botSecret or apiKey. Pass them to adstelo.grammy/adstelo.telegraf
|
|
57
|
+
throw new Error("Missing botSecret or apiKey. Pass them to adstelo.grammy/adstelo.telegraf.");
|
|
58
58
|
}
|
|
59
59
|
init(options);
|
|
60
60
|
if (!validationPromise) {
|
|
@@ -99,7 +99,7 @@ async function validateInitCredentials() {
|
|
|
99
99
|
}
|
|
100
100
|
async function reportEvent(input) {
|
|
101
101
|
if (!config.botSecret || !config.apiKey) {
|
|
102
|
-
throw new Error("SDK not initialized.
|
|
102
|
+
throw new Error("SDK not initialized. Pass credentials via adstelo.grammy/adstelo.telegraf.");
|
|
103
103
|
}
|
|
104
104
|
if (!input?.userId || !input?.event) {
|
|
105
105
|
return { ok: false, detail: "Missing userId or event" };
|
|
@@ -168,9 +168,6 @@ function adsteloGrammyMiddleware(options) {
|
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
170
|
var adstelo = {
|
|
171
|
-
init,
|
|
172
|
-
reportEvent,
|
|
173
|
-
validateInitCredentials,
|
|
174
171
|
telegraf: adsteloTelegrafMiddleware,
|
|
175
172
|
grammy: adsteloGrammyMiddleware
|
|
176
173
|
};
|
|
@@ -181,9 +178,6 @@ var _internal = {
|
|
|
181
178
|
};
|
|
182
179
|
export {
|
|
183
180
|
_internal,
|
|
184
|
-
adstelo
|
|
185
|
-
init,
|
|
186
|
-
reportEvent,
|
|
187
|
-
validateInitCredentials
|
|
181
|
+
adstelo
|
|
188
182
|
};
|
|
189
183
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import crypto from \"node:crypto\";\n\nexport type InitOptions = {\n botSecret: string;\n apiKey: string;\n cooldownSeconds?: number;\n baseUrl?: string;\n};\n\nexport type ReportEventInput = {\n chatId: number | string;\n userId: number | string;\n event: string;\n isStart?: boolean;\n};\n\ntype Config = {\n apiKey: string | null;\n botSecret: string | null;\n endpoint: string;\n validateEndpoint: string;\n cooldownSeconds: number;\n};\n\nconst DEFAULT_BASE_URL = \"https://sdk.adstelo.com\";\n\nconst config: Config = {\n apiKey: null,\n botSecret: null,\n endpoint: `${DEFAULT_BASE_URL}/event`,\n validateEndpoint: `${DEFAULT_BASE_URL}/event/validate`,\n cooldownSeconds: 2\n};\n\nlet initialized = false;\nlet validationPromise: Promise<void> | null = null;\nconst cooldownMap = new Map<string, number>();\n\nfunction buildHeaders(payloadBytes: string) {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"ngrok-skip-browser-warning\": \"true\"\n };\n\n if (config.apiKey) {\n headers[\"X-Api-Key\"] = config.apiKey;\n const signature = crypto\n .createHmac(\"sha256\", config.apiKey)\n .update(payloadBytes)\n .digest(\"hex\");\n headers[\"X-Signature\"] = signature;\n }\n\n return headers;\n}\n\nfunction nowSeconds() {\n return Math.floor(Date.now() / 1000);\n}\n\nfunction cooldownKey(userId: string | number, event: string) {\n return `${userId}:${event}`;\n}\n\nfunction allowEvent(userId: string | number, event: string) {\n const key = cooldownKey(userId, event);\n const current = nowSeconds();\n const last = cooldownMap.get(key) ?? 0;\n if (current - last < config.cooldownSeconds) {\n return false;\n }\n cooldownMap.set(key, current);\n return true;\n}\n\nexport function init(options: InitOptions) {\n if (!options || !options.botSecret || !options.apiKey) {\n throw new Error(\"botSecret and apiKey are required\");\n }\n\n config.botSecret = options.botSecret;\n config.apiKey = options.apiKey;\n config.cooldownSeconds = options.cooldownSeconds ?? 2;\n\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n config.endpoint = `${baseUrl.replace(/\\/$/, \"\")}/event`;\n config.validateEndpoint = `${baseUrl.replace(/\\/$/, \"\")}/event/validate`;\n initialized = true;\n}\n\nfunction ensureInit(options?: InitOptions) {\n if (initialized) return;\n if (!options?.botSecret || !options?.apiKey) {\n throw new Error(\"Missing botSecret or apiKey. Pass them to adstelo.grammy/adstelo.telegraf or call init().\");\n }\n init(options);\n if (!validationPromise) {\n validationPromise = validateInitCredentials()\n .then(({ ok, detail }) => {\n if (!ok) {\n console.error(\"[adstelo] init validation failed:\", detail);\n process.exit(1);\n }\n console.log(\"[adstelo] init validation ok\");\n })\n .catch((err) => {\n console.error(\"[adstelo] init validation failed:\", err?.message || err);\n process.exit(1);\n });\n }\n}\n\nexport async function validateInitCredentials() {\n if (!config.botSecret) {\n return { ok: false, detail: \"Missing botSecret\" };\n }\n if (!config.apiKey) {\n return { ok: false, detail: \"Missing apiKey\" };\n }\n\n const payload = { secret: config.botSecret };\n const payloadBytes = JSON.stringify(payload);\n const res = await fetch(config.validateEndpoint, {\n method: \"POST\",\n headers: buildHeaders(payloadBytes),\n body: payloadBytes\n });\n\n if (res.ok) {\n return { ok: true, detail: \"ok\" };\n }\n\n let detail = `HTTP ${res.status}`;\n try {\n const data = await res.json();\n if (data && typeof data.detail === \"string\") {\n detail = data.detail;\n }\n } catch {\n // ignore\n }\n return { ok: false, detail };\n}\n\nexport async function reportEvent(input: ReportEventInput) {\n if (!config.botSecret || !config.apiKey) {\n throw new Error(\"SDK not initialized. Call init() first.\");\n }\n if (!input?.userId || !input?.event) {\n return { ok: false, detail: \"Missing userId or event\" };\n }\n\n if (!allowEvent(input.userId, input.event)) {\n return { ok: true, detail: \"cooldown\" };\n }\n\n const payload = {\n chat_id: input.chatId,\n user_id: input.userId,\n event: input.event,\n ts: Date.now() / 1000,\n is_start: Boolean(input.isStart),\n secret: config.botSecret\n };\n\n const payloadBytes = JSON.stringify(payload);\n const res = await fetch(config.endpoint, {\n method: \"POST\",\n headers: buildHeaders(payloadBytes),\n body: payloadBytes\n });\n\n return { ok: res.ok, status: res.status };\n}\n\nfunction inferEventFromMessage(message: any) {\n if (!message) return \"message\";\n if (message.photo?.length) return \"photo\";\n if (message.video) return \"video\";\n if (message.sticker) return \"sticker\";\n if (message.animation) return \"media\";\n return \"message\";\n}\n\nfunction adsteloTelegrafMiddleware(options?: InitOptions) {\n ensureInit(options);\n return async (ctx: any, next: () => Promise<void>) => {\n try {\n const event = ctx?.callbackQuery\n ? \"button\"\n : ctx?.inlineQuery\n ? \"inline_query\"\n : inferEventFromMessage(ctx?.message);\n const chatId = ctx?.chat?.id ?? ctx?.message?.chat?.id;\n const userId = ctx?.from?.id;\n const isStart = typeof ctx?.message?.text === \"string\" && ctx.message.text.startsWith(\"/start\");\n\n if (chatId && userId) {\n await reportEvent({ chatId, userId, event, isStart });\n }\n } catch {\n // swallow\n }\n\n if (next) {\n await next();\n }\n };\n}\n\nfunction adsteloGrammyMiddleware(options?: InitOptions) {\n ensureInit(options);\n return async (ctx: any, next: () => Promise<void>) => {\n try {\n const event = ctx?.callbackQuery\n ? \"button\"\n : ctx?.inlineQuery\n ? \"inline_query\"\n : inferEventFromMessage(ctx?.message);\n const chatId = ctx?.chat?.id ?? ctx?.message?.chat?.id;\n const userId = ctx?.from?.id;\n const isStart = typeof ctx?.message?.text === \"string\" && ctx.message.text.startsWith(\"/start\");\n\n if (chatId && userId) {\n await reportEvent({ chatId, userId, event, isStart });\n }\n } catch {\n // swallow\n }\n\n if (next) {\n await next();\n }\n };\n}\n\nexport const adstelo = {\n init,\n reportEvent,\n validateInitCredentials,\n telegraf: adsteloTelegrafMiddleware,\n grammy: adsteloGrammyMiddleware\n};\n\nexport const _internal = {\n buildHeaders,\n allowEvent,\n inferEventFromMessage\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import crypto from \"node:crypto\";\n\nexport type InitOptions = {\n botSecret: string;\n apiKey: string;\n cooldownSeconds?: number;\n baseUrl?: string;\n};\n\ntype ReportEventInput = {\n chatId: number | string;\n userId: number | string;\n event: string;\n isStart?: boolean;\n};\n\ntype Config = {\n apiKey: string | null;\n botSecret: string | null;\n endpoint: string;\n validateEndpoint: string;\n cooldownSeconds: number;\n};\n\nconst DEFAULT_BASE_URL = \"https://sdk.adstelo.com\";\n\nconst config: Config = {\n apiKey: null,\n botSecret: null,\n endpoint: `${DEFAULT_BASE_URL}/event`,\n validateEndpoint: `${DEFAULT_BASE_URL}/event/validate`,\n cooldownSeconds: 2\n};\n\nlet initialized = false;\nlet validationPromise: Promise<void> | null = null;\nconst cooldownMap = new Map<string, number>();\n\nfunction buildHeaders(payloadBytes: string) {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"ngrok-skip-browser-warning\": \"true\"\n };\n\n if (config.apiKey) {\n headers[\"X-Api-Key\"] = config.apiKey;\n const signature = crypto\n .createHmac(\"sha256\", config.apiKey)\n .update(payloadBytes)\n .digest(\"hex\");\n headers[\"X-Signature\"] = signature;\n }\n\n return headers;\n}\n\nfunction nowSeconds() {\n return Math.floor(Date.now() / 1000);\n}\n\nfunction cooldownKey(userId: string | number, event: string) {\n return `${userId}:${event}`;\n}\n\nfunction allowEvent(userId: string | number, event: string) {\n const key = cooldownKey(userId, event);\n const current = nowSeconds();\n const last = cooldownMap.get(key) ?? 0;\n if (current - last < config.cooldownSeconds) {\n return false;\n }\n cooldownMap.set(key, current);\n return true;\n}\n\nfunction init(options: InitOptions) {\n if (!options || !options.botSecret || !options.apiKey) {\n throw new Error(\"botSecret and apiKey are required\");\n }\n\n config.botSecret = options.botSecret;\n config.apiKey = options.apiKey;\n config.cooldownSeconds = options.cooldownSeconds ?? 2;\n\n const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n config.endpoint = `${baseUrl.replace(/\\/$/, \"\")}/event`;\n config.validateEndpoint = `${baseUrl.replace(/\\/$/, \"\")}/event/validate`;\n initialized = true;\n}\n\nfunction ensureInit(options?: InitOptions) {\n if (initialized) return;\n if (!options?.botSecret || !options?.apiKey) {\n throw new Error(\"Missing botSecret or apiKey. Pass them to adstelo.grammy/adstelo.telegraf.\");\n }\n init(options);\n if (!validationPromise) {\n validationPromise = validateInitCredentials()\n .then(({ ok, detail }) => {\n if (!ok) {\n console.error(\"[adstelo] init validation failed:\", detail);\n process.exit(1);\n }\n console.log(\"[adstelo] init validation ok\");\n })\n .catch((err) => {\n console.error(\"[adstelo] init validation failed:\", err?.message || err);\n process.exit(1);\n });\n }\n}\n\nasync function validateInitCredentials() {\n if (!config.botSecret) {\n return { ok: false, detail: \"Missing botSecret\" };\n }\n if (!config.apiKey) {\n return { ok: false, detail: \"Missing apiKey\" };\n }\n\n const payload = { secret: config.botSecret };\n const payloadBytes = JSON.stringify(payload);\n const res = await fetch(config.validateEndpoint, {\n method: \"POST\",\n headers: buildHeaders(payloadBytes),\n body: payloadBytes\n });\n\n if (res.ok) {\n return { ok: true, detail: \"ok\" };\n }\n\n let detail = `HTTP ${res.status}`;\n try {\n const data = await res.json();\n if (data && typeof data.detail === \"string\") {\n detail = data.detail;\n }\n } catch {\n // ignore\n }\n return { ok: false, detail };\n}\n\nasync function reportEvent(input: ReportEventInput) {\n if (!config.botSecret || !config.apiKey) {\n throw new Error(\"SDK not initialized. Pass credentials via adstelo.grammy/adstelo.telegraf.\");\n }\n if (!input?.userId || !input?.event) {\n return { ok: false, detail: \"Missing userId or event\" };\n }\n\n if (!allowEvent(input.userId, input.event)) {\n return { ok: true, detail: \"cooldown\" };\n }\n\n const payload = {\n chat_id: input.chatId,\n user_id: input.userId,\n event: input.event,\n ts: Date.now() / 1000,\n is_start: Boolean(input.isStart),\n secret: config.botSecret\n };\n\n const payloadBytes = JSON.stringify(payload);\n const res = await fetch(config.endpoint, {\n method: \"POST\",\n headers: buildHeaders(payloadBytes),\n body: payloadBytes\n });\n\n return { ok: res.ok, status: res.status };\n}\n\nfunction inferEventFromMessage(message: any) {\n if (!message) return \"message\";\n if (message.photo?.length) return \"photo\";\n if (message.video) return \"video\";\n if (message.sticker) return \"sticker\";\n if (message.animation) return \"media\";\n return \"message\";\n}\n\nfunction adsteloTelegrafMiddleware(options?: InitOptions) {\n ensureInit(options);\n return async (ctx: any, next: () => Promise<void>) => {\n try {\n const event = ctx?.callbackQuery\n ? \"button\"\n : ctx?.inlineQuery\n ? \"inline_query\"\n : inferEventFromMessage(ctx?.message);\n const chatId = ctx?.chat?.id ?? ctx?.message?.chat?.id;\n const userId = ctx?.from?.id;\n const isStart = typeof ctx?.message?.text === \"string\" && ctx.message.text.startsWith(\"/start\");\n\n if (chatId && userId) {\n await reportEvent({ chatId, userId, event, isStart });\n }\n } catch {\n // swallow\n }\n\n if (next) {\n await next();\n }\n };\n}\n\nfunction adsteloGrammyMiddleware(options?: InitOptions) {\n ensureInit(options);\n return async (ctx: any, next: () => Promise<void>) => {\n try {\n const event = ctx?.callbackQuery\n ? \"button\"\n : ctx?.inlineQuery\n ? \"inline_query\"\n : inferEventFromMessage(ctx?.message);\n const chatId = ctx?.chat?.id ?? ctx?.message?.chat?.id;\n const userId = ctx?.from?.id;\n const isStart = typeof ctx?.message?.text === \"string\" && ctx.message.text.startsWith(\"/start\");\n\n if (chatId && userId) {\n await reportEvent({ chatId, userId, event, isStart });\n }\n } catch {\n // swallow\n }\n\n if (next) {\n await next();\n }\n };\n}\n\nexport const adstelo = {\n telegraf: adsteloTelegrafMiddleware,\n grammy: adsteloGrammyMiddleware\n};\n\nexport const _internal = {\n buildHeaders,\n allowEvent,\n inferEventFromMessage\n};\n"],"mappings":"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","names":[]}
|